Merge "Enable hard/soft reboot with accelerators."

This commit is contained in:
Zuul 2020-03-27 15:32:05 +00:00 committed by Gerrit Code Review
commit 2cfb0a467d
12 changed files with 98 additions and 16 deletions

View File

@ -3680,6 +3680,15 @@ class ComputeManager(manager.Manager):
# Manager-detach
self.detach_volume(context, volume_id, instance)
def _get_accel_info(self, context, instance):
dp_name = instance.flavor.extra_specs.get('accel:device_profile')
if dp_name:
cyclient = cyborg.get_client(context)
accel_info = cyclient.get_arqs_for_instance(instance.uuid)
else:
accel_info = []
return accel_info
@wrap_exception()
@reverts_task_state
@wrap_instance_event(prefix='compute')
@ -3714,6 +3723,8 @@ class ComputeManager(manager.Manager):
network_info = self.network_api.get_instance_nw_info(context, instance)
accel_info = self._get_accel_info(context, instance)
self._notify_about_instance_usage(context, instance, "reboot.start")
compute_utils.notify_about_instance_action(
context, instance, self.host,
@ -3755,6 +3766,7 @@ class ComputeManager(manager.Manager):
network_info,
reboot_type,
block_device_info=block_device_info,
accel_info=accel_info,
bad_volumes_callback=bad_volumes_callback)
except Exception as error:

View File

