Merge "Add iDRAC RAID deploy steps"
This commit is contained in:
commit
9de0a66aab
@ -27,20 +27,26 @@ drac_exceptions = importutils.try_import('dracclient.exceptions')
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def validate_job_queue(node):
|
||||
def validate_job_queue(node, name_prefix=None):
|
||||
"""Validates the job queue on the node.
|
||||
|
||||
It raises an exception if an unfinished configuration job exists.
|
||||
|
||||
:param node: an ironic node object.
|
||||
:param name_prefix: A name prefix for jobs to validate.
|
||||
:raises: DracOperationError on an error from python-dracclient.
|
||||
"""
|
||||
|
||||
unfinished_jobs = list_unfinished_jobs(node)
|
||||
if unfinished_jobs:
|
||||
msg = _('Unfinished config jobs found: %(jobs)r. Make sure they are '
|
||||
'completed before retrying.') % {'jobs': unfinished_jobs}
|
||||
raise exception.DracOperationError(error=msg)
|
||||
if name_prefix is not None:
|
||||
# Filter out jobs that don't match the name prefix.
|
||||
unfinished_jobs = [job for job in unfinished_jobs
|
||||
if job.name.startswith(name_prefix)]
|
||||
if not unfinished_jobs:
|
||||
return
|
||||
msg = _('Unfinished config jobs found: %(jobs)r. Make sure they are '
|
||||
'completed before retrying.') % {'jobs': unfinished_jobs}
|
||||
raise exception.DracOperationError(error=msg)
|
||||
|
||||
|
||||
def get_job(node, job_id):
|
||||
|
@ -26,11 +26,11 @@ from oslo_utils import units
|
||||
from ironic.common import exception
|
||||
from ironic.common.i18n import _
|
||||
from ironic.common import raid as raid_common
|
||||
from ironic.common import states
|
||||
from ironic.conductor import task_manager
|
||||
from ironic.conductor import utils as manager_utils
|
||||
from ironic.conf import CONF
|
||||
from ironic.drivers import base
|
||||
from ironic.drivers.modules import deploy_utils
|
||||
from ironic.drivers.modules.drac import common as drac_common
|
||||
from ironic.drivers.modules.drac import job as drac_job
|
||||
|
||||
@ -163,6 +163,18 @@ def _is_raid_controller(node, raid_controller_fqdd, raid_controllers=None):
|
||||
raise exception.DracOperationError(error=exc)
|
||||
|
||||
|
||||
def _validate_job_queue(node, raid_controller=None):
|
||||
"""Validate that there are no pending jobs for this controller.
|
||||
|
||||
:param node: an ironic node object.
|
||||
:param raid_controller: id of the RAID controller.
|
||||
"""
|
||||
kwargs = {}
|
||||
if raid_controller:
|
||||
kwargs["name_prefix"] = "Config:RAID:%s" % raid_controller
|
||||
drac_job.validate_job_queue(node, **kwargs)
|
||||
|
||||
|
||||
def create_virtual_disk(node, raid_controller, physical_disks, raid_level,
|
||||
size_mb, disk_name=None, span_length=None,
|
||||
span_depth=None):
|
||||
@ -185,7 +197,9 @@ def create_virtual_disk(node, raid_controller, physical_disks, raid_level,
|
||||
values to be applied.
|
||||
:raises: DracOperationError on an error from python-dracclient.
|
||||
"""
|
||||
drac_job.validate_job_queue(node)
|
||||
# This causes config to fail, because the boot mode is set via a config
|
||||
# job.
|
||||
_validate_job_queue(node, raid_controller)
|
||||
|
||||
client = drac_common.get_drac_client(node)
|
||||
|
||||
@ -215,7 +229,8 @@ def delete_virtual_disk(node, virtual_disk):
|
||||
values to be applied.
|
||||
:raises: DracOperationError on an error from python-dracclient.
|
||||
"""
|
||||
drac_job.validate_job_queue(node)
|
||||
# NOTE(mgoddard): Cannot specify raid_controller as we don't know it.
|
||||
_validate_job_queue(node)
|
||||
|
||||
client = drac_common.get_drac_client(node)
|
||||
|
||||
@ -247,7 +262,7 @@ def _reset_raid_config(node, raid_controller):
|
||||
"""
|
||||
try:
|
||||
|
||||
drac_job.validate_job_queue(node)
|
||||
_validate_job_queue(node, raid_controller)
|
||||
|
||||
client = drac_common.get_drac_client(node)
|
||||
return client.reset_raid_config(raid_controller)
|
||||
@ -279,7 +294,7 @@ def clear_foreign_config(node, raid_controller):
|
||||
"""
|
||||
try:
|
||||
|
||||
drac_job.validate_job_queue(node)
|
||||
_validate_job_queue(node, raid_controller)
|
||||
|
||||
client = drac_common.get_drac_client(node)
|
||||
return client.clear_foreign_config(raid_controller)
|
||||
@ -480,13 +495,18 @@ def _volume_usage_per_disk_mb(logical_disk, physical_disks, spans_count=1,
|
||||
return int(stripes_per_disk * stripe_size_kb / units.Ki)
|
||||
|
||||
|
||||
def _find_configuration(logical_disks, physical_disks):
|
||||
def _find_configuration(logical_disks, physical_disks, pending_delete):
|
||||
"""Find RAID configuration.
|
||||
|
||||
This method transforms the RAID configuration defined in Ironic to a format
|
||||
that is required by dracclient. This includes matching the physical disks
|
||||
to RAID volumes when it's not pre-defined, or in general calculating
|
||||
missing properties.
|
||||
|
||||
:param logical_disks: list of logical disk definitions.
|
||||
:param physical_disks: list of physical disk definitions.
|
||||
:param pending_delete: Whether there is a pending deletion of virtual
|
||||
disks that should be accounted for.
|
||||
"""
|
||||
|
||||
# shared physical disks of RAID volumes size_gb='MAX' should be
|
||||
@ -508,7 +528,7 @@ def _find_configuration(logical_disks, physical_disks):
|
||||
free_space_mb = {}
|
||||
for disk in physical_disks:
|
||||
# calculate free disk space
|
||||
free_space_mb[disk] = disk.free_size_mb
|
||||
free_space_mb[disk] = _get_disk_free_size_mb(disk, pending_delete)
|
||||
|
||||
disk_type = (disk.controller, disk.media_type, disk.interface_type,
|
||||
disk.size_mb)
|
||||
@ -550,7 +570,8 @@ def _find_configuration(logical_disks, physical_disks):
|
||||
if volumes_without_disks:
|
||||
result, free_space_mb = (
|
||||
_assign_disks_to_volume(volumes_without_disks,
|
||||
physical_disks_by_type, free_space_mb))
|
||||
physical_disks_by_type, free_space_mb,
|
||||
pending_delete))
|
||||
if not result:
|
||||
# try again using the reserved physical disks in addition
|
||||
for disk_type, disks in physical_disks_by_type.items():
|
||||
@ -560,7 +581,8 @@ def _find_configuration(logical_disks, physical_disks):
|
||||
result, free_space_mb = (
|
||||
_assign_disks_to_volume(volumes_without_disks,
|
||||
physical_disks_by_type,
|
||||
free_space_mb))
|
||||
free_space_mb,
|
||||
pending_delete))
|
||||
if not result:
|
||||
error_msg = _('failed to find matching physical disks for all '
|
||||
'logical disks')
|
||||
@ -636,7 +658,7 @@ def _calculate_volume_props(logical_disk, physical_disks, free_space_mb):
|
||||
|
||||
|
||||
def _assign_disks_to_volume(logical_disks, physical_disks_by_type,
|
||||
free_space_mb):
|
||||
free_space_mb, pending_delete):
|
||||
logical_disk = logical_disks.pop(0)
|
||||
raid_level = logical_disk['raid_level']
|
||||
|
||||
@ -664,8 +686,12 @@ def _assign_disks_to_volume(logical_disks, physical_disks_by_type,
|
||||
# filter out disks already in use if sharing is disabled
|
||||
if ('share_physical_disks' not in logical_disk
|
||||
or not logical_disk['share_physical_disks']):
|
||||
initial_free_size_mb = {
|
||||
disk: _get_disk_free_size_mb(disk, pending_delete)
|
||||
for disk in disks
|
||||
}
|
||||
disks = [disk for disk in disks
|
||||
if disk.free_size_mb == free_space_mb[disk]]
|
||||
if initial_free_size_mb[disk] == free_space_mb[disk]]
|
||||
|
||||
max_spans = _calculate_spans(raid_level, len(disks))
|
||||
min_spans = min([2, max_spans])
|
||||
@ -701,7 +727,8 @@ def _assign_disks_to_volume(logical_disks, physical_disks_by_type,
|
||||
result, candidate_free_space_mb = (
|
||||
_assign_disks_to_volume(logical_disks,
|
||||
physical_disks_by_type,
|
||||
candidate_free_space_mb))
|
||||
candidate_free_space_mb,
|
||||
pending_delete))
|
||||
if result:
|
||||
logical_disks.append(candidate_volume)
|
||||
return (True, candidate_free_space_mb)
|
||||
@ -742,11 +769,12 @@ def _commit_to_controllers(node, controllers, substep="completed"):
|
||||
enumerated value indicating whether the server must
|
||||
be rebooted only if raid controller does not support
|
||||
realtime.
|
||||
:param substep: contain sub cleaning step which executes any raid
|
||||
configuration job if set after cleaning step.
|
||||
:param substep: contain sub cleaning or deploy step which executes any raid
|
||||
configuration job if set after cleaning or deploy step.
|
||||
(default to completed)
|
||||
:returns: states.CLEANWAIT if deletion is in progress asynchronously
|
||||
or None if it is completed.
|
||||
:returns: states.CLEANWAIT (cleaning) or states.DEPLOYWAIT (deployment) if
|
||||
configuration is in progress asynchronously or None if it is
|
||||
completed.
|
||||
"""
|
||||
if not controllers:
|
||||
LOG.debug('No changes on any of the controllers on node %s',
|
||||
@ -796,9 +824,28 @@ def _commit_to_controllers(node, controllers, substep="completed"):
|
||||
raid_controller)
|
||||
|
||||
node.driver_internal_info = driver_internal_info
|
||||
node.save()
|
||||
|
||||
return states.CLEANWAIT
|
||||
# Signal whether the node has been rebooted, that we do not need to execute
|
||||
# the step again, and that this completion of this step is triggered
|
||||
# through async polling.
|
||||
# NOTE(mgoddard): set_async_step_flags calls node.save().
|
||||
deploy_utils.set_async_step_flags(
|
||||
node,
|
||||
reboot=not all_realtime,
|
||||
skip_current_step=True,
|
||||
polling=True)
|
||||
|
||||
return deploy_utils.get_async_step_return_state(node)
|
||||
|
||||
|
||||
def _get_disk_free_size_mb(disk, pending_delete):
|
||||
"""Return the size of free space on the disk in MB.
|
||||
|
||||
:param disk: a PhysicalDisk object.
|
||||
:param pending_delete: Whether there is a pending deletion of all virtual
|
||||
disks.
|
||||
"""
|
||||
return disk.size_mb if pending_delete else disk.free_size_mb
|
||||
|
||||
|
||||
class DracWSManRAID(base.RAIDInterface):
|
||||
@ -807,6 +854,16 @@ class DracWSManRAID(base.RAIDInterface):
|
||||
"""Return the properties of the interface."""
|
||||
return drac_common.COMMON_PROPERTIES
|
||||
|
||||
@base.deploy_step(priority=0,
|
||||
argsinfo=base.RAID_APPLY_CONFIGURATION_ARGSINFO)
|
||||
def apply_configuration(self, task, raid_config, create_root_volume=True,
|
||||
create_nonroot_volumes=False,
|
||||
delete_existing=True):
|
||||
return super(DracRAID, self).apply_configuration(
|
||||
task, raid_config, create_root_volume=create_root_volume,
|
||||
create_nonroot_volumes=create_nonroot_volumes,
|
||||
delete_existing=delete_existing)
|
||||
|
||||
@METRICS.timer('DracRAID.create_configuration')
|
||||
@base.clean_step(priority=0, abortable=False, argsinfo={
|
||||
'create_root_volume': {
|
||||
@ -822,11 +879,20 @@ class DracWSManRAID(base.RAIDInterface):
|
||||
'Defaults to `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 'False'."
|
||||
),
|
||||
"required": False,
|
||||
}
|
||||
})
|
||||
def create_configuration(self, task,
|
||||
create_root_volume=True,
|
||||
create_nonroot_volumes=True):
|
||||
create_nonroot_volumes=True,
|
||||
delete_existing=False):
|
||||
"""Create the RAID configuration.
|
||||
|
||||
This method creates the RAID configuration on the given node.
|
||||
@ -838,8 +904,12 @@ class DracWSManRAID(base.RAIDInterface):
|
||||
:param create_nonroot_volumes: If True, non-root volumes are
|
||||
created. If False, no non-root volumes are created. Default
|
||||
is True.
|
||||
:returns: states.CLEANWAIT if creation is in progress asynchronously
|
||||
or None if it is completed.
|
||||
:param delete_existing: Setting this to True indicates to delete RAID
|
||||
configuration prior to creating the new configuration. Default is
|
||||
False.
|
||||
:returns: states.CLEANWAIT (cleaning) or states.DEPLOYWAIT (deployment)
|
||||
if creation is in progress asynchronously or None if it is
|
||||
completed.
|
||||
:raises: MissingParameterValue, if node.target_raid_config is missing
|
||||
or empty.
|
||||
:raises: DracOperationError on an error from python-dracclient.
|
||||
@ -864,13 +934,18 @@ class DracWSManRAID(base.RAIDInterface):
|
||||
|
||||
del disk['size_gb']
|
||||
|
||||
if delete_existing:
|
||||
controllers = self._delete_configuration_no_commit(task)
|
||||
else:
|
||||
controllers = list()
|
||||
|
||||
physical_disks = list_physical_disks(node)
|
||||
logical_disks = _find_configuration(logical_disks, physical_disks)
|
||||
logical_disks = _find_configuration(logical_disks, physical_disks,
|
||||
pending_delete=delete_existing)
|
||||
|
||||
logical_disks_to_create = _filter_logical_disks(
|
||||
logical_disks, create_root_volume, create_nonroot_volumes)
|
||||
|
||||
controllers = list()
|
||||
for logical_disk in logical_disks_to_create:
|
||||
controller = dict()
|
||||
controller_cap = create_virtual_disk(
|
||||
@ -892,28 +967,19 @@ class DracWSManRAID(base.RAIDInterface):
|
||||
|
||||
@METRICS.timer('DracRAID.delete_configuration')
|
||||
@base.clean_step(priority=0)
|
||||
@base.deploy_step(priority=0)
|
||||
def delete_configuration(self, task):
|
||||
"""Delete the RAID configuration.
|
||||
|
||||
:param task: a TaskManager instance containing the node to act on.
|
||||
:returns: states.CLEANWAIT if deletion is in progress asynchronously
|
||||
or None if it is completed.
|
||||
:returns: states.CLEANWAIT (cleaning) or states.DEPLOYWAIT (deployment)
|
||||
if deletion is in progress asynchronously or None if it is
|
||||
completed.
|
||||
:raises: DracOperationError on an error from python-dracclient.
|
||||
"""
|
||||
node = task.node
|
||||
|
||||
controllers = list()
|
||||
drac_raid_controllers = list_raid_controllers(node)
|
||||
for cntrl in drac_raid_controllers:
|
||||
if _is_raid_controller(node, cntrl.id, drac_raid_controllers):
|
||||
controller = dict()
|
||||
controller_cap = _reset_raid_config(node, cntrl.id)
|
||||
controller["raid_controller"] = cntrl.id
|
||||
controller["is_reboot_required"] = controller_cap[
|
||||
"is_reboot_required"]
|
||||
controllers.append(controller)
|
||||
|
||||
return _commit_to_controllers(node, controllers,
|
||||
controllers = self._delete_configuration_no_commit(task)
|
||||
return _commit_to_controllers(task.node, controllers,
|
||||
substep="delete_foreign_config")
|
||||
|
||||
@METRICS.timer('DracRAID.get_logical_disks')
|
||||
@ -1005,18 +1071,18 @@ class DracWSManRAID(base.RAIDInterface):
|
||||
if 'raid_config_substep' in node.driver_internal_info:
|
||||
if node.driver_internal_info['raid_config_substep'] == \
|
||||
'delete_foreign_config':
|
||||
self._execute_cleaning_foreign_drives(task, node)
|
||||
self._execute_foreign_drives(task, node)
|
||||
elif node.driver_internal_info['raid_config_substep'] == \
|
||||
'completed':
|
||||
self._complete_raid_cleaning_substep(task, node)
|
||||
self._complete_raid_substep(task, node)
|
||||
else:
|
||||
self._complete_raid_cleaning_substep(task, node)
|
||||
self._complete_raid_substep(task, node)
|
||||
else:
|
||||
self._clear_raid_substep(node)
|
||||
self._clear_raid_config_job_failure(node)
|
||||
self._set_clean_failed(task, config_job)
|
||||
self._set_failed(task, config_job)
|
||||
|
||||
def _execute_cleaning_foreign_drives(self, task, node):
|
||||
def _execute_foreign_drives(self, task, node):
|
||||
controllers = list()
|
||||
jobs_required = False
|
||||
for controller_id in node.driver_internal_info[
|
||||
@ -1034,17 +1100,17 @@ class DracWSManRAID(base.RAIDInterface):
|
||||
if not jobs_required:
|
||||
LOG.info(
|
||||
"No foreign drives detected, so "
|
||||
"resume cleaning")
|
||||
self._complete_raid_cleaning_substep(task, node)
|
||||
"resume %s", "cleaning" if node.clean_step else "deployment")
|
||||
self._complete_raid_substep(task, node)
|
||||
else:
|
||||
_commit_to_controllers(
|
||||
node,
|
||||
controllers,
|
||||
substep='completed')
|
||||
|
||||
def _complete_raid_cleaning_substep(self, task, node):
|
||||
def _complete_raid_substep(self, task, node):
|
||||
self._clear_raid_substep(node)
|
||||
self._resume_cleaning(task)
|
||||
self._resume(task)
|
||||
|
||||
def _clear_raid_substep(self, node):
|
||||
driver_internal_info = node.driver_internal_info
|
||||
@ -1076,7 +1142,7 @@ class DracWSManRAID(base.RAIDInterface):
|
||||
node.driver_internal_info = driver_internal_info
|
||||
node.save()
|
||||
|
||||
def _set_clean_failed(self, task, config_job):
|
||||
def _set_failed(self, task, config_job):
|
||||
LOG.error("RAID configuration job failed for node %(node)s. "
|
||||
"Failed config job: %(config_job_id)s. "
|
||||
"Message: '%(message)s'.",
|
||||
@ -1085,14 +1151,33 @@ class DracWSManRAID(base.RAIDInterface):
|
||||
task.node.last_error = config_job.message
|
||||
task.process_event('fail')
|
||||
|
||||
def _resume_cleaning(self, task):
|
||||
def _resume(self, task):
|
||||
raid_common.update_raid_info(
|
||||
task.node, self.get_logical_disks(task))
|
||||
driver_internal_info = task.node.driver_internal_info
|
||||
driver_internal_info['cleaning_reboot'] = True
|
||||
task.node.driver_internal_info = driver_internal_info
|
||||
task.node.save()
|
||||
manager_utils.notify_conductor_resume_clean(task)
|
||||
if task.node.clean_step:
|
||||
manager_utils.notify_conductor_resume_clean(task)
|
||||
else:
|
||||
manager_utils.notify_conductor_resume_deploy(task)
|
||||
|
||||
def _delete_configuration_no_commit(self, task):
|
||||
"""Delete existing RAID configuration without committing the change.
|
||||
|
||||
:param task: A TaskManager instance.
|
||||
:returns: A set of names of RAID controllers which need RAID changes to
|
||||
be committed.
|
||||
"""
|
||||
node = task.node
|
||||
controllers = list()
|
||||
drac_raid_controllers = list_raid_controllers(node)
|
||||
for cntrl in drac_raid_controllers:
|
||||
if _is_raid_controller(node, cntrl.id, drac_raid_controllers):
|
||||
controller = dict()
|
||||
controller_cap = _reset_raid_config(node, cntrl.id)
|
||||
controller["raid_controller"] = cntrl.id
|
||||
controller["is_reboot_required"] = controller_cap[
|
||||
"is_reboot_required"]
|
||||
controllers.append(controller)
|
||||
return controllers
|
||||
|
||||
|
||||
class DracRAID(DracWSManRAID):
|
||||
|
@ -111,6 +111,25 @@ class DracJobTestCase(test_utils.BaseDracTest):
|
||||
self.assertRaises(exception.DracOperationError,
|
||||
drac_job.validate_job_queue, self.node)
|
||||
|
||||
def test_validate_job_queue_name_prefix(self, mock_get_drac_client):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_drac_client.return_value = mock_client
|
||||
mock_client.list_jobs.return_value = [self.job]
|
||||
|
||||
drac_job.validate_job_queue(self.node, name_prefix='Fake')
|
||||
|
||||
mock_client.list_jobs.assert_called_once_with(only_unfinished=True)
|
||||
|
||||
def test_validate_job_queue_name_prefix_invalid(self,
|
||||
mock_get_drac_client):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_drac_client.return_value = mock_client
|
||||
mock_client.list_jobs.return_value = [self.job]
|
||||
|
||||
self.assertRaises(exception.DracOperationError,
|
||||
drac_job.validate_job_queue, self.node,
|
||||
name_prefix='ConfigBIOS')
|
||||
|
||||
|
||||
@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
|
||||
autospec=True)
|
||||
|
@ -139,9 +139,8 @@ class DracPeriodicTaskTestCase(db_base.DbTestCase):
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid.DracRAID, 'get_logical_disks',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(manager_utils, 'notify_conductor_resume_clean')
|
||||
def test__check_node_raid_jobs_with_completed_job(
|
||||
self, mock_notify_conductor_resume_clean,
|
||||
def _test__check_node_raid_jobs_with_completed_job(
|
||||
self, mock_notify_conductor_resume,
|
||||
mock_get_logical_disks, mock_get_drac_client):
|
||||
expected_logical_disk = {'size_gb': 558,
|
||||
'raid_level': '1',
|
||||
@ -171,14 +170,29 @@ class DracPeriodicTaskTestCase(db_base.DbTestCase):
|
||||
self.node.driver_internal_info['raid_config_job_ids'])
|
||||
self.assertEqual([expected_logical_disk],
|
||||
self.node.raid_config['logical_disks'])
|
||||
mock_notify_conductor_resume_clean.assert_called_once_with(task)
|
||||
mock_notify_conductor_resume.assert_called_once_with(task)
|
||||
|
||||
@mock.patch.object(manager_utils, 'notify_conductor_resume_clean')
|
||||
def test__check_node_raid_jobs_with_completed_job_in_clean(
|
||||
self, mock_notify_conductor_resume):
|
||||
self.node.clean_step = {'foo': 'bar'}
|
||||
self.node.save()
|
||||
self._test__check_node_raid_jobs_with_completed_job(
|
||||
mock_notify_conductor_resume)
|
||||
|
||||
@mock.patch.object(manager_utils, 'notify_conductor_resume_deploy')
|
||||
def test__check_node_raid_jobs_with_completed_job_in_deploy(
|
||||
self, mock_notify_conductor_resume):
|
||||
self._test__check_node_raid_jobs_with_completed_job(
|
||||
mock_notify_conductor_resume)
|
||||
|
||||
@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
|
||||
autospec=True)
|
||||
def test__check_node_raid_jobs_with_failed_job(self, mock_get_drac_client):
|
||||
# mock node.driver_internal_info
|
||||
# mock node.driver_internal_info and node.clean_step
|
||||
driver_internal_info = {'raid_config_job_ids': ['42']}
|
||||
self.node.driver_internal_info = driver_internal_info
|
||||
self.node.clean_step = {'foo': 'bar'}
|
||||
self.node.save()
|
||||
# mock task
|
||||
task = mock.Mock(node=self.node, context=self.context)
|
||||
@ -207,9 +221,8 @@ class DracPeriodicTaskTestCase(db_base.DbTestCase):
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid.DracRAID, 'get_logical_disks',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(manager_utils, 'notify_conductor_resume_clean')
|
||||
def test__check_node_raid_jobs_with_completed_job_already_failed(
|
||||
self, mock_notify_conductor_resume_clean,
|
||||
def _test__check_node_raid_jobs_with_completed_job_already_failed(
|
||||
self, mock_notify_conductor_resume,
|
||||
mock_get_logical_disks, mock_get_drac_client):
|
||||
expected_logical_disk = {'size_gb': 558,
|
||||
'raid_level': '1',
|
||||
@ -242,14 +255,28 @@ class DracPeriodicTaskTestCase(db_base.DbTestCase):
|
||||
self.node.driver_internal_info)
|
||||
self.assertNotIn('logical_disks', self.node.raid_config)
|
||||
task.process_event.assert_called_once_with('fail')
|
||||
self.assertFalse(mock_notify_conductor_resume.called)
|
||||
|
||||
@mock.patch.object(manager_utils, 'notify_conductor_resume_clean')
|
||||
def test__check_node_raid_jobs_with_completed_job_already_failed_in_clean(
|
||||
self, mock_notify_conductor_resume):
|
||||
self.node.clean_step = {'foo': 'bar'}
|
||||
self.node.save()
|
||||
self._test__check_node_raid_jobs_with_completed_job_already_failed(
|
||||
mock_notify_conductor_resume)
|
||||
|
||||
@mock.patch.object(manager_utils, 'notify_conductor_resume_deploy')
|
||||
def test__check_node_raid_jobs_with_completed_job_already_failed_in_deploy(
|
||||
self, mock_notify_conductor_resume):
|
||||
self._test__check_node_raid_jobs_with_completed_job_already_failed(
|
||||
mock_notify_conductor_resume)
|
||||
|
||||
@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid.DracRAID, 'get_logical_disks',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(manager_utils, 'notify_conductor_resume_clean')
|
||||
def test__check_node_raid_jobs_with_multiple_jobs_completed(
|
||||
self, mock_notify_conductor_resume_clean,
|
||||
def _test__check_node_raid_jobs_with_multiple_jobs_completed(
|
||||
self, mock_notify_conductor_resume,
|
||||
mock_get_logical_disks, mock_get_drac_client):
|
||||
expected_logical_disk = {'size_gb': 558,
|
||||
'raid_level': '1',
|
||||
@ -282,15 +309,28 @@ class DracPeriodicTaskTestCase(db_base.DbTestCase):
|
||||
self.node.driver_internal_info)
|
||||
self.assertEqual([expected_logical_disk],
|
||||
self.node.raid_config['logical_disks'])
|
||||
mock_notify_conductor_resume_clean.assert_called_once_with(task)
|
||||
mock_notify_conductor_resume.assert_called_once_with(task)
|
||||
|
||||
@mock.patch.object(manager_utils, 'notify_conductor_resume_clean')
|
||||
def test__check_node_raid_jobs_with_multiple_jobs_completed_in_clean(
|
||||
self, mock_notify_conductor_resume):
|
||||
self.node.clean_step = {'foo': 'bar'}
|
||||
self.node.save()
|
||||
self._test__check_node_raid_jobs_with_multiple_jobs_completed(
|
||||
mock_notify_conductor_resume)
|
||||
|
||||
@mock.patch.object(manager_utils, 'notify_conductor_resume_deploy')
|
||||
def test__check_node_raid_jobs_with_multiple_jobs_completed_in_deploy(
|
||||
self, mock_notify_conductor_resume):
|
||||
self._test__check_node_raid_jobs_with_multiple_jobs_completed(
|
||||
mock_notify_conductor_resume)
|
||||
|
||||
@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid.DracRAID, 'get_logical_disks',
|
||||
spec_set=True, autospec=True)
|
||||
@mock.patch.object(manager_utils, 'notify_conductor_resume_clean')
|
||||
def test__check_node_raid_jobs_with_multiple_jobs_failed(
|
||||
self, mock_notify_conductor_resume_clean,
|
||||
def _test__check_node_raid_jobs_with_multiple_jobs_failed(
|
||||
self, mock_notify_conductor_resume,
|
||||
mock_get_logical_disks, mock_get_drac_client):
|
||||
expected_logical_disk = {'size_gb': 558,
|
||||
'raid_level': '1',
|
||||
@ -327,3 +367,18 @@ class DracPeriodicTaskTestCase(db_base.DbTestCase):
|
||||
self.node.driver_internal_info)
|
||||
self.assertNotIn('logical_disks', self.node.raid_config)
|
||||
task.process_event.assert_called_once_with('fail')
|
||||
self.assertFalse(mock_notify_conductor_resume.called)
|
||||
|
||||
@mock.patch.object(manager_utils, 'notify_conductor_resume_clean')
|
||||
def test__check_node_raid_jobs_with_multiple_jobs_failed_in_clean(
|
||||
self, mock_notify_conductor_resume):
|
||||
self.node.clean_step = {'foo': 'bar'}
|
||||
self.node.save()
|
||||
self._test__check_node_raid_jobs_with_multiple_jobs_failed(
|
||||
mock_notify_conductor_resume)
|
||||
|
||||
@mock.patch.object(manager_utils, 'notify_conductor_resume_deploy')
|
||||
def test__check_node_raid_jobs_with_multiple_jobs_failed_in_deploy(
|
||||
self, mock_notify_conductor_resume):
|
||||
self._test__check_node_raid_jobs_with_multiple_jobs_failed(
|
||||
mock_notify_conductor_resume)
|
||||
|
@ -166,7 +166,8 @@ class DracManageVirtualDisksTestCase(test_utils.BaseDracTest):
|
||||
drac_raid.create_virtual_disk(
|
||||
self.node, 'controller', ['disk1', 'disk2'], '1+0', 43008)
|
||||
|
||||
mock_validate_job_queue.assert_called_once_with(self.node)
|
||||
mock_validate_job_queue.assert_called_once_with(
|
||||
self.node, name_prefix='Config:RAID:controller')
|
||||
mock_client.create_virtual_disk.assert_called_once_with(
|
||||
'controller', ['disk1', 'disk2'], '1+0', 43008, None, None, None)
|
||||
|
||||
@ -182,7 +183,8 @@ class DracManageVirtualDisksTestCase(test_utils.BaseDracTest):
|
||||
self.node, 'controller', ['disk1', 'disk2'], '1+0', 43008,
|
||||
disk_name='name', span_length=3, span_depth=2)
|
||||
|
||||
mock_validate_job_queue.assert_called_once_with(self.node)
|
||||
mock_validate_job_queue.assert_called_once_with(
|
||||
self.node, name_prefix='Config:RAID:controller')
|
||||
mock_client.create_virtual_disk.assert_called_once_with(
|
||||
'controller', ['disk1', 'disk2'], '1+0', 43008, 'name', 3, 2)
|
||||
|
||||
@ -234,7 +236,8 @@ class DracManageVirtualDisksTestCase(test_utils.BaseDracTest):
|
||||
drac_raid._reset_raid_config(
|
||||
self.node, 'controller')
|
||||
|
||||
mock_validate_job_queue.assert_called_once_with(self.node)
|
||||
mock_validate_job_queue.assert_called_once_with(
|
||||
self.node, name_prefix='Config:RAID:controller')
|
||||
mock_client.reset_raid_config.assert_called_once_with(
|
||||
'controller')
|
||||
|
||||
@ -262,7 +265,8 @@ class DracManageVirtualDisksTestCase(test_utils.BaseDracTest):
|
||||
drac_raid.clear_foreign_config(
|
||||
self.node, 'RAID.Integrated.1-1')
|
||||
|
||||
mock_validate_job_queue.assert_called_once_with(self.node)
|
||||
mock_validate_job_queue.assert_called_once_with(
|
||||
self.node, 'Config:RAID:RAID.Integrated.1-1')
|
||||
mock_client.clear_foreign_config.assert_called_once_with(
|
||||
'RAID.Integrated.1-1')
|
||||
|
||||
@ -499,7 +503,8 @@ class DracCreateRaidConfigurationHelpersTestCase(test_utils.BaseDracTest):
|
||||
'Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1']
|
||||
|
||||
logical_disks = drac_raid._find_configuration(logical_disks,
|
||||
physical_disks)
|
||||
physical_disks,
|
||||
False)
|
||||
|
||||
self.assertEqual(expected_contoller,
|
||||
logical_disks[0]['controller'])
|
||||
@ -525,7 +530,8 @@ class DracCreateRaidConfigurationHelpersTestCase(test_utils.BaseDracTest):
|
||||
'Disk.Bay.6:Enclosure.Internal.0-1:RAID.Integrated.1-1']
|
||||
|
||||
logical_disks = drac_raid._find_configuration(logical_disks,
|
||||
physical_disks)
|
||||
physical_disks,
|
||||
False)
|
||||
|
||||
self.assertEqual(expected_contoller,
|
||||
logical_disks[0]['controller'])
|
||||
@ -553,7 +559,8 @@ class DracCreateRaidConfigurationHelpersTestCase(test_utils.BaseDracTest):
|
||||
physical_disks = self._generate_physical_disks()
|
||||
|
||||
logical_disks = drac_raid._find_configuration(logical_disks,
|
||||
physical_disks)
|
||||
physical_disks,
|
||||
False)
|
||||
|
||||
self.assertEqual(3, len(logical_disks))
|
||||
# step 1
|
||||
@ -591,6 +598,33 @@ class DracCreateRaidConfigurationHelpersTestCase(test_utils.BaseDracTest):
|
||||
'Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1']},
|
||||
logical_disks)
|
||||
|
||||
def test__find_configuration_pending_delete(self):
|
||||
logical_disks = [
|
||||
{'size_mb': 102400,
|
||||
'raid_level': '5',
|
||||
'is_root_volume': True,
|
||||
'disk_type': 'hdd'}
|
||||
]
|
||||
physical_disks = self._generate_physical_disks()
|
||||
# No free space, but deletion pending means they're still usable.
|
||||
physical_disks = [disk._replace(free_size_mb=0)
|
||||
for disk in physical_disks]
|
||||
|
||||
expected_contoller = 'RAID.Integrated.1-1'
|
||||
expected_physical_disk_ids = [
|
||||
'Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1',
|
||||
'Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1',
|
||||
'Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1']
|
||||
|
||||
logical_disks = drac_raid._find_configuration(logical_disks,
|
||||
physical_disks,
|
||||
True)
|
||||
|
||||
self.assertEqual(expected_contoller,
|
||||
logical_disks[0]['controller'])
|
||||
self.assertEqual(expected_physical_disk_ids,
|
||||
logical_disks[0]['physical_disks'])
|
||||
|
||||
|
||||
class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
|
||||
@ -652,6 +686,7 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
[self.root_logical_disk] + self.nonroot_logical_disks)
|
||||
self.target_raid_configuration = {'logical_disks': self.logical_disks}
|
||||
self.node.target_raid_config = self.target_raid_configuration
|
||||
self.node.clean_step = {'foo': 'bar'}
|
||||
self.node.save()
|
||||
|
||||
def _generate_physical_disks(self):
|
||||
@ -664,26 +699,43 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
|
||||
@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid, '_reset_raid_config', autospec=True)
|
||||
@mock.patch.object(drac_raid, 'list_physical_disks', autospec=True)
|
||||
@mock.patch.object(drac_job, 'validate_job_queue', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid, 'commit_config', spec_set=True,
|
||||
autospec=True)
|
||||
def test_create_configuration(
|
||||
self, mock_commit_config, mock_validate_job_queue,
|
||||
mock_list_physical_disks, mock_get_drac_client):
|
||||
def _test_create_configuration(
|
||||
self, expected_state, mock_commit_config, mock_validate_job_queue,
|
||||
mock_list_physical_disks, mock__reset_raid_config,
|
||||
mock_get_drac_client):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_drac_client.return_value = mock_client
|
||||
physical_disks = self._generate_physical_disks()
|
||||
mock_list_physical_disks.return_value = physical_disks
|
||||
mock_commit_config.return_value = '42'
|
||||
raid_controller_dict = {
|
||||
'id': 'RAID.Integrated.1-1',
|
||||
'description': 'Integrated RAID Controller 1',
|
||||
'manufacturer': 'DELL',
|
||||
'model': 'PERC H710 Mini',
|
||||
'primary_status': 'ok',
|
||||
'firmware_version': '21.3.0-0009',
|
||||
'bus': '1',
|
||||
'supports_realtime': True}
|
||||
raid_controller = test_utils.make_raid_controller(
|
||||
raid_controller_dict)
|
||||
mock_client.list_raid_controllers.return_value = [raid_controller]
|
||||
mock__reset_raid_config.return_value = {
|
||||
'is_reboot_required': constants.RebootRequired.optional,
|
||||
'is_commit_required': True}
|
||||
mock_client.create_virtual_disk.return_value = {
|
||||
'is_reboot_required': constants.RebootRequired.optional,
|
||||
'is_commit_required': True}
|
||||
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.raid.create_configuration(
|
||||
return_value = task.driver.raid.create_configuration(
|
||||
task, create_root_volume=True, create_nonroot_volumes=False)
|
||||
|
||||
mock_client.create_virtual_disk.assert_called_once_with(
|
||||
@ -696,10 +748,19 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
task.node, raid_controller='RAID.Integrated.1-1', reboot=False,
|
||||
realtime=True)
|
||||
|
||||
self.assertEqual(expected_state, return_value)
|
||||
self.node.refresh()
|
||||
self.assertEqual(['42'],
|
||||
self.node.driver_internal_info['raid_config_job_ids'])
|
||||
|
||||
def test_create_configuration_in_clean(self):
|
||||
self._test_create_configuration(states.CLEANWAIT)
|
||||
|
||||
def test_create_configuration_in_deploy(self):
|
||||
self.node.clean_step = None
|
||||
self.node.save()
|
||||
self._test_create_configuration(states.DEPLOYWAIT)
|
||||
|
||||
@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid, 'list_physical_disks', autospec=True)
|
||||
@ -709,7 +770,8 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
autospec=True)
|
||||
def test_create_configuration_no_change(
|
||||
self, mock_commit_config, mock_validate_job_queue,
|
||||
mock_list_physical_disks, mock_get_drac_client):
|
||||
mock_list_physical_disks,
|
||||
mock_get_drac_client):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_drac_client.return_value = mock_client
|
||||
physical_disks = self._generate_physical_disks()
|
||||
@ -721,7 +783,8 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
return_value = task.driver.raid.create_configuration(
|
||||
task, create_root_volume=False, create_nonroot_volumes=False)
|
||||
task, create_root_volume=False, create_nonroot_volumes=False,
|
||||
delete_existing=False)
|
||||
|
||||
self.assertEqual(0, mock_client.create_virtual_disk.call_count)
|
||||
self.assertEqual(0, mock_commit_config.call_count)
|
||||
@ -731,6 +794,72 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
self.node.refresh()
|
||||
self.assertNotIn('raid_config_job_ids', self.node.driver_internal_info)
|
||||
|
||||
@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid, '_reset_raid_config', autospec=True)
|
||||
@mock.patch.object(drac_raid, 'list_virtual_disks', autospec=True)
|
||||
@mock.patch.object(drac_raid, 'list_physical_disks', autospec=True)
|
||||
@mock.patch.object(drac_job, 'validate_job_queue', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid, 'commit_config', spec_set=True,
|
||||
autospec=True)
|
||||
def test_create_configuration_delete_existing(
|
||||
self, mock_commit_config,
|
||||
mock_validate_job_queue,
|
||||
mock_list_physical_disks,
|
||||
mock_list_virtual_disks,
|
||||
mock__reset_raid_config,
|
||||
mock_get_drac_client):
|
||||
self.node.clean_step = None
|
||||
self.node.save()
|
||||
mock_client = mock.Mock()
|
||||
mock_get_drac_client.return_value = mock_client
|
||||
|
||||
physical_disks = self._generate_physical_disks()
|
||||
raid_controller_dict = {
|
||||
'id': 'RAID.Integrated.1-1',
|
||||
'description': 'Integrated RAID Controller 1',
|
||||
'manufacturer': 'DELL',
|
||||
'model': 'PERC H710 Mini',
|
||||
'primary_status': 'ok',
|
||||
'firmware_version': '21.3.0-0009',
|
||||
'bus': '1',
|
||||
'supports_realtime': True}
|
||||
raid_controller = test_utils.make_raid_controller(
|
||||
raid_controller_dict)
|
||||
mock_list_physical_disks.return_value = physical_disks
|
||||
mock_commit_config.return_value = '42'
|
||||
mock_client.list_raid_controllers.return_value = [raid_controller]
|
||||
mock__reset_raid_config.return_value = {
|
||||
'is_reboot_required': constants.RebootRequired.optional,
|
||||
'is_commit_required': True}
|
||||
|
||||
mock_client.create_virtual_disk.return_value = {
|
||||
'is_reboot_required': constants.RebootRequired.optional,
|
||||
'is_commit_required': True
|
||||
}
|
||||
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
return_value = task.driver.raid.create_configuration(
|
||||
task, create_root_volume=True, create_nonroot_volumes=False,
|
||||
delete_existing=True)
|
||||
mock_client.create_virtual_disk.assert_called_once_with(
|
||||
'RAID.Integrated.1-1',
|
||||
['Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1',
|
||||
'Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1'],
|
||||
'1', 51200, None, 2, 1)
|
||||
mock_commit_config.assert_called_once_with(
|
||||
task.node, raid_controller='RAID.Integrated.1-1',
|
||||
realtime=True, reboot=False)
|
||||
|
||||
self.assertEqual(1, mock_commit_config.call_count)
|
||||
|
||||
self.assertEqual(states.DEPLOYWAIT, return_value)
|
||||
self.node.refresh()
|
||||
self.assertEqual(['42'],
|
||||
self.node.driver_internal_info['raid_config_job_ids'])
|
||||
|
||||
@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid, 'list_physical_disks', autospec=True)
|
||||
@ -765,7 +894,8 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.raid.create_configuration(
|
||||
task, create_root_volume=True, create_nonroot_volumes=True)
|
||||
task, create_root_volume=True, create_nonroot_volumes=True,
|
||||
delete_existing=False)
|
||||
|
||||
mock_client.create_virtual_disk.assert_called_once_with(
|
||||
'RAID.Integrated.1-1',
|
||||
@ -821,7 +951,8 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.raid.create_configuration(
|
||||
task, create_root_volume=True, create_nonroot_volumes=True)
|
||||
task, create_root_volume=True, create_nonroot_volumes=True,
|
||||
delete_existing=False)
|
||||
|
||||
mock_client.create_virtual_disk.assert_called_once_with(
|
||||
'RAID.Integrated.1-1',
|
||||
@ -873,7 +1004,8 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.raid.create_configuration(
|
||||
task, create_root_volume=True, create_nonroot_volumes=True)
|
||||
task, create_root_volume=True, create_nonroot_volumes=True,
|
||||
delete_existing=False)
|
||||
mock_client.create_virtual_disk.assert_has_calls(
|
||||
[mock.call(
|
||||
'controller-2',
|
||||
@ -941,7 +1073,8 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.raid.create_configuration(
|
||||
task, create_root_volume=True, create_nonroot_volumes=True)
|
||||
task, create_root_volume=True, create_nonroot_volumes=True,
|
||||
delete_existing=False)
|
||||
mock_client.create_virtual_disk.assert_has_calls(
|
||||
[mock.call(
|
||||
'RAID.Integrated.1-1',
|
||||
@ -1004,7 +1137,8 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.raid.create_configuration(
|
||||
task, create_root_volume=True, create_nonroot_volumes=True)
|
||||
task, create_root_volume=True, create_nonroot_volumes=True,
|
||||
delete_existing=False)
|
||||
|
||||
mock_client.create_virtual_disk.assert_has_calls(
|
||||
[mock.call(
|
||||
@ -1069,7 +1203,8 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.raid.create_configuration(
|
||||
task, create_root_volume=True, create_nonroot_volumes=True)
|
||||
task, create_root_volume=True, create_nonroot_volumes=True,
|
||||
delete_existing=False)
|
||||
|
||||
mock_client.create_virtual_disk.assert_has_calls(
|
||||
[mock.call(
|
||||
@ -1162,7 +1297,8 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.raid.create_configuration(
|
||||
task, create_root_volume=True, create_nonroot_volumes=True)
|
||||
task, create_root_volume=True, create_nonroot_volumes=True,
|
||||
delete_existing=False)
|
||||
|
||||
mock_client.create_virtual_disk.assert_has_calls(
|
||||
[mock.call(
|
||||
@ -1189,6 +1325,7 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
|
||||
@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid, '_reset_raid_config', autospec=True)
|
||||
@mock.patch.object(drac_raid, 'list_physical_disks', autospec=True)
|
||||
@mock.patch.object(drac_job, 'validate_job_queue', spec_set=True,
|
||||
autospec=True)
|
||||
@ -1196,7 +1333,8 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
autospec=True)
|
||||
def test_create_configuration_fails_with_sharing_disabled(
|
||||
self, mock_commit_config, mock_validate_job_queue,
|
||||
mock_list_physical_disks, mock_get_drac_client):
|
||||
mock_list_physical_disks, mock__reset_raid_config,
|
||||
mock_get_drac_client):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_drac_client.return_value = mock_client
|
||||
|
||||
@ -1210,7 +1348,18 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
self.physical_disks = self.physical_disks[0:3]
|
||||
physical_disks = self._generate_physical_disks()
|
||||
mock_list_physical_disks.return_value = physical_disks
|
||||
|
||||
raid_controller_dict = {
|
||||
'id': 'RAID.Integrated.1-1',
|
||||
'description': 'Integrated RAID Controller 1',
|
||||
'manufacturer': 'DELL',
|
||||
'model': 'PERC H710 Mini',
|
||||
'primary_status': 'ok',
|
||||
'firmware_version': '21.3.0-0009',
|
||||
'bus': '1',
|
||||
'supports_realtime': True}
|
||||
raid_controller = test_utils.make_raid_controller(
|
||||
raid_controller_dict)
|
||||
mock_client.list_raid_controllers.return_value = [raid_controller]
|
||||
mock_commit_config.return_value = '42'
|
||||
mock_client.create_virtual_disk.return_value = {
|
||||
'is_reboot_required': constants.RebootRequired.optional,
|
||||
@ -1262,7 +1411,8 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
task.driver.raid.create_configuration(
|
||||
task, create_root_volume=True, create_nonroot_volumes=True)
|
||||
task, create_root_volume=True, create_nonroot_volumes=True,
|
||||
delete_existing=False)
|
||||
|
||||
mock_client.create_virtual_disk.assert_has_calls(
|
||||
[mock.call(
|
||||
@ -1332,10 +1482,12 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
self.assertRaises(
|
||||
exception.DracOperationError,
|
||||
task.driver.raid.create_configuration,
|
||||
task, create_root_volume=True, create_nonroot_volumes=True)
|
||||
task, create_root_volume=True, create_nonroot_volumes=True,
|
||||
delete_existing=False)
|
||||
|
||||
@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid, '_reset_raid_config', autospec=True)
|
||||
@mock.patch.object(drac_raid, 'list_physical_disks', autospec=True)
|
||||
@mock.patch.object(drac_job, 'validate_job_queue', spec_set=True,
|
||||
autospec=True)
|
||||
@ -1346,7 +1498,7 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
def test_create_configuration_fails_if_not_enough_space(
|
||||
self, mock_create_virtual_disk, mock_commit_config,
|
||||
mock_validate_job_queue, mock_list_physical_disks,
|
||||
mock_get_drac_client):
|
||||
mock__reset_raid_config, mock_get_drac_client):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_drac_client.return_value = mock_client
|
||||
|
||||
@ -1362,6 +1514,21 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
self.physical_disks = self.physical_disks[0:3]
|
||||
physical_disks = self._generate_physical_disks()
|
||||
mock_list_physical_disks.return_value = physical_disks
|
||||
raid_controller_dict = {
|
||||
'id': 'RAID.Integrated.1-1',
|
||||
'description': 'Integrated RAID Controller 1',
|
||||
'manufacturer': 'DELL',
|
||||
'model': 'PERC H710 Mini',
|
||||
'primary_status': 'ok',
|
||||
'firmware_version': '21.3.0-0009',
|
||||
'bus': '1',
|
||||
'supports_realtime': True}
|
||||
raid_controller = test_utils.make_raid_controller(
|
||||
raid_controller_dict)
|
||||
mock_client.list_raid_controllers.return_value = [raid_controller]
|
||||
mock__reset_raid_config.return_value = {
|
||||
'is_reboot_required': constants.RebootRequired.optional,
|
||||
'is_commit_required': True}
|
||||
|
||||
mock_commit_config.return_value = '42'
|
||||
mock_create_virtual_disk.return_value = {
|
||||
@ -1377,6 +1544,8 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
|
||||
@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid, '_reset_raid_config', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid, 'list_physical_disks', autospec=True)
|
||||
@mock.patch.object(drac_job, 'validate_job_queue', spec_set=True,
|
||||
autospec=True)
|
||||
@ -1387,7 +1556,7 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
def test_create_configuration_fails_if_disk_already_reserved(
|
||||
self, mock_create_virtual_disk, mock_commit_config,
|
||||
mock_validate_job_queue, mock_list_physical_disks,
|
||||
mock_get_drac_client):
|
||||
mock__reset_raid_config, mock_get_drac_client):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_drac_client.return_value = mock_client
|
||||
|
||||
@ -1406,7 +1575,24 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
physical_disks = self._generate_physical_disks()
|
||||
mock_list_physical_disks.return_value = physical_disks
|
||||
|
||||
raid_controller_dict = {
|
||||
'id': 'RAID.Integrated.1-1',
|
||||
'description': 'Integrated RAID Controller 1',
|
||||
'manufacturer': 'DELL',
|
||||
'model': 'PERC H710 Mini',
|
||||
'primary_status': 'ok',
|
||||
'firmware_version': '21.3.0-0009',
|
||||
'bus': '1',
|
||||
'supports_realtime': True}
|
||||
raid_controller = test_utils.make_raid_controller(
|
||||
raid_controller_dict)
|
||||
mock_client.list_raid_controllers.return_value = [raid_controller]
|
||||
|
||||
mock_commit_config.return_value = '42'
|
||||
mock__reset_raid_config.return_value = {
|
||||
'is_reboot_required': constants.RebootRequired.optional,
|
||||
'is_commit_required': True}
|
||||
|
||||
mock_create_virtual_disk.return_value = {
|
||||
'is_reboot_required': constants.RebootRequired.optional,
|
||||
'is_commit_required': True}
|
||||
@ -1420,18 +1606,18 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
|
||||
@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid, '_reset_raid_config', autospec=True)
|
||||
@mock.patch.object(drac_raid, 'list_raid_controllers', autospec=True)
|
||||
@mock.patch.object(drac_job, 'validate_job_queue', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid, 'commit_config', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid, '_reset_raid_config', spec_set=True,
|
||||
autospec=True)
|
||||
def test_delete_configuration(self, mock__reset_raid_config,
|
||||
mock_commit_config,
|
||||
mock_validate_job_queue,
|
||||
mock_list_raid_controllers,
|
||||
mock_get_drac_client):
|
||||
def _test_delete_configuration(self, expected_state,
|
||||
mock_commit_config,
|
||||
mock_validate_job_queue,
|
||||
mock_list_raid_controllers,
|
||||
mock__reset_raid_config,
|
||||
mock_get_drac_client):
|
||||
mock_client = mock.Mock()
|
||||
mock_get_drac_client.return_value = mock_client
|
||||
raid_controller_dict = {
|
||||
@ -1459,11 +1645,19 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
task.node, raid_controller='RAID.Integrated.1-1', reboot=False,
|
||||
realtime=True)
|
||||
|
||||
self.assertEqual(states.CLEANWAIT, return_value)
|
||||
self.assertEqual(expected_state, return_value)
|
||||
self.node.refresh()
|
||||
self.assertEqual(['42'],
|
||||
self.node.driver_internal_info['raid_config_job_ids'])
|
||||
|
||||
def test_delete_configuration_in_clean(self):
|
||||
self._test_delete_configuration(states.CLEANWAIT)
|
||||
|
||||
def test_delete_configuration_in_deploy(self):
|
||||
self.node.clean_step = None
|
||||
self.node.save()
|
||||
self._test_delete_configuration(states.DEPLOYWAIT)
|
||||
|
||||
@mock.patch.object(drac_common, 'get_drac_client', spec_set=True,
|
||||
autospec=True)
|
||||
@mock.patch.object(drac_raid, 'list_raid_controllers', autospec=True)
|
||||
@ -1568,7 +1762,7 @@ class DracRaidInterfaceTestCase(test_utils.BaseDracTest):
|
||||
|
||||
with task_manager.acquire(self.context, self.node.uuid,
|
||||
shared=False) as task:
|
||||
return_value = task.driver.raid._execute_cleaning_foreign_drives(
|
||||
return_value = task.driver.raid._execute_foreign_drives(
|
||||
task, self.node)
|
||||
mock_resume.assert_called_once_with(
|
||||
task, 'cleaning', 'continue_node_clean')
|
||||
|
@ -0,0 +1,10 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Adds support for deploy steps to ``raid`` interface of ``idrac``
|
||||
hardware type. The methods ``apply_configuration`` and
|
||||
``delete_configuration`` can be used as deploy steps.
|
||||
- |
|
||||
Adds a new ``delete_existing`` argument to the ``create_configuration``
|
||||
clean step on the ``idrac`` ``raid`` interface which can be used to
|
||||
delete existing virtual disks. The default for this argument is ``False``.
|
Loading…
x
Reference in New Issue
Block a user