Adds raid validation for in-band AgentRAID deploy step

This commit adds support for validation of raid configuration of
in-band AgentRAID deploy step 'apply_configuration' and adds a post
deploy hook to update root device hint.

Change-Id: I52c1ad3e10d9fab3c2366d40af39667a299eb774
This commit is contained in:
Shivanand Tendulker 2020-07-21 12:46:10 -04:00
parent d867488e90
commit a5ce4dd8d0
3 changed files with 97 additions and 13 deletions

View File

@ -59,6 +59,21 @@ OPTIONAL_PROPERTIES = {
'``image_https_proxy`` are not specified. Optional.'), '``image_https_proxy`` are not specified. Optional.'),
} }
_RAID_APPLY_CONFIGURATION_ARGSINFO = {
"raid_config": {
"description": "The RAID configuration to apply.",
"required": True,
},
"delete_existing": {
"description": (
"Setting this to 'True' indicates to delete existing RAID "
"configuration prior to creating the new configuration. "
"Default value is 'True'."
),
"required": False,
}
}
COMMON_PROPERTIES = REQUIRED_PROPERTIES.copy() COMMON_PROPERTIES = REQUIRED_PROPERTIES.copy()
COMMON_PROPERTIES.update(OPTIONAL_PROPERTIES) COMMON_PROPERTIES.update(OPTIONAL_PROPERTIES)
COMMON_PROPERTIES.update(agent_base.VENDOR_PROPERTIES) COMMON_PROPERTIES.update(agent_base.VENDOR_PROPERTIES)
@ -634,6 +649,25 @@ class AgentRAID(base.RAIDInterface):
""" """
return agent_base.get_steps(task, 'deploy', interface='raid') return agent_base.get_steps(task, 'deploy', interface='raid')
@METRICS.timer('AgentRAID.apply_configuration')
@base.deploy_step(priority=0,
argsinfo=_RAID_APPLY_CONFIGURATION_ARGSINFO)
def apply_configuration(self, task, raid_config,
delete_existing=True):
"""Applies RAID configuration on the given node.
:param task: A TaskManager instance.
:param raid_config: The RAID configuration to apply.
:param delete_existing: Setting this to True indicates to delete RAID
configuration prior to creating the new configuration.
:raises: InvalidParameterValue, if the RAID configuration is invalid.
:returns: states.DEPLOYWAIT if RAID configuration is in progress
asynchronously or None if it is complete.
"""
self.validate_raid_config(task, raid_config)
step = task.node.deploy_step
return agent_base.execute_step(task, step, 'deploy')
@METRICS.timer('AgentRAID.create_configuration') @METRICS.timer('AgentRAID.create_configuration')
@base.clean_step(priority=0) @base.clean_step(priority=0)
def create_configuration(self, task, def create_configuration(self, task,
@ -682,6 +716,8 @@ class AgentRAID(base.RAIDInterface):
@staticmethod @staticmethod
@agent_base.post_clean_step_hook( @agent_base.post_clean_step_hook(
interface='raid', step='create_configuration') interface='raid', step='create_configuration')
@agent_base.post_deploy_step_hook(
interface='raid', step='apply_configuration')
def _create_configuration_final(task, command): def _create_configuration_final(task, command):
"""Clean step hook after a RAID configuration was created. """Clean step hook after a RAID configuration was created.
@ -699,15 +735,21 @@ class AgentRAID(base.RAIDInterface):
the 'command' argument passed. the 'command' argument passed.
""" """
try: try:
clean_result = command['command_result']['clean_result'] if task.node.provision_state == states.DEPLOYWAIT:
operation = "deploying"
result = command['command_result']['deploy_result']
else:
operation = "cleaning"
result = command['command_result']['clean_result']
except KeyError: except KeyError:
raise exception.IronicException( raise exception.IronicException(
_("Agent ramdisk didn't return a proper command result while " _("Agent ramdisk didn't return a proper command result while "
"cleaning %(node)s. It returned '%(result)s' after command " "%(operation)s %(node)s. It returned '%(result)s' after "
"execution.") % {'node': task.node.uuid, "command execution.") % {'operation': operation,
'node': task.node.uuid,
'result': command}) 'result': command})
raid.update_raid_info(task.node, clean_result) raid.update_raid_info(task.node, result)
@METRICS.timer('AgentRAID.delete_configuration') @METRICS.timer('AgentRAID.delete_configuration')
@base.clean_step(priority=0) @base.clean_step(priority=0)

View File

@ -1618,8 +1618,8 @@ class AgentRAIDTestCase(db_base.DbTestCase):
self.config(enabled_raid_interfaces=['fake', 'agent', 'no-raid']) self.config(enabled_raid_interfaces=['fake', 'agent', 'no-raid'])
self.target_raid_config = { self.target_raid_config = {
"logical_disks": [ "logical_disks": [
{'size_gb': 200, 'raid_level': 0, 'is_root_volume': True}, {'size_gb': 200, 'raid_level': "0", 'is_root_volume': True},
{'size_gb': 200, 'raid_level': 5} {'size_gb': 200, 'raid_level': "5"}
]} ]}
self.clean_step = {'step': 'create_configuration', self.clean_step = {'step': 'create_configuration',
'interface': 'raid'} 'interface': 'raid'}
@ -1661,6 +1661,25 @@ class AgentRAIDTestCase(db_base.DbTestCase):
self.assertEqual('apply_configuration', ret[0]['step']) self.assertEqual('apply_configuration', ret[0]['step'])
@mock.patch.object(agent_base, 'execute_step', autospec=True)
def test_apply_configuration(self, execute_mock):
deploy_step = {
'interface': 'raid',
'step': 'apply_configuration',
'args': {
'raid_config': self.target_raid_config,
'delete_existing': True
},
'priority': 82
}
with task_manager.acquire(self.context, self.node.uuid) as task:
execute_mock.return_value = states.DEPLOYWAIT
task.node.deploy_step = deploy_step
return_value = task.driver.raid.apply_configuration(
task, self.target_raid_config, delete_existing=True)
self.assertEqual(states.DEPLOYWAIT, return_value)
execute_mock.assert_called_once_with(task, deploy_step, 'deploy')
@mock.patch.object(raid, 'filter_target_raid_config', autospec=True) @mock.patch.object(raid, 'filter_target_raid_config', autospec=True)
@mock.patch.object(agent_base, 'execute_step', autospec=True) @mock.patch.object(agent_base, 'execute_step', autospec=True)
def test_create_configuration(self, execute_mock, def test_create_configuration(self, execute_mock,
@ -1761,16 +1780,33 @@ class AgentRAIDTestCase(db_base.DbTestCase):
update_raid_info_mock.assert_called_once_with(task.node, 'foo') update_raid_info_mock.assert_called_once_with(task.node, 'foo')
@mock.patch.object(raid, 'update_raid_info', autospec=True) @mock.patch.object(raid, 'update_raid_info', autospec=True)
def test__create_configuration_final_registered( def _test__create_configuration_final_registered(
self, update_raid_info_mock): self, update_raid_info_mock, step_type='clean'):
self.node.clean_step = {'interface': 'raid', step = {'interface': 'raid'}
'step': 'create_configuration'} if step_type == 'clean':
step['step'] = 'create_configuration'
self.node.clean_step = step
state = states.CLEANWAIT
command = {'command_result': {'clean_result': 'foo'}} command = {'command_result': {'clean_result': 'foo'}}
create_hook = agent_base._get_post_step_hook(self.node, 'clean') create_hook = agent_base._get_post_step_hook(self.node, 'clean')
else:
step['step'] = 'apply_configuration'
self.node.deploy_step = step
command = {'command_result': {'deploy_result': 'foo'}}
state = states.DEPLOYWAIT
create_hook = agent_base._get_post_step_hook(self.node, 'deploy')
with task_manager.acquire(self.context, self.node.uuid) as task: with task_manager.acquire(self.context, self.node.uuid) as task:
task.node.provision_state = state
create_hook(task, command) create_hook(task, command)
update_raid_info_mock.assert_called_once_with(task.node, 'foo') update_raid_info_mock.assert_called_once_with(task.node, 'foo')
def test__create_configuration_final_registered_clean(self):
self._test__create_configuration_final_registered(step_type='clean')
def test__create_configuration_final_registered_deploy(self):
self._test__create_configuration_final_registered(step_type='deploy')
@mock.patch.object(raid, 'update_raid_info', autospec=True) @mock.patch.object(raid, 'update_raid_info', autospec=True)
def test__create_configuration_final_bad_command_result( def test__create_configuration_final_bad_command_result(
self, update_raid_info_mock): self, update_raid_info_mock):

View File

@ -0,0 +1,6 @@
---
features:
- |
Adds raid configuration validation to deploy step ``apply_configuration``
of ``agent`` RAID interface. Also, a post deploy hook has been added to
this deploy step to update root device hint.