Support resuming an instance with shares (compute manager part)

Allow to resume an instance with shares attached.

Manila is the OpenStack Shared Filesystems service.
These series of patches implement changes required in Nova to allow the shares
provided by Manila to be associated with and attached to instances using
virtiofs.

Implements: blueprint libvirt-virtiofs-attach-manila-shares
Change-Id: I41639e51b624be0d09f8dad25e66cb8bd0185311
This commit is contained in:
René Ribaud
2022-10-03 17:56:06 +02:00
parent dcb9f4a94d
commit 8ab51e4422
2 changed files with 65 additions and 2 deletions
+8 -1
View File
@@ -7203,6 +7203,13 @@ class ComputeManager(manager.Manager):
block_device_info = self._get_instance_block_device_info(
context, instance, bdms=bdms)
# This allows passing share_info to the resume operation for
# futur usage. However, this scenario is currently not possible
# because suspending an instance with a share is not permitted
# by libvirt. As a result, the suspend action involving a share
# is blocked by the API.
share_info = self._get_share_info(context, instance)
compute_utils.notify_about_instance_action(context, instance,
self.host, action=fields.NotificationAction.RESUME,
phase=fields.NotificationPhase.START, bdms=bdms)
@@ -7212,7 +7219,7 @@ class ComputeManager(manager.Manager):
with self._error_out_instance_on_exception(context, instance,
instance_state=instance.vm_state):
self.driver.resume(context, instance, network_info,
block_device_info)
block_device_info, share_info)
instance.power_state = self._get_power_state(instance)
+57 -1
View File
@@ -2877,12 +2877,17 @@ class ComputeTestCase(BaseTestCase,
action='unpause', phase='end')])
self.compute.terminate_instance(self.context, instance, [])
@mock.patch('nova.virt.fake.FakeDriver.resume')
@mock.patch('nova.compute.manager.ComputeManager._get_share_info')
@mock.patch('nova.compute.utils.notify_about_instance_action')
@mock.patch('nova.context.RequestContext.elevated')
def test_suspend(self, mock_context, mock_notify):
def test_suspend(self, mock_context, mock_notify, mock_get_share_info,
mock_resume):
# ensure instance can be suspended and resumed.
context = self.context
mock_context.return_value = context
share_info = objects.ShareMappingList()
mock_get_share_info.return_value = share_info
instance = self._create_fake_instance_obj()
self.compute.build_and_run_instance(context, instance, {}, {}, {},
[], block_device_mapping=[])
@@ -2906,6 +2911,57 @@ class ComputeTestCase(BaseTestCase,
action='suspend', phase='start'),
mock.call(context, instance, 'fake-mini',
action='suspend', phase='end')])
mock_get_share_info.assert_called_once_with(context, instance)
mock_resume.assert_called_once_with(
self.context, instance, mock.ANY, mock.ANY, share_info)
self.compute.terminate_instance(self.context, instance, [])
@mock.patch('nova.compute.manager.ComputeManager.deny_share')
@mock.patch('nova.virt.fake.FakeDriver.resume')
@mock.patch('nova.compute.manager.ComputeManager._get_share_info')
@mock.patch('nova.compute.utils.notify_about_instance_action')
@mock.patch('nova.context.RequestContext.elevated')
def test_suspend_with_share(self, mock_context, mock_notify,
mock_get_share_info, mock_resume, mock_deny_share):
# ensure instance can be suspended and resumed.
context = self.context
mock_context.return_value = context
share_info = self.fake_share_info()
mock_get_share_info.return_value = share_info
instance = self._create_fake_instance_obj()
self.compute.build_and_run_instance(context, instance, {}, {}, {},
[], block_device_mapping=[])
instance.task_state = task_states.SUSPENDING
instance.save()
self.compute.suspend_instance(context, instance)
instance.task_state = task_states.RESUMING
instance.save()
self.compute.resume_instance(context, instance)
self.assertEqual(len(self.notifier.notifications), 6)
msg = self.notifier.notifications[2]
self.assertEqual(msg.event_type,
'compute.instance.suspend.start')
msg = self.notifier.notifications[3]
self.assertEqual(msg.event_type,
'compute.instance.suspend.end')
mock_notify.assert_has_calls([
mock.call(context, instance, 'fake-mini',
action='suspend', phase='start'),
mock.call(context, instance, 'fake-mini',
action='suspend', phase='end')])
mock_get_share_info.assert_called_once_with(context, instance)
mock_resume.assert_called_once_with(
self.context, instance, mock.ANY, mock.ANY, share_info)
# Because we have shares, terminate the instance requires
# to deny the share, so mocking is required
self.compute.terminate_instance(self.context, instance, [])
def test_suspend_error(self):