@ -2975,6 +2975,7 @@ class ComputeTestCase(BaseTestCase,
launched_at=timeutils.utcnow()))
instance = objects.Instance._from_db_object(econtext,
objects.Instance(), db_instance)
instance.flavor = self.default_flavor
updated_dbinstance1 = fake_instance.fake_db_instance(
**dict(uuid=uuids.db_instance_1,
@ -3042,7 +3043,8 @@ class ComputeTestCase(BaseTestCase,
expected_call_info = {
'args': (econtext, instance, expected_nw_info,
reboot_type),
'kwargs': {'block_device_info': fake_block_dev_info}}
'kwargs': {'block_device_info': fake_block_dev_info,
'accel_info': []}}
fault = exception.InstanceNotFound(instance_id='instance-0000')
def fake_reboot(self, *args, **kwargs):
@ -3158,6 +3160,58 @@ class ComputeTestCase(BaseTestCase,
def test_reboot_hard_and_delete_and_rescued(self):
self._test_reboot(False, test_delete=True, test_unrescue=True)
@mock.patch('nova.virt.fake.FakeDriver.reboot')
@mock.patch('nova.objects.instance.Instance.save')
@mock.patch.object(objects.BlockDeviceMappingList, 'get_by_instance_uuid')
@mock.patch.object(compute_manager.ComputeManager,
'_get_instance_block_device_info')
@mock.patch.object(compute_manager.ComputeManager,
'_notify_about_instance_usage')
@mock.patch.object(compute_manager.ComputeManager, '_instance_update')
@mock.patch.object(db, 'instance_update_and_get_original')
@mock.patch.object(compute_manager.ComputeManager, '_get_power_state')
@mock.patch('nova.compute.utils.notify_about_instance_action')
def _test_reboot_with_accels(self, mock_notify_action, mock_get_power,
mock_get_orig, mock_update, mock_notify_usage,
mock_get_blk, mock_get_bdms, mock_inst_save, mock_reboot,
extra_specs=None, accel_info=None):
self.compute.network_api.get_instance_nw_info = mock.Mock()
reboot_type = 'SOFT'
instance = self._create_fake_instance_obj()
if extra_specs:
instance.flavor.extra_specs = extra_specs
self.compute.reboot_instance(self.context, instance=instance,
block_device_info=None, reboot_type=reboot_type)
mock_reboot.assert_called_once_with(
mock.ANY, instance, mock.ANY, reboot_type,
block_device_info=mock.ANY,
bad_volumes_callback=mock.ANY,
accel_info=accel_info or []
)
return instance['uuid']
@mock.patch('nova.accelerator.cyborg._CyborgClient.get_arqs_for_instance')
def test_reboot_with_accels_ok(self, mock_get_arqs):
dp_name = 'mydp'
extra_specs = {'accel:device_profile': dp_name}
_, accel_info = fixtures.get_arqs(dp_name)
mock_get_arqs.return_value = accel_info
instance_uuid = self._test_reboot_with_accels(
extra_specs=extra_specs, accel_info=accel_info)
mock_get_arqs.assert_called_once_with(instance_uuid)
@mock.patch('nova.accelerator.cyborg._CyborgClient.get_arqs_for_instance')
def test_reboot_with_accels_no_dp(self, mock_get_arqs):
self._test_reboot_with_accels(extra_specs=None, accel_info=None)
mock_get_arqs.assert_not_called()
@mock.patch.object(jsonutils, 'to_primitive')
def test_reboot_fail(self, mock_to_primitive):
self._test_reboot(False, fail_reboot=True)

View File

@ -15595,9 +15595,10 @@ class LibvirtConnTestCase(test.NoDBTestCase,
backend = self.useFixture(fake_imagebackend.ImageBackendFixture())
accel_info = [{'k1': 'v1', 'k2': 'v2'}]
with mock.patch('os.path.exists', return_value=True):
drvr._hard_reboot(self.context, instance, network_info,
block_device_info)
block_device_info, accel_info=accel_info)
disks = backend.disks
@ -15622,7 +15623,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
mock_get_guest_xml.assert_called_once_with(self.context, instance,
network_info, mock.ANY, mock.ANY,
block_device_info=block_device_info, mdevs=[uuids.mdev1])
block_device_info=block_device_info, mdevs=[uuids.mdev1],
accel_info=accel_info)
mock_create_domain_and_network.assert_called_once_with(self.context,
dummyxml, instance, network_info,
block_device_info=block_device_info, vifs_already_plugged=True)

View File

@ -430,7 +430,8 @@ class ComputeDriver(object):
raise NotImplementedError()
def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None, bad_volumes_callback=None):
block_device_info=None, bad_volumes_callback=None,
accel_info=None):
"""Reboot the specified instance.
After this is called successfully, the instance's state
@ -445,6 +446,8 @@ class ComputeDriver(object):
:param block_device_info: Info pertaining to attached volumes
:param bad_volumes_callback: Function to handle any bad volumes
encountered
:param accel_info: List of accelerator request dicts. The exact
data struct is doc'd in nova/virt/driver.py::spawn().
"""
raise NotImplementedError()

View File

@ -208,7 +208,8 @@ class FakeDriver(driver.ComputeDriver):
update_task_state(task_state=task_states.IMAGE_UPLOADING)
def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None, bad_volumes_callback=None):
block_device_info=None, bad_volumes_callback=None,
accel_info=None):
# If the guest is not on the hypervisor and we're doing a hard reboot
# then mimic the libvirt driver by spawning the guest.
if (instance.uuid not in self.instances and

View File

@ -165,7 +165,8 @@ class HyperVDriver(driver.ComputeDriver):
admin_password, network_info, block_device_info)
def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None, bad_volumes_callback=None):
block_device_info=None, bad_volumes_callback=None,
accel_info=None):
self._vmops.reboot(instance, network_info, reboot_type)
def destroy(self, context, instance, network_info, block_device_info=None,

View File

@ -1371,7 +1371,8 @@ class IronicDriver(virt_driver.ComputeDriver):
node.uuid, instance=instance)
def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None, bad_volumes_callback=None):
block_device_info=None, bad_volumes_callback=None,
accel_info=None):
"""Reboot the specified instance.
NOTE: Unlike the libvirt driver, this method does not delete
@ -1386,7 +1387,8 @@ class IronicDriver(virt_driver.ComputeDriver):
Ignored by this driver.
:param bad_volumes_callback: Function to handle any bad volumes
encountered. Ignored by this driver.
:param accel_info: List of accelerator request dicts. The exact
data struct is doc'd in nova/virt/driver.py::spawn().
"""
LOG.debug('Reboot(type %s) called for instance',
reboot_type, instance=instance)

