From 28c376a6b7b9d26cd3d30b61aec522e3185fd358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= Date: Thu, 21 Jun 2012 15:28:05 +0100 Subject: [PATCH] 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. Change-Id: I250532af14262962777e354324e9aa89d5ecbea1 --- nova/virt/disk/api.py | 39 ++++++++++++++------------------------- nova/virt/libvirt/connection.py | 23 +++++++---------------- 2 files changed, 21 insertions(+), 41 deletions(-) diff --git a/nova/virt/disk/api.py b/nova/virt/disk/api.py index 6cb19f2..6756ac2 100644 --- a/nova/virt/disk/api.py +++ b/nova/virt/disk/api.py @@ -224,7 +224,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 @@ -237,21 +237,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.Error(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: @@ -291,19 +277,22 @@ def destroy_container(img): LOG.exception(_('Failed to remove container: %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 _inject_file_into_fs(fs, path, contents): @@ -314,7 +303,7 @@ def _inject_file_into_fs(fs, path, contents): run_as_root=True) -def _inject_metadata_into_fs(metadata, fs, execute=None): +def _inject_metadata_into_fs(metadata, fs): metadata_path = os.path.join(fs, "meta.js") metadata = dict([(m.key, m.value) for m in metadata]) @@ -322,7 +311,7 @@ def _inject_metadata_into_fs(metadata, fs, execute=None): process_input=json.dumps(metadata), run_as_root=True) -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. @@ -344,7 +333,7 @@ def _inject_key_into_fs(key, fs, execute=None): process_input=''.join(key_data), run_as_root=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. @@ -357,7 +346,7 @@ def _inject_net_into_fs(net, fs, execute=None): utils.execute('tee', netfile, process_input=net, run_as_root=True) -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/connection.py b/nova/virt/libvirt/connection.py index e0943ba..0fcba6a 100644 --- a/nova/virt/libvirt/connection.py +++ b/nova/virt/libvirt/connection.py @@ -965,12 +965,6 @@ class LibvirtConnection(driver.ComputeDriver): fp.write(data) return fpath - def _inject_files(self, instance, files, partition): - disk_path = os.path.join(FLAGS.instances_path, - instance['name'], 'disk') - 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']) @@ -1360,11 +1354,13 @@ class LibvirtConnection(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 = basepath('disk.config') img_id = 'config-drive' @@ -1372,13 +1368,13 @@ class LibvirtConnection(driver.ComputeDriver): injection_path = basepath('disk') 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) @@ -1396,11 +1392,6 @@ class LibvirtConnection(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']) -- 1.7.6.4