From b1556c2009f5388c6a53341a4601c783f1b0666a Mon Sep 17 00:00:00 2001 From: xiexs Date: Tue, 23 Feb 2016 01:29:36 -0500 Subject: [PATCH] ironic: Add trigger crash dump support to ironic driver This patch adds a new method "trigger_crash_dump" to Ironic virt driver. Ironic supports this feature since Ironic API version 1.29. It also requires python-ironicclient >= 1.11.0. Change-Id: I33812abbff919e5e477334c3bc46309491d14b6a Implements: blueprint inject-nmi-ironic Co-Authored-By: Tang Chen Co-Authored-By: xiexs Depends-On: Iac112b82bab9cdf8a383879f9424cb368df741d6 --- doc/source/support-matrix.ini | 2 +- .../unit/virt/ironic/test_client_wrapper.py | 2 +- nova/tests/unit/virt/ironic/test_driver.py | 23 +++++++++++++++++++ nova/tests/unit/virt/ironic/utils.py | 3 +++ nova/virt/ironic/client_wrapper.py | 2 +- nova/virt/ironic/driver.py | 18 +++++++++++++++ ...bp-inject-nmi-ironic-be5405065b6dd890.yaml | 5 ++++ 7 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 releasenotes/notes/bp-inject-nmi-ironic-be5405065b6dd890.yaml diff --git a/doc/source/support-matrix.ini b/doc/source/support-matrix.ini index 360e6d86935d..08d7d238d2f5 100644 --- a/doc/source/support-matrix.ini +++ b/doc/source/support-matrix.ini @@ -667,7 +667,7 @@ driver-impl-libvirt-lxc=missing driver-impl-libvirt-xen=missing driver-impl-vmware=missing driver-impl-hyperv=missing -driver-impl-ironic=missing +driver-impl-ironic=complete driver-impl-libvirt-vz-vm=missing driver-impl-libvirt-vz-ct=missing diff --git a/nova/tests/unit/virt/ironic/test_client_wrapper.py b/nova/tests/unit/virt/ironic/test_client_wrapper.py index c11e62effcd5..e501de0153b6 100644 --- a/nova/tests/unit/virt/ironic/test_client_wrapper.py +++ b/nova/tests/unit/virt/ironic/test_client_wrapper.py @@ -72,7 +72,7 @@ class IronicClientWrapperTestCase(test.NoDBTestCase): expected = {'session': 'session', 'max_retries': CONF.ironic.api_max_retries, 'retry_interval': CONF.ironic.api_retry_interval, - 'os_ironic_api_version': '1.28', + 'os_ironic_api_version': '1.29', 'ironic_url': None} mock_ir_cli.assert_called_once_with(1, **expected) diff --git a/nova/tests/unit/virt/ironic/test_driver.py b/nova/tests/unit/virt/ironic/test_driver.py index 4712bc3537a5..02ba4dff3b26 100644 --- a/nova/tests/unit/virt/ironic/test_driver.py +++ b/nova/tests/unit/virt/ironic/test_driver.py @@ -1339,6 +1339,29 @@ class IronicDriverTestCase(test.NoDBTestCase): self.driver.reboot(self.ctx, instance, None, None) mock_sp.assert_called_once_with(node.uuid, 'reboot') + @mock.patch.object(ironic_driver.IronicDriver, + '_validate_instance_and_node') + @mock.patch.object(FAKE_CLIENT.node, 'inject_nmi') + def test_trigger_crash_dump(self, mock_nmi, fake_validate): + node = ironic_utils.get_test_node() + fake_validate.return_value = node + instance = fake_instance.fake_instance_obj(self.ctx, + node=node.uuid) + self.driver.trigger_crash_dump(instance) + mock_nmi.assert_called_once_with(node.uuid) + + @mock.patch.object(ironic_driver.IronicDriver, + '_validate_instance_and_node') + @mock.patch.object(FAKE_CLIENT.node, 'inject_nmi') + def test_trigger_crash_dump_error(self, mock_nmi, fake_validate): + node = ironic_utils.get_test_node() + fake_validate.return_value = node + mock_nmi.side_effect = ironic_exception.BadRequest() + instance = fake_instance.fake_instance_obj(self.ctx, + node=node.uuid) + self.assertRaises(ironic_exception.BadRequest, + self.driver.trigger_crash_dump, instance) + @mock.patch.object(loopingcall, 'FixedIntervalLoopingCall') @mock.patch.object(ironic_driver.IronicDriver, '_validate_instance_and_node') diff --git a/nova/tests/unit/virt/ironic/utils.py b/nova/tests/unit/virt/ironic/utils.py index 86f1150e38a8..9469b5202b11 100644 --- a/nova/tests/unit/virt/ironic/utils.py +++ b/nova/tests/unit/virt/ironic/utils.py @@ -142,6 +142,9 @@ class FakeNodeClient(object): def vif_detach(self, node_uuid, port_id): pass + def inject_nmi(self, node_uuid): + pass + class FakeClient(object): diff --git a/nova/virt/ironic/client_wrapper.py b/nova/virt/ironic/client_wrapper.py index ee740cbf0930..f26bd1e52a0d 100644 --- a/nova/virt/ironic/client_wrapper.py +++ b/nova/virt/ironic/client_wrapper.py @@ -32,7 +32,7 @@ ironic = None IRONIC_GROUP = nova.conf.ironic.ironic_group # The API version required by the Ironic driver -IRONIC_API_VERSION = (1, 28) +IRONIC_API_VERSION = (1, 29) class IronicClientWrapper(object): diff --git a/nova/virt/ironic/driver.py b/nova/virt/ironic/driver.py index c89173cfdf3a..46c9d6d7b91f 100644 --- a/nova/virt/ironic/driver.py +++ b/nova/virt/ironic/driver.py @@ -1035,6 +1035,24 @@ class IronicDriver(virt_driver.ComputeDriver): LOG.info(_LI('Successfully powered on Ironic node %s'), node.uuid, instance=instance) + def trigger_crash_dump(self, instance): + """Trigger crash dump mechanism on the given instance. + + Stalling instances can be triggered to dump the crash data. How the + guest OS reacts in details, depends on the configuration of it. + + :param instance: The instance where the crash dump should be triggered. + + :return: None + """ + LOG.debug('Trigger crash dump called for instance', instance=instance) + node = self._validate_instance_and_node(instance) + + self.ironicclient.call("node.inject_nmi", node.uuid) + + LOG.info(_LI('Successfully triggered crash dump into Ironic node %s'), + node.uuid, instance=instance) + def refresh_security_group_rules(self, security_group_id): """Refresh security group rules from data store. diff --git a/releasenotes/notes/bp-inject-nmi-ironic-be5405065b6dd890.yaml b/releasenotes/notes/bp-inject-nmi-ironic-be5405065b6dd890.yaml new file mode 100644 index 000000000000..4a446cb7acf4 --- /dev/null +++ b/releasenotes/notes/bp-inject-nmi-ironic-be5405065b6dd890.yaml @@ -0,0 +1,5 @@ +--- +features: + - Adds trigger crash dump support to ironic virt driver. This feature + requires the Ironic service to support API version 1.29 or later. + It also requires python-ironicclient >= 1.11.0.