def create_configuration(raid_config): """Create a RAID configuration on this server. This method creates the given RAID configuration on the server based on the input passed. :param raid_config: The dictionary containing the requested RAID configuration. This data structure should be as follows: raid_config = {'logical_disks': [{'raid_level': 1, 'size_gb': 100}, <info-for-logical-disk-2> ]} :raises exception.InvalidInputError, if input is invalid. """ validate(raid_config) server = objects.Server() logical_disks_sorted = sorted(raid_config['logical_disks'], cmp=_compare_logical_disks) for logical_disk in logical_disks_sorted: if 'physical_disks' not in logical_disk: # TODO(rameshg87): hpssa module should be capable of finding # the suitable controller and physical disks if it not provided # by using hints. This is a supported use-case, but not implemented # as of now. Will be implemented soon. # _find_physical_disks(logical_disk, server) msg = ("Mentioning logical_disks without 'controller' and " "'physical_disks' is not supported as of now.") raise exception.InvalidInputError(reason=msg) controller_id = logical_disk['controller'] controller = server.get_controller_by_id(controller_id) if not controller: msg = ("Unable to find controller named '%s'" % controller_id) raise exception.InvalidInputError(reason=msg) for physical_disk in logical_disk['physical_disks']: disk_obj = controller.get_physical_drive_by_id(physical_disk) if not disk_obj: msg = ("Unable to find physical disk '%(physical_disk)s' " "on '%(controller)s'" % { 'physical_disk': physical_disk, 'controller': controller_id }) raise exception.InvalidInputError(reason=msg) physical_drive_ids = logical_disk['physical_disks'] controller.create_logical_drive(logical_disk, physical_drive_ids) server.refresh()
def push_power_button(self, target_value): """Reset the system in hpe exclusive manner. :param target_value: The target value to be set. :raises: InvalidInputError, if the target value is not allowed. :raises: SushyError, on an error from iLO. """ if target_value not in mappings.PUSH_POWER_BUTTON_VALUE_MAP_REV: msg = ('The parameter "%(parameter)s" value "%(target_value)s" is ' 'invalid. Valid values are: %(valid_power_values)s' % { 'parameter': 'target_value', 'target_value': target_value, 'valid_power_values': (mappings.PUSH_POWER_BUTTON_VALUE_MAP_REV.keys()) }) raise exception.InvalidInputError(msg) value = mappings.PUSH_POWER_BUTTON_VALUE_MAP_REV[target_value] target_uri = ( self._get_hpe_push_power_button_action_element().target_uri) self._conn.post(target_uri, data={'PushType': value})
def extract(self): """Extracts the raw firmware file from its compact format Extracts the raw firmware file from its compact file format (already set as attribute in FirmwareImageControllerBase constructor). :raises: InvalidInputError, if raw firmware file not found :raises: ImageExtractionFailed, for extraction related issues :returns: the raw firmware file with the complete path :returns: boolean(True) to indicate that a new file got generated after successful extraction. """ target_file = self.fw_file common.add_exec_permission_to(target_file) # create a temp directory where the extraction will occur temp_dir = tempfile.mkdtemp() extract_path = os.path.join(temp_dir, self.fw_filename) try: self._do_extract(target_file, extract_path) except exception.ImageExtractionFailed: # clean up the partial extracted content, if any, # along with temp dir and re-raise the exception shutil.rmtree(temp_dir, ignore_errors=True) raise # creating a new hard link to the core firmware file firmware_file_path = _get_firmware_file_in_new_path(extract_path) # delete the entire extracted content along with temp dir. shutil.rmtree(temp_dir, ignore_errors=True) if not firmware_file_path: raise exception.InvalidInputError( "Raw firmware file not found in: '%s'" % target_file) return firmware_file_path, True
def validate(raid_config): """Validates the RAID configuration provided. This method validates the RAID configuration provided against a JSON schema. :param raid_config: The RAID configuration to be validated. :raises: InvalidInputError, if validation of the input fails. """ raid_schema_fobj = open(RAID_CONFIG_SCHEMA, 'r') raid_config_schema = json.load(raid_schema_fobj) try: jsonschema.validate(raid_config, raid_config_schema) except json_schema_exc.ValidationError as e: raise exception.InvalidInputError(e.message) for logical_disk in raid_config['logical_disks']: # If user has provided 'number_of_physical_disks' or # 'physical_disks', validate that they have mentioned at least # minimum number of physical disks required for that RAID level. raid_level = logical_disk['raid_level'] min_disks_reqd = constants.RAID_LEVEL_MIN_DISKS[raid_level] no_of_disks_specified = None if 'number_of_physical_disks' in logical_disk: no_of_disks_specified = logical_disk['number_of_physical_disks'] elif 'physical_disks' in logical_disk: no_of_disks_specified = len(logical_disk['physical_disks']) if (no_of_disks_specified and no_of_disks_specified < min_disks_reqd): msg = ("RAID level %(raid_level)s requires at least %(number)s " "disks." % { 'raid_level': raid_level, 'number': min_disks_reqd }) raise exception.InvalidInputError(msg)
def _get_hash_object(hash_algo_name): """Create a hash object based on given algorithm. :param hash_algo_name: name of the hashing algorithm. :raises: InvalidInputError, on unsupported or invalid input. :returns: a hash object based on the given named algorithm. """ algorithms = (hashlib.algorithms_guaranteed if six.PY3 else hashlib.algorithms) if hash_algo_name not in algorithms: msg = ("Unsupported/Invalid hash name '%s' provided." % hash_algo_name) raise exception.InvalidInputError(msg) return getattr(hashlib, hash_algo_name)()
def validate(raid_config): """Validates the RAID configuration provided. This method validates the RAID configuration provided against a JSON schema. :param raid_config: The RAID configuration to be validated. :raises: InvalidInputError, if validation of the input fails. """ raid_schema_fobj = open(RAID_CONFIG_SCHEMA, 'r') raid_config_schema = json.load(raid_schema_fobj) try: jsonschema.validate(raid_config, raid_config_schema) except json_schema_exc.ValidationError as e: raise exception.InvalidInputError(e.message)
def wrapper(self, filename, component_type): """Wrapper around ``update_firmware`` call. :param filename: location of the raw firmware file. :param component_type: Type of component to be applied to. """ component_type = component_type and component_type.lower() if (component_type not in SUPPORTED_FIRMWARE_UPDATE_COMPONENTS): msg = ("Got invalid component type for firmware update: " "``update_firmware`` is not supported on %(component)s" % { 'component': component_type }) LOG.error(self._(msg)) # noqa raise exception.InvalidInputError(msg) return func(self, filename, component_type)
def enable_secure_boot(self, secure_boot_enable): """Enable/Disable secure boot on the server. Caller needs to reset the server after issuing this command to bring this into effect. :param secure_boot_enable: True, if secure boot needs to be enabled for next boot, else False. :raises: InvalidInputError, if the validation of the input fails :raises: SushyError, on an error from iLO. """ if not isinstance(secure_boot_enable, bool): msg = ('The parameter "%(parameter)s" value "%(value)s" is ' 'invalid. Valid values are: True/False.' % { 'parameter': 'secure_boot_enable', 'value': secure_boot_enable }) raise exception.InvalidInputError(msg) self._conn.patch(self.path, data={'SecureBootEnable': secure_boot_enable})
def reset_keys(self, target_value): """Resets the secure boot keys. :param target_value: The target value to be set. :raises: InvalidInputError, if the target value is not allowed. :raises: SushyError, on an error from iLO. """ valid_keys_resets = self.get_allowed_reset_keys_values() if target_value not in valid_keys_resets: msg = ('The parameter "%(parameter)s" value "%(target_value)s" is ' 'invalid. Valid values are: %(valid_keys_reset_values)s' % { 'parameter': 'target_value', 'target_value': target_value, 'valid_keys_reset_values': valid_keys_resets }) raise exception.InvalidInputError(msg) value = mappings.SECUREBOOT_RESET_KEYS_MAP_REV[target_value] target_uri = (self._get_reset_keys_action_element().target_uri) self._conn.post(target_uri, data={'ResetKeysType': value})
def get_fw_extractor(fw_file): """Gets the firmware extractor object fine-tuned for specified type :param fw_file: compact firmware file to be extracted from :raises: InvalidInputError, for unsupported file types :returns: FirmwareImageExtractor object """ fw_img_extractor = FirmwareImageExtractor(fw_file) extension = fw_img_extractor.fw_file_ext.lower() if extension == '.scexe': # assign _do_extract attribute to refer to _extract_scexe_file fw_img_extractor._do_extract = types.MethodType( _extract_scexe_file, fw_img_extractor) elif extension == '.rpm': # assign _do_extract attribute to refer to _extract_rpm_file fw_img_extractor._do_extract = types.MethodType( _extract_rpm_file, fw_img_extractor) elif extension in RAW_FIRMWARE_EXTNS: # Note(deray): Assigning ``extract`` attribute to return # 1. the firmware file itself # 2. boolean (False) to indicate firmware file is not extracted def dummy_extract(self): """Dummy (no-op) extract method :returns: the same firmware file with the complete path :returns: boolean(False) to indicate that a new file is not generated. """ return fw_img_extractor.fw_file, False fw_img_extractor.extract = types.MethodType(dummy_extract, fw_img_extractor) else: raise exception.InvalidInputError( 'Unexpected compact firmware file type: %s' % fw_file) return fw_img_extractor
def create_configuration(raid_config): """Create a RAID configuration on this server. This method creates the given RAID configuration on the server based on the input passed. :param raid_config: The dictionary containing the requested RAID configuration. This data structure should be as follows: raid_config = {'logical_disks': [{'raid_level': 1, 'size_gb': 100}, <info-for-logical-disk-2> ]} :returns: the current raid configuration. This is same as raid_config with some extra properties like root_device_hint, volume_name, controller, physical_disks, etc filled for each logical disk after its creation. :raises exception.InvalidInputError, if input is invalid. :raises exception.HPSSAOperationError, if all the controllers are in HBA mode. """ server = objects.Server() select_controllers = lambda x: not x.properties.get( 'HBA Mode Enabled', False) _select_controllers_by(server, select_controllers, 'RAID enabled') validate(raid_config) # Make sure we create the large disks first. This is avoid the # situation that we avoid giving large disks to smaller requests. # For example, consider this: # - two logical disks - LD1(50), LD(100) # - have 4 physical disks - PD1(50), PD2(50), PD3(100), PD4(100) # # In this case, for RAID1 configuration, if we were to consider # LD1 first and allocate PD3 and PD4 for it, then allocation would # fail. So follow a particular order for allocation. # # Also make sure we create the MAX logical_disks the last to make sure # we allot only the remaining space available. logical_disks_sorted = ( sorted( (x for x in raid_config['logical_disks'] if x['size_gb'] != "MAX"), reverse=True, key=lambda x: x['size_gb']) + [x for x in raid_config['logical_disks'] if x['size_gb'] == "MAX"]) if any(logical_disk['share_physical_disks'] for logical_disk in logical_disks_sorted if 'share_physical_disks' in logical_disk): logical_disks_sorted = _sort_shared_logical_disks(logical_disks_sorted) # We figure out the new disk created by recording the wwns # before and after the create, and then figuring out the # newly found wwn from it. wwns_before_create = set([x.wwn for x in server.get_logical_drives()]) for logical_disk in logical_disks_sorted: if 'physical_disks' not in logical_disk: disk_allocator.allocate_disks(logical_disk, server, raid_config) controller_id = logical_disk['controller'] controller = server.get_controller_by_id(controller_id) if not controller: msg = ( "Unable to find controller named '%(controller)s'." " The available controllers are '%(ctrl_list)s'." % { 'controller': controller_id, 'ctrl_list': ', '.join([c.id for c in server.controllers]) }) raise exception.InvalidInputError(reason=msg) if 'physical_disks' in logical_disk: for physical_disk in logical_disk['physical_disks']: disk_obj = controller.get_physical_drive_by_id(physical_disk) if not disk_obj: msg = ("Unable to find physical disk '%(physical_disk)s' " "on '%(controller)s'" % { 'physical_disk': physical_disk, 'controller': controller_id }) raise exception.InvalidInputError(msg) controller.create_logical_drive(logical_disk) # Now find the new logical drive created. server.refresh() wwns_after_create = set([x.wwn for x in server.get_logical_drives()]) new_wwn = wwns_after_create - wwns_before_create if not new_wwn: reason = ("Newly created logical disk with raid_level " "'%(raid_level)s' and size %(size_gb)s GB not " "found." % { 'raid_level': logical_disk['raid_level'], 'size_gb': logical_disk['size_gb'] }) raise exception.HPSSAOperationError(reason=reason) new_logical_disk = server.get_logical_drive_by_wwn(new_wwn.pop()) new_log_drive_properties = new_logical_disk.get_logical_drive_dict() logical_disk.update(new_log_drive_properties) wwns_before_create = wwns_after_create.copy() _update_physical_disk_details(raid_config, server) return raid_config
def raising_invalid_input_error_exc_with(msg, **kwargs): raise exception.InvalidInputError(msg, **kwargs)