From d05eb2475b7efc55f220d8f4e09bf409e16fcbb9 Mon Sep 17 00:00:00 2001 From: Zhijiang Hu Date: Wed, 17 Jan 2018 14:45:39 +0800 Subject: [PATCH] Support power reset command Some OpenStack installer such as [1] use power reset when switching from bootstrap kernel to OS installation kernel. So we'd better implement this. [1] https://review.openstack.org/#/admin/projects/openstack/daisycloud-core Change-Id: I60df3a31c7600d35d50212538fbfffd22bf7c729 Signed-off-by: Zhijiang Hu --- README.rst | 4 ++-- virtualbmc/tests/unit/test_vbmc.py | 24 ++++++++++++++++++++++++ virtualbmc/vbmc.py | 14 ++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 26499f7..26efb1f 100644 --- a/README.rst +++ b/README.rst @@ -16,8 +16,8 @@ Supported IPMI commands .. code-block:: bash - # Power the virtual machine on, off, graceful off and NMI - ipmitool -I lanplus -U admin -P password -H 127.0.0.1 power on|off|soft|diag + # Power the virtual machine on, off, graceful off, NMI and reset + ipmitool -I lanplus -U admin -P password -H 127.0.0.1 power on|off|soft|diag|reset # Check the power status ipmitool -I lanplus -U admin -P password -H 127.0.0.1 power status diff --git a/virtualbmc/tests/unit/test_vbmc.py b/virtualbmc/tests/unit/test_vbmc.py index 57bd268..b2e2498 100644 --- a/virtualbmc/tests/unit/test_vbmc.py +++ b/virtualbmc/tests/unit/test_vbmc.py @@ -176,6 +176,30 @@ class VirtualBMCTestCase(base.TestCase): mock_libvirt_domain.return_value.destroy.assert_not_called() self._assert_libvirt_calls(mock_libvirt_domain, mock_libvirt_open) + def test_power_reset_is_on(self, mock_libvirt_domain, mock_libvirt_open): + domain = mock_libvirt_domain.return_value + domain.isActive.return_value = True + self.vbmc.power_reset() + + domain.reset.assert_called_once_with() + self._assert_libvirt_calls(mock_libvirt_domain, mock_libvirt_open) + + def test_power_reset_is_off(self, mock_libvirt_domain, mock_libvirt_open): + domain = mock_libvirt_domain.return_value + domain.isActive.return_value = False + self.vbmc.power_reset() + + # power is already off, assert reset() wasn't invoked + domain.reset.assert_not_called() + self._assert_libvirt_calls(mock_libvirt_domain, mock_libvirt_open) + + def test_power_reset_error(self, mock_libvirt_domain, mock_libvirt_open): + mock_libvirt_domain.side_effect = libvirt.libvirtError('boom') + ret = self.vbmc.power_reset() + self.assertEqual(0xd5, ret) + mock_libvirt_domain.return_value.reset.assert_not_called() + self._assert_libvirt_calls(mock_libvirt_domain, mock_libvirt_open) + def test_power_shutdown_is_on(self, mock_libvirt_domain, mock_libvirt_open): domain = mock_libvirt_domain.return_value diff --git a/virtualbmc/vbmc.py b/virtualbmc/vbmc.py index 59d0fda..383f185 100644 --- a/virtualbmc/vbmc.py +++ b/virtualbmc/vbmc.py @@ -162,3 +162,17 @@ class VirtualBMC(bmc.Bmc): 'error': e}) # Command not supported in present state return 0xd5 + + def power_reset(self): + LOG.debug('Power reset called for domain %s', self.domain_name) + try: + with utils.libvirt_open(**self._conn_args) as conn: + domain = utils.get_libvirt_domain(conn, self.domain_name) + if domain.isActive(): + domain.reset() + except libvirt.libvirtError as e: + LOG.error('Error reseting the domain %(domain)s. ' + 'Error: %(error)s' % {'domain': self.domain_name, + 'error': e}) + # Command not supported in present state + return 0xd5