blob: bc76b77079553102c20cce7604cfcd951e8c07bc [file] [log] [blame]
# -*- coding: utf-8 -*-
import json
import logging
import os
import shutil
import six
import tempfile
import yaml
from oslo_utils import uuidutils
from oslo_utils import fileutils
from oslo_concurrency import processutils
class ConfigDriveBuilder(object):
"""Build config drives, optionally as a context manager."""
def __init__(self, image_file):
self.image_file = image_file
self.mdfiles=[]
def __enter__(self):
fileutils.delete_if_exists(self.image_file)
return self
def __exit__(self, exctype, excval, exctb):
self.make_drive()
def add_file(self, path, data):
self.mdfiles.append((path, data))
def _add_file(self, basedir, path, data):
filepath = os.path.join(basedir, path)
dirname = os.path.dirname(filepath)
fileutils.ensure_tree(dirname)
with open(filepath, 'wb') as f:
if isinstance(data, six.text_type):
data = data.encode('utf-8')
f.write(data)
def _write_md_files(self, basedir):
for data in self.mdfiles:
self._add_file(basedir, data[0], data[1])
def _make_iso9660(self, path, tmpdir):
processutils.execute('mkisofs',
'-o', path,
'-ldots',
'-allow-lowercase',
'-allow-multidot',
'-l',
'-V', 'config-2',
'-r',
'-J',
'-quiet',
tmpdir,
attempts=1,
run_as_root=False)
def make_drive(self):
"""Make the config drive.
:raises ProcessExecuteError if a helper process has failed.
"""
try:
tmpdir = tempfile.mkdtemp()
self._write_md_files(tmpdir)
self._make_iso9660(self.image_file, tmpdir)
finally:
shutil.rmtree(tmpdir)
def generate(
dst,
hostname,
domainname,
instance_id=None,
user_data=None,
network_data=None,
saltconfig=None
):
''' Generate config drive
:param dst: destination file to place config drive.
:param hostname: hostname of Instance.
:param domainname: instance domain.
:param instance_id: UUID of the instance.
:param user_data: custom user data dictionary. type: json
:param network_data: custom network info dictionary. type: json
:param saltconfig: salt minion configuration. type: json
'''
instance_md = {}
instance_md['uuid'] = instance_id or uuidutils.generate_uuid()
instance_md['hostname'] = '%s.%s' % (hostname, domainname)
instance_md['name'] = hostname
if user_data:
user_data = '#cloud-config\n\n' + yaml.dump(yaml.load(user_data), default_flow_style=False)
if saltconfig:
user_data += yaml.dump(yaml.load(str(saltconfig)), default_flow_style=False)
data = json.dumps(instance_md)
with ConfigDriveBuilder(dst) as cfgdrive:
cfgdrive.add_file('openstack/latest/meta_data.json', data)
if user_data:
cfgdrive.add_file('openstack/latest/user_data', user_data)
if network_data:
cfgdrive.add_file('openstack/latest/network_data.json', network_data)
cfgdrive.add_file('openstack/latest/vendor_data.json', '{}')
cfgdrive.add_file('openstack/latest/vendor_data2.json', '{}')