Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions nova/tests/unit/virt/vmwareapi/test_driver_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1596,6 +1596,12 @@ def test_power_off(self, mock_update_cached_instances):
info = self._get_info()
self._check_vm_info(info, power_state.SHUTDOWN)

@mock.patch.object(vmops.VMwareVMOps, 'trigger_crash_dump')
def test_trigger_crash_dump(self, mock_trigger_crash_dump):
self._create_vm()
self.conn.trigger_crash_dump(self.instance)
mock_trigger_crash_dump.assert_called_once_with(self.instance)

def test_power_off_non_existent(self):
self._create_instance()
self.assertRaises(exception.InstanceNotFound, self.conn.power_off,
Expand Down
37 changes: 37 additions & 0 deletions nova/tests/unit/virt/vmwareapi/test_vm_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -1813,6 +1813,43 @@ def test_power_off_instance_power_state_exception(self, fake_get_ref):
fake_wait_for_task.assert_called_once_with('fake-task')
self.assertFalse(fake_get_ref.called)

@mock.patch.object(vm_util, "get_vm_ref")
def test_trigger_crash_dump(self, fake_get_ref):
session = fake.FakeSession()
with test.nested(
mock.patch.object(session, '_call_method'),
) as (fake_call_method,):
vm_util.trigger_crash_dump(session, self._instance, 'fake-vm-ref')
fake_call_method.assert_called_once_with(session.vim,
"SendNMI",
'fake-vm-ref')
self.assertFalse(fake_get_ref.called)

@mock.patch.object(vm_util, "get_vm_ref", return_value="fake-vm-ref")
def test_trigger_crash_dump_no_vm_ref(self, fake_get_ref):
session = fake.FakeSession()
with test.nested(
mock.patch.object(session, '_call_method')
) as (fake_call_method,):
vm_util.trigger_crash_dump(session, self._instance)
fake_get_ref.assert_called_once_with(session, self._instance)
fake_call_method.assert_called_once_with(session.vim,
"SendNMI",
'fake-vm-ref')

@mock.patch.object(vm_util, "get_vm_ref")
def test_trigger_crash_dump_power_state_exception(self, fake_get_ref):
session = fake.FakeSession()
with test.nested(
mock.patch.object(session, '_call_method',
side_effect=vexc.InvalidPowerStateException),
) as (fake_call_method, ):
vm_util.trigger_crash_dump(session, self._instance, 'fake-vm-ref')
fake_call_method.assert_called_once_with(session.vim,
"SendNMI",
'fake-vm-ref')
self.assertFalse(fake_get_ref.called)

def test_get_vm_create_spec_updated_hw_version(self):
extra_specs = vm_util.ExtraSpecs(hw_version='vmx-08')
result = vm_util.get_vm_create_spec(fake.FakeFactory(),
Expand Down
6 changes: 6 additions & 0 deletions nova/tests/unit/virt/vmwareapi/test_vmops.py
Original file line number Diff line number Diff line change
Expand Up @@ -4034,3 +4034,9 @@ def specced_flavor(specs):
extra_specs = self._vmops._get_extra_specs(
specced_flavor({'trait:CUSTOM_NUMASIZE_C48_M729': 'forbidden'}))
self.assertEqual(extra_specs.numa_prefer_ht, '')

@mock.patch.object(vm_util, 'trigger_crash_dump')
def test_trigger_crash_dump(self, mock_trigger_crash_dump):
self._vmops.trigger_crash_dump(self._instance)
mock_trigger_crash_dump.assert_called_once_with(self._session,
self._instance)
3 changes: 3 additions & 0 deletions nova/virt/vmwareapi/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,9 @@ def power_on(self, context, instance, network_info,
"""Power on the specified instance."""
self._vmops.power_on(instance)

def trigger_crash_dump(self, instance):
self._vmops.trigger_crash_dump(instance)

def poll_rebooting_instances(self, timeout, instances):
"""Poll for rebooting instances."""
self._vmops.poll_rebooting_instances(timeout, instances)
Expand Down
13 changes: 13 additions & 0 deletions nova/virt/vmwareapi/vm_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2072,6 +2072,19 @@ def power_on_instance(session, instance, vm_ref=None):
LOG.debug("VM already powered on", instance=instance)


def trigger_crash_dump(session, instance, vm_ref=None):
"""Trigger a crashdump by sending an NMI"""
if vm_ref is None:
vm_ref = get_vm_ref(session, instance)

LOG.debug("Sending NMI to VM", instance=instance)
try:
session._call_method(session.vim, "SendNMI", vm_ref)
LOG.debug("NMI sent to VM", instance=instance)
except vexc.InvalidPowerStateException:
LOG.info("VM is powered off", instance=instance)


def _get_vm_port_indices(session, vm_ref):
extra_config = session._call_method(vutil,
'get_object_property',
Expand Down
3 changes: 3 additions & 0 deletions nova/virt/vmwareapi/vmops.py
Original file line number Diff line number Diff line change
Expand Up @@ -2202,6 +2202,9 @@ def power_on(self, instance):
vm_util.power_on_instance(self._session, instance)
self.update_cached_instances()

def trigger_crash_dump(self, instance):
vm_util.trigger_crash_dump(self._session, instance)

def _update_instance_progress(self, context, instance, step, total_steps):
"""Update instance progress percent to reflect current step number
"""
Expand Down