Merge "virt: Provide block_device_info during rescue"

This commit is contained in:
Zuul 2020-04-10 07:17:28 +00:00 committed by Gerrit Code Review
commit b6f3d393aa
14 changed files with 61 additions and 30 deletions

View File

@ -4150,6 +4150,11 @@ class ComputeManager(manager.Manager):
rescue_image_meta = self._get_rescue_image(context, instance,
rescue_image_ref)
bdms = objects.BlockDeviceMappingList.get_by_instance_uuid(
context, instance.uuid)
block_device_info = self._get_instance_block_device_info(
context, instance, bdms=bdms)
extra_usage_info = {'rescue_image_name':
self._get_image_name(rescue_image_meta)}
self._notify_about_instance_usage(context, instance,
@ -4162,9 +4167,9 @@ class ComputeManager(manager.Manager):
try:
self._power_off_instance(context, instance, clean_shutdown)
self.driver.rescue(context, instance,
network_info,
rescue_image_meta, admin_password)
self.driver.rescue(context, instance, network_info,
rescue_image_meta, admin_password,
block_device_info)
except Exception as e:
LOG.exception("Error trying to Rescue Instance",
instance=instance)

View File

@ -2277,7 +2277,7 @@ class ComputeTestCase(BaseTestCase,
'unrescued': False}
def fake_rescue(self, context, instance_ref, network_info, image_meta,
rescue_password):
rescue_password, block_device_info):
called['rescued'] = True
self.stub_out('nova.virt.fake.FakeDriver.rescue', fake_rescue)
@ -2309,7 +2309,7 @@ class ComputeTestCase(BaseTestCase,
def test_rescue_notifications(self, mock_context, mock_notify):
# Ensure notifications on instance rescue.
def fake_rescue(self, context, instance_ref, network_info, image_meta,
rescue_password):
rescue_password, block_device_info):
pass
self.stub_out('nova.virt.fake.FakeDriver.rescue', fake_rescue)
@ -2406,14 +2406,18 @@ class ComputeTestCase(BaseTestCase,
self.compute.terminate_instance(self.context, instance, [])
@mock.patch.object(nova.compute.manager.ComputeManager,
'_get_instance_block_device_info')
@mock.patch.object(fake.FakeDriver, 'power_off')
@mock.patch.object(fake.FakeDriver, 'rescue')
@mock.patch.object(compute_manager.ComputeManager, '_get_rescue_image')
def test_rescue_handle_err(self, mock_get, mock_rescue, mock_power_off):
def test_rescue_handle_err(self, mock_get, mock_rescue, mock_power_off,
mock_get_block_info):
# If the driver fails to rescue, instance state should got to ERROR
# and the exception should be converted to InstanceNotRescuable
inst_obj = self._create_fake_instance_obj()
mock_get.return_value = objects.ImageMeta.from_dict({})
mock_get_block_info.return_value = mock.sentinel.block_device_info
mock_rescue.side_effect = RuntimeError("Try again later")
expected_message = ('Instance %s cannot be rescued: '
@ -2429,13 +2433,16 @@ class ComputeTestCase(BaseTestCase,
self.assertEqual(vm_states.ERROR, inst_obj.vm_state)
mock_get.assert_called_once_with(mock.ANY, inst_obj, mock.ANY)
mock_rescue.assert_called_once_with(mock.ANY, inst_obj, [],
mock.ANY, 'password')
mock.ANY, 'password',
mock.sentinel.block_device_info)
@mock.patch.object(nova.compute.manager.ComputeManager,
'_get_instance_block_device_info')
@mock.patch.object(image_api.API, "get")
@mock.patch.object(fake.FakeDriver, 'power_off')
@mock.patch.object(nova.virt.fake.FakeDriver, "rescue")
def test_rescue_with_image_specified(self, mock_rescue, mock_power_off,
mock_image_get):
mock_image_get, mock_get_block_info):
image_ref = uuids.image_instance
rescue_image_meta = {}
params = {"task_state": task_states.RESCUING}
@ -2445,6 +2452,7 @@ class ComputeTestCase(BaseTestCase,
mock_context = mock.Mock()
mock_context.elevated.return_value = ctxt
mock_get_block_info.return_value = mock.sentinel.block_device_info
mock_image_get.return_value = rescue_image_meta
self.compute.rescue_instance(mock_context, instance=instance,
@ -2454,14 +2462,17 @@ class ComputeTestCase(BaseTestCase,
mock_image_get.assert_called_with(ctxt, image_ref)
mock_rescue.assert_called_with(ctxt, instance, [],
test.MatchType(objects.ImageMeta),
'password')
'password',
mock.sentinel.block_device_info)
self.compute.terminate_instance(ctxt, instance, [])
@mock.patch.object(nova.compute.manager.ComputeManager,
'_get_instance_block_device_info')
@mock.patch.object(image_api.API, "get")
@mock.patch.object(fake.FakeDriver, 'power_off')
@mock.patch.object(nova.virt.fake.FakeDriver, "rescue")
def test_rescue_with_base_image_when_image_not_specified(self,
mock_rescue, mock_power_off, mock_image_get):
mock_rescue, mock_power_off, mock_image_get, mock_get_block_info):
image_ref = FAKE_IMAGE_REF
system_meta = {"image_base_image_ref": image_ref}
rescue_image_meta = {}
@ -2473,6 +2484,7 @@ class ComputeTestCase(BaseTestCase,
mock_context = mock.Mock()
mock_context.elevated.return_value = ctxt
mock_get_block_info.return_value = mock.sentinel.block_device_info
mock_image_get.return_value = rescue_image_meta
self.compute.rescue_instance(mock_context, instance=instance,
@ -2484,7 +2496,8 @@ class ComputeTestCase(BaseTestCase,
mock_rescue.assert_called_with(ctxt, instance, [],
test.MatchType(objects.ImageMeta),
'password')
'password',
mock.sentinel.block_device_info)
self.compute.terminate_instance(self.context, instance, [])
def test_power_on(self):

View File

@ -4301,6 +4301,11 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
return_value=fake_nw_info),
mock.patch.object(self.compute, '_get_rescue_image',
return_value=rescue_image_meta),
mock.patch.object(objects.BlockDeviceMappingList,
'get_by_instance_uuid',
return_value=mock.sentinel.bdms),
mock.patch.object(self.compute, '_get_instance_block_device_info',
return_value=mock.sentinel.block_device_info),
mock.patch.object(self.compute, '_notify_about_instance_usage'),
mock.patch.object(self.compute, '_power_off_instance'),
mock.patch.object(self.compute.driver, 'rescue'),
@ -4310,8 +4315,9 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
mock.patch.object(instance, 'save')
) as (
elevated_context, get_nw_info, get_rescue_image,
notify_instance_usage, power_off_instance, driver_rescue,
notify_usage_exists, get_power_state, instance_save
get_bdm_list, get_block_info, notify_instance_usage,
power_off_instance, driver_rescue, notify_usage_exists,
get_power_state, instance_save
):
self.compute.rescue_instance(
self.context, instance, rescue_password='verybadpass',
@ -4327,6 +4333,9 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
get_nw_info.assert_called_once_with(self.context, instance)
get_rescue_image.assert_called_once_with(
self.context, instance, None)
get_bdm_list.assert_called_once_with(self.context, instance.uuid)
get_block_info.assert_called_once_with(self.context, instance,
bdms=mock.sentinel.bdms)
extra_usage_info = {'rescue_image_name': uuids.image_name}
notify_calls = [
@ -4344,7 +4353,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
driver_rescue.assert_called_once_with(
self.context, instance, fake_nw_info, rescue_image_meta,
'verybadpass')
'verybadpass', mock.sentinel.block_device_info)
notify_usage_exists.assert_called_once_with(self.compute.notifier,
self.context, instance, 'fake-mini', current_period=True)

View File

@ -3004,7 +3004,7 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
instance = fake_instance.fake_instance_obj(self.ctx,
node=node.uuid)
self.driver.rescue(self.ctx, instance, None, None, 'xyz')
self.driver.rescue(self.ctx, instance, None, None, 'xyz', None)
mock_sps.assert_called_once_with(node.uuid, 'rescue',
rescue_password='xyz')
@ -3021,7 +3021,7 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
self.assertRaises(exception.InstanceRescueFailure,
self.driver.rescue,
self.ctx, instance, None, None, 'xyz')
self.ctx, instance, None, None, 'xyz', None)
@mock.patch.object(ironic_driver.IronicDriver,
'_validate_instance_and_node')
@ -3035,7 +3035,7 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
self.assertRaises(exception.InstanceRescueFailure,
self.driver.rescue,
self.ctx, instance, None, None, 'xyz')
self.ctx, instance, None, None, 'xyz', None)
@mock.patch.object(ironic_driver.IronicDriver,
'_validate_instance_and_node')
@ -3051,7 +3051,7 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
self.assertRaises(exception.InstanceRescueFailure,
self.driver.rescue,
self.ctx, instance, None, None, 'xyz')
self.ctx, instance, None, None, 'xyz', None)
@mock.patch.object(loopingcall, 'FixedIntervalLoopingCall')
@mock.patch.object(FAKE_CLIENT.node, 'set_provision_state')

