Merge "Support rescuing an instance with shares"
This commit is contained in:
@@ -5038,6 +5038,8 @@ class ComputeManager(manager.Manager):
|
|||||||
block_device_info = self._get_instance_block_device_info(
|
block_device_info = self._get_instance_block_device_info(
|
||||||
context, instance, bdms=bdms)
|
context, instance, bdms=bdms)
|
||||||
|
|
||||||
|
share_info = self._get_share_info(context, instance)
|
||||||
|
|
||||||
extra_usage_info = {'rescue_image_name':
|
extra_usage_info = {'rescue_image_name':
|
||||||
self._get_image_name(rescue_image_meta)}
|
self._get_image_name(rescue_image_meta)}
|
||||||
self._notify_about_instance_usage(context, instance,
|
self._notify_about_instance_usage(context, instance,
|
||||||
@@ -5050,9 +5052,11 @@ class ComputeManager(manager.Manager):
|
|||||||
try:
|
try:
|
||||||
self._power_off_instance(context, instance, clean_shutdown)
|
self._power_off_instance(context, instance, clean_shutdown)
|
||||||
|
|
||||||
|
self._mount_all_shares(context, instance, share_info)
|
||||||
|
|
||||||
self.driver.rescue(context, instance, network_info,
|
self.driver.rescue(context, instance, network_info,
|
||||||
rescue_image_meta, admin_password,
|
rescue_image_meta, admin_password,
|
||||||
block_device_info)
|
block_device_info, share_info)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.exception("Error trying to Rescue Instance",
|
LOG.exception("Error trying to Rescue Instance",
|
||||||
instance=instance)
|
instance=instance)
|
||||||
|
|||||||
@@ -2417,7 +2417,7 @@ class ComputeTestCase(BaseTestCase,
|
|||||||
'unrescued': False}
|
'unrescued': False}
|
||||||
|
|
||||||
def fake_rescue(self, context, instance_ref, network_info, image_meta,
|
def fake_rescue(self, context, instance_ref, network_info, image_meta,
|
||||||
rescue_password, block_device_info):
|
rescue_password, block_device_info, share_info):
|
||||||
called['rescued'] = True
|
called['rescued'] = True
|
||||||
|
|
||||||
self.stub_out('nova.virt.fake.FakeDriver.rescue', fake_rescue)
|
self.stub_out('nova.virt.fake.FakeDriver.rescue', fake_rescue)
|
||||||
@@ -2448,7 +2448,7 @@ class ComputeTestCase(BaseTestCase,
|
|||||||
def test_rescue_notifications(self, mock_context, mock_notify):
|
def test_rescue_notifications(self, mock_context, mock_notify):
|
||||||
# Ensure notifications on instance rescue.
|
# Ensure notifications on instance rescue.
|
||||||
def fake_rescue(self, context, instance_ref, network_info, image_meta,
|
def fake_rescue(self, context, instance_ref, network_info, image_meta,
|
||||||
rescue_password, block_device_info):
|
rescue_password, block_device_info, share_info):
|
||||||
pass
|
pass
|
||||||
self.stub_out('nova.virt.fake.FakeDriver.rescue', fake_rescue)
|
self.stub_out('nova.virt.fake.FakeDriver.rescue', fake_rescue)
|
||||||
|
|
||||||
@@ -2545,13 +2545,14 @@ class ComputeTestCase(BaseTestCase,
|
|||||||
|
|
||||||
self.compute.terminate_instance(self.context, instance, [])
|
self.compute.terminate_instance(self.context, instance, [])
|
||||||
|
|
||||||
|
@mock.patch('nova.compute.manager.ComputeManager._get_share_info')
|
||||||
@mock.patch.object(nova.compute.manager.ComputeManager,
|
@mock.patch.object(nova.compute.manager.ComputeManager,
|
||||||
'_get_instance_block_device_info')
|
'_get_instance_block_device_info')
|
||||||
@mock.patch.object(fake.FakeDriver, 'power_off')
|
@mock.patch.object(fake.FakeDriver, 'power_off')
|
||||||
@mock.patch.object(fake.FakeDriver, 'rescue')
|
@mock.patch.object(fake.FakeDriver, 'rescue')
|
||||||
@mock.patch.object(compute_manager.ComputeManager, '_get_rescue_image')
|
@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):
|
mock_get_block_info, mock_get_share_info):
|
||||||
# If the driver fails to rescue, instance state should got to ERROR
|
# If the driver fails to rescue, instance state should got to ERROR
|
||||||
# and the exception should be converted to InstanceNotRescuable
|
# and the exception should be converted to InstanceNotRescuable
|
||||||
inst_obj = self._create_fake_instance_obj()
|
inst_obj = self._create_fake_instance_obj()
|
||||||
@@ -2562,6 +2563,9 @@ class ComputeTestCase(BaseTestCase,
|
|||||||
expected_message = ('Instance %s cannot be rescued: '
|
expected_message = ('Instance %s cannot be rescued: '
|
||||||
'Driver Error: Try again later' % inst_obj.uuid)
|
'Driver Error: Try again later' % inst_obj.uuid)
|
||||||
|
|
||||||
|
share_info = objects.ShareMappingList()
|
||||||
|
mock_get_share_info.return_value = share_info
|
||||||
|
|
||||||
with testtools.ExpectedException(
|
with testtools.ExpectedException(
|
||||||
exception.InstanceNotRescuable, expected_message):
|
exception.InstanceNotRescuable, expected_message):
|
||||||
self.compute.rescue_instance(
|
self.compute.rescue_instance(
|
||||||
@@ -2573,18 +2577,25 @@ class ComputeTestCase(BaseTestCase,
|
|||||||
mock_get.assert_called_once_with(mock.ANY, inst_obj, mock.ANY)
|
mock_get.assert_called_once_with(mock.ANY, inst_obj, mock.ANY)
|
||||||
mock_rescue.assert_called_once_with(mock.ANY, inst_obj, [],
|
mock_rescue.assert_called_once_with(mock.ANY, inst_obj, [],
|
||||||
mock.ANY, 'password',
|
mock.ANY, 'password',
|
||||||
mock.sentinel.block_device_info)
|
mock.sentinel.block_device_info,
|
||||||
|
share_info)
|
||||||
|
|
||||||
|
@mock.patch.object(nova.virt.fake.FakeDriver, "mount_share")
|
||||||
|
@mock.patch('nova.compute.manager.ComputeManager._get_share_info')
|
||||||
@mock.patch.object(nova.compute.manager.ComputeManager,
|
@mock.patch.object(nova.compute.manager.ComputeManager,
|
||||||
'_get_instance_block_device_info')
|
'_get_instance_block_device_info')
|
||||||
@mock.patch.object(image_api.API, "get")
|
@mock.patch.object(image_api.API, "get")
|
||||||
@mock.patch.object(fake.FakeDriver, 'power_off')
|
@mock.patch.object(fake.FakeDriver, 'power_off')
|
||||||
@mock.patch.object(nova.virt.fake.FakeDriver, "rescue")
|
@mock.patch.object(nova.virt.fake.FakeDriver, "rescue")
|
||||||
def test_rescue_with_image_specified(self, mock_rescue, mock_power_off,
|
def test_rescue_with_image_specified(self, mock_rescue, mock_power_off,
|
||||||
mock_image_get, mock_get_block_info):
|
mock_image_get, mock_get_block_info, mock_get_share_info,
|
||||||
|
mock_drv_mount):
|
||||||
image_ref = uuids.image_instance
|
image_ref = uuids.image_instance
|
||||||
rescue_image_meta = {}
|
rescue_image_meta = {}
|
||||||
params = {"task_state": task_states.RESCUING}
|
params = {"task_state": task_states.RESCUING}
|
||||||
|
share_info = objects.ShareMappingList()
|
||||||
|
mock_get_share_info.return_value = share_info
|
||||||
|
|
||||||
instance = self._create_fake_instance_obj(params=params)
|
instance = self._create_fake_instance_obj(params=params)
|
||||||
|
|
||||||
ctxt = context.get_admin_context()
|
ctxt = context.get_admin_context()
|
||||||
@@ -2599,24 +2610,30 @@ class ComputeTestCase(BaseTestCase,
|
|||||||
clean_shutdown=True)
|
clean_shutdown=True)
|
||||||
|
|
||||||
mock_image_get.assert_called_with(ctxt, image_ref)
|
mock_image_get.assert_called_with(ctxt, image_ref)
|
||||||
|
mock_drv_mount.assert_not_called()
|
||||||
mock_rescue.assert_called_with(ctxt, instance, [],
|
mock_rescue.assert_called_with(ctxt, instance, [],
|
||||||
test.MatchType(objects.ImageMeta),
|
test.MatchType(objects.ImageMeta),
|
||||||
'password',
|
'password',
|
||||||
mock.sentinel.block_device_info)
|
mock.sentinel.block_device_info,
|
||||||
|
share_info)
|
||||||
self.compute.terminate_instance(ctxt, instance, [])
|
self.compute.terminate_instance(ctxt, instance, [])
|
||||||
|
|
||||||
|
@mock.patch.object(nova.virt.fake.FakeDriver, "mount_share")
|
||||||
|
@mock.patch('nova.compute.manager.ComputeManager._get_share_info')
|
||||||
@mock.patch.object(nova.compute.manager.ComputeManager,
|
@mock.patch.object(nova.compute.manager.ComputeManager,
|
||||||
'_get_instance_block_device_info')
|
'_get_instance_block_device_info')
|
||||||
@mock.patch.object(image_api.API, "get")
|
@mock.patch.object(image_api.API, "get")
|
||||||
@mock.patch.object(fake.FakeDriver, 'power_off')
|
@mock.patch.object(fake.FakeDriver, 'power_off')
|
||||||
@mock.patch.object(nova.virt.fake.FakeDriver, "rescue")
|
@mock.patch.object(nova.virt.fake.FakeDriver, "rescue")
|
||||||
def test_rescue_with_base_image_when_image_not_specified(self,
|
def test_rescue_with_image_specified_and_share(
|
||||||
mock_rescue, mock_power_off, mock_image_get, mock_get_block_info):
|
self, mock_rescue, mock_power_off, mock_image_get, mock_get_block_info,
|
||||||
image_ref = FAKE_IMAGE_REF
|
mock_get_share_info, mock_drv_mount):
|
||||||
system_meta = {"image_base_image_ref": image_ref}
|
image_ref = uuids.image_instance
|
||||||
rescue_image_meta = {}
|
rescue_image_meta = {}
|
||||||
params = {"task_state": task_states.RESCUING,
|
params = {"task_state": task_states.RESCUING}
|
||||||
"system_metadata": system_meta}
|
share_info = self.fake_share_info()
|
||||||
|
mock_get_share_info.return_value = share_info
|
||||||
|
|
||||||
instance = self._create_fake_instance_obj(params=params)
|
instance = self._create_fake_instance_obj(params=params)
|
||||||
|
|
||||||
ctxt = context.get_admin_context()
|
ctxt = context.get_admin_context()
|
||||||
@@ -2626,6 +2643,99 @@ class ComputeTestCase(BaseTestCase,
|
|||||||
mock_get_block_info.return_value = mock.sentinel.block_device_info
|
mock_get_block_info.return_value = mock.sentinel.block_device_info
|
||||||
mock_image_get.return_value = rescue_image_meta
|
mock_image_get.return_value = rescue_image_meta
|
||||||
|
|
||||||
|
mock_get_share_info.return_value = share_info
|
||||||
|
|
||||||
|
self.compute.rescue_instance(mock_context, instance=instance,
|
||||||
|
rescue_password="password", rescue_image_ref=image_ref,
|
||||||
|
clean_shutdown=True)
|
||||||
|
|
||||||
|
mock_image_get.assert_called_with(ctxt, image_ref)
|
||||||
|
mock_drv_mount.assert_called_with(ctxt, instance, share_info[0])
|
||||||
|
mock_rescue.assert_called_with(
|
||||||
|
ctxt,
|
||||||
|
instance,
|
||||||
|
[],
|
||||||
|
test.MatchType(objects.ImageMeta),
|
||||||
|
"password",
|
||||||
|
mock.sentinel.block_device_info,
|
||||||
|
share_info,
|
||||||
|
)
|
||||||
|
self.compute.terminate_instance(ctxt, instance, [])
|
||||||
|
|
||||||
|
@mock.patch('nova.objects.instance_fault.InstanceFault.create')
|
||||||
|
@mock.patch.object(nova.virt.fake.FakeDriver, "mount_share")
|
||||||
|
@mock.patch('nova.compute.manager.ComputeManager._get_share_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_and_mount_error(
|
||||||
|
self, mock_rescue, mock_power_off, mock_image_get, mock_get_block_info,
|
||||||
|
mock_get_share_info, mock_drv_mount, mock_db_fault):
|
||||||
|
image_ref = uuids.image_instance
|
||||||
|
rescue_image_meta = {}
|
||||||
|
params = {"task_state": task_states.RESCUING}
|
||||||
|
share_info = self.fake_share_info()
|
||||||
|
mock_get_share_info.return_value = share_info
|
||||||
|
|
||||||
|
instance = self._create_fake_instance_obj(params=params)
|
||||||
|
|
||||||
|
ctxt = context.get_admin_context()
|
||||||
|
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
|
||||||
|
|
||||||
|
mock_drv_mount.side_effect = exception.ShareMountError(
|
||||||
|
share_id=share_info[0].share_id,
|
||||||
|
server_id=instance.uuid,
|
||||||
|
reason="fake_reason",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertRaises(
|
||||||
|
exception.InstanceNotRescuable,
|
||||||
|
self.compute.rescue_instance,
|
||||||
|
mock_context,
|
||||||
|
instance=instance,
|
||||||
|
rescue_password="password",
|
||||||
|
rescue_image_ref=image_ref,
|
||||||
|
clean_shutdown=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(instance.vm_state, 'error')
|
||||||
|
self.compute.terminate_instance(ctxt, instance, [])
|
||||||
|
|
||||||
|
@mock.patch('nova.compute.manager.ComputeManager._get_share_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_base_image_when_image_not_specified(self,
|
||||||
|
mock_rescue, mock_power_off, mock_image_get, mock_get_block_info,
|
||||||
|
mock_get_share_info):
|
||||||
|
image_ref = FAKE_IMAGE_REF
|
||||||
|
system_meta = {"image_base_image_ref": image_ref}
|
||||||
|
rescue_image_meta = {}
|
||||||
|
params = {"task_state": task_states.RESCUING,
|
||||||
|
"system_metadata": system_meta}
|
||||||
|
share_info = objects.ShareMappingList()
|
||||||
|
mock_get_share_info.return_value = share_info
|
||||||
|
|
||||||
|
instance = self._create_fake_instance_obj(params=params)
|
||||||
|
|
||||||
|
ctxt = context.get_admin_context()
|
||||||
|
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
|
||||||
|
|
||||||
|
share_info = objects.ShareMappingList()
|
||||||
|
mock_get_share_info.return_value = share_info
|
||||||
|
|
||||||
self.compute.rescue_instance(mock_context, instance=instance,
|
self.compute.rescue_instance(mock_context, instance=instance,
|
||||||
rescue_password="password",
|
rescue_password="password",
|
||||||
rescue_image_ref=None,
|
rescue_image_ref=None,
|
||||||
@@ -2636,7 +2746,8 @@ class ComputeTestCase(BaseTestCase,
|
|||||||
mock_rescue.assert_called_with(ctxt, instance, [],
|
mock_rescue.assert_called_with(ctxt, instance, [],
|
||||||
test.MatchType(objects.ImageMeta),
|
test.MatchType(objects.ImageMeta),
|
||||||
'password',
|
'password',
|
||||||
mock.sentinel.block_device_info)
|
mock.sentinel.block_device_info,
|
||||||
|
share_info)
|
||||||
self.compute.terminate_instance(self.context, instance, [])
|
self.compute.terminate_instance(self.context, instance, [])
|
||||||
|
|
||||||
def test_power_on(self):
|
def test_power_on(self):
|
||||||
|
|||||||
@@ -5706,6 +5706,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
|
|||||||
fake_nw_info = network_model.NetworkInfo()
|
fake_nw_info = network_model.NetworkInfo()
|
||||||
rescue_image_meta = objects.ImageMeta.from_dict(
|
rescue_image_meta = objects.ImageMeta.from_dict(
|
||||||
{'id': uuids.image_id, 'name': uuids.image_name})
|
{'id': uuids.image_id, 'name': uuids.image_name})
|
||||||
|
|
||||||
with test.nested(
|
with test.nested(
|
||||||
mock.patch.object(self.context, 'elevated',
|
mock.patch.object(self.context, 'elevated',
|
||||||
return_value=self.context),
|
return_value=self.context),
|
||||||
@@ -5724,13 +5725,18 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
|
|||||||
mock.patch.object(compute_utils, 'notify_usage_exists'),
|
mock.patch.object(compute_utils, 'notify_usage_exists'),
|
||||||
mock.patch.object(self.compute, '_get_power_state',
|
mock.patch.object(self.compute, '_get_power_state',
|
||||||
return_value=power_state.RUNNING),
|
return_value=power_state.RUNNING),
|
||||||
mock.patch.object(instance, 'save')
|
mock.patch.object(instance, 'save'),
|
||||||
|
mock.patch('nova.compute.manager.ComputeManager._get_share_info')
|
||||||
) as (
|
) as (
|
||||||
elevated_context, get_nw_info, get_rescue_image,
|
elevated_context, get_nw_info, get_rescue_image,
|
||||||
get_bdm_list, get_block_info, notify_instance_usage,
|
get_bdm_list, get_block_info, notify_instance_usage,
|
||||||
power_off_instance, driver_rescue, notify_usage_exists,
|
power_off_instance, driver_rescue, notify_usage_exists,
|
||||||
get_power_state, instance_save
|
get_power_state, instance_save, mock_get_share_info
|
||||||
):
|
):
|
||||||
|
|
||||||
|
share_info = objects.ShareMappingList()
|
||||||
|
mock_get_share_info.return_value = share_info
|
||||||
|
|
||||||
self.compute.rescue_instance(
|
self.compute.rescue_instance(
|
||||||
self.context, instance, rescue_password='verybadpass',
|
self.context, instance, rescue_password='verybadpass',
|
||||||
rescue_image_ref=None, clean_shutdown=clean_shutdown)
|
rescue_image_ref=None, clean_shutdown=clean_shutdown)
|
||||||
@@ -5765,7 +5771,7 @@ class ComputeManagerUnitTestCase(test.NoDBTestCase,
|
|||||||
|
|
||||||
driver_rescue.assert_called_once_with(
|
driver_rescue.assert_called_once_with(
|
||||||
self.context, instance, fake_nw_info, rescue_image_meta,
|
self.context, instance, fake_nw_info, rescue_image_meta,
|
||||||
'verybadpass', mock.sentinel.block_device_info)
|
'verybadpass', mock.sentinel.block_device_info, share_info)
|
||||||
|
|
||||||
notify_usage_exists.assert_called_once_with(self.compute.notifier,
|
notify_usage_exists.assert_called_once_with(self.compute.notifier,
|
||||||
self.context, instance, 'fake-mini', current_period=True)
|
self.context, instance, 'fake-mini', current_period=True)
|
||||||
|
|||||||
@@ -2645,9 +2645,11 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
|
|||||||
|
|
||||||
fake_looping_call = FakeLoopingCall()
|
fake_looping_call = FakeLoopingCall()
|
||||||
mock_looping.return_value = fake_looping_call
|
mock_looping.return_value = fake_looping_call
|
||||||
|
share_info = objects.ShareMappingList()
|
||||||
instance = fake_instance.fake_instance_obj(self.ctx, node=node.id)
|
instance = fake_instance.fake_instance_obj(self.ctx, node=node.id)
|
||||||
|
|
||||||
self.driver.rescue(self.ctx, instance, None, None, 'xyz', None)
|
self.driver.rescue(self.ctx, instance, None, None, 'xyz', None,
|
||||||
|
share_info)
|
||||||
self.mock_conn.set_node_provision_state.assert_called_once_with(
|
self.mock_conn.set_node_provision_state.assert_called_once_with(
|
||||||
node.id, 'rescue', rescue_password='xyz',
|
node.id, 'rescue', rescue_password='xyz',
|
||||||
)
|
)
|
||||||
@@ -2660,12 +2662,13 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
|
|||||||
mock_looping.return_value = fake_looping_call
|
mock_looping.return_value = fake_looping_call
|
||||||
self.mock_conn.set_node_provision_state.side_effect = \
|
self.mock_conn.set_node_provision_state.side_effect = \
|
||||||
sdk_exc.BadRequestException()
|
sdk_exc.BadRequestException()
|
||||||
|
share_info = objects.ShareMappingList()
|
||||||
instance = fake_instance.fake_instance_obj(self.ctx, node=node.id)
|
instance = fake_instance.fake_instance_obj(self.ctx, node=node.id)
|
||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.InstanceRescueFailure,
|
exception.InstanceRescueFailure,
|
||||||
self.driver.rescue,
|
self.driver.rescue,
|
||||||
self.ctx, instance, None, None, 'xyz', None,
|
self.ctx, instance, None, None, 'xyz', None, share_info
|
||||||
)
|
)
|
||||||
self.mock_conn.set_node_provision_state.assert_called_once_with(
|
self.mock_conn.set_node_provision_state.assert_called_once_with(
|
||||||
node.id, 'rescue', rescue_password='xyz',
|
node.id, 'rescue', rescue_password='xyz',
|
||||||
@@ -2680,11 +2683,12 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
|
|||||||
fake_validate.side_effect = exception.InstanceNotFound(
|
fake_validate.side_effect = exception.InstanceNotFound(
|
||||||
instance_id='fake',
|
instance_id='fake',
|
||||||
)
|
)
|
||||||
|
share_info = objects.ShareMappingList()
|
||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.InstanceRescueFailure,
|
exception.InstanceRescueFailure,
|
||||||
self.driver.rescue,
|
self.driver.rescue,
|
||||||
self.ctx, instance, None, None, 'xyz', None,
|
self.ctx, instance, None, None, 'xyz', None, share_info
|
||||||
)
|
)
|
||||||
|
|
||||||
@mock.patch.object(ironic_driver.IronicDriver,
|
@mock.patch.object(ironic_driver.IronicDriver,
|
||||||
@@ -2695,12 +2699,13 @@ class IronicDriverSyncTestCase(IronicDriverTestCase):
|
|||||||
last_error='rescue failed')
|
last_error='rescue failed')
|
||||||
|
|
||||||
fake_validate.return_value = node
|
fake_validate.return_value = node
|
||||||
|
share_info = objects.ShareMappingList()
|
||||||
instance = fake_instance.fake_instance_obj(self.ctx, node=node.id)
|
instance = fake_instance.fake_instance_obj(self.ctx, node=node.id)
|
||||||
|
|
||||||
self.assertRaises(
|
self.assertRaises(
|
||||||
exception.InstanceRescueFailure,
|
exception.InstanceRescueFailure,
|
||||||
self.driver.rescue,
|
self.driver.rescue,
|
||||||
self.ctx, instance, None, None, 'xyz', None,
|
self.ctx, instance, None, None, 'xyz', None, share_info
|
||||||
)
|
)
|
||||||
|
|
||||||
@mock.patch.object(loopingcall, 'FixedIntervalLoopingCall')
|
@mock.patch.object(loopingcall, 'FixedIntervalLoopingCall')
|
||||||
|
|||||||
@@ -26207,7 +26207,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
|
|||||||
self, instance, mock_instance_metadata, mock_supports_direct_io,
|
self, instance, mock_instance_metadata, mock_supports_direct_io,
|
||||||
mock_build_device_metadata, mock_set_host_enabled, mock_get_mdev,
|
mock_build_device_metadata, mock_set_host_enabled, mock_get_mdev,
|
||||||
mock_get_image_meta_by_ref, image_meta_dict=None, exists=None,
|
mock_get_image_meta_by_ref, image_meta_dict=None, exists=None,
|
||||||
instance_image_meta_dict=None, block_device_info=None,
|
instance_image_meta_dict=None, block_device_info=None, share_info=None
|
||||||
):
|
):
|
||||||
|
|
||||||
self.flags(instances_path=self.useFixture(fixtures.TempDir()).path)
|
self.flags(instances_path=self.useFixture(fixtures.TempDir()).path)
|
||||||
@@ -26246,9 +26246,11 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
|
|||||||
mock.patch.object(self.drvr, '_connect_volume'),
|
mock.patch.object(self.drvr, '_connect_volume'),
|
||||||
) as (mock_create_guest, mock_connect_volume):
|
) as (mock_create_guest, mock_connect_volume):
|
||||||
|
|
||||||
|
share_info = objects.ShareMappingList()
|
||||||
|
|
||||||
self.drvr.rescue(self.context, instance,
|
self.drvr.rescue(self.context, instance,
|
||||||
network_info, image_meta, rescue_password,
|
network_info, image_meta, rescue_password,
|
||||||
block_device_info)
|
block_device_info, share_info)
|
||||||
|
|
||||||
self.assertTrue(mock_create_guest.called)
|
self.assertTrue(mock_create_guest.called)
|
||||||
|
|
||||||
@@ -26378,9 +26380,10 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
|
|||||||
# Assert that InstanceNotRescuable is raised for lxc virt_type
|
# Assert that InstanceNotRescuable is raised for lxc virt_type
|
||||||
|
|
||||||
self.flags(virt_type='lxc', group='libvirt')
|
self.flags(virt_type='lxc', group='libvirt')
|
||||||
|
share_info = objects.ShareMappingList()
|
||||||
self.assertRaises(exception.InstanceNotRescuable, self.drvr.rescue,
|
self.assertRaises(exception.InstanceNotRescuable, self.drvr.rescue,
|
||||||
self.context, instance, network_info,
|
self.context, instance, network_info,
|
||||||
rescue_image_meta, None, None)
|
rescue_image_meta, None, None, share_info)
|
||||||
|
|
||||||
def test_rescue_stable_device(self):
|
def test_rescue_stable_device(self):
|
||||||
# Assert the imagebackend behaviour and domain device layout
|
# Assert the imagebackend behaviour and domain device layout
|
||||||
@@ -26452,12 +26455,15 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
|
|||||||
'block_device_mapping': bdms}
|
'block_device_mapping': bdms}
|
||||||
bdm = block_device_info['block_device_mapping'][0]
|
bdm = block_device_info['block_device_mapping'][0]
|
||||||
bdm['connection_info'] = conn_info
|
bdm['connection_info'] = conn_info
|
||||||
|
share_info = objects.ShareMappingList()
|
||||||
|
|
||||||
backend, domain = self._test_rescue(
|
backend, domain = self._test_rescue(
|
||||||
instance,
|
instance,
|
||||||
image_meta_dict=rescue_image_meta_dict,
|
image_meta_dict=rescue_image_meta_dict,
|
||||||
instance_image_meta_dict=inst_image_meta_dict,
|
instance_image_meta_dict=inst_image_meta_dict,
|
||||||
block_device_info=block_device_info)
|
block_device_info=block_device_info,
|
||||||
|
share_info=share_info,
|
||||||
|
)
|
||||||
|
|
||||||
# Assert that we created the expected set of disks, and no others
|
# Assert that we created the expected set of disks, and no others
|
||||||
self.assertEqual(['disk.rescue', 'kernel.rescue', 'ramdisk.rescue'],
|
self.assertEqual(['disk.rescue', 'kernel.rescue', 'ramdisk.rescue'],
|
||||||
@@ -26526,16 +26532,18 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
|
|||||||
) as (
|
) as (
|
||||||
mock_create, mock_destroy, mock_get_guest_xml, mock_create_image,
|
mock_create, mock_destroy, mock_get_guest_xml, mock_create_image,
|
||||||
mock_get_existing_xml, mock_inst_path, mock_get_disk_info,
|
mock_get_existing_xml, mock_inst_path, mock_get_disk_info,
|
||||||
mock_image_get, mock_from_dict, mock_open,
|
mock_image_get, mock_from_dict, mock_open
|
||||||
):
|
):
|
||||||
self.flags(virt_type='kvm', group='libvirt')
|
self.flags(virt_type='kvm', group='libvirt')
|
||||||
mock_image_get.return_value = mock.sentinel.bdm_image_meta_dict
|
mock_image_get.return_value = mock.sentinel.bdm_image_meta_dict
|
||||||
mock_from_dict.return_value = mock.sentinel.bdm_image_meta
|
mock_from_dict.return_value = mock.sentinel.bdm_image_meta
|
||||||
mock_get_disk_info.return_value = disk_info
|
mock_get_disk_info.return_value = disk_info
|
||||||
|
|
||||||
|
share_info = nova.objects.share_mapping.ShareMappingList()
|
||||||
|
|
||||||
drvr.rescue(self.context, instance, network_info,
|
drvr.rescue(self.context, instance, network_info,
|
||||||
rescue_image_meta, mock.sentinel.rescue_password,
|
rescue_image_meta, mock.sentinel.rescue_password,
|
||||||
block_device_info)
|
block_device_info, share_info=share_info)
|
||||||
|
|
||||||
# Assert that we fetch image metadata from Glance using the image
|
# Assert that we fetch image metadata from Glance using the image
|
||||||
# uuid stashed in the BDM and build an image_meta object using the
|
# uuid stashed in the BDM and build an image_meta object using the
|
||||||
@@ -26555,7 +26563,7 @@ class LibvirtDriverTestCase(test.NoDBTestCase, TraitsComparisonMixin):
|
|||||||
mock_get_guest_xml.assert_called_once_with(
|
mock_get_guest_xml.assert_called_once_with(
|
||||||
self.context, instance, network_info, disk_info,
|
self.context, instance, network_info, disk_info,
|
||||||
mock.sentinel.bdm_image_meta, rescue=mock.ANY, mdevs=mock.ANY,
|
mock.sentinel.bdm_image_meta, rescue=mock.ANY, mdevs=mock.ANY,
|
||||||
block_device_info=block_device_info)
|
block_device_info=block_device_info, share_info=share_info)
|
||||||
|
|
||||||
def test_rescue_stable_device_bfv(self):
|
def test_rescue_stable_device_bfv(self):
|
||||||
"""Assert the disk layout when rescuing BFV instances"""
|
"""Assert the disk layout when rescuing BFV instances"""
|
||||||
|
|||||||
@@ -284,8 +284,9 @@ class _VirtDriverTestCase(_FakeDriverBackendTestCase):
|
|||||||
def test_rescue(self):
|
def test_rescue(self):
|
||||||
image_meta = objects.ImageMeta.from_dict({})
|
image_meta = objects.ImageMeta.from_dict({})
|
||||||
instance_ref, network_info = self._get_running_instance()
|
instance_ref, network_info = self._get_running_instance()
|
||||||
|
share_info = objects.ShareMappingList()
|
||||||
self.connection.rescue(self.ctxt, instance_ref, network_info,
|
self.connection.rescue(self.ctxt, instance_ref, network_info,
|
||||||
image_meta, '', None)
|
image_meta, '', None, share_info)
|
||||||
|
|
||||||
@catch_notimplementederror
|
@catch_notimplementederror
|
||||||
def test_unrescue_unrescued_instance(self):
|
def test_unrescue_unrescued_instance(self):
|
||||||
@@ -297,8 +298,9 @@ class _VirtDriverTestCase(_FakeDriverBackendTestCase):
|
|||||||
def test_unrescue_rescued_instance(self, mock_unlink):
|
def test_unrescue_rescued_instance(self, mock_unlink):
|
||||||
image_meta = objects.ImageMeta.from_dict({})
|
image_meta = objects.ImageMeta.from_dict({})
|
||||||
instance_ref, network_info = self._get_running_instance()
|
instance_ref, network_info = self._get_running_instance()
|
||||||
|
share_info = objects.ShareMappingList()
|
||||||
self.connection.rescue(self.ctxt, instance_ref, network_info,
|
self.connection.rescue(self.ctxt, instance_ref, network_info,
|
||||||
image_meta, '', None)
|
image_meta, '', None, share_info)
|
||||||
self.connection.unrescue(self.ctxt, instance_ref)
|
self.connection.unrescue(self.ctxt, instance_ref)
|
||||||
|
|
||||||
@catch_notimplementederror
|
@catch_notimplementederror
|
||||||
|
|||||||
+3
-1
@@ -1016,7 +1016,7 @@ class ComputeDriver(object):
|
|||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def rescue(self, context, instance, network_info, image_meta,
|
def rescue(self, context, instance, network_info, image_meta,
|
||||||
rescue_password, block_device_info):
|
rescue_password, block_device_info, share_info):
|
||||||
"""Rescue the specified instance.
|
"""Rescue the specified instance.
|
||||||
|
|
||||||
:param nova.context.RequestContext context:
|
:param nova.context.RequestContext context:
|
||||||
@@ -1030,6 +1030,8 @@ class ComputeDriver(object):
|
|||||||
:param rescue_password: new root password to set for rescue.
|
:param rescue_password: new root password to set for rescue.
|
||||||
:param dict block_device_info:
|
:param dict block_device_info:
|
||||||
The block device mapping of the instance.
|
The block device mapping of the instance.
|
||||||
|
:param nova.objects.share_mapping.ShareMapingList share_info
|
||||||
|
list of share_mapping
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -245,7 +245,7 @@ class FakeDriver(driver.ComputeDriver):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def rescue(self, context, instance, network_info, image_meta,
|
def rescue(self, context, instance, network_info, image_meta,
|
||||||
rescue_password, block_device_info):
|
rescue_password, block_device_info, share_info):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def unrescue(
|
def unrescue(
|
||||||
|
|||||||
@@ -2150,7 +2150,7 @@ class IronicDriver(virt_driver.ComputeDriver):
|
|||||||
raise exception.IronicAPIVersionNotAvailable(version=version)
|
raise exception.IronicAPIVersionNotAvailable(version=version)
|
||||||
|
|
||||||
def rescue(self, context, instance, network_info, image_meta,
|
def rescue(self, context, instance, network_info, image_meta,
|
||||||
rescue_password, block_device_info):
|
rescue_password, block_device_info, share_info):
|
||||||
"""Rescue the specified instance.
|
"""Rescue the specified instance.
|
||||||
|
|
||||||
:param nova.context.RequestContext context:
|
:param nova.context.RequestContext context:
|
||||||
@@ -2165,6 +2165,8 @@ class IronicDriver(virt_driver.ComputeDriver):
|
|||||||
:param rescue_password: new root password to set for rescue.
|
:param rescue_password: new root password to set for rescue.
|
||||||
:param dict block_device_info:
|
:param dict block_device_info:
|
||||||
The block device mapping of the instance.
|
The block device mapping of the instance.
|
||||||
|
:param nova.objects.share_mapping.ShareMapingList share_info
|
||||||
|
optional list of share_mapping
|
||||||
:raise InstanceRescueFailure if rescue fails.
|
:raise InstanceRescueFailure if rescue fails.
|
||||||
"""
|
"""
|
||||||
LOG.debug('Rescue called for instance', instance=instance)
|
LOG.debug('Rescue called for instance', instance=instance)
|
||||||
|
|||||||
@@ -4465,7 +4465,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def rescue(self, context, instance, network_info, image_meta,
|
def rescue(self, context, instance, network_info, image_meta,
|
||||||
rescue_password, block_device_info):
|
rescue_password, block_device_info, share_info):
|
||||||
"""Loads a VM using rescue images.
|
"""Loads a VM using rescue images.
|
||||||
|
|
||||||
A rescue is normally performed when something goes wrong with the
|
A rescue is normally performed when something goes wrong with the
|
||||||
@@ -4496,9 +4496,13 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
:param rescue_password: new root password to set for rescue.
|
:param rescue_password: new root password to set for rescue.
|
||||||
:param dict block_device_info:
|
:param dict block_device_info:
|
||||||
The block device mapping of the instance.
|
The block device mapping of the instance.
|
||||||
|
:param nova.objects.ShareMappingList share_info:
|
||||||
|
list of share_mapping
|
||||||
"""
|
"""
|
||||||
|
|
||||||
instance_dir = libvirt_utils.get_instance_path(instance)
|
instance_dir = libvirt_utils.get_instance_path(instance)
|
||||||
unrescue_xml = self._get_existing_domain_xml(instance, network_info)
|
unrescue_xml = self._get_existing_domain_xml(
|
||||||
|
instance, network_info, share_info=share_info)
|
||||||
unrescue_xml_path = os.path.join(instance_dir, 'unrescue.xml')
|
unrescue_xml_path = os.path.join(instance_dir, 'unrescue.xml')
|
||||||
with open(unrescue_xml_path, 'w') as f:
|
with open(unrescue_xml_path, 'w') as f:
|
||||||
f.write(unrescue_xml)
|
f.write(unrescue_xml)
|
||||||
@@ -4584,7 +4588,8 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
xml = self._get_guest_xml(context, instance, network_info, disk_info,
|
xml = self._get_guest_xml(context, instance, network_info, disk_info,
|
||||||
image_meta, rescue=rescue_images,
|
image_meta, rescue=rescue_images,
|
||||||
mdevs=mdevs,
|
mdevs=mdevs,
|
||||||
block_device_info=block_device_info)
|
block_device_info=block_device_info,
|
||||||
|
share_info=share_info)
|
||||||
self._destroy(instance)
|
self._destroy(instance)
|
||||||
self._create_guest(
|
self._create_guest(
|
||||||
context, xml, instance, post_xml_callback=gen_confdrive,
|
context, xml, instance, post_xml_callback=gen_confdrive,
|
||||||
|
|||||||
@@ -656,7 +656,7 @@ class VMwareVCDriver(driver.ComputeDriver):
|
|||||||
self._vmops.resume(instance)
|
self._vmops.resume(instance)
|
||||||
|
|
||||||
def rescue(self, context, instance, network_info, image_meta,
|
def rescue(self, context, instance, network_info, image_meta,
|
||||||
rescue_password, block_device_info):
|
rescue_password, block_device_info, share_info):
|
||||||
"""Rescue the specified instance."""
|
"""Rescue the specified instance."""
|
||||||
self._vmops.rescue(context, instance, network_info, image_meta)
|
self._vmops.rescue(context, instance, network_info, image_meta)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user