From 0d166cae0113cd28f9253ff12450d47b71fe0a40 Mon Sep 17 00:00:00 2001 From: Pádraig Brady Date: Mon, 25 Jun 2012 13:52:46 +0100 Subject: only mount guest image once when injecting files Previously we could incur the costly guest mount operation twice, if injecting files with any of net, ssh keys, password, metadata. Instead now inject files in the same operation. Also cleanup the internal injection functions a little by removing the unused 'execute' parameter. Partly mitigates the impact of bug 1013689. Change-Id: Ib66d327e745593cf1e5897470750d609b2a58980 --- nova/virt/disk/api.py | 39 ++++++++++++++------------------------- nova/virt/libvirt/driver.py | 23 +++++++---------------- nova/virt/xenapi/vm_utils.py | 6 +++--- 3 files changed, 24 insertions(+), 44 deletions(-) diff --git a/nova/virt/disk/api.py b/nova/virt/disk/api.py index 766c9ebd7..cf3b2f894 100644 --- a/nova/virt/disk/api.py +++ b/nova/virt/disk/api.py @@ -229,7 +229,7 @@ class _DiskImage(object): def inject_data(image, key=None, net=None, metadata=None, admin_password=None, - partition=None, use_cow=False): + files=None, partition=None, use_cow=False): """Injects a ssh key and optionally net data into a disk image. it will mount the image as a fully partitioned disk and attempt to inject @@ -242,21 +242,7 @@ def inject_data(image, if img.mount(): try: inject_data_into_fs(img.mount_dir, - key, net, metadata, admin_password, - utils.execute) - finally: - img.umount() - else: - raise exception.NovaException(img.errors) - - -def inject_files(image, files, partition=None, use_cow=False): - """Injects arbitrary files into a disk image""" - img = _DiskImage(image=image, partition=partition, use_cow=use_cow) - if img.mount(): - try: - for (path, contents) in files: - _inject_file_into_fs(img.mount_dir, path, contents) + key, net, metadata, admin_password, files) finally: img.umount() else: @@ -297,19 +283,22 @@ def destroy_container(img): LOG.exception(_('Failed to unmount container filesystem: %s'), exn) -def inject_data_into_fs(fs, key, net, metadata, admin_password, execute): +def inject_data_into_fs(fs, key, net, metadata, admin_password, files): """Injects data into a filesystem already mounted by the caller. Virt connections can call this directly if they mount their fs in a different way to inject_data """ if key: - _inject_key_into_fs(key, fs, execute=execute) + _inject_key_into_fs(key, fs) if net: - _inject_net_into_fs(net, fs, execute=execute) + _inject_net_into_fs(net, fs) if metadata: - _inject_metadata_into_fs(metadata, fs, execute=execute) + _inject_metadata_into_fs(metadata, fs) if admin_password: - _inject_admin_password_into_fs(admin_password, fs, execute=execute) + _inject_admin_password_into_fs(admin_password, fs) + if files: + for (path, contents) in files: + _inject_file_into_fs(fs, path, contents) def _join_and_check_path_within_fs(fs, *args): @@ -342,12 +331,12 @@ def _inject_file_into_fs(fs, path, contents, append=False): utils.execute('tee', *args, **kwargs) -def _inject_metadata_into_fs(metadata, fs, execute=None): +def _inject_metadata_into_fs(metadata, fs): metadata = dict([(m.key, m.value) for m in metadata]) _inject_file_into_fs(fs, 'meta.js', jsonutils.dumps(metadata)) -def _inject_key_into_fs(key, fs, execute=None): +def _inject_key_into_fs(key, fs): """Add the given public ssh key to root's authorized_keys. key is an ssh key string. @@ -371,7 +360,7 @@ def _inject_key_into_fs(key, fs, execute=None): _inject_file_into_fs(fs, keyfile, key_data, append=True) -def _inject_net_into_fs(net, fs, execute=None): +def _inject_net_into_fs(net, fs): """Inject /etc/network/interfaces into the filesystem rooted at fs. net is the contents of /etc/network/interfaces. @@ -385,7 +374,7 @@ def _inject_net_into_fs(net, fs, execute=None): _inject_file_into_fs(fs, netfile, net) -def _inject_admin_password_into_fs(admin_passwd, fs, execute=None): +def _inject_admin_password_into_fs(admin_passwd, fs): """Set the root password to admin_passwd admin_password is a root password diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 0f62a9c52..e24df7be8 100644 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -1062,12 +1062,6 @@ class LibvirtDriver(driver.ComputeDriver): fp.write(data) return fpath - def _inject_files(self, instance, files, partition): - disk_path = self.image_backend.image(instance['name'], - 'disk').path - disk.inject_files(disk_path, files, partition=partition, - use_cow=FLAGS.use_cow_images) - @exception.wrap_exception() def get_console_output(self, instance): virt_dom = self._lookup_by_name(instance['name']) @@ -1400,11 +1394,13 @@ class LibvirtDriver(driver.ComputeDriver): metadata = instance.get('metadata') if FLAGS.libvirt_inject_password: - admin_password = instance.get('admin_pass') + admin_pass = instance.get('admin_pass') else: - admin_password = None + admin_pass = None + + files = instance.get('injected_files') - if any((key, net, metadata, admin_password)): + if any((key, net, metadata, admin_pass, files)): if config_drive: # Should be True or None by now. injection_path = raw('disk.config').path img_id = 'config-drive' @@ -1412,13 +1408,13 @@ class LibvirtDriver(driver.ComputeDriver): injection_path = image('disk').path img_id = instance.image_ref - for injection in ('metadata', 'key', 'net', 'admin_password'): + for injection in ('metadata', 'key', 'net', 'admin_pass', 'files'): if locals()[injection]: LOG.info(_('Injecting %(injection)s into image' ' %(img_id)s'), locals(), instance=instance) try: disk.inject_data(injection_path, - key, net, metadata, admin_password, + key, net, metadata, admin_pass, files, partition=target_partition, use_cow=FLAGS.use_cow_images) @@ -1436,11 +1432,6 @@ class LibvirtDriver(driver.ComputeDriver): if FLAGS.libvirt_type == 'uml': libvirt_utils.chown(basepath('disk'), 'root') - files_to_inject = instance.get('injected_files') - if files_to_inject: - self._inject_files(instance, files_to_inject, - partition=target_partition) - @staticmethod def _volume_in_mapping(mount_device, block_device_info): block_device_list = [block_device.strip_dev(vol['mount_device']) diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index bd69923d6..b14ccb064 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -1863,10 +1863,10 @@ def _mounted_processing(device, key, net, metadata): if not _find_guest_agent(tmpdir, FLAGS.xenapi_agent_path): LOG.info(_('Manipulating interface files directly')) # for xenapi, we don't 'inject' admin_password here, - # it's handled at instance startup time + # it's handled at instance startup time, nor do we + # support injecting arbitrary files here. disk.inject_data_into_fs(tmpdir, - key, net, metadata, None, - utils.execute) + key, net, metadata, None, None) finally: utils.execute('umount', dev_path, run_as_root=True) else: -- cgit