Merge "Enable hard/soft reboot with accelerators."
This commit is contained in:
commit
2cfb0a467d
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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')
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user