Report libvirt failures as IPMI-retryable

It seems that at times of high concurrency, libvirt
occassionally fails on supposedly some race condition
what leads to client failure (e.g. Ironic). This change
is to tell Ironic that it should try some more times rather
than bailing out right away.

Change-Id: I5848d721305c887fb7803ca4b302565aa4b83c88
Story: #2001798
Task: #15076
This commit is contained in:
Ilya Etingof 2018-04-27 13:19:55 +02:00
parent b06dc796c9
commit 72f873d9f4
2 changed files with 23 additions and 23 deletions

View File

@ -103,7 +103,7 @@ class VirtualBMCTestCase(base.TestCase):
mock_libvirt_open):
mock_libvirt_domain.side_effect = libvirt.libvirtError('boom')
ret = self.vbmc.set_boot_device('network')
self.assertEqual(0xd5, ret)
self.assertEqual(0xc0, ret)
self._assert_libvirt_calls(mock_libvirt_domain, mock_libvirt_open)
def test_set_boot_device_unkown_device_error(self, mock_libvirt_domain,
@ -135,7 +135,7 @@ class VirtualBMCTestCase(base.TestCase):
mock_libvirt_open):
mock_libvirt_domain.side_effect = libvirt.libvirtError('boom')
ret = self.vbmc.get_power_state()
self.assertEqual(0xd5, ret)
self.assertEqual(0xC0, ret)
self._assert_libvirt_calls(mock_libvirt_domain, mock_libvirt_open,
readonly=True)
@ -159,7 +159,7 @@ class VirtualBMCTestCase(base.TestCase):
def test_pulse_diag_error(self, mock_libvirt_domain, mock_libvirt_open):
mock_libvirt_domain.side_effect = libvirt.libvirtError('boom')
ret = self.vbmc.pulse_diag()
self.assertEqual(0xd5, ret)
self.assertEqual(0xC0, ret)
mock_libvirt_domain.return_value.injectNMI.assert_not_called()
self._assert_libvirt_calls(mock_libvirt_domain, mock_libvirt_open)
@ -183,7 +183,7 @@ class VirtualBMCTestCase(base.TestCase):
def test_power_off_error(self, mock_libvirt_domain, mock_libvirt_open):
mock_libvirt_domain.side_effect = libvirt.libvirtError('boom')
ret = self.vbmc.power_off()
self.assertEqual(0xd5, ret)
self.assertEqual(0xC0, ret)
mock_libvirt_domain.return_value.destroy.assert_not_called()
self._assert_libvirt_calls(mock_libvirt_domain, mock_libvirt_open)
@ -207,7 +207,7 @@ class VirtualBMCTestCase(base.TestCase):
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)
self.assertEqual(0xC0, ret)
mock_libvirt_domain.return_value.reset.assert_not_called()
self._assert_libvirt_calls(mock_libvirt_domain, mock_libvirt_open)
@ -234,7 +234,7 @@ class VirtualBMCTestCase(base.TestCase):
mock_libvirt_open):
mock_libvirt_domain.side_effect = libvirt.libvirtError('boom')
ret = self.vbmc.power_shutdown()
self.assertEqual(0xd5, ret)
self.assertEqual(0xC0, ret)
mock_libvirt_domain.return_value.shutdown.assert_not_called()
self._assert_libvirt_calls(mock_libvirt_domain, mock_libvirt_open)
@ -258,7 +258,7 @@ class VirtualBMCTestCase(base.TestCase):
def test_power_on_error(self, mock_libvirt_domain, mock_libvirt_open):
mock_libvirt_domain.side_effect = libvirt.libvirtError('boom')
ret = self.vbmc.power_on()
self.assertEqual(0xd5, ret)
self.assertEqual(0xC0, ret)
self.assertFalse(mock_libvirt_domain.return_value.create.called)
self._assert_libvirt_calls(mock_libvirt_domain, mock_libvirt_open)

View File

@ -29,8 +29,8 @@ POWERON = 1
# Second Generation v2.0 Document Revision 1.1 October 1, 2013
# https://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmi-second-gen-interface-spec-v2-rev1-1.pdf
#
# Command not supported in present state
IPMI_COMMAND_NOT_SUPPORTED = 0xd5
# Command failed and can be retried
IPMI_COMMAND_NODE_BUSY = 0xC0
# Invalid data field in request
IPMI_INVALID_DATA = 0xcc
@ -138,8 +138,8 @@ class VirtualBMC(bmc.Bmc):
LOG.error('Failed setting the boot device %(bootdev)s for '
'domain %(domain)s', {'bootdev': device,
'domain': self.domain_name})
# Command not supported in present state
return IPMI_COMMAND_NOT_SUPPORTED
# Command failed, but let client to retry
return IPMI_COMMAND_NODE_BUSY
def get_power_state(self):
LOG.debug('Get power state called for domain %s', self.domain_name)
@ -152,8 +152,8 @@ class VirtualBMC(bmc.Bmc):
LOG.error('Error getting the power state of domain %(domain)s. '
'Error: %(error)s', {'domain': self.domain_name,
'error': e})
# Command not supported in present state
return IPMI_COMMAND_NOT_SUPPORTED
# Command failed, but let client to retry
return IPMI_COMMAND_NODE_BUSY
return POWEROFF
@ -168,8 +168,8 @@ class VirtualBMC(bmc.Bmc):
LOG.error('Error powering diag the domain %(domain)s. '
'Error: %(error)s' % {'domain': self.domain_name,
'error': e})
# Command not supported in present state
return IPMI_COMMAND_NOT_SUPPORTED
# Command failed, but let client to retry
return IPMI_COMMAND_NODE_BUSY
def power_off(self):
LOG.debug('Power off called for domain %s', self.domain_name)
@ -182,8 +182,8 @@ class VirtualBMC(bmc.Bmc):
LOG.error('Error powering off the domain %(domain)s. '
'Error: %(error)s' % {'domain': self.domain_name,
'error': e})
# Command not supported in present state
return IPMI_COMMAND_NOT_SUPPORTED
# Command failed, but let client to retry
return IPMI_COMMAND_NODE_BUSY
def power_on(self):
LOG.debug('Power on called for domain %s', self.domain_name)
@ -196,8 +196,8 @@ class VirtualBMC(bmc.Bmc):
LOG.error('Error powering on the domain %(domain)s. '
'Error: %(error)s' % {'domain': self.domain_name,
'error': e})
# Command not supported in present state
return IPMI_COMMAND_NOT_SUPPORTED
# Command failed, but let client to retry
return IPMI_COMMAND_NODE_BUSY
def power_shutdown(self):
LOG.debug('Soft power off called for domain %s', self.domain_name)
@ -210,8 +210,8 @@ class VirtualBMC(bmc.Bmc):
LOG.error('Error soft powering off the domain %(domain)s. '
'Error: %(error)s' % {'domain': self.domain_name,
'error': e})
# Command not supported in present state
return IPMI_COMMAND_NOT_SUPPORTED
# Command failed, but let client to retry
return IPMI_COMMAND_NODE_BUSY
def power_reset(self):
LOG.debug('Power reset called for domain %s', self.domain_name)
@ -224,8 +224,8 @@ class VirtualBMC(bmc.Bmc):
LOG.error('Error reseting the domain %(domain)s. '
'Error: %(error)s' % {'domain': self.domain_name,
'error': e})
# Command not supported in present state
return IPMI_COMMAND_NOT_SUPPORTED
# Command failed, but let client to retry
return IPMI_COMMAND_NODE_BUSY
def is_active(self):
try: