def delete_virtual_disk(self, virtual_disk): """Deletes a virtual disk The deleted virtual disk will be in pending state. For the changes to be applied, a config job must be created and the node must be rebooted. :param virtual_disk: id of the virtual disk :returns: a dictionary containing: - The is_commit_required key with the value always set to True indicating that a config job must be created to complete virtual disk deletion. - The is_reboot_required key with a RebootRequired enumerated value indicating whether the server must be rebooted to complete virtual disk deletion. :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC interface :raises: DRACUnexpectedReturnValue on return value mismatch """ selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', 'CreationClassName': 'DCIM_RAIDService', 'SystemName': 'DCIM:ComputerSystem', 'Name': 'DCIM:RAIDService'} properties = {'Target': virtual_disk} doc = self.client.invoke(uris.DCIM_RAIDService, 'DeleteVirtualDisk', selectors, properties, expected_return_value=utils.RET_SUCCESS) return utils.build_return_dict(doc, uris.DCIM_RAIDService, is_commit_required_value=True)
def convert_physical_disks(self, physical_disks, raid_enable): """Converts a list of physical disks into or out of RAID mode. Disks can be enabled or disabled for RAID mode. :param physical_disks: list of FQDD ID strings of the physical disks to update :param raid_enable: boolean flag, set to True if the disk is to become part of the RAID. The same flag is applied to all listed disks :returns: a dictionary containing: - The is_commit_required key with the value always set to True indicating that a config job must be created to complete disk conversion. - The is_reboot_required key with a RebootRequired enumerated value indicating whether the server must be rebooted to complete disk conversion. """ invocation = 'ConvertToRAID' if raid_enable else 'ConvertToNonRAID' selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', 'CreationClassName': 'DCIM_RAIDService', 'SystemName': 'DCIM:ComputerSystem', 'Name': 'DCIM:RAIDService'} properties = {'PDArray': physical_disks} doc = self.client.invoke(uris.DCIM_RAIDService, invocation, selectors, properties, expected_return_value=utils.RET_SUCCESS) return utils.build_return_dict(doc, uris.DCIM_RAIDService, is_commit_required_value=True)
def reset_raid_config(self, raid_controller): """Delete all virtual disk and unassign all hotspares The job to reset the RAID controller config will be in pending state. For the changes to be applied, a config job must be created. :param raid_controller: id of the RAID controller :returns: a dictionary containing: - The is_commit_required key with the value always set to True indicating that a config job must be created to reset configuration. - The is_reboot_required key with a RebootRequired enumerated value indicating whether the server must be rebooted to reset configuration. :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC interface :raises: DRACUnexpectedReturnValue on return value mismatch """ selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', 'CreationClassName': 'DCIM_RAIDService', 'SystemName': 'DCIM:ComputerSystem', 'Name': 'DCIM:RAIDService'} properties = {'Target': raid_controller} doc = self.client.invoke(uris.DCIM_RAIDService, 'ResetConfig', selectors, properties, expected_return_value=utils.RET_SUCCESS) return utils.build_return_dict(doc, uris.DCIM_RAIDService, is_commit_required_value=True)
def clear_foreign_config(self, raid_controller): """Free up foreign drives The job to clear foreign config will be in pending state. For the changes to be applied, a config job must be created. :param raid_controller: id of the RAID controller :returns: a dictionary containing: - The is_commit_required key with the value always set to True indicating that a config job must be created to clear foreign configuration. - The is_reboot_required key with a RebootRequired enumerated value indicating whether the server must be rebooted to clear foreign configuration. :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC interface :raises: DRACUnexpectedReturnValue on return value mismatch """ selectors = {'SystemCreationClassName': 'DCIM_ComputerSystem', 'CreationClassName': 'DCIM_RAIDService', 'SystemName': 'DCIM:ComputerSystem', 'Name': 'DCIM:RAIDService'} properties = {'Target': raid_controller} doc = self.client.invoke(uris.DCIM_RAIDService, 'ClearForeignConfig', selectors, properties, check_return_value=False) is_commit_required_value = True is_reboot_required_value = None ret_value = utils.find_xml(doc, 'ReturnValue', uris.DCIM_RAIDService).text if ret_value == utils.RET_ERROR: message_id = utils.find_xml(doc, 'MessageID', uris.DCIM_RAIDService).text # A MessageID 'STOR018' indicates no foreign drive was # detected. Return a value which informs the caller nothing # further needs to be done. if message_id == NO_FOREIGN_DRIVE: is_commit_required_value = False is_reboot_required_value = constants.RebootRequired.false else: message = utils.find_xml(doc, 'Message', uris.DCIM_RAIDService).text raise exceptions.DRACOperationFailed( drac_messages=message) return utils.build_return_dict( doc, uris.DCIM_RAIDService, is_commit_required_value=is_commit_required_value, is_reboot_required_value=is_reboot_required_value)
def change_physical_disk_state(self, mode, controllers_to_physical_disk_ids=None): """Convert disks RAID status This method intelligently converts the requested physical disks from RAID to JBOD or vice versa. It does this by only converting the disks that are not already in the correct state. :param mode: constants.RaidStatus enumeration that indicates the mode to change the disks to. :param controllers_to_physical_disk_ids: Dictionary of controllers and corresponding disk ids to convert to the requested mode. :returns: a dictionary containing: - conversion_results, a dictionary that maps controller ids to the conversion results for that controller. The conversion results are a dict that contains: - The is_commit_required key with the value always set to True indicating that a config job must be created to complete disk conversion. - The is_reboot_required key with a RebootRequired enumerated value indicating whether the server must be rebooted to complete disk conversion. Also contained in the main dict are the following key/values, which are deprecated, should not be used, and will be removed in a future release: - is_reboot_required, a boolean stating whether a reboot is required or not. - commit_required_ids, a list of controller ids that will need to commit their pending RAID changes via a config job. :raises: DRACOperationFailed on error reported back by the DRAC and the exception message does not contain NOT_SUPPORTED_MSG constant. :raises: Exception on unknown error. """ physical_disks = self.list_physical_disks() raid = constants.RaidStatus.raid if not controllers_to_physical_disk_ids: controllers_to_physical_disk_ids = collections.defaultdict(list) all_controllers = self.list_raid_controllers() for physical_d in physical_disks: # Weed out disks that are not attached to a RAID controller if self.is_raid_controller(physical_d.controller, all_controllers): physical_disk_ids = controllers_to_physical_disk_ids[ physical_d.controller] physical_disk_ids.append(physical_d.id) '''Modify controllers_to_physical_disk_ids dict by inspecting desired status vs current status of each controller's disks. Raise exception if there are any failed drives or drives not in status 'ready' or 'non-RAID' ''' final_ctls_to_phys_disk_ids = self._check_disks_status( mode, physical_disks, controllers_to_physical_disk_ids) is_reboot_required = False controllers = [] controllers_to_results = {} for controller, physical_disk_ids \ in final_ctls_to_phys_disk_ids.items(): if physical_disk_ids: LOG.debug("Converting the following disks to {} on RAID " "controller {}: {}".format(mode, controller, str(physical_disk_ids))) try: conversion_results = \ self.convert_physical_disks(physical_disk_ids, mode == raid) except exceptions.DRACOperationFailed as ex: if constants.NOT_SUPPORTED_MSG in str(ex): LOG.debug("Controller {} does not support " "JBOD mode".format(controller)) controllers_to_results[controller] = \ utils.build_return_dict( doc=None, resource_uri=None, is_commit_required_value=False, is_reboot_required_value=constants. RebootRequired.false) else: raise else: controllers_to_results[controller] = conversion_results # Remove the code below when is_reboot_required and # commit_required_ids are deprecated reboot_true = constants.RebootRequired.true reboot_optional = constants.RebootRequired.optional _is_reboot_required = \ conversion_results["is_reboot_required"] is_reboot_required = is_reboot_required \ or (_is_reboot_required in [reboot_true, reboot_optional]) controllers.append(controller) else: controllers_to_results[controller] = \ utils.build_return_dict( doc=None, resource_uri=None, is_commit_required_value=False, is_reboot_required_value=constants. RebootRequired.false) return { 'conversion_results': controllers_to_results, 'is_reboot_required': is_reboot_required, 'commit_required_ids': controllers }
def create_virtual_disk(self, raid_controller, physical_disks, raid_level, size_mb, disk_name=None, span_length=None, span_depth=None): """Creates a virtual disk The created virtual disk will be in pending state. For the changes to be applied, a config job must be created and the node must be rebooted. :param raid_controller: id of the RAID controller :param physical_disks: ids of the physical disks :param raid_level: RAID level of the virtual disk :param size_mb: size of the virtual disk in megabytes :param disk_name: name of the virtual disk (optional) :param span_length: number of disks per span (optional) :param span_depth: number of spans in virtual disk (optional) :returns: a dictionary containing: - The is_commit_required key with the value always set to True indicating that a config job must be created to complete virtual disk creation. - The is_reboot_required key with a RebootRequired enumerated value indicating whether the server must be rebooted to complete virtual disk creation. :raises: WSManRequestFailure on request failures :raises: WSManInvalidResponse when receiving invalid response :raises: DRACOperationFailed on error reported back by the DRAC interface :raises: DRACUnexpectedReturnValue on return value mismatch :raises: InvalidParameterValue on invalid input parameter """ virtual_disk_prop_names = [] virtual_disk_prop_values = [] error_msgs = [] # RAID controller validation if not raid_controller: error_msgs.append("'raid_controller' is not supplied") # physical disks validation if not physical_disks: error_msgs.append("'physical_disks' is not supplied") # size validation utils.validate_integer_value(size_mb, 'size_mb', error_msgs) virtual_disk_prop_names.append('Size') virtual_disk_prop_values.append(str(size_mb)) # RAID level validation virtual_disk_prop_names.append('RAIDLevel') try: virtual_disk_prop_values.append(RAID_LEVELS[str(raid_level)]) except KeyError: error_msgs.append("'raid_level' is invalid") if disk_name is not None: virtual_disk_prop_names.append('VirtualDiskName') virtual_disk_prop_values.append(disk_name) if span_depth is not None: utils.validate_integer_value(span_depth, 'span_depth', error_msgs) virtual_disk_prop_names.append('SpanDepth') virtual_disk_prop_values.append(str(span_depth)) if span_length is not None: utils.validate_integer_value(span_length, 'span_length', error_msgs) virtual_disk_prop_names.append('SpanLength') virtual_disk_prop_values.append(str(span_length)) if error_msgs: msg = ('The following errors were encountered while parsing ' 'the provided parameters: %r') % ','.join(error_msgs) raise exceptions.InvalidParameterValue(reason=msg) selectors = { 'SystemCreationClassName': 'DCIM_ComputerSystem', 'CreationClassName': 'DCIM_RAIDService', 'SystemName': 'DCIM:ComputerSystem', 'Name': 'DCIM:RAIDService' } properties = { 'Target': raid_controller, 'PDArray': physical_disks, 'VDPropNameArray': virtual_disk_prop_names, 'VDPropValueArray': virtual_disk_prop_values } doc = self.client.invoke(uris.DCIM_RAIDService, 'CreateVirtualDisk', selectors, properties, expected_return_value=utils.RET_SUCCESS) return utils.build_return_dict(doc, uris.DCIM_RAIDService, is_commit_required_value=True)