View File

@ -3070,7 +3070,8 @@ class LibvirtDriver(driver.ComputeDriver):
self._volume_refresh_connection_info(context, instance, volume_id)
def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None, bad_volumes_callback=None):
block_device_info=None, bad_volumes_callback=None,
accel_info=None):
"""Reboot a virtual machine, given an instance reference."""
if reboot_type == 'SOFT':
# NOTE(vish): This will attempt to do a graceful shutdown/restart.
@ -3091,7 +3092,7 @@ class LibvirtDriver(driver.ComputeDriver):
"Trying hard reboot.",
instance=instance)
return self._hard_reboot(context, instance, network_info,
block_device_info)
block_device_info, accel_info)
def _soft_reboot(self, instance):
"""Attempt to shutdown and restart the instance gracefully.
@ -3143,7 +3144,7 @@ class LibvirtDriver(driver.ComputeDriver):
return False
def _hard_reboot(self, context, instance, network_info,
block_device_info=None):
block_device_info=None, accel_info=None):
"""Reboot a virtual machine, given an instance reference.
Performs a Libvirt reset (if supported) on the domain.
@ -3185,7 +3186,7 @@ class LibvirtDriver(driver.ComputeDriver):
xml = self._get_guest_xml(context, instance, network_info, disk_info,
instance.image_meta,
block_device_info=block_device_info,
mdevs=mdevs)
mdevs=mdevs, accel_info=accel_info)
# NOTE(mdbooth): context.auth_token will not be set when we call
# _hard_reboot from resume_state_on_host_boot()

View File

@ -473,7 +473,8 @@ class PowerVMDriver(driver.ComputeDriver):
vm.power_on(self.adapter, instance)
def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None, bad_volumes_callback=None):
block_device_info=None, bad_volumes_callback=None,
accel_info=None):
"""Reboot the specified instance.
After this is called successfully, the instance's state
@ -489,6 +490,8 @@ class PowerVMDriver(driver.ComputeDriver):
:param block_device_info: Info pertaining to attached volumes
:param bad_volumes_callback: Function to handle any bad volumes
encountered
:param accel_info: List of accelerator request dicts. The exact
data struct is doc'd in nova/virt/driver.py::spawn().
"""
self._log_operation(reboot_type + ' reboot', instance)
vm.reboot(self.adapter, instance, reboot_type == 'HARD')

View File

@ -570,7 +570,8 @@ class VMwareVCDriver(driver.ComputeDriver):
self._vmops.snapshot(context, instance, image_id, update_task_state)
def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None, bad_volumes_callback=None):
block_device_info=None, bad_volumes_callback=None,
accel_info=None):
"""Reboot VM instance."""
self._vmops.reboot(instance, network_info, reboot_type)

View File

@ -252,7 +252,8 @@ class XenAPIDriver(driver.ComputeDriver):
self._vmops.post_interrupted_snapshot_cleanup(context, instance)
def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None, bad_volumes_callback=None):
block_device_info=None, bad_volumes_callback=None,
accel_info=None):
"""Reboot VM instance."""
self._vmops.reboot(instance, reboot_type,
bad_volumes_callback=bad_volumes_callback)

View File

@ -405,7 +405,8 @@ class ZVMDriver(driver.ComputeDriver):
self._hypervisor.guest_unpause(instance.name)
def reboot(self, context, instance, network_info, reboot_type,
block_device_info=None, bad_volumes_callback=None):
block_device_info=None, bad_volumes_callback=None,
accel_info=None):
if reboot_type == 'SOFT':
self._hypervisor.guest_reboot(instance.name)