Ironic: Add soft reboot support to ironic driver
This patch gets Ironic virt driver to support soft reboot. Ironic API supports soft reboot since API version 1.27. The API version has already been bumped to 1.28. Change-Id: I4e61ebf852f61e3c0a511b49f0304d3138ef022e Implements: blueprint soft-reboot-poweroff Co-Authored-By: Tang Chen <chen.tang@easystack.cn> Co-Authored-By: xiexs <xiexs@cn.fujitsu.com>
This commit is contained in:
parent
32e2654152
commit
f3c774a96b
@ -1336,9 +1336,42 @@ class IronicDriverTestCase(test.NoDBTestCase):
|
||||
mock_looping.return_value = fake_looping_call
|
||||
instance = fake_instance.fake_instance_obj(self.ctx,
|
||||
node=node.uuid)
|
||||
self.driver.reboot(self.ctx, instance, None, None)
|
||||
self.driver.reboot(self.ctx, instance, None, 'HARD')
|
||||
mock_sp.assert_called_once_with(node.uuid, 'reboot')
|
||||
|
||||
@mock.patch.object(loopingcall, 'FixedIntervalLoopingCall')
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'_validate_instance_and_node')
|
||||
@mock.patch.object(FAKE_CLIENT.node, 'set_power_state')
|
||||
def test_reboot_soft(self, mock_sp, fake_validate, mock_looping):
|
||||
node = ironic_utils.get_test_node()
|
||||
fake_validate.side_effect = [node, node]
|
||||
|
||||
fake_looping_call = FakeLoopingCall()
|
||||
mock_looping.return_value = fake_looping_call
|
||||
instance = fake_instance.fake_instance_obj(self.ctx,
|
||||
node=node.uuid)
|
||||
self.driver.reboot(self.ctx, instance, None, 'SOFT')
|
||||
mock_sp.assert_called_once_with(node.uuid, 'reboot', soft=True)
|
||||
|
||||
@mock.patch.object(loopingcall, 'FixedIntervalLoopingCall')
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'_validate_instance_and_node')
|
||||
@mock.patch.object(FAKE_CLIENT.node, 'set_power_state')
|
||||
def test_reboot_soft_not_supported(self, mock_sp, fake_validate,
|
||||
mock_looping):
|
||||
node = ironic_utils.get_test_node()
|
||||
fake_validate.side_effect = [node, node]
|
||||
mock_sp.side_effect = [ironic_exception.BadRequest(), None]
|
||||
|
||||
fake_looping_call = FakeLoopingCall()
|
||||
mock_looping.return_value = fake_looping_call
|
||||
instance = fake_instance.fake_instance_obj(self.ctx,
|
||||
node=node.uuid)
|
||||
self.driver.reboot(self.ctx, instance, None, 'SOFT')
|
||||
mock_sp.assert_has_calls([mock.call(node.uuid, 'reboot', soft=True),
|
||||
mock.call(node.uuid, 'reboot')])
|
||||
|
||||
@mock.patch.object(loopingcall, 'FixedIntervalLoopingCall')
|
||||
@mock.patch.object(ironic_driver.IronicDriver,
|
||||
'_validate_instance_and_node')
|
||||
|
@ -147,7 +147,7 @@ class FakeNodeClient(object):
|
||||
def list_ports(self, node_uuid, detail=False):
|
||||
pass
|
||||
|
||||
def set_power_state(self, node_uuid, target):
|
||||
def set_power_state(self, node_uuid, target, soft=False):
|
||||
pass
|
||||
|
||||
def set_provision_state(self, node_uuid, target):
|
||||
|
@ -993,8 +993,6 @@ class IronicDriver(virt_driver.ComputeDriver):
|
||||
block_device_info=None, bad_volumes_callback=None):
|
||||
"""Reboot the specified instance.
|
||||
|
||||
NOTE: Ironic does not support soft-off, so this method
|
||||
always performs a hard-reboot.
|
||||
NOTE: Unlike the libvirt driver, this method does not delete
|
||||
and recreate the instance; it preserves local state.
|
||||
|
||||
@ -1002,23 +1000,40 @@ class IronicDriver(virt_driver.ComputeDriver):
|
||||
:param instance: The instance object.
|
||||
:param network_info: Instance network information. Ignored by
|
||||
this driver.
|
||||
:param reboot_type: Either a HARD or SOFT reboot. Ignored by
|
||||
this driver.
|
||||
:param reboot_type: Either a HARD or SOFT reboot.
|
||||
:param block_device_info: Info pertaining to attached volumes.
|
||||
Ignored by this driver.
|
||||
:param bad_volumes_callback: Function to handle any bad volumes
|
||||
encountered. Ignored by this driver.
|
||||
|
||||
"""
|
||||
LOG.debug('Reboot called for instance', instance=instance)
|
||||
LOG.debug('Reboot(type %s) called for instance',
|
||||
reboot_type, instance=instance)
|
||||
node = self._validate_instance_and_node(instance)
|
||||
self.ironicclient.call("node.set_power_state", node.uuid, 'reboot')
|
||||
|
||||
hard = True
|
||||
if reboot_type == 'SOFT':
|
||||
try:
|
||||
self.ironicclient.call("node.set_power_state", node.uuid,
|
||||
'reboot', soft=True)
|
||||
hard = False
|
||||
except ironic.exc.BadRequest as exc:
|
||||
LOG.info(_LI('Soft reboot is not supported by ironic hardware '
|
||||
'driver. Falling back to hard reboot: %s'),
|
||||
exc,
|
||||
instance=instance)
|
||||
|
||||
if hard:
|
||||
self.ironicclient.call("node.set_power_state", node.uuid, 'reboot')
|
||||
|
||||
timer = loopingcall.FixedIntervalLoopingCall(
|
||||
self._wait_for_power_state, instance, 'reboot')
|
||||
timer.start(interval=CONF.ironic.api_retry_interval).wait()
|
||||
LOG.info(_LI('Successfully rebooted Ironic node %s'),
|
||||
node.uuid, instance=instance)
|
||||
LOG.info(_LI('Successfully rebooted(type %(type)s) Ironic node '
|
||||
'%(node)s'),
|
||||
{'type': ('HARD' if hard else 'SOFT'),
|
||||
'node': node.uuid},
|
||||
instance=instance)
|
||||
|
||||
def power_off(self, instance, timeout=0, retry_interval=0):
|
||||
"""Power off the specified instance.
|
||||
|
@ -0,0 +1,6 @@
|
||||
---
|
||||
features:
|
||||
- Adds soft reboot support to Ironic virt driver. If hardware driver in
|
||||
Ironic doesn't support soft reboot, hard reboot is tried. This feature
|
||||
requires the Ironic service to support API version 1.27 or later. It also
|
||||
requires python-ironicclient >= 1.10.0.
|
Loading…
Reference in New Issue
Block a user