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:
parent
ce163996ce
commit
b1986361a8
|
@ -38,6 +38,41 @@ LOG = logging.getLogger(__name__)
|
||||||
RAID_CONFIG_SCHEMA = os.path.join(os.path.dirname(__file__),
|
RAID_CONFIG_SCHEMA = os.path.join(os.path.dirname(__file__),
|
||||||
'raid_config_schema.json')
|
'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):
|
class BareDriver(object):
|
||||||
"""A bare driver object which will have interfaces attached later.
|
"""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)
|
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
|
@abc.abstractmethod
|
||||||
def create_configuration(self, task,
|
def create_configuration(self, task,
|
||||||
create_root_volume=True,
|
create_root_volume=True,
|
||||||
create_nonroot_volumes=True):
|
create_nonroot_volumes=True,
|
||||||
|
delete_existing=True):
|
||||||
"""Creates RAID configuration on the given node.
|
"""Creates RAID configuration on the given node.
|
||||||
|
|
||||||
This method creates a 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
|
:param create_nonroot_volumes: Setting this to False indicates
|
||||||
not to create non-root volumes (all except the root volume) in the
|
not to create non-root volumes (all except the root volume) in the
|
||||||
node's target_raid_config. Default value is True.
|
node's target_raid_config. Default value is True.
|
||||||
:returns: states.CLEANWAIT if RAID configuration is in progress
|
:param delete_existing: Setting this to True indicates to delete RAID
|
||||||
asynchronously or None if it is complete.
|
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
|
@abc.abstractmethod
|
||||||
|
@ -1156,8 +1231,9 @@ class RAIDInterface(BaseInterface):
|
||||||
cleared by the implementation.
|
cleared by the implementation.
|
||||||
|
|
||||||
:param task: A TaskManager instance.
|
:param task: A TaskManager instance.
|
||||||
:returns: states.CLEANWAIT if deletion is in progress
|
:returns: states.CLEANWAIT (cleaning) or states.DEPLOYWAIT (deployment)
|
||||||
asynchronously or None if it is complete.
|
if deletion is in progress asynchronously, or None if it is
|
||||||
|
complete.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_logical_disk_properties(self):
|
def get_logical_disk_properties(self):
|
||||||
|
|
|
@ -19,6 +19,7 @@ import mock
|
||||||
|
|
||||||
from ironic.common import exception
|
from ironic.common import exception
|
||||||
from ironic.common import raid
|
from ironic.common import raid
|
||||||
|
from ironic.common import states
|
||||||
from ironic.drivers import base as driver_base
|
from ironic.drivers import base as driver_base
|
||||||
from ironic.drivers.modules import fake
|
from ironic.drivers.modules import fake
|
||||||
from ironic.tests import base
|
from ironic.tests import base
|
||||||
|
@ -574,7 +575,8 @@ class MyRAIDInterface(driver_base.RAIDInterface):
|
||||||
|
|
||||||
def create_configuration(self, task,
|
def create_configuration(self, task,
|
||||||
create_root_volume=True,
|
create_root_volume=True,
|
||||||
create_nonroot_volumes=True):
|
create_nonroot_volumes=True,
|
||||||
|
delete_existing=True):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def delete_configuration(self, task):
|
def delete_configuration(self, task):
|
||||||
|
@ -626,6 +628,68 @@ class RAIDInterfaceTestCase(base.TestCase):
|
||||||
raid_interface.get_logical_disk_properties()
|
raid_interface.get_logical_disk_properties()
|
||||||
get_properties_mock.assert_called_once_with(raid_schema)
|
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):
|
class TestDeployInterface(base.TestCase):
|
||||||
@mock.patch.object(driver_base.LOG, 'warning', autospec=True)
|
@mock.patch.object(driver_base.LOG, 'warning', autospec=True)
|
||||||
|
|
Loading…
Reference in New Issue