Source code for ironic.drivers.modules.ilo.raid

# Copyright 2018 Hewlett Packard Enterprise Development LP
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

"""
iLO5 RAID specific methods
"""

from ironic_lib import metrics_utils
from oslo_log import log as logging
from oslo_utils import importutils

from ironic.common import exception
from ironic.common.i18n import _
from ironic.common import raid
from ironic.common import states
from ironic.conductor import utils as manager_utils
from ironic import conf
from ironic.drivers import base
from ironic.drivers.modules import deploy_utils
from ironic.drivers.modules.ilo import common as ilo_common


LOG = logging.getLogger(__name__)
CONF = conf.CONF
METRICS = metrics_utils.get_metrics_logger(__name__)

ilo_error = importutils.try_import('proliantutils.exception')


[docs]class Ilo5RAID(base.RAIDInterface): """Implementation of OOB RAIDInterface for iLO5.""" _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, } }
[docs] def get_properties(self): """Return the properties of the interface.""" return ilo_common.REQUIRED_PROPERTIES
def _set_step_failed(self, task, msg, exc): LOG.error("RAID configuration job failed for node %(node)s. " "Message: '%(message)s'.", {'node': task.node.uuid, 'message': msg}) task.node.last_error = msg task.process_event('fail') def _set_driver_internal_true_value(self, task, *keys): driver_internal_info = task.node.driver_internal_info for key in keys: driver_internal_info[key] = True task.node.driver_internal_info = driver_internal_info task.node.save() def _set_driver_internal_false_value(self, task, *keys): driver_internal_info = task.node.driver_internal_info for key in keys: driver_internal_info[key] = False task.node.driver_internal_info = driver_internal_info task.node.save() def _pop_driver_internal_values(self, task, *keys): driver_internal_info = task.node.driver_internal_info for key in keys: driver_internal_info.pop(key, None) task.node.driver_internal_info = driver_internal_info task.node.save() def _prepare_for_read_raid(self, task, raid_step): deploy_opts = deploy_utils.build_agent_options(task.node) task.driver.boot.prepare_ramdisk(task, deploy_opts) manager_utils.node_power_action(task, states.REBOOT) if raid_step == 'create_raid': self._set_driver_internal_true_value( task, 'ilo_raid_create_in_progress') else: self._set_driver_internal_true_value( task, 'ilo_raid_delete_in_progress') deploy_utils.set_async_step_flags(task.node, reboot=True, skip_current_step=False)
[docs] @base.deploy_step(priority=0, argsinfo=_RAID_APPLY_CONFIGURATION_ARGSINFO) def apply_configuration(self, task, raid_config, create_root_volume=True, create_nonroot_volumes=False): return super(Ilo5RAID, self).apply_configuration( task, raid_config, create_root_volume=create_root_volume, create_nonroot_volumes=create_nonroot_volumes)
[docs] @METRICS.timer('Ilo5RAID.create_configuration') @base.clean_step(priority=0, abortable=False, argsinfo={ 'create_root_volume': { 'description': ( 'This specifies whether to create the root volume. ' 'Defaults to `True`.' ), 'required': False }, 'create_nonroot_volumes': { 'description': ( 'This specifies whether to create the non-root volumes. ' 'Defaults to `True`.' ), 'required': False } }) def create_configuration(self, task, create_root_volume=True, create_nonroot_volumes=True): """Create a RAID configuration on a bare metal using agent ramdisk. This method creates a RAID configuration on the given node. :param task: a TaskManager instance. :param create_root_volume: If True, a root volume is created during RAID configuration. Otherwise, no root volume is created. Default is True. :param create_nonroot_volumes: If True, non-root volumes are created. If False, no non-root volumes are created. Default is True. :raises: MissingParameterValue, if node.target_raid_config is missing or was found to be empty after skipping root volume and/or non-root volumes. :raises: NodeCleaningFailure, on failure to execute clean step. :raises: InstanceDeployFailure, on failure to execute deploy step. """ node = task.node target_raid_config = raid.filter_target_raid_config( node, create_root_volume=create_root_volume, create_nonroot_volumes=create_nonroot_volumes) driver_internal_info = node.driver_internal_info driver_internal_info['target_raid_config'] = target_raid_config node.driver_internal_info = driver_internal_info node.save() LOG.debug("Calling OOB RAID create_configuration for node %(node)s " "with the following target RAID configuration: %(target)s", {'node': node.uuid, 'target': target_raid_config}) ilo_object = ilo_common.get_ilo_object(node) try: # Raid configuration in progress, checking status if not driver_internal_info.get('ilo_raid_create_in_progress'): ilo_object.create_raid_configuration(target_raid_config) self._prepare_for_read_raid(task, 'create_raid') return deploy_utils.get_async_step_return_state(node) else: # Raid configuration is done, updating raid_config raid_conf = ( ilo_object.read_raid_configuration( raid_config=target_raid_config)) fields = ['ilo_raid_create_in_progress'] if node.clean_step: fields.append('skip_current_clean_step') else: fields.append('skip_current_deploy_step') self._pop_driver_internal_values(task, *fields) if len(raid_conf['logical_disks']): raid.update_raid_info(node, raid_conf) LOG.debug("Node %(uuid)s raid create clean step is done.", {'uuid': node.uuid}) else: # Raid configuration failed msg = (_("Step create_configuration failed " "on node %(node)s with error: " "Unable to create raid") % {'node': node.uuid}) if node.clean_step: raise exception.NodeCleaningFailure(msg) else: raise exception.InstanceDeployFailure(reason=msg) except ilo_error.IloError as ilo_exception: operation = (_("Failed to create raid configuration on node %s") % node.uuid) fields = ['ilo_raid_create_in_progress'] if node.clean_step: fields.append('skip_current_clean_step') else: fields.append('skip_current_deploy_step') self._pop_driver_internal_values(task, *fields) self._set_step_failed(task, operation, ilo_exception)
[docs] @METRICS.timer('Ilo5RAID.delete_configuration') @base.clean_step(priority=0, abortable=False) @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. :raises: NodeCleaningFailure, on failure to execute clean step. :raises: InstanceDeployFailure, on failure to execute deploy step. """ node = task.node LOG.debug("OOB RAID delete_configuration invoked for node %s.", node.uuid) driver_internal_info = node.driver_internal_info ilo_object = ilo_common.get_ilo_object(node) try: # Raid configuration in progress, checking status if not driver_internal_info.get('ilo_raid_delete_in_progress'): ilo_object.delete_raid_configuration() self._prepare_for_read_raid(task, 'delete_raid') return deploy_utils.get_async_step_return_state(node) else: # Raid configuration is done, updating raid_config raid_conf = ilo_object.read_raid_configuration() fields = ['ilo_raid_delete_in_progress'] if node.clean_step: fields.append('skip_current_clean_step') else: fields.append('skip_current_deploy_step') self._pop_driver_internal_values(task, *fields) if not len(raid_conf['logical_disks']): node.raid_config = {} LOG.debug("Node %(uuid)s raid delete clean step is done.", {'uuid': node.uuid}) else: # Raid configuration failed err_msg = (_("Step delete_configuration failed " "on node %(node)s with error: " "Unable to delete these logical disks: " "%(disks)s") % {'node': node.uuid, 'disks': raid_conf['logical_disks']}) if node.clean_step: raise exception.NodeCleaningFailure(err_msg) else: raise exception.InstanceDeployFailure(reason=err_msg) except ilo_error.IloLogicalDriveNotFoundError: LOG.info("No logical drive found to delete on node %(node)s", {'node': node.uuid}) except ilo_error.IloError as ilo_exception: operation = (_("Failed to delete raid configuration on node %s") % node.uuid) self._pop_driver_internal_values(task, 'ilo_raid_delete_in_progress', 'skip_current_clean_step') fields = ['ilo_raid_delete_in_progress'] if node.clean_step: fields.append('skip_current_clean_step') else: fields.append('skip_current_deploy_step') self._pop_driver_internal_values(task, *fields) self._set_step_failed(task, operation, ilo_exception)