Add new method 'apply_configuration' to RAIDInterface

This commit adds new method 'apply_configuration' to RAIDInterface.
This method would be used as deploy step and would accept the
target raid config as argsinfo argument.

Co-Authored-By: Mark Goddard <mark@stackhpc.com>
Change-Id: If50294f5413e67bb333ebba53fb3dab251f5317d
Story: 2003817
Task: 26571
Task: 30004
Task: 36061
This commit is contained in:
Shivanand Tendulker 2019-08-02 01:49:57 -04:00
parent ce163996ce
commit b1986361a8
2 changed files with 146 additions and 6 deletions

View File

@ -38,6 +38,41 @@ LOG = logging.getLogger(__name__)
RAID_CONFIG_SCHEMA = os.path.join(os.path.dirname(__file__),
'raid_config_schema.json')
RAID_APPLY_CONFIGURATION_ARGSINFO = {
"raid_config": {
"description": "The RAID configuration to apply.",
"required": True,
},
"create_root_volume": {
"description": (
"Setting this to 'False' indicates not to create root "
"volume that is specified in 'raid_config'. Default "
"value is 'True'."
),
"required": False,
},
"create_nonroot_volumes": {
"description": (
"Setting this to 'False' indicates not to create "
"non-root volumes (all except the root volume) in "
"'raid_config'. Default value is 'True'."
),
"required": False,
},
"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,
}
}
"""
This may be used as the deploy_step argsinfo argument for RAID interfaces
implementing an apply_configuration deploy step.
"""
class BareDriver(object):
"""A bare driver object which will have interfaces attached later.
@ -1120,10 +1155,47 @@ class RAIDInterface(BaseInterface):
"""
raid.validate_configuration(raid_config, self.raid_schema)
# NOTE(mgoddard): This is not marked as a deploy step, because it requires
# the create_configuration method to support use during deployment, which
# might not be true for all implementations. Subclasses wishing to expose
# an apply_configuration deploy step should implement this method with a
# deploy_step decorator. The RAID_APPLY_CONFIGURATION_ARGSINFO variable may
# be used for the deploy_step argsinfo argument. The create_configuration
# method must also accept a delete_existing argument.
def apply_configuration(self, task, raid_config, create_root_volume=True,
create_nonroot_volumes=True,
delete_existing=True):
"""Applies RAID configuration on the given node.
:param task: A TaskManager instance.
:param raid_config: The RAID configuration to apply.
:param create_root_volume: Setting this to False indicates
not to create root volume that is specified in raid_config.
Default value is True.
:param create_nonroot_volumes: Setting this to False indicates
not to create non-root volumes (all except the root volume) in
raid_config. Default value is True.
: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)
node = task.node
node.target_raid_config = raid_config
node.save()
return self.create_configuration(
task,
create_root_volume=create_root_volume,
create_nonroot_volumes=create_nonroot_volumes,
delete_existing=delete_existing)
@abc.abstractmethod
def create_configuration(self, task,
create_root_volume=True,
create_nonroot_volumes=True):
create_nonroot_volumes=True,
delete_existing=True):
"""Creates RAID configuration on the given node.
This method creates a RAID configuration on the given node.
@ -1143,8 +1215,11 @@ class RAIDInterface(BaseInterface):
:param create_nonroot_volumes: Setting this to False indicates
not to create non-root volumes (all except the root volume) in the
node's target_raid_config. Default value is True.
:returns: states.CLEANWAIT if RAID configuration is in progress
asynchronously or None if it is complete.
:param delete_existing: Setting this to True indicates to delete RAID
configuration prior to creating the new configuration.
:returns: states.CLEANWAIT (cleaning) or states.DEPLOYWAIT (deployment)
if RAID configuration is in progress asynchronously, or None if it
is complete.
"""
@abc.abstractmethod
@ -1156,8 +1231,9 @@ class RAIDInterface(BaseInterface):
cleared by the implementation.
:param task: A TaskManager instance.
:returns: states.CLEANWAIT if deletion is in progress
asynchronously or None if it is complete.
:returns: states.CLEANWAIT (cleaning) or states.DEPLOYWAIT (deployment)
if deletion is in progress asynchronously, or None if it is
complete.
"""
def get_logical_disk_properties(self):

