def _resume_cleaning(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)
def _test_update_raid_info(self, current_config, capabilities=None): node = self.node if capabilities: properties = node.properties properties['capabilities'] = capabilities del properties['local_gb'] node.properties = properties target_raid_config = json.loads(raid_constants.RAID_CONFIG_OKAY) node.target_raid_config = target_raid_config node.save() raid.update_raid_info(node, current_config) properties = node.properties current = node.raid_config target = node.target_raid_config self.assertIsNotNone(current['last_updated']) self.assertIsInstance(current['logical_disks'][0], dict) if current_config['logical_disks'][0].get('is_root_volume'): self.assertEqual({'wwn': '600508B100'}, properties['root_device']) self.assertEqual(100, properties['local_gb']) self.assertIn('raid_level:1', properties['capabilities']) if capabilities: self.assertIn(capabilities, properties['capabilities']) else: self.assertNotIn('local_gb', properties) self.assertNotIn('root_device', properties) if capabilities: self.assertNotIn('raid_level:1', properties['capabilities']) # Verify node.target_raid_config is preserved. self.assertEqual(target_raid_config, target)
def _test_update_raid_info(self, current_config, capabilities=None): node = obj_utils.create_test_node(self.context, driver='fake') if capabilities: properties = node.properties properties['capabilities'] = capabilities del properties['local_gb'] node.properties = properties node.save() raid.update_raid_info(node, current_config) properties = node.properties current = node.raid_config target = node.target_raid_config self.assertIsNotNone(current['last_updated']) self.assertIsInstance(current['logical_disks'][0], dict) if current_config['logical_disks'][0].get('is_root_volume'): self.assertEqual({'wwn': '600508B100'}, properties['root_device']) self.assertEqual(100, properties['local_gb']) self.assertIn('raid_level:1', properties['capabilities']) if capabilities: self.assertIn(capabilities, properties['capabilities']) else: self.assertNotIn('local_gb', properties) self.assertNotIn('root_device', properties) if capabilities: self.assertNotIn('raid_level:1', properties['capabilities']) self.assertEqual({}, target)
def _commit_raid_config(task): """Perform to commit RAID config into node.""" node = task.node node_uuid = task.node.uuid raid_config = {'logical_disks': []} raid_adapter = _get_raid_adapter(node) raid_adapter_info = raid_adapter['Server']['HWConfigurationIrmc'][ 'Adapters']['RAIDAdapter'][0] controller = raid_adapter_info['@AdapterId'] raid_config['logical_disks'].append({'controller': controller}) logical_drives = raid_adapter_info['LogicalDrives']['LogicalDrive'] for logical_drive in logical_drives: raid_config['logical_disks'].append({'irmc_raid_info': { 'logical_drive_number': logical_drive['@Number'], 'raid_level': logical_drive['RaidLevel'], 'name': logical_drive['Name'], ' size': logical_drive['Size']}}) for physical_drive in \ raid_adapter_info['PhysicalDisks']['PhysicalDisk']: raid_config['logical_disks'].append({'physical_drives': { 'physical_drive': physical_drive}}) node.raid_config = raid_config raid_common.update_raid_info(node, node.raid_config) LOG.info('RAID config is created successfully on node %s', node_uuid) return states.CLEANWAIT
def _create_configuration_final(task, command): """Clean step hook after a RAID configuration was created. This method is invoked as a post clean step hook by the Ironic conductor once a create raid configuration is completed successfully. The node (properties, capabilities, RAID information) will be updated to reflect the actual RAID configuration that was created. :param task: a TaskManager instance. :param command: A command result structure of the RAID operation returned from agent ramdisk on query of the status of command(s). :raises: InvalidParameterValue, if 'current_raid_config' has more than one root volume or if node.properties['capabilities'] is malformed. :raises: IronicException, if clean_result couldn't be found within the 'command' argument passed. """ try: clean_result = command['command_result']['clean_result'] except KeyError: raise exception.IronicException( _("Agent ramdisk didn't return a proper command result while " "cleaning %(node)s. It returned '%(result)s' after command " "execution.") % {'node': task.node.uuid, 'result': command}) raid.update_raid_info(task.node, clean_result)
def _test_update_raid_info(self, current_config, capabilities=None): node = obj_utils.create_test_node(self.context, driver="fake") if capabilities: properties = node.properties properties["capabilities"] = capabilities del properties["local_gb"] node.properties = properties target_raid_config = json.loads(raid_constants.RAID_CONFIG_OKAY) node.target_raid_config = target_raid_config node.save() raid.update_raid_info(node, current_config) properties = node.properties current = node.raid_config target = node.target_raid_config self.assertIsNotNone(current["last_updated"]) self.assertIsInstance(current["logical_disks"][0], dict) if current_config["logical_disks"][0].get("is_root_volume"): self.assertEqual({"wwn": "600508B100"}, properties["root_device"]) self.assertEqual(100, properties["local_gb"]) self.assertIn("raid_level:1", properties["capabilities"]) if capabilities: self.assertIn(capabilities, properties["capabilities"]) else: self.assertNotIn("local_gb", properties) self.assertNotIn("root_device", properties) if capabilities: self.assertNotIn("raid_level:1", properties["capabilities"]) # Verify node.target_raid_config is preserved. self.assertEqual(target_raid_config, target)
def _create_configuration_final(task, command): """Clean step hook after a RAID configuration was created. This method is invoked as a post clean step hook by the Ironic conductor once a create raid configuration is completed successfully. The node (properties, capabilities, RAID information) will be updated to reflect the actual RAID configuration that was created. :param task: a TaskManager instance. :param command: A command result structure of the RAID operation returned from agent ramdisk on query of the status of command(s). :raises: InvalidParameterValue, if 'current_raid_config' has more than one root volume or if node.properties['capabilities'] is malformed. :raises: IronicException, if clean_result couldn't be found within the 'command' argument passed. """ try: clean_result = command['command_result']['clean_result'] except KeyError: raise exception.IronicException( _("Agent ramdisk didn't return a proper command result while " "cleaning %(node)s. It returned '%(result)s' after command " "execution.") % { 'node': task.node.uuid, 'result': command }) raid.update_raid_info(task.node, clean_result)
def _resume_cleaning(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)
def _commit_raid_config(task): """Perform to commit RAID config into node.""" node = task.node node_uuid = task.node.uuid raid_config = {'logical_disks': []} raid_adapter = _get_raid_adapter(node) raid_adapter_info = raid_adapter['Server']['HWConfigurationIrmc'][ 'Adapters']['RAIDAdapter'][0] controller = raid_adapter_info['@AdapterId'] raid_config['logical_disks'].append({'controller': controller}) logical_drives = raid_adapter_info['LogicalDrives']['LogicalDrive'] for logical_drive in logical_drives: raid_config['logical_disks'].append({ 'irmc_raid_info': { 'logical_drive_number': logical_drive['@Number'], 'raid_level': logical_drive['RaidLevel'], 'name': logical_drive['Name'], ' size': logical_drive['Size'] } }) for physical_drive in \ raid_adapter_info['PhysicalDisks']['PhysicalDisk']: raid_config['logical_disks'].append( {'physical_drives': { 'physical_drive': physical_drive }}) node.raid_config = raid_config raid_common.update_raid_info(node, node.raid_config) LOG.info('RAID config is created successfully on node %s', node_uuid) return states.CLEANWAIT
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)
def _resume_cleaning(self, task): raid_common.update_raid_info( task.node, self.get_logical_disks(task)) agent_base_vendor._notify_conductor_resume_clean(task)
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 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 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 states.CLEANWAIT else: # Raid configuration is done, updating raid_config raid_conf = ( ilo_object.read_raid_configuration( raid_config=target_raid_config)) 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}) self._pop_driver_internal_values( task, 'ilo_raid_create_in_progress', 'cleaning_reboot', 'skip_current_clean_step') node.driver_internal_info = driver_internal_info node.save() else: # Raid configuration failed msg = "Unable to create raid" self._pop_driver_internal_values( task, 'ilo_raid_create_in_progress', 'cleaning_reboot', 'skip_current_clean_step') node.driver_internal_info = driver_internal_info node.save() raise exception.NodeCleaningFailure( "Clean step create_configuration failed " "on node %(node)s with error: %(err)s" % {'node': node.uuid, 'err': msg}) except ilo_error.IloError as ilo_exception: operation = (_("Failed to create raid configuration on node %s") % node.uuid) self._pop_driver_internal_values(task, 'ilo_raid_create_in_progress', 'cleaning_reboot', 'skip_current_clean_step') node.driver_internal_info = driver_internal_info node.save() self._set_clean_failed(task, operation, ilo_exception)
def _resume_cleaning(self, task): raid_common.update_raid_info(task.node, task.node.raid_config) manager_utils.notify_conductor_resume_clean(task)
def _query_raid_config_fgi_status(self, manager, context): """Periodic tasks to check the progress of running RAID config.""" filters = {'reserved': False, 'provision_state': states.CLEANWAIT, 'maintenance': False} fields = ['raid_config'] node_list = manager.iter_nodes(fields=fields, filters=filters) for (node_uuid, driver, conductor_group, raid_config) in node_list: try: lock_purpose = 'checking async RAID configuration tasks' with task_manager.acquire(context, node_uuid, purpose=lock_purpose, shared=True) as task: node = task.node node_uuid = task.node.uuid if not isinstance(task.driver.raid, IRMCRAID): continue if task.node.target_raid_config is None: continue if not raid_config or raid_config.get('fgi_status'): continue task.upgrade_lock() if node.provision_state != states.CLEANWAIT: continue # Avoid hitting clean_callback_timeout expiration node.touch_provisioning() try: report = irmc_common.get_irmc_report(node) except client.scci.SCCIInvalidInputError: raid_config.update({'fgi_status': RAID_FAILED}) raid_common.update_raid_info(node, raid_config) self._set_clean_failed(task, RAID_FAILED) continue except client.scci.SCCIClientError: raid_config.update({'fgi_status': RAID_FAILED}) raid_common.update_raid_info(node, raid_config) self._set_clean_failed(task, RAID_FAILED) continue fgi_status_dict = _get_fgi_status(report, node_uuid) # Note(trungnv): Allow to check until RAID mechanism to be # completed with RAID information in report. if fgi_status_dict == 'completing': continue if not fgi_status_dict: raid_config.update({'fgi_status': RAID_FAILED}) raid_common.update_raid_info(node, raid_config) self._set_clean_failed(task, fgi_status_dict) continue if all(fgi_status == 'Idle' for fgi_status in fgi_status_dict.values()): raid_config.update({'fgi_status': RAID_COMPLETED}) LOG.info('RAID configuration has completed on ' 'node %(node)s with fgi_status is %(fgi)s', {'node': node_uuid, 'fgi': RAID_COMPLETED}) self._resume_cleaning(task) except exception.NodeNotFound: LOG.info('During query_raid_config_job_status, node ' '%(node)s was not found raid_config and presumed ' 'deleted by another process.', {'node': node_uuid}) except exception.NodeLocked: LOG.info('During query_raid_config_job_status, node ' '%(node)s was already locked by another process. ' 'Skip.', {'node': node_uuid})
def _resume_cleaning(self, task): raid_common.update_raid_info(task.node, self.get_logical_disks(task)) agent_base_vendor._notify_conductor_resume_clean(task)
def _query_raid_config_fgi_status(self, manager, context): """Periodic tasks to check the progress of running RAID config.""" filters = { 'reserved': False, 'provision_state': states.CLEANWAIT, 'maintenance': False } fields = ['raid_config'] node_list = manager.iter_nodes(fields=fields, filters=filters) for (node_uuid, driver, conductor_group, raid_config) in node_list: try: lock_purpose = 'checking async RAID configuration tasks' with task_manager.acquire(context, node_uuid, purpose=lock_purpose, shared=True) as task: node = task.node node_uuid = task.node.uuid if not isinstance(task.driver.raid, IRMCRAID): continue if task.node.target_raid_config is None: continue if not raid_config or raid_config.get('fgi_status'): continue task.upgrade_lock() if node.provision_state != states.CLEANWAIT: continue # Avoid hitting clean_callback_timeout expiration node.touch_provisioning() try: report = irmc_common.get_irmc_report(node) except client.scci.SCCIInvalidInputError: raid_config.update({'fgi_status': RAID_FAILED}) raid_common.update_raid_info(node, raid_config) self._set_clean_failed(task, RAID_FAILED) continue except client.scci.SCCIClientError: raid_config.update({'fgi_status': RAID_FAILED}) raid_common.update_raid_info(node, raid_config) self._set_clean_failed(task, RAID_FAILED) continue fgi_status_dict = _get_fgi_status(report, node_uuid) # Note(trungnv): Allow to check until RAID mechanism to be # completed with RAID information in report. if fgi_status_dict == 'completing': continue if not fgi_status_dict: raid_config.update({'fgi_status': RAID_FAILED}) raid_common.update_raid_info(node, raid_config) self._set_clean_failed(task, fgi_status_dict) continue if all(fgi_status == 'Idle' for fgi_status in fgi_status_dict.values()): raid_config.update({'fgi_status': RAID_COMPLETED}) LOG.info( 'RAID configuration has completed on ' 'node %(node)s with fgi_status is %(fgi)s', { 'node': node_uuid, 'fgi': RAID_COMPLETED }) self._resume_cleaning(task) except exception.NodeNotFound: LOG.info( 'During query_raid_config_job_status, node ' '%(node)s was not found raid_config and presumed ' 'deleted by another process.', {'node': node_uuid}) except exception.NodeLocked: LOG.info( 'During query_raid_config_job_status, node ' '%(node)s was already locked by another process. ' 'Skip.', {'node': node_uuid})
def _resume_cleaning(self, task): raid_common.update_raid_info(task.node, self.get_logical_disks(task)) manager_utils.notify_conductor_resume_clean(task)