Merge "libvirt: Combine injection info in InjectionInfo"
This commit is contained in:
commit
668f2f9631
@ -365,6 +365,11 @@ def fake_disk_info_json(instance, type='qcow2'):
|
||||
return jsonutils.dumps(disk_info.values())
|
||||
|
||||
|
||||
def get_injection_info(network_info=None, admin_pass=None, files=None):
|
||||
return libvirt_driver.InjectionInfo(
|
||||
network_info=network_info, admin_pass=admin_pass, files=files)
|
||||
|
||||
|
||||
def _concurrency(signal, wait, done, target, is_block_dev=False):
|
||||
signal.send()
|
||||
wait.wait()
|
||||
@ -10530,12 +10535,13 @@ class LibvirtConnTestCase(test.NoDBTestCase):
|
||||
fake_imagebackend.ImageBackendFixture(exists=lambda path: False))
|
||||
|
||||
mock_build_device_metadata.return_value = None
|
||||
|
||||
injection_info = get_injection_info(
|
||||
network_info=mock.sentinel.network_info,
|
||||
admin_pass=mock.sentinel.admin_pass,
|
||||
files=mock.sentinel.files
|
||||
)
|
||||
drvr = libvirt_driver.LibvirtDriver(fake.FakeVirtAPI(), False)
|
||||
drvr._create_configdrive(self.context, instance,
|
||||
admin_pass=mock.sentinel.admin_pass,
|
||||
files=mock.sentinel.files,
|
||||
network_info=mock.sentinel.network_info)
|
||||
drvr._create_configdrive(self.context, instance, injection_info)
|
||||
|
||||
expected_config_drive_path = os.path.join(
|
||||
CONF.instances_path, instance.uuid, 'disk.config')
|
||||
@ -16238,13 +16244,14 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
|
||||
disk_images = {'image_id': None}
|
||||
|
||||
drvr._create_and_inject_local_root(self.context, instance_ref, False,
|
||||
'', disk_images, [], None, [], True, None)
|
||||
'', disk_images, get_injection_info(),
|
||||
None)
|
||||
self.assertFalse(mock_inject.called)
|
||||
|
||||
@mock.patch('nova.virt.netutils.get_injected_network_template')
|
||||
@mock.patch('nova.virt.disk.api.inject_data')
|
||||
@mock.patch.object(libvirt_driver.LibvirtDriver, "_conn")
|
||||
def _test_inject_data(self, driver_params, path, disk_params,
|
||||
def _test_inject_data(self, instance, injection_info, path, disk_params,
|
||||
mock_conn, disk_inject_data, inj_network,
|
||||
called=True):
|
||||
class ImageBackend(object):
|
||||
@ -16265,7 +16272,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
|
||||
return_value=image_backend):
|
||||
self.flags(inject_partition=0, group='libvirt')
|
||||
|
||||
self.drvr._inject_data(image_backend, **driver_params)
|
||||
self.drvr._inject_data(image_backend, instance, injection_info)
|
||||
|
||||
if called:
|
||||
disk_inject_data.assert_called_once_with(
|
||||
@ -16275,18 +16282,10 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
|
||||
|
||||
self.assertEqual(disk_inject_data.called, called)
|
||||
|
||||
def _test_inject_data_default_driver_params(self, **params):
|
||||
return {
|
||||
'instance': self._create_instance(params=params),
|
||||
'network_info': None,
|
||||
'admin_pass': None,
|
||||
'files': None
|
||||
}
|
||||
|
||||
def test_inject_data_adminpass(self):
|
||||
self.flags(inject_password=True, group='libvirt')
|
||||
driver_params = self._test_inject_data_default_driver_params()
|
||||
driver_params['admin_pass'] = 'foobar'
|
||||
instance = self._create_instance()
|
||||
injection_info = get_injection_info(admin_pass='foobar')
|
||||
disk_params = [
|
||||
None, # key
|
||||
None, # net
|
||||
@ -16294,16 +16293,16 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
|
||||
'foobar', # admin_pass
|
||||
None, # files
|
||||
]
|
||||
self._test_inject_data(driver_params, "/path", disk_params)
|
||||
self._test_inject_data(instance, injection_info, "/path", disk_params)
|
||||
|
||||
# Test with the configuration setted to false.
|
||||
self.flags(inject_password=False, group='libvirt')
|
||||
self._test_inject_data(driver_params, "/path",
|
||||
disk_params, called=False)
|
||||
self._test_inject_data(instance, injection_info, "/path", disk_params,
|
||||
called=False)
|
||||
|
||||
def test_inject_data_key(self):
|
||||
driver_params = self._test_inject_data_default_driver_params()
|
||||
driver_params['instance']['key_data'] = 'key-content'
|
||||
instance = self._create_instance(params={'key_data': 'key-content'})
|
||||
injection_info = get_injection_info()
|
||||
|
||||
self.flags(inject_key=True, group='libvirt')
|
||||
disk_params = [
|
||||
@ -16313,18 +16312,17 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
|
||||
None, # admin_pass
|
||||
None, # files
|
||||
]
|
||||
self._test_inject_data(driver_params, "/path", disk_params)
|
||||
self._test_inject_data(instance, injection_info, "/path",
|
||||
disk_params)
|
||||
|
||||
# Test with the configuration setted to false.
|
||||
self.flags(inject_key=False, group='libvirt')
|
||||
self._test_inject_data(driver_params, "/path",
|
||||
disk_params, called=False)
|
||||
self._test_inject_data(instance, injection_info, "/path", disk_params,
|
||||
called=False)
|
||||
|
||||
def test_inject_data_metadata(self):
|
||||
instance_metadata = {'metadata': {'data': 'foo'}}
|
||||
driver_params = self._test_inject_data_default_driver_params(
|
||||
**instance_metadata
|
||||
)
|
||||
instance = self._create_instance(params={'metadata': {'data': 'foo'}})
|
||||
injection_info = get_injection_info()
|
||||
disk_params = [
|
||||
None, # key
|
||||
None, # net
|
||||
@ -16332,11 +16330,11 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
|
||||
None, # admin_pass
|
||||
None, # files
|
||||
]
|
||||
self._test_inject_data(driver_params, "/path", disk_params)
|
||||
self._test_inject_data(instance, injection_info, "/path", disk_params)
|
||||
|
||||
def test_inject_data_files(self):
|
||||
driver_params = self._test_inject_data_default_driver_params()
|
||||
driver_params['files'] = ['file1', 'file2']
|
||||
instance = self._create_instance()
|
||||
injection_info = get_injection_info(files=['file1', 'file2'])
|
||||
disk_params = [
|
||||
None, # key
|
||||
None, # net
|
||||
@ -16344,11 +16342,11 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
|
||||
None, # admin_pass
|
||||
['file1', 'file2'], # files
|
||||
]
|
||||
self._test_inject_data(driver_params, "/path", disk_params)
|
||||
self._test_inject_data(instance, injection_info, "/path", disk_params)
|
||||
|
||||
def test_inject_data_net(self):
|
||||
driver_params = self._test_inject_data_default_driver_params()
|
||||
driver_params['network_info'] = {'net': 'eno1'}
|
||||
instance = self._create_instance()
|
||||
injection_info = get_injection_info(network_info={'net': 'eno1'})
|
||||
disk_params = [
|
||||
None, # key
|
||||
{'net': 'eno1'}, # net
|
||||
@ -16356,10 +16354,11 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
|
||||
None, # admin_pass
|
||||
None, # files
|
||||
]
|
||||
self._test_inject_data(driver_params, "/path", disk_params)
|
||||
self._test_inject_data(instance, injection_info, "/path", disk_params)
|
||||
|
||||
def test_inject_not_exist_image(self):
|
||||
driver_params = self._test_inject_data_default_driver_params()
|
||||
instance = self._create_instance()
|
||||
injection_info = get_injection_info()
|
||||
disk_params = [
|
||||
'key-content', # key
|
||||
None, # net
|
||||
@ -16367,7 +16366,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase):
|
||||
None, # admin_pass
|
||||
None, # files
|
||||
]
|
||||
self._test_inject_data(driver_params, "/fail/path",
|
||||
self._test_inject_data(instance, injection_info, "/fail/path",
|
||||
disk_params, called=False)
|
||||
|
||||
def _test_attach_detach_interface(self, method, power_state,
|
||||
|
@ -141,6 +141,9 @@ CONSOLE = "console=tty0 console=ttyS0"
|
||||
GuestNumaConfig = collections.namedtuple(
|
||||
'GuestNumaConfig', ['cpuset', 'cputune', 'numaconfig', 'numatune'])
|
||||
|
||||
InjectionInfo = collections.namedtuple(
|
||||
'InjectionInfo', ['network_info', 'files', 'admin_pass'])
|
||||
|
||||
libvirt_volume_drivers = [
|
||||
'iscsi=nova.virt.libvirt.volume.iscsi.LibvirtISCSIVolumeDriver',
|
||||
'iser=nova.virt.libvirt.volume.iser.LibvirtISERVolumeDriver',
|
||||
@ -2595,15 +2598,15 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
instance,
|
||||
image_meta,
|
||||
rescue=True)
|
||||
injection_info = InjectionInfo(network_info=network_info,
|
||||
admin_pass=rescue_password,
|
||||
files=None)
|
||||
gen_confdrive = functools.partial(self._create_configdrive,
|
||||
context, instance,
|
||||
admin_pass=rescue_password,
|
||||
network_info=network_info,
|
||||
suffix='.rescue')
|
||||
context, instance, injection_info,
|
||||
rescue=True)
|
||||
self._create_image(context, instance, disk_info['mapping'],
|
||||
suffix='.rescue', disk_images=rescue_images,
|
||||
network_info=network_info,
|
||||
admin_pass=rescue_password)
|
||||
injection_info=injection_info, suffix='.rescue',
|
||||
disk_images=rescue_images)
|
||||
xml = self._get_guest_xml(context, instance, network_info, disk_info,
|
||||
image_meta, rescue=rescue_images)
|
||||
self._destroy(instance)
|
||||
@ -2649,17 +2652,15 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
instance,
|
||||
image_meta,
|
||||
block_device_info)
|
||||
injection_info = InjectionInfo(network_info=network_info,
|
||||
files=injected_files,
|
||||
admin_pass=admin_password)
|
||||
gen_confdrive = functools.partial(self._create_configdrive,
|
||||
context, instance,
|
||||
admin_pass=admin_password,
|
||||
files=injected_files,
|
||||
network_info=network_info)
|
||||
self._create_image(context, instance,
|
||||
disk_info['mapping'],
|
||||
network_info=network_info,
|
||||
block_device_info=block_device_info,
|
||||
files=injected_files,
|
||||
admin_pass=admin_password)
|
||||
injection_info)
|
||||
self._create_image(context, instance, disk_info['mapping'],
|
||||
injection_info=injection_info,
|
||||
block_device_info=block_device_info)
|
||||
|
||||
# Required by Quobyte CI
|
||||
self._ensure_console_log_for_instance(instance)
|
||||
@ -2926,11 +2927,6 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
instance=instance)
|
||||
libvirt_utils.file_open(console_file, 'a').close()
|
||||
|
||||
@staticmethod
|
||||
def _get_disk_config_path(instance, suffix=''):
|
||||
return os.path.join(libvirt_utils.get_instance_path(instance),
|
||||
'disk.config' + suffix)
|
||||
|
||||
@staticmethod
|
||||
def _get_disk_config_image_type():
|
||||
# TODO(mikal): there is a bug here if images_type has
|
||||
@ -2949,20 +2945,18 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
block_device_info)
|
||||
return bool(block_device.get_root_bdm(block_device_mapping))
|
||||
|
||||
def _inject_data(self, injection_image, instance, network_info,
|
||||
admin_pass, files):
|
||||
def _inject_data(self, disk, instance, injection_info):
|
||||
"""Injects data in a disk image
|
||||
|
||||
Helper used for injecting data in a disk image file system.
|
||||
|
||||
Keyword arguments:
|
||||
injection_image -- An Image object we're injecting into
|
||||
instance -- a dict that refers instance specifications
|
||||
network_info -- a dict that refers network speficications
|
||||
admin_pass -- a string used to set an admin password
|
||||
files -- a list of files needs to be injected
|
||||
:param disk: The disk we're injecting into (an Image object)
|
||||
:param instance: The instance we're injecting into
|
||||
:param injection_info: Injection info
|
||||
"""
|
||||
# Handles the partition need to be used.
|
||||
LOG.debug('Checking root disk injection %(info)s',
|
||||
info=str(injection_info), instance=instance)
|
||||
target_partition = None
|
||||
if not instance.kernel_id:
|
||||
target_partition = CONF.libvirt.inject_partition
|
||||
@ -2980,19 +2974,25 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
# Handles the admin password injection.
|
||||
if not CONF.libvirt.inject_password:
|
||||
admin_pass = None
|
||||
else:
|
||||
admin_pass = injection_info.admin_pass
|
||||
|
||||
# Handles the network injection.
|
||||
net = netutils.get_injected_network_template(
|
||||
network_info, libvirt_virt_type=CONF.libvirt.virt_type)
|
||||
injection_info.network_info,
|
||||
libvirt_virt_type=CONF.libvirt.virt_type)
|
||||
|
||||
# Handles the metadata injection
|
||||
metadata = instance.get('metadata')
|
||||
|
||||
if any((key, net, metadata, admin_pass, files)):
|
||||
if any((key, net, metadata, admin_pass, injection_info.files)):
|
||||
LOG.debug('Injecting %(info)s', info=str(injection_info),
|
||||
instance=instance)
|
||||
img_id = instance.image_ref
|
||||
try:
|
||||
disk_api.inject_data(injection_image.get_model(self._conn),
|
||||
key, net, metadata, admin_pass, files,
|
||||
disk_api.inject_data(disk.get_model(self._conn),
|
||||
key, net, metadata, admin_pass,
|
||||
injection_info.files,
|
||||
partition=target_partition,
|
||||
mandatory=('files',))
|
||||
except Exception as e:
|
||||
@ -3006,10 +3006,8 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
# method doesn't fail if an image already exists but instead
|
||||
# think that it will be reused (ie: (live)-migration/resize)
|
||||
def _create_image(self, context, instance,
|
||||
disk_mapping, suffix='',
|
||||
disk_images=None, network_info=None,
|
||||
block_device_info=None, files=None,
|
||||
admin_pass=None, inject_files=True,
|
||||
disk_mapping, injection_info=None, suffix='',
|
||||
disk_images=None, block_device_info=None,
|
||||
fallback_from_host=None,
|
||||
ignore_bdi_for_swap=False):
|
||||
booted_from_volume = self._is_booted_from_volume(block_device_info)
|
||||
@ -3049,9 +3047,9 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
libvirt_utils.chown(image('disk').path, 'root')
|
||||
|
||||
self._create_and_inject_local_root(context, instance,
|
||||
booted_from_volume, suffix, disk_images,
|
||||
network_info, admin_pass, files, inject_files,
|
||||
fallback_from_host)
|
||||
booted_from_volume, suffix,
|
||||
disk_images, injection_info,
|
||||
fallback_from_host)
|
||||
|
||||
# Lookup the filesystem type if required
|
||||
os_type_with_default = disk_api.get_fs_type_for_os_type(
|
||||
@ -3132,12 +3130,12 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
swap_mb=swap_mb)
|
||||
|
||||
def _create_and_inject_local_root(self, context, instance,
|
||||
booted_from_volume, suffix, disk_images,
|
||||
network_info, admin_pass, files, inject_files,
|
||||
fallback_from_host):
|
||||
booted_from_volume, suffix, disk_images,
|
||||
injection_info, fallback_from_host):
|
||||
# File injection only if needed
|
||||
need_inject = (not configdrive.required_by(instance) and
|
||||
inject_files and CONF.libvirt.inject_partition != -2)
|
||||
injection_info is not None and
|
||||
CONF.libvirt.inject_partition != -2)
|
||||
|
||||
# NOTE(ndipanov): Even if disk_mapping was passed in, which
|
||||
# currently happens only on rescue - we still don't want to
|
||||
@ -3167,49 +3165,60 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
instance, size, fallback_from_host)
|
||||
|
||||
if need_inject:
|
||||
self._inject_data(backend, instance, network_info, admin_pass,
|
||||
files)
|
||||
self._inject_data(backend, instance, injection_info)
|
||||
|
||||
elif need_inject:
|
||||
LOG.warning(_LW('File injection into a boot from volume '
|
||||
'instance is not supported'), instance=instance)
|
||||
|
||||
def _create_configdrive(self, context, instance, admin_pass=None,
|
||||
files=None, network_info=None, suffix=''):
|
||||
def _create_configdrive(self, context, instance, injection_info,
|
||||
rescue=False):
|
||||
# As this method being called right after the definition of a
|
||||
# domain, but before its actual launch, device metadata will be built
|
||||
# and saved in the instance for it to be used by the config drive and
|
||||
# the metadata service.
|
||||
instance.device_metadata = self._build_device_metadata(context,
|
||||
instance)
|
||||
config_drive_image = None
|
||||
if configdrive.required_by(instance):
|
||||
LOG.info(_LI('Using config drive'), instance=instance)
|
||||
|
||||
config_drive_image = self.image_backend.by_name(
|
||||
instance, 'disk.config' + suffix,
|
||||
self._get_disk_config_image_type())
|
||||
name = 'disk.config'
|
||||
if rescue:
|
||||
name += '.rescue'
|
||||
|
||||
config_disk = self.image_backend.by_name(
|
||||
instance, name, self._get_disk_config_image_type())
|
||||
|
||||
# Don't overwrite an existing config drive
|
||||
if not config_drive_image.exists():
|
||||
if not config_disk.exists():
|
||||
extra_md = {}
|
||||
if admin_pass:
|
||||
extra_md['admin_pass'] = admin_pass
|
||||
if injection_info.admin_pass:
|
||||
extra_md['admin_pass'] = injection_info.admin_pass
|
||||
|
||||
inst_md = instance_metadata.InstanceMetadata(
|
||||
instance, content=files, extra_md=extra_md,
|
||||
network_info=network_info, request_context=context)
|
||||
instance, content=injection_info.files, extra_md=extra_md,
|
||||
network_info=injection_info.network_info,
|
||||
request_context=context)
|
||||
|
||||
cdb = configdrive.ConfigDriveBuilder(instance_md=inst_md)
|
||||
with cdb:
|
||||
config_drive_local_path = self._get_disk_config_path(
|
||||
instance, suffix)
|
||||
# NOTE(mdbooth): We're hardcoding here the path of the
|
||||
# config disk when using the flat backend. This isn't
|
||||
# good, but it's required because we need a local path we
|
||||
# know we can write to in case we're subsequently
|
||||
# importing into rbd. This will be cleaned up when we
|
||||
# replace this with a call to create_from_func, but that
|
||||
# can't happen until we've updated the backends and we
|
||||
# teach them not to cache config disks. This isn't
|
||||
# possible while we're still using cache() under the hood.
|
||||
config_disk_local_path = os.path.join(
|
||||
libvirt_utils.get_instance_path(instance), name)
|
||||
LOG.info(_LI('Creating config drive at %(path)s'),
|
||||
{'path': config_drive_local_path},
|
||||
{'path': config_disk_local_path},
|
||||
instance=instance)
|
||||
|
||||
try:
|
||||
cdb.make_drive(config_drive_local_path)
|
||||
cdb.make_drive(config_disk_local_path)
|
||||
except processutils.ProcessExecutionError as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE('Creating config drive failed '
|
||||
@ -3217,14 +3226,13 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
e, instance=instance)
|
||||
|
||||
try:
|
||||
config_drive_image.import_file(
|
||||
instance, config_drive_local_path,
|
||||
'disk.config' + suffix)
|
||||
config_disk.import_file(
|
||||
instance, config_disk_local_path, name)
|
||||
finally:
|
||||
# NOTE(mikal): if the config drive was imported into RBD,
|
||||
# then we no longer need the local copy
|
||||
if CONF.libvirt.images_type == 'rbd':
|
||||
os.unlink(config_drive_local_path)
|
||||
os.unlink(config_disk_local_path)
|
||||
|
||||
def _prepare_pci_devices_for_use(self, pci_devices):
|
||||
# kvm , qemu support managed mode
|
||||
@ -7305,17 +7313,17 @@ class LibvirtDriver(driver.ComputeDriver):
|
||||
# NOTE: This has the intended side-effect of fetching a missing
|
||||
# backing file.
|
||||
self._create_image(context, instance, block_disk_info['mapping'],
|
||||
network_info=network_info,
|
||||
block_device_info=block_device_info,
|
||||
inject_files=False, ignore_bdi_for_swap=True,
|
||||
ignore_bdi_for_swap=True,
|
||||
fallback_from_host=migration.source_compute)
|
||||
|
||||
# Required by Quobyte CI
|
||||
self._ensure_console_log_for_instance(instance)
|
||||
|
||||
gen_confdrive = functools.partial(self._create_configdrive,
|
||||
context, instance,
|
||||
network_info=network_info)
|
||||
gen_confdrive = functools.partial(
|
||||
self._create_configdrive, context, instance,
|
||||
InjectionInfo(admin_pass=None, network_info=network_info,
|
||||
files=None))
|
||||
|
||||
# Convert raw disks to qcow2 if migrating to host which uses
|
||||
# qcow2 from host which uses raw.
|
||||
|
Loading…
x
Reference in New Issue
Block a user