View File

@ -19,6 +19,7 @@ import mock
from ironic.common import exception
from ironic.common import raid
from ironic.common import states
from ironic.drivers import base as driver_base
from ironic.drivers.modules import fake
from ironic.tests import base
@ -574,7 +575,8 @@ class MyRAIDInterface(driver_base.RAIDInterface):
def create_configuration(self, task,
create_root_volume=True,
create_nonroot_volumes=True):
create_nonroot_volumes=True,
delete_existing=True):
pass
def delete_configuration(self, task):
@ -626,6 +628,68 @@ class RAIDInterfaceTestCase(base.TestCase):
raid_interface.get_logical_disk_properties()
get_properties_mock.assert_called_once_with(raid_schema)
@mock.patch.object(MyRAIDInterface, 'create_configuration', autospec=True)
@mock.patch.object(MyRAIDInterface, 'validate_raid_config',
autospec=True)
def test_apply_configuration(self, mock_validate, mock_create):
raid_interface = MyRAIDInterface()
node_mock = mock.MagicMock(target_raid_config=None)
task_mock = mock.MagicMock(node=node_mock)
mock_create.return_value = states.DEPLOYWAIT
raid_config = 'some_raid_config'
result = raid_interface.apply_configuration(task_mock, raid_config)
self.assertEqual(states.DEPLOYWAIT, result)
mock_validate.assert_called_once_with(raid_interface, task_mock,
raid_config)
mock_create.assert_called_once_with(raid_interface, task_mock,
create_root_volume=True,
create_nonroot_volumes=True,
delete_existing=True)
self.assertEqual(raid_config, node_mock.target_raid_config)
@mock.patch.object(MyRAIDInterface, 'create_configuration', autospec=True)
@mock.patch.object(MyRAIDInterface, 'validate_raid_config',
autospec=True)
def test_apply_configuration_delete_existing(self, mock_validate,
mock_create):
raid_interface = MyRAIDInterface()
node_mock = mock.MagicMock(target_raid_config=None)
task_mock = mock.MagicMock(node=node_mock)
mock_create.return_value = states.DEPLOYWAIT
raid_config = 'some_raid_config'
result = raid_interface.apply_configuration(task_mock, raid_config,
delete_existing=True)
self.assertEqual(states.DEPLOYWAIT, result)
mock_validate.assert_called_once_with(raid_interface, task_mock,
raid_config)
mock_create.assert_called_once_with(raid_interface, task_mock,
create_root_volume=True,
create_nonroot_volumes=True,
delete_existing=True)
self.assertEqual(raid_config, node_mock.target_raid_config)
@mock.patch.object(MyRAIDInterface, 'create_configuration', autospec=True)
@mock.patch.object(MyRAIDInterface, 'validate_raid_config',
autospec=True)
def test_apply_configuration_invalid(self, mock_validate, mock_create):
raid_interface = MyRAIDInterface()
node_mock = mock.MagicMock(target_raid_config=None)
task_mock = mock.MagicMock(node=node_mock)
mock_validate.side_effect = exception.InvalidParameterValue('bad')
raid_config = 'some_raid_config'
self.assertRaises(exception.InvalidParameterValue,
raid_interface.apply_configuration, task_mock,
raid_config)
mock_validate.assert_called_once_with(raid_interface, task_mock,
raid_config)
self.assertFalse(mock_create.called)
self.assertIsNone(node_mock.target_raid_config)
class TestDeployInterface(base.TestCase):
@mock.patch.object(driver_base.LOG, 'warning', autospec=True)