[ansible] honor deploy_forces_oob_reboot

To use this driver property, tasks that soft poweroff the deploy ramdisk
in-band are tagged with additional 'shutdown' tag and are executed
separately.

Change-Id: Ie7bae9dd9fa17a764599390362e1c7f6926c7746
This commit is contained in:
Pavlo Shchelokovskyy 2017-03-17 15:49:31 +00:00
parent 6e8cd3163f
commit e1ece310fa
4 changed files with 77 additions and 21 deletions

View File

@ -23,6 +23,7 @@ from ironic_lib import utils as irlib_utils
from oslo_concurrency import processutils
from oslo_config import cfg
from oslo_log import log
from oslo_utils import strutils
from oslo_utils import units
import retrying
import six
@ -386,7 +387,10 @@ class AnsibleDeploy(agent_base.HeartbeatMixin, base.DeployInterface):
def get_properties(self):
"""Return the properties of the interface."""
return COMMON_PROPERTIES
props = COMMON_PROPERTIES.copy()
# NOTE(pas-ha) this is to get the deploy_forces_oob_reboot property
props.update(agent_base.VENDOR_PROPERTIES)
return props
def validate(self, task):
"""Validate the driver-specific Node deployment info."""
@ -409,7 +413,9 @@ class AnsibleDeploy(agent_base.HeartbeatMixin, base.DeployInterface):
def _ansible_deploy(self, task, node_address):
"""Internal function for deployment to a node."""
notags = ['wait'] if CONF.ansible.use_ramdisk_callback else []
notags = ['shutdown']
if CONF.ansible.use_ramdisk_callback:
notags.append('wait')
node = task.node
LOG.debug('IP of node %(node)s is %(ip)s',
{'node': node.uuid, 'ip': node_address})
@ -622,21 +628,33 @@ class AnsibleDeploy(agent_base.HeartbeatMixin, base.DeployInterface):
return task.driver.power.get_power_state(task)
node = task.node
oob_power_off = strutils.bool_from_string(
node.driver_info.get('deploy_forces_oob_reboot', False))
try:
try:
_wait_until_powered_off(task)
except Exception as e:
LOG.warning(_LW('Failed to soft power off node %(node_uuid)s '
'in at least %(timeout)d seconds. '
'Error: %(error)s'),
{'node_uuid': task.node.uuid,
'timeout': (wait * (attempts - 1)) / 1000,
'error': e})
# NOTE(pas-ha) flush is a part of deploy playbook
# so if it finished successfully we can safely
# power off the node out-of-band
if not oob_power_off:
try:
node_address = _get_node_ip(task)
playbook, user, key = _parse_ansible_driver_info(
node)
node_list = [(node.uuid, node_address, user, node.extra)]
extra_vars = _prepare_extra_vars(node_list)
_run_playbook(playbook, extra_vars, key,
tags=['shutdown'])
_wait_until_powered_off(task)
except Exception as e:
LOG.warning(
_LW('Failed to soft power off node %(node_uuid)s '
'in at least %(timeout)d seconds. '
'Error: %(error)s'),
{'node_uuid': node.uuid,
'timeout': (wait * (attempts - 1)) / 1000,
'error': e})
# NOTE(pas-ha) flush is a part of deploy playbook
# so if it finished successfully we can safely
# power off the node out-of-band
manager_utils.node_power_action(task, states.POWER_OFF)
else:
manager_utils.node_power_action(task, states.POWER_OFF)
task.driver.network.remove_provisioning_network(task)
task.driver.network.configure_tenant_networks(task)
manager_utils.node_power_action(task, states.POWER_ON)

View File

@ -9,5 +9,6 @@
- hosts: ironic
roles:
- deploy
- shutdown
- role: deploy
- role: shutdown
tags: shutdown

View File

@ -444,7 +444,8 @@ class TestAnsibleDeploy(db_base.DbTestCase):
def test_get_properties(self):
self.assertEqual(
set(ansible_deploy.COMMON_PROPERTIES),
set(list(ansible_deploy.COMMON_PROPERTIES) +
['deploy_forces_oob_reboot']),
set(self.driver.get_properties()))
@mock.patch.object(deploy_utils, 'check_for_missing_params',
@ -792,7 +793,7 @@ class TestAnsibleDeploy(db_base.DbTestCase):
(self.node['uuid'],
DRIVER_INTERNAL_INFO['ansible_cleaning_ip'],
'test_u')]}, 'test_k',
notags=['wait'])
notags=['shutdown', 'wait'])
@mock.patch.object(ansible_deploy, '_run_playbook', autospec=True)
@mock.patch.object(ansible_deploy, '_prepare_extra_vars', autospec=True)
@ -834,14 +835,43 @@ class TestAnsibleDeploy(db_base.DbTestCase):
(self.node['uuid'],
DRIVER_INTERNAL_INFO['ansible_cleaning_ip'],
'test_u')]}, 'test_k',
notags=['wait', 'parted'])
notags=['shutdown', 'wait', 'parted'])
@mock.patch.object(fake.FakePower, 'get_power_state',
return_value=states.POWER_OFF)
@mock.patch.object(utils, 'node_power_action', autospec=True)
def test_reboot_and_finish_deploy_force_reboot(self, power_action_mock,
get_pow_state_mock):
d_info = self.node.driver_info
d_info['deploy_forces_oob_reboot'] = True
self.node.driver_info = d_info
self.node.save()
self.config(group='ansible',
post_deploy_get_power_state_retry_interval=0)
self.node.provision_state = states.DEPLOYING
self.node.save()
with task_manager.acquire(self.context, self.node.uuid) as task:
with mock.patch.object(task.driver, 'network') as net_mock:
self.driver.reboot_and_finish_deploy(task)
net_mock.remove_provisioning_network.assert_called_once_with(
task)
net_mock.configure_tenant_networks.assert_called_once_with(
task)
expected_power_calls = [((task, states.POWER_OFF),),
((task, states.POWER_ON),)]
self.assertEqual(expected_power_calls,
power_action_mock.call_args_list)
get_pow_state_mock.assert_not_called()
@mock.patch.object(ansible_deploy, '_run_playbook', autospec=True)
@mock.patch.object(utils, 'node_power_action', autospec=True)
@mock.patch.object(fake.FakePower, 'get_power_state',
return_value=states.POWER_ON)
def test_reboot_and_finish_deploy_soft_poweroff_retry(self,
get_pow_state_mock,
power_action_mock):
power_action_mock,
ansible_mock):
self.config(group='ansible',
post_deploy_get_power_state_retry_interval=0)
self.config(group='ansible',
@ -868,6 +898,8 @@ class TestAnsibleDeploy(db_base.DbTestCase):
((task, states.POWER_ON),)]
self.assertEqual(expected_power_calls,
power_action_mock.call_args_list)
ansible_mock.assert_called_once_with(mock.ANY, mock.ANY, mock.ANY,
tags=['shutdown'])
@mock.patch.object(ansible_deploy, '_get_node_ip_heartbeat', autospec=True,
return_value='1.2.3.4')

View File

@ -0,0 +1,5 @@
---
features:
- |
ansible-deploy driver now honors ``deploy-forces-oob-reboot`` driver
property