Merge "Enable hard/soft reboot with accelerators."
This commit is contained in:
commit
2cfb0a467d
@ -3680,6 +3680,15 @@ class ComputeManager(manager.Manager):
|
|||||||
# Manager-detach
|
# Manager-detach
|
||||||
self.detach_volume(context, volume_id, instance)
|
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()
|
@wrap_exception()
|
||||||
@reverts_task_state
|
@reverts_task_state
|
||||||
@wrap_instance_event(prefix='compute')
|
@wrap_instance_event(prefix='compute')
|
||||||
@ -3714,6 +3723,8 @@ class ComputeManager(manager.Manager):
|
|||||||
|
|
||||||
network_info = self.network_api.get_instance_nw_info(context, instance)
|
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")
|
self._notify_about_instance_usage(context, instance, "reboot.start")
|
||||||
compute_utils.notify_about_instance_action(
|
compute_utils.notify_about_instance_action(
|
||||||
context, instance, self.host,
|
context, instance, self.host,
|
||||||
@ -3755,6 +3766,7 @@ class ComputeManager(manager.Manager):
|
|||||||
network_info,
|
network_info,
|
||||||
reboot_type,
|
reboot_type,
|
||||||
block_device_info=block_device_info,
|
block_device_info=block_device_info,
|
||||||
|
accel_info=accel_info,
|
||||||
bad_volumes_callback=bad_volumes_callback)
|
bad_volumes_callback=bad_volumes_callback)
|
||||||
|
|
||||||
except Exception as error:
|
except Exception as error:
|
||||||
|
@ -2975,6 +2975,7 @@ class ComputeTestCase(BaseTestCase,
|
|||||||
launched_at=timeutils.utcnow()))
|
launched_at=timeutils.utcnow()))
|
||||||
instance = objects.Instance._from_db_object(econtext,
|
instance = objects.Instance._from_db_object(econtext,
|
||||||
objects.Instance(), db_instance)
|
objects.Instance(), db_instance)
|
||||||
|
instance.flavor = self.default_flavor
|
||||||
|
|
||||||
updated_dbinstance1 = fake_instance.fake_db_instance(
|
updated_dbinstance1 = fake_instance.fake_db_instance(
|
||||||
**dict(uuid=uuids.db_instance_1,
|
**dict(uuid=uuids.db_instance_1,
|
||||||
@ -3042,7 +3043,8 @@ class ComputeTestCase(BaseTestCase,
|
|||||||
expected_call_info = {
|
expected_call_info = {
|
||||||
'args': (econtext, instance, expected_nw_info,
|
'args': (econtext, instance, expected_nw_info,
|
||||||
reboot_type),
|
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')
|
fault = exception.InstanceNotFound(instance_id='instance-0000')
|
||||||
|
|
||||||
def fake_reboot(self, *args, **kwargs):
|
def fake_reboot(self, *args, **kwargs):
|
||||||
@ -3158,6 +3160,58 @@ class ComputeTestCase(BaseTestCase,
|
|||||||
def test_reboot_hard_and_delete_and_rescued(self):
|
def test_reboot_hard_and_delete_and_rescued(self):
|
||||||
self._test_reboot(False, test_delete=True, test_unrescue=True)
|
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')
|
@mock.patch.object(jsonutils, 'to_primitive')
|
||||||
def test_reboot_fail(self, mock_to_primitive):
|
def test_reboot_fail(self, mock_to_primitive):
|
||||||
self._test_reboot(False, fail_reboot=True)
|
self._test_reboot(False, fail_reboot=True)
|
||||||
|
@ -15595,9 +15595,10 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
|
|
||||||
backend = self.useFixture(fake_imagebackend.ImageBackendFixture())
|
backend = self.useFixture(fake_imagebackend.ImageBackendFixture())
|
||||||
|
|
||||||
|
accel_info = [{'k1': 'v1', 'k2': 'v2'}]
|
||||||
with mock.patch('os.path.exists', return_value=True):
|
with mock.patch('os.path.exists', return_value=True):
|
||||||
drvr._hard_reboot(self.context, instance, network_info,
|
drvr._hard_reboot(self.context, instance, network_info,
|
||||||
block_device_info)
|
block_device_info, accel_info=accel_info)
|
||||||
|
|
||||||
disks = backend.disks
|
disks = backend.disks
|
||||||
|
|
||||||
@ -15622,7 +15623,8 @@ class LibvirtConnTestCase(test.NoDBTestCase,
|
|||||||
|
|
||||||
mock_get_guest_xml.assert_called_once_with(self.context, instance,
|
mock_get_guest_xml.assert_called_once_with(self.context, instance,
|
||||||
network_info, mock.ANY, mock.ANY,
|
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,
|
mock_create_domain_and_network.assert_called_once_with(self.context,
|
||||||
dummyxml, instance, network_info,
|
dummyxml, instance, network_info,
|
||||||
block_device_info=block_device_info, vifs_already_plugged=True)
|
block_device_info=block_device_info, vifs_already_plugged=True)
|
||||||
|
@ -430,7 +430,8 @@ class ComputeDriver(object):
|
|||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def reboot(self, context, instance, network_info, reboot_type,
|
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.
|
"""Reboot the specified instance.
|
||||||
|
|
||||||
After this is called successfully, the instance's state
|
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 block_device_info: Info pertaining to attached volumes
|
||||||
:param bad_volumes_callback: Function to handle any bad volumes
|
:param bad_volumes_callback: Function to handle any bad volumes
|
||||||
encountered
|
encountered
|
||||||
|
:param accel_info: List of accelerator request dicts. The exact
|
||||||
|
data struct is doc'd in nova/virt/driver.py::spawn().
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@ -208,7 +208,8 @@ class FakeDriver(driver.ComputeDriver):
|
|||||||
update_task_state(task_state=task_states.IMAGE_UPLOADING)
|
update_task_state(task_state=task_states.IMAGE_UPLOADING)
|
||||||
|
|
||||||
def reboot(self, context, instance, network_info, reboot_type,
|
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
|
# If the guest is not on the hypervisor and we're doing a hard reboot
|
||||||
# then mimic the libvirt driver by spawning the guest.
|
# then mimic the libvirt driver by spawning the guest.
|
||||||
if (instance.uuid not in self.instances and
|
if (instance.uuid not in self.instances and
|
||||||
|
@ -165,7 +165,8 @@ class HyperVDriver(driver.ComputeDriver):
|
|||||||
admin_password, network_info, block_device_info)
|
admin_password, network_info, block_device_info)
|
||||||
|
|
||||||
def reboot(self, context, instance, network_info, reboot_type,
|
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)
|
self._vmops.reboot(instance, network_info, reboot_type)
|
||||||
|
|
||||||
def destroy(self, context, instance, network_info, block_device_info=None,
|
def destroy(self, context, instance, network_info, block_device_info=None,
|
||||||
|
@ -1371,7 +1371,8 @@ class IronicDriver(virt_driver.ComputeDriver):
|
|||||||
node.uuid, instance=instance)
|
node.uuid, instance=instance)
|
||||||
|
|
||||||
def reboot(self, context, instance, network_info, reboot_type,
|
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.
|
"""Reboot the specified instance.
|
||||||
|
|
||||||
NOTE: Unlike the libvirt driver, this method does not delete
|
NOTE: Unlike the libvirt driver, this method does not delete
|
||||||
@ -1386,7 +1387,8 @@ class IronicDriver(virt_driver.ComputeDriver):
|
|||||||
Ignored by this driver.
|
Ignored by this driver.
|
||||||
:param bad_volumes_callback: Function to handle any bad volumes
|
:param bad_volumes_callback: Function to handle any bad volumes
|
||||||
encountered. Ignored by this driver.
|
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',
|
LOG.debug('Reboot(type %s) called for instance',
|
||||||
reboot_type, instance=instance)
|
reboot_type, instance=instance)
|
||||||
|
@ -3070,7 +3070,8 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
self._volume_refresh_connection_info(context, instance, volume_id)
|
self._volume_refresh_connection_info(context, instance, volume_id)
|
||||||
|
|
||||||
def reboot(self, context, instance, network_info, reboot_type,
|
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."""
|
"""Reboot a virtual machine, given an instance reference."""
|
||||||
if reboot_type == 'SOFT':
|
if reboot_type == 'SOFT':
|
||||||
# NOTE(vish): This will attempt to do a graceful shutdown/restart.
|
# NOTE(vish): This will attempt to do a graceful shutdown/restart.
|
||||||
@ -3091,7 +3092,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
"Trying hard reboot.",
|
"Trying hard reboot.",
|
||||||
instance=instance)
|
instance=instance)
|
||||||
return self._hard_reboot(context, instance, network_info,
|
return self._hard_reboot(context, instance, network_info,
|
||||||
block_device_info)
|
block_device_info, accel_info)
|
||||||
|
|
||||||
def _soft_reboot(self, instance):
|
def _soft_reboot(self, instance):
|
||||||
"""Attempt to shutdown and restart the instance gracefully.
|
"""Attempt to shutdown and restart the instance gracefully.
|
||||||
@ -3143,7 +3144,7 @@ class LibvirtDriver(driver.ComputeDriver):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def _hard_reboot(self, context, instance, network_info,
|
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.
|
"""Reboot a virtual machine, given an instance reference.
|
||||||
|
|
||||||
Performs a Libvirt reset (if supported) on the domain.
|
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,
|
xml = self._get_guest_xml(context, instance, network_info, disk_info,
|
||||||
instance.image_meta,
|
instance.image_meta,
|
||||||
block_device_info=block_device_info,
|
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
|
# NOTE(mdbooth): context.auth_token will not be set when we call
|
||||||
# _hard_reboot from resume_state_on_host_boot()
|
# _hard_reboot from resume_state_on_host_boot()
|
||||||
|
@ -473,7 +473,8 @@ class PowerVMDriver(driver.ComputeDriver):
|
|||||||
vm.power_on(self.adapter, instance)
|
vm.power_on(self.adapter, instance)
|
||||||
|
|
||||||
def reboot(self, context, instance, network_info, reboot_type,
|
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.
|
"""Reboot the specified instance.
|
||||||
|
|
||||||
After this is called successfully, the instance's state
|
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 block_device_info: Info pertaining to attached volumes
|
||||||
:param bad_volumes_callback: Function to handle any bad volumes
|
:param bad_volumes_callback: Function to handle any bad volumes
|
||||||
encountered
|
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)
|
self._log_operation(reboot_type + ' reboot', instance)
|
||||||
vm.reboot(self.adapter, instance, reboot_type == 'HARD')
|
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)
|
self._vmops.snapshot(context, instance, image_id, update_task_state)
|
||||||
|
|
||||||
def reboot(self, context, instance, network_info, reboot_type,
|
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."""
|
"""Reboot VM instance."""
|
||||||
self._vmops.reboot(instance, network_info, reboot_type)
|
self._vmops.reboot(instance, network_info, reboot_type)
|
||||||
|
|
||||||
|
@ -252,7 +252,8 @@ class XenAPIDriver(driver.ComputeDriver):
|
|||||||
self._vmops.post_interrupted_snapshot_cleanup(context, instance)
|
self._vmops.post_interrupted_snapshot_cleanup(context, instance)
|
||||||
|
|
||||||
def reboot(self, context, instance, network_info, reboot_type,
|
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."""
|
"""Reboot VM instance."""
|
||||||
self._vmops.reboot(instance, reboot_type,
|
self._vmops.reboot(instance, reboot_type,
|
||||||
bad_volumes_callback=bad_volumes_callback)
|
bad_volumes_callback=bad_volumes_callback)
|
||||||
|
@ -405,7 +405,8 @@ class ZVMDriver(driver.ComputeDriver):
|
|||||||
self._hypervisor.guest_unpause(instance.name)
|
self._hypervisor.guest_unpause(instance.name)
|
||||||
|
|
||||||
def reboot(self, context, instance, network_info, reboot_type,
|
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':
|
if reboot_type == 'SOFT':
|
||||||
self._hypervisor.guest_reboot(instance.name)
|
self._hypervisor.guest_reboot(instance.name)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user