View File

@ -22576,7 +22576,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
self.drvr, '_create_domain',
side_effect=fake_create_domain) as mock_create_domain:
self.drvr.rescue(self.context, instance,
network_info, image_meta, rescue_password)
network_info, image_meta, rescue_password, None)
self.assertTrue(mock_create_domain.called)

View File

@ -298,7 +298,7 @@ class _VirtDriverTestCase(_FakeDriverBackendTestCase):
image_meta = objects.ImageMeta.from_dict({})
instance_ref, network_info = self._get_running_instance()
self.connection.rescue(self.ctxt, instance_ref, network_info,
image_meta, '')
image_meta, '', None)
@catch_notimplementederror
@mock.patch('os.unlink')
@ -313,7 +313,7 @@ class _VirtDriverTestCase(_FakeDriverBackendTestCase):
image_meta = objects.ImageMeta.from_dict({})
instance_ref, network_info = self._get_running_instance()
self.connection.rescue(self.ctxt, instance_ref, network_info,
image_meta, '')
image_meta, '', None)
self.connection.unrescue(instance_ref, network_info)
@catch_notimplementederror

View File

@ -1315,7 +1315,7 @@ class XenAPIVMTestCase(stubs.XenAPITestBase,
{'id': IMAGE_VHD,
'disk_format': 'vhd',
'properties': {'vm_mode': 'xen'}})
conn.rescue(self.context, instance, [], image_meta, '')
conn.rescue(self.context, instance, [], image_meta, '', None)
vm = xenapi_fake.get_record('VM', vm_ref)
rescue_name = "%s-rescue" % vm["name_label"]
@ -1351,7 +1351,7 @@ class XenAPIVMTestCase(stubs.XenAPITestBase,
self.conn._vmops, '_start',
side_effect=test.TestingException('Start Error')):
self.assertRaises(test.TestingException, self.conn.rescue,
self.context, instance, [], image_meta, '')
self.context, instance, [], image_meta, '', [])
# confirm original disk still exists:
vdi_ref2, vdi_rec2 = vm_utils.get_vdi_for_vm_safely(session,

View File

@ -850,7 +850,7 @@ class ComputeDriver(object):
raise NotImplementedError()
def rescue(self, context, instance, network_info, image_meta,
rescue_password):
rescue_password, block_device_info):
"""Rescue the specified instance.
:param nova.context.RequestContext context:
@ -862,6 +862,8 @@ class ComputeDriver(object):
:param nova.objects.ImageMeta image_meta:
The metadata of the image of the instance.
:param rescue_password: new root password to set for rescue.
:param dict block_device_info:
The block device mapping of the instance.
"""
raise NotImplementedError()

