Fix config drive

Running tempest tests against nova-lxd discovered LXD is not working
properly.

ISO creation and handling was not working properly. Initially,
it was assumed that users can mount and ISO in their unprivileged
container. However this is not the case, which makes injecting
the ISO of the configdrive into an instance useless.

Now when a configdrive is needed, we create the ISO outside the
container, mount and copy the files to an directory on the host
and inject the path into the container.

Signed-off-by: Chuck Short <chuck.short@canonical.com>
This commit is contained in:
Chuck Short 2016-01-24 21:22:34 -05:00
parent 0ce890473c
commit 42803c3986
3 changed files with 48 additions and 13 deletions

View File

@ -73,7 +73,7 @@ class LXDContainerConfig(object):
config = self.configure_disk_path(configdrive_dir,
'var/lib/cloud',
'configdrive', instance)
container_config['devices'].upate(config)
container_config['devices'].update(config)
if container_config is None:
msg = _('Failed to get container configuration for %s') \

View File

@ -25,6 +25,7 @@ import shutil
from oslo_config import cfg
from oslo_log import log as logging
from oslo_utils import excutils
from oslo_utils import fileutils
from oslo_utils import units
from nova import exception
@ -64,6 +65,7 @@ class LXDContainerOperations(object):
self.session = session.LXDAPISession()
self.vif_driver = vif.LXDGenericDriver()
self.instance_dir = None
def list_instances(self):
return self.session.container_list()
@ -109,6 +111,13 @@ class LXDContainerOperations(object):
raise exception.InstanceExists(name=instance.name)
try:
# Ensure that the instance directory exists
self.instance_dir = \
self.container_dir.get_instance_dir(instance_name)
if not os.path.exists(self.instance_dir):
fileutils.ensure_tree(self.instance_dir)
# Step 1 - Fetch the image from glance
self._fetch_image(context, instance, image_meta)
@ -225,17 +234,43 @@ class LXDContainerOperations(object):
inst_md = instance_metadata.InstanceMetadata(instance,
content=injected_files,
extra_md=extra_md)
name = instance.name
try:
with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
container_configdrive = (
self.container_dir.get_container_configdrive(name)
)
cdb.make_drive(container_configdrive)
except Exception as e:
with excutils.save_and_reraise_exception():
LOG.error(_LE('Creating config drive failed with error: %s'),
e, instance=instance)
# Create the ISO image so we can inject the contents of the ISO
# into the container
iso_path = os.path.join(self.instance_dir, 'configdirve.iso')
with configdrive.ConfigDriveBuilder(instance_md=inst_md) as cdb:
try:
cdb.make_drive(iso_path)
except Exception as e:
with excutils.save_and_reraise_exception():
LOG.error(_LE('Creating config drive failed with error: %s'),
e, instance=instance)
# Copy the metadata info from the ISO into the container
configdrive_dir = \
self.container_dir.get_container_configdrive(instance.name)
with utils.tempdir() as tmpdir:
mounted = False
try:
_, err = utils.execute('mount',
'-o',
'loop,uid=%d,gid=%d' % (os.getuid(),
os.getgid()),
iso_path, tmpdir,
run_as_root=True)
mounted = True
# Copy and adjust the files from the ISO so that we
# dont have the ISO mounted during the life cycle of the
# instance and the directory can be removed once the instance
# is terminated
for ent in os.listdir(tmpdir):
shutil.copytree(os.path.join(tmpdir, ent),
os.path.join(configdrive_dir, ent))
utils.execute('chmod', '-R', '775', configdrive_dir,
run_as_root=True)
finally:
if mounted:
utils.execute('umount', tmpdir, run_as_root=True)
def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None, bad_volumes_callback=None):

View File

@ -52,7 +52,7 @@ class LXDContainerDirectories(object):
def get_container_configdrive(self, instance):
return os.path.join(CONF.instances_path,
instance,
'config-drive')
'configdrive')
def get_console_path(self, instance):
return os.path.join(CONF.lxd.root_dir,