View File

@ -238,7 +238,7 @@ class FakeDriver(driver.ComputeDriver):
pass
def rescue(self, context, instance, network_info, image_meta,
rescue_password):
rescue_password, block_device_info):
pass
def unrescue(self, instance, network_info):

View File

@ -357,7 +357,7 @@ class HyperVDriver(driver.ComputeDriver):
return self._vmops.detach_interface(instance, vif)
def rescue(self, context, instance, network_info, image_meta,
rescue_password):
rescue_password, block_device_info):
self._vmops.rescue_instance(context, instance, network_info,
image_meta, rescue_password)

View File

@ -2120,7 +2120,7 @@ class IronicDriver(virt_driver.ComputeDriver):
version=max_version)
def rescue(self, context, instance, network_info, image_meta,
rescue_password):
rescue_password, block_device_info):
"""Rescue the specified instance.
:param nova.context.RequestContext context:
@ -2133,6 +2133,8 @@ class IronicDriver(virt_driver.ComputeDriver):
:param nova.objects.ImageMeta image_meta:
The metadata of the image of the instance. Ignored by this driver.
:param rescue_password: new root password to set for rescue.
:param dict block_device_info:
The block device mapping of the instance.
:raise InstanceRescueFailure if rescue fails.
"""
LOG.debug('Rescue called for instance', instance=instance)

View File

@ -3409,7 +3409,7 @@ class LibvirtDriver(driver.ComputeDriver):
self._hard_reboot(context, instance, network_info, block_device_info)
def rescue(self, context, instance, network_info, image_meta,
rescue_password):
rescue_password, block_device_info):
"""Loads a VM using rescue images.
A rescue is normally performed when something goes wrong with the

View File

@ -646,7 +646,7 @@ class VMwareVCDriver(driver.ComputeDriver):
self._vmops.resume(instance)
def rescue(self, context, instance, network_info, image_meta,
rescue_password):
rescue_password, block_device_info):
"""Rescue the specified instance."""
self._vmops.rescue(context, instance, network_info, image_meta)

View File

@ -313,7 +313,7 @@ class XenAPIDriver(driver.ComputeDriver):
self._vmops.resume(instance)
def rescue(self, context, instance, network_info, image_meta,
rescue_password):
rescue_password, block_device_info):
"""Rescue the specified instance."""
self._vmops.rescue(context, instance, network_info, image_meta,
rescue_password)