def _validate_volume_boot(self, task): """Validate information for volume boot with this interface. This interface requires physical information of connectors to configure remote boot to iRMC. Physical information of LAN ports is also required since VIOM feature manages all adapters. :param task: a TaskManager instance containing the node to act on. :raises: InvalidParameterValue: If invalid value is set to resources. :raises: MissingParameterValue: If some value is not set to resources. """ if not deploy_utils.get_remote_boot_volume(task): # No boot volume. Nothing to validate. return irmc_common.parse_driver_info(task.node) for port in task.ports: self._validate_lan_port(task.node, port) for vt in task.volume_targets: if vt.volume_type == 'iscsi': self._validate_iscsi_connectors(task) elif vt.volume_type == 'fibre_channel': self._validate_fc_connectors(task)
def test_parse_driver_info_missing_multiple_params(self): del self.node.driver_info['irmc_password'] del self.node.driver_info['irmc_address'] try: irmc_common.parse_driver_info(self.node) self.fail("parse_driver_info did not throw exception.") except exception.MissingParameterValue as e: self.assertIn('irmc_password', str(e)) self.assertIn('irmc_address', str(e))
def validate(self, task): """Validate the driver-specific inspection information. This method validates whether the 'driver_info' property of the supplied node contains the required information for this driver. :param task: a TaskManager instance containing the node to act on. :raises: InvalidParameterValue if required driver_info attribute is missing or invalid on the node. :raises: MissingParameterValue if a required parameter is missing. """ irmc_common.parse_driver_info(task.node)
def validate(self, task): """Validate the driver-specific management information. This method validates whether the 'driver_info' property of the supplied node contains the required information for this driver. :param task: A TaskManager instance containing the node to act on. :raises: InvalidParameterValue if required parameters are invalid. :raises: MissingParameterValue if a required parameter is missing. """ irmc_common.parse_driver_info(task.node) irmc_common.update_ipmi_properties(task) super(IRMCManagement, self).validate(task)
def apply_configuration(self, task, settings): """Applies BIOS configuration on the given node. This method takes the BIOS settings from the settings param and applies BIOS configuration on the given node. After the BIOS configuration is done, self.cache_bios_settings() may be called to sync the node's BIOS-related information with the BIOS configuration applied on the node. It will also validate the given settings before applying any settings and manage failures when setting an invalid BIOS config. In the case of needing password to update the BIOS config, it will be taken from the driver_info properties. :param task: a TaskManager instance. :param settings: Dictionary containing the BIOS configuration. It may be an empty dictionary as well. :raises: IRMCOperationError,if apply bios settings failed. """ irmc_info = irmc_common.parse_driver_info(task.node) try: LOG.info('Apply BIOS configuration for node %(node_uuid)s: ' '%(settings)s', {'settings': settings, 'node_uuid': task.node.uuid}) irmc.elcm.set_bios_configuration(irmc_info, settings) # NOTE(trungnv): Fix failed cleaning during rebooting node # when combine OOB and IB steps in manual clean. self._resume_cleaning(task) except irmc.scci.SCCIError as e: LOG.error('Failed to apply BIOS configuration on node ' '%(node_uuid)s. Error: %(error)s', {'node_uuid': task.node.uuid, 'error': e}) raise exception.IRMCOperationError( operation='Apply BIOS configuration', error=e)
def backup_bios_config(task): """Backup BIOS config from a node. :param task: a TaskManager instance containing the node to act on. :raises: IRMCOperationError on failure. """ node_uuid = task.node.uuid # Skip this operation if the clean step 'restore' is disabled if CONF.irmc.clean_priority_restore_irmc_bios_config == 0: LOG.debug('Skipped the operation backup_BIOS_config for node %s ' 'as the clean step restore_BIOS_config is disabled.', node_uuid) return irmc_info = irmc_common.parse_driver_info(task.node) try: # Backup bios config result = irmc.elcm.backup_bios_config(irmc_info) except irmc.scci.SCCIError as e: LOG.error('Failed to backup BIOS config for node %(node)s. ' 'Error: %(error)s', {'node': node_uuid, 'error': e}) raise exception.IRMCOperationError(operation='backup BIOS config', error=e) # Save bios config into the driver_internal_info internal_info = task.node.driver_internal_info internal_info['irmc_bios_config'] = result['bios_config'] task.node.driver_internal_info = internal_info task.node.save() LOG.info('BIOS config is backed up successfully for node %s', node_uuid)
def _configure_boot_from_volume(self, task): """Set information for booting from a remote volume to iRMC. :param task: a TaskManager instance containing the node to act on. :raises: IRMCOperationError if iRMC operation failed """ irmc_info = irmc_common.parse_driver_info(task.node) viom_conf = viom.VIOMConfiguration(irmc_info, identification=task.node.uuid) self._register_lan_ports(viom_conf, task) for vt in task.volume_targets: if vt.volume_type == 'iscsi': self._set_iscsi_target(task, viom_conf, vt) elif vt.volume_type == 'fibre_channel': self._set_fc_target(task, viom_conf, vt) try: LOG.debug('Set VIOM configuration for node %(node)s: %(table)s', {'node': task.node.uuid, 'table': viom_conf.dump_json()}) viom_conf.apply() except scci.SCCIError as e: LOG.error('iRMC failed to set VIOM configuration for node ' '%(node)s: %(error)s', {'node': task.node.uuid, 'error': e}) raise exception.IRMCOperationError( operation='Configure VIOM', error=e)
def cache_bios_settings(self, task): """Store or update BIOS settings on the given node. This method stores BIOS properties to the bios settings db :param task: a TaskManager instance. :raises: IRMCOperationError,if get bios settings failed. :returns: None if it is complete. """ irmc_info = irmc_common.parse_driver_info(task.node) node_id = task.node.id try: settings = irmc.elcm.get_bios_settings(irmc_info) except irmc.scci.SCCIError as e: LOG.error('Failed to retrieve the current BIOS settings for node ' '%(node)s. Error: %(error)s', {'node': task.node.uuid, 'error': e}) raise exception.IRMCOperationError(operation='Cache BIOS settings', error=e) create_list, update_list, delete_list, nochange_list = ( objects.BIOSSettingList.sync_node_setting(task.context, node_id, settings)) if len(create_list) > 0: objects.BIOSSettingList.create(task.context, node_id, create_list) if len(update_list) > 0: objects.BIOSSettingList.save(task.context, node_id, update_list) if len(delete_list) > 0: delete_names = [setting['name'] for setting in delete_list] objects.BIOSSettingList.delete(task.context, node_id, delete_names)
def test_parse_driver_option_default(self): self.node.driver_info = {"irmc_address": "1.2.3.4", "irmc_username": "******", "irmc_password": "******"} info = irmc_common.parse_driver_info(self.node) self.assertEqual("basic", info.get("irmc_auth_method")) self.assertEqual(443, info.get("irmc_port")) self.assertEqual(60, info.get("irmc_client_timeout")) self.assertEqual("ipmitool", info.get("irmc_sensor_method"))
def test_parse_driver_info(self): info = irmc_common.parse_driver_info(self.node) self.assertIsNotNone(info.get('irmc_address')) self.assertIsNotNone(info.get('irmc_username')) self.assertIsNotNone(info.get('irmc_password')) self.assertIsNotNone(info.get('irmc_client_timeout')) self.assertIsNotNone(info.get('irmc_port')) self.assertIsNotNone(info.get('irmc_auth_method'))
def test_parse_driver_info(self): info = irmc_common.parse_driver_info(self.node) self.assertIsNotNone(info.get("irmc_address")) self.assertIsNotNone(info.get("irmc_username")) self.assertIsNotNone(info.get("irmc_password")) self.assertIsNotNone(info.get("irmc_client_timeout")) self.assertIsNotNone(info.get("irmc_port")) self.assertIsNotNone(info.get("irmc_auth_method")) self.assertIsNotNone(info.get("irmc_sensor_method"))
def setUp(self): super(IRMCManagementTestCase, self).setUp() driver_info = INFO_DICT mgr_utils.mock_the_extension_manager(driver="fake_irmc") self.driver = driver_factory.get_driver("fake_irmc") self.node = obj_utils.create_test_node(self.context, driver='fake_irmc', driver_info=driver_info) self.info = irmc_common.parse_driver_info(self.node)
def test_set_secure_boot_mode_fail(self, mock_scci, mock_elcm): irmc_common.scci.SCCIError = Exception mock_elcm.set_secure_boot_mode.side_effect = Exception with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: self.assertRaises(exception.IRMCOperationError, irmc_common.set_secure_boot_mode, task.node, True) info = irmc_common.parse_driver_info(task.node) mock_elcm.set_secure_boot_mode.assert_called_once_with( info, True)
def _restore_bios_config(task): """Restore BIOS config to a node. :param task: a TaskManager instance containing the node to act on. :raises: IRMCOperationError if the operation fails. """ node_uuid = task.node.uuid # Get bios config stored in the node object bios_config = task.node.driver_internal_info.get('irmc_bios_config') if not bios_config: LOG.info('Skipped operation "restore BIOS config" on node %s ' 'as the backup data not found.', node_uuid) return def _remove_bios_config(task, reboot_flag=False): """Remove backup bios config from the node.""" internal_info = task.node.driver_internal_info internal_info.pop('irmc_bios_config', None) # NOTE(tiendc): If reboot flag is raised, then the BM will # reboot and cause a bug if the next clean step is in-band. # See https://storyboard.openstack.org/#!/story/2002731 if reboot_flag: internal_info['cleaning_reboot'] = True task.node.driver_internal_info = internal_info task.node.save() irmc_info = irmc_common.parse_driver_info(task.node) try: # Restore bios config irmc.elcm.restore_bios_config(irmc_info, bios_config) except irmc.scci.SCCIError as e: # If the input bios config is not correct or corrupted, then # we should remove it from the node object. if isinstance(e, irmc.scci.SCCIInvalidInputError): _remove_bios_config(task) LOG.error('Failed to restore BIOS config on node %(node)s. ' 'Error: %(error)s', {'node': node_uuid, 'error': e}) raise exception.IRMCOperationError(operation='restore BIOS config', error=e) # Remove the backup data after restoring _remove_bios_config(task, reboot_flag=True) LOG.info('BIOS config is restored successfully on node %s', node_uuid) # Change power state to ON as server is automatically # shutdown after the operation. manager_utils.node_power_action(task, states.POWER_ON)
def setUp(self): super(IRMCManagementFunctionsTestCase, self).setUp() driver_info = INFO_DICT mgr_utils.mock_the_extension_manager(driver="fake_irmc") self.driver = driver_factory.get_driver("fake_irmc") self.node = obj_utils.create_test_node(self.context, driver='fake_irmc', driver_info=driver_info) self.info = irmc_common.parse_driver_info(self.node) irmc_management.irmc.scci.SCCIError = Exception irmc_management.irmc.scci.SCCIInvalidInputError = ValueError
def get_sensors_data(self, task): """Get sensors data method. It gets sensor data from the task's node via SCCI, and convert the data from XML to the dict format. :param task: A TaskManager instance. :raises: FailedToGetSensorData when getting the sensor data fails. :raises: FailedToParseSensorData when parsing sensor data fails. :raises: InvalidParameterValue if required parameters are invalid. :raises: MissingParameterValue if a required parameter is missing. :returns: Returns a consistent formatted dict of sensor data grouped by sensor type, which can be processed by Ceilometer. Example:: { 'Sensor Type 1': { 'Sensor ID 1': { 'Sensor Reading': 'Value1 Units1', 'Sensor ID': 'Sensor ID 1', 'Units': 'Units1' }, 'Sensor ID 2': { 'Sensor Reading': 'Value2 Units2', 'Sensor ID': 'Sensor ID 2', 'Units': 'Units2' } }, 'Sensor Type 2': { 'Sensor ID 3': { 'Sensor Reading': 'Value3 Units3', 'Sensor ID': 'Sensor ID 3', 'Units': 'Units3' }, 'Sensor ID 4': { 'Sensor Reading': 'Value4 Units4', 'Sensor ID': 'Sensor ID 4', 'Units': 'Units4' } } } """ # irmc_common.parse_driver_info() makes sure that # d_info['irmc_sensor_method'] is either 'scci' or 'ipmitool'. d_info = irmc_common.parse_driver_info(task.node) sensor_method = d_info["irmc_sensor_method"] if sensor_method == "scci": return _get_sensors_data(task) elif sensor_method == "ipmitool": return super(IRMCManagement, self).get_sensors_data(task)
def test_parse_driver_info(self): info = irmc_common.parse_driver_info(self.node) self.assertEqual('1.2.3.4', info['irmc_address']) self.assertEqual('admin0', info['irmc_username']) self.assertEqual('fake0', info['irmc_password']) self.assertEqual(60, info['irmc_client_timeout']) self.assertEqual(80, info['irmc_port']) self.assertEqual('digest', info['irmc_auth_method']) self.assertEqual('ipmitool', info['irmc_sensor_method']) self.assertEqual('v2c', info['irmc_snmp_version']) self.assertEqual(161, info['irmc_snmp_port']) self.assertEqual('public', info['irmc_snmp_community']) self.assertFalse(info['irmc_snmp_security'])
def test_parse_driver_info(self): info = irmc_common.parse_driver_info(self.node) self.assertIsNotNone(info['irmc_address']) self.assertIsNotNone(info['irmc_username']) self.assertIsNotNone(info['irmc_password']) self.assertIsNotNone(info['irmc_client_timeout']) self.assertIsNotNone(info['irmc_port']) self.assertIsNotNone(info['irmc_auth_method']) self.assertIsNotNone(info['irmc_sensor_method']) self.assertIsNotNone(info['irmc_snmp_version']) self.assertIsNotNone(info['irmc_snmp_port']) self.assertIsNotNone(info['irmc_snmp_community']) self.assertFalse(info['irmc_snmp_security'])
def test_cache_bios_settings(self, get_bios_settings_mock, delete_mock, save_mock, create_mock, sync_node_setting_mock): settings = [{ "name": "launch_csm_enabled", "value": True }, { "name": "hyper_threading_enabled", "value": True }, { "name": "cpu_vt_enabled", "value": True }] with task_manager.acquire(self.context, self.node.uuid) as task: irmc_info = irmc_common.parse_driver_info(task.node) get_bios_settings_mock.return_value = settings sync_node_setting_mock.return_value = \ ( [ { "name": "launch_csm_enabled", "value": True }], [ { "name": "hyper_threading_enabled", "value": True }], [ { "name": "cpu_vt_enabled", "value": True }], [] ) task.driver.bios.cache_bios_settings(task) get_bios_settings_mock.assert_called_once_with(irmc_info) sync_node_setting_mock.assert_called_once_with( task.context, task.node.id, settings) create_mock.assert_called_once_with( task.context, task.node.id, sync_node_setting_mock.return_value[0]) save_mock.assert_called_once_with( task.context, task.node.id, sync_node_setting_mock.return_value[1]) delete_names = \ [setting['name'] for setting in sync_node_setting_mock.return_value[2]] delete_mock.assert_called_once_with(task.context, task.node.id, delete_names)
def test_parse_driver_info(self): info = irmc_common.parse_driver_info(self.node) self.assertEqual('1.2.3.4', info['irmc_address']) self.assertEqual('admin0', info['irmc_username']) self.assertEqual('fake0', info['irmc_password']) self.assertEqual(60, info['irmc_client_timeout']) self.assertEqual(80, info['irmc_port']) self.assertEqual('digest', info['irmc_auth_method']) self.assertEqual('ipmitool', info['irmc_sensor_method']) self.assertEqual('v2c', info['irmc_snmp_version']) self.assertEqual(161, info['irmc_snmp_port']) self.assertEqual('public', info['irmc_snmp_community']) self.assertFalse(info['irmc_snmp_security'])
def _restore_bios_config(task): """Restore BIOS config to a node. :param task: a TaskManager instance containing the node to act on. :raises: IRMCOperationError if the operation fails. """ node_uuid = task.node.uuid # Get bios config stored in the node object bios_config = task.node.driver_internal_info.get('irmc_bios_config') if not bios_config: LOG.info('Skipped operation "restore BIOS config" on node %s ' 'as the backup data not found.', node_uuid) return def _remove_bios_config(task): """Remove backup bios config from the node.""" internal_info = task.node.driver_internal_info internal_info.pop('irmc_bios_config', None) task.node.driver_internal_info = internal_info task.node.save() irmc_info = irmc_common.parse_driver_info(task.node) try: # Restore bios config irmc.elcm.restore_bios_config(irmc_info, bios_config) except irmc.scci.SCCIError as e: # If the input bios config is not correct or corrupted, then # we should remove it from the node object. if isinstance(e, irmc.scci.SCCIInvalidInputError): _remove_bios_config(task) LOG.error('Failed to restore BIOS config on node %(node)s. ' 'Error: %(error)s', {'node': node_uuid, 'error': e}) raise exception.IRMCOperationError(operation='restore BIOS config', error=e) # Remove the backup data after restoring _remove_bios_config(task) LOG.info('BIOS config is restored successfully on node %s', node_uuid) # Change power state to ON as server is automatically # shutdown after the operation. manager_utils.node_power_action(task, states.POWER_ON)
def _cleanup_boot_from_volume(self, task, reboot=False): """Clear remote boot configuration. :param task: a task from TaskManager. :param reboot: True if reboot node soon :raises: IRMCOperationError if iRMC operation failed """ irmc_info = irmc_common.parse_driver_info(task.node) try: viom_conf = viom.VIOMConfiguration(irmc_info, task.node.uuid) viom_conf.terminate(reboot=reboot) except scci.SCCIError as e: LOG.error('iRMC failed to terminate VIOM configuration from ' 'node %(node)s: %(error)s', {'node': task.node.uuid, 'error': e}) raise exception.IRMCOperationError(operation='Terminate VIOM', error=e)
def _cleanup_boot_from_volume(self, task, reboot=False): """Clear remote boot configuration. :param task: a task from TaskManager. :param reboot: True if reboot node soon :raises: IRMCOperationError if iRMC operation failed """ irmc_info = irmc_common.parse_driver_info(task.node) try: viom_conf = viom.VIOMConfiguration(irmc_info, task.node.uuid) viom_conf.terminate(reboot=reboot) except scci.SCCIError as e: LOG.error('iRMC failed to terminate VIOM configuration from ' 'node %(node)s: %(error)s', {'node': task.node.uuid, 'error': e}) raise exception.IRMCOperationError(operation='Terminate VIOM', error=e)
def _get_mac_addresses(node): """Get mac addresses of the node. :param node: node object. :raises: SNMPFailure if SNMP operation failed. :returns: a list of mac addresses. """ d_info = irmc_common.parse_driver_info(node) snmp_client = snmp.SNMPClient(d_info['irmc_address'], d_info['irmc_snmp_port'], d_info['irmc_snmp_version'], d_info['irmc_snmp_community'], d_info['irmc_snmp_security']) node_classes = snmp_client.get_next(NODE_CLASS_OID) mac_addresses = snmp_client.get_next(MAC_ADDRESS_OID) return [a for c, a in zip(node_classes, mac_addresses) if c == NODE_CLASS_OID_VALUE['primary']]
def test_apply_configuration(self, get_bios_settings_mock, set_bios_configuration_mock): settings = [{ "name": "launch_csm_enabled", "value": True }, { "name": "hyper_threading_enabled", "value": True }, { "name": "cpu_vt_enabled", "value": True }] with task_manager.acquire(self.context, self.node.uuid) as task: irmc_info = irmc_common.parse_driver_info(task.node) task.node.save = mock.Mock() get_bios_settings_mock.return_value = settings task.driver.bios.apply_configuration(task, settings) set_bios_configuration_mock.assert_called_once_with( irmc_info, settings)
def apply_configuration(self, task, settings): """Applies BIOS configuration on the given node. This method takes the BIOS settings from the settings param and applies BIOS configuration on the given node. After the BIOS configuration is done, self.cache_bios_settings() may be called to sync the node's BIOS-related information with the BIOS configuration applied on the node. It will also validate the given settings before applying any settings and manage failures when setting an invalid BIOS config. In the case of needing password to update the BIOS config, it will be taken from the driver_info properties. :param task: a TaskManager instance. :param settings: Dictionary containing the BIOS configuration. It may be an empty dictionary as well. :raises: IRMCOperationError,if apply bios settings failed. """ irmc_info = irmc_common.parse_driver_info(task.node) try: LOG.info( 'Apply BIOS configuration for node %(node_uuid)s: ' '%(settings)s', { 'settings': settings, 'node_uuid': task.node.uuid }) irmc.elcm.set_bios_configuration(irmc_info, settings) # NOTE(trungnv): Fix failed cleaning during rebooting node # when combine OOB and IB steps in manual clean. self._resume_cleaning(task) except irmc.scci.SCCIError as e: LOG.error( 'Failed to apply BIOS configuration on node ' '%(node_uuid)s. Error: %(error)s', { 'node_uuid': task.node.uuid, 'error': e }) raise exception.IRMCOperationError( operation='Apply BIOS configuration', error=e)
def _get_mac_addresses(node): """Get mac addresses of the node. :param node: node object. :raises: SNMPFailure if SNMP operation failed. :returns: a list of mac addresses. """ d_info = irmc_common.parse_driver_info(node) snmp_client = snmp.SNMPClient(d_info['irmc_address'], d_info['irmc_snmp_port'], d_info['irmc_snmp_version'], d_info['irmc_snmp_community'], d_info['irmc_snmp_security']) node_classes = snmp_client.get_next(NODE_CLASS_OID) mac_addresses = snmp_client.get_next(MAC_ADDRESS_OID) return [ a for c, a in zip(node_classes, mac_addresses) if c == NODE_CLASS_OID_VALUE['primary'] ]
def backup_bios_config(task): """Backup BIOS config from a node. :param task: a TaskManager instance containing the node to act on. :raises: IRMCOperationError on failure. """ node_uuid = task.node.uuid # Skip this operation if the clean step 'restore' is disabled if CONF.irmc.clean_priority_restore_irmc_bios_config == 0: LOG.debug( 'Skipped the operation backup_BIOS_config for node %s ' 'as the clean step restore_BIOS_config is disabled.', node_uuid) return irmc_info = irmc_common.parse_driver_info(task.node) try: # Backup bios config result = irmc.elcm.backup_bios_config(irmc_info) except irmc.scci.SCCIError as e: LOG.error( 'Failed to backup BIOS config for node %(node)s. ' 'Error: %(error)s', { 'node': node_uuid, 'error': e }) raise exception.IRMCOperationError(operation='backup BIOS config', error=e) # Save bios config into the driver_internal_info internal_info = task.node.driver_internal_info internal_info['irmc_bios_config'] = result['bios_config'] task.node.driver_internal_info = internal_info task.node.save() LOG.info('BIOS config is backed up successfully for node %s', node_uuid)
def _inspect_hardware(node, existing_traits=None, **kwargs): """Inspect the node and get hardware information. :param node: node object. :param existing_traits: existing traits list. :param kwargs: the dictionary of additional parameters. :raises: HardwareInspectionFailure, if unable to get essential hardware properties. :returns: a pair of dictionary and list, the dictionary contains keys as in IRMCInspect.ESSENTIAL_PROPERTIES and its inspected values, the list contains mac addresses. """ capabilities_props = set(CAPABILITIES_PROPERTIES) new_traits = list(existing_traits) if existing_traits else [] # Remove all capabilities item which will be inspected in the existing # capabilities of node if 'capabilities' in node.properties: existing_cap = node.properties['capabilities'].split(',') for item in capabilities_props: for prop in existing_cap: if item == prop.split(':')[0]: existing_cap.remove(prop) node.properties['capabilities'] = ",".join(existing_cap) # get gpu_ids, fpga_ids in ironic configuration gpu_ids = [gpu_id.lower() for gpu_id in CONF.irmc.gpu_ids] fpga_ids = [fpga_id.lower() for fpga_id in CONF.irmc.fpga_ids] # if gpu_ids = [], pci_gpu_devices will not be inspected if len(gpu_ids) == 0: capabilities_props.remove('pci_gpu_devices') # if fpga_ids = [], cpu_fpga will not be inspected if len(fpga_ids) == 0: capabilities_props.remove('cpu_fpga') try: report = irmc_common.get_irmc_report(node) props = scci.get_essential_properties(report, IRMCInspect.ESSENTIAL_PROPERTIES) d_info = irmc_common.parse_driver_info(node) capabilities = scci.get_capabilities_properties(d_info, capabilities_props, gpu_ids, fpga_ids=fpga_ids, **kwargs) if capabilities: if capabilities.get('pci_gpu_devices') == 0: capabilities.pop('pci_gpu_devices') cpu_fpga = capabilities.pop('cpu_fpga', 0) if cpu_fpga == 0 and 'CUSTOM_CPU_FPGA' in new_traits: new_traits.remove('CUSTOM_CPU_FPGA') elif cpu_fpga != 0 and 'CUSTOM_CPU_FPGA' not in new_traits: new_traits.append('CUSTOM_CPU_FPGA') if capabilities.get('trusted_boot') is False: capabilities.pop('trusted_boot') capabilities = utils.get_updated_capabilities( node.properties.get('capabilities'), capabilities) if capabilities: props['capabilities'] = capabilities macs = _get_mac_addresses(node) except (scci.SCCIInvalidInputError, scci.SCCIClientError, exception.SNMPFailure) as e: error = (_("Inspection failed for node %(node_id)s " "with the following error: %(error)s") % { 'node_id': node.uuid, 'error': e }) raise exception.HardwareInspectionFailure(error=error) return props, macs, new_traits
def setUp(self): super(IRMCManagementTestCase, self).setUp() self.info = irmc_common.parse_driver_info(self.node)
def _wait_power_state(task, target_state, timeout=None): """Wait for having changed to the target power state. :param task: A TaskManager instance containing the node to act on. :raises: IRMCOperationError if the target state acknowledge failed. :raises: SNMPFailure if SNMP request failed. """ node = task.node d_info = irmc_common.parse_driver_info(node) snmp_client = snmp.SNMPClient(d_info['irmc_address'], d_info['irmc_snmp_port'], d_info['irmc_snmp_version'], d_info['irmc_snmp_community'], d_info['irmc_snmp_security']) interval = CONF.irmc.snmp_polling_interval retry_timeout_soft = timeout or CONF.conductor.soft_power_off_timeout max_retry = int(retry_timeout_soft / interval) def _wait(mutable): mutable['boot_status_value'] = snmp_client.get(BOOT_STATUS_OID) LOG.debug( "iRMC SNMP agent of %(node_id)s returned " "boot status value %(bootstatus)s on attempt %(times)s.", { 'node_id': node.uuid, 'bootstatus': BOOT_STATUS[mutable['boot_status_value']], 'times': mutable['times'] }) if _is_expected_power_state(target_state, mutable['boot_status_value']): mutable['state'] = target_state raise loopingcall.LoopingCallDone() mutable['times'] += 1 if mutable['times'] > max_retry: mutable['state'] = states.ERROR raise loopingcall.LoopingCallDone() store = {'state': None, 'times': 0, 'boot_status_value': None} timer = loopingcall.FixedIntervalLoopingCall(_wait, store) timer.start(interval=interval).wait() if store['state'] == target_state: # iRMC acknowledged the target state node.last_error = None node.power_state = (states.POWER_OFF if target_state == states.SOFT_POWER_OFF else states.POWER_ON) node.target_power_state = states.NOSTATE node.save() LOG.info( 'iRMC successfully set node %(node_id)s ' 'power state to %(bootstatus)s.', { 'node_id': node.uuid, 'bootstatus': BOOT_STATUS[store['boot_status_value']] }) else: # iRMC failed to acknowledge the target state last_error = (_('iRMC returned unexpected boot status value %s') % BOOT_STATUS[store['boot_status_value']]) node.last_error = last_error node.power_state = states.ERROR node.target_power_state = states.NOSTATE node.save() LOG.error( 'iRMC failed to acknowledge the target state for node ' '%(node_id)s. Error: %(last_error)s', { 'node_id': node.uuid, 'last_error': last_error }) error = _('unexpected boot status value') raise exception.IRMCOperationError(operation=target_state, error=error)
def setUp(self): super(IRMCManagementFunctionsTestCase, self).setUp() self.info = irmc_common.parse_driver_info(self.node) irmc_management.irmc.scci.SCCIError = Exception irmc_management.irmc.scci.SCCIInvalidInputError = ValueError
def _wait_power_state(task, target_state, timeout=None): """Wait for having changed to the target power state. :param task: A TaskManager instance containing the node to act on. :raises: IRMCOperationError if the target state acknowledge failed. :raises: SNMPFailure if SNMP request failed. """ node = task.node d_info = irmc_common.parse_driver_info(node) snmp_client = snmp.SNMPClient(d_info['irmc_address'], d_info['irmc_snmp_port'], d_info['irmc_snmp_version'], d_info['irmc_snmp_community'], d_info['irmc_snmp_security']) interval = CONF.irmc.snmp_polling_interval retry_timeout_soft = timeout or CONF.conductor.soft_power_off_timeout max_retry = int(retry_timeout_soft / interval) def _wait(mutable): mutable['boot_status_value'] = snmp_client.get(BOOT_STATUS_OID) LOG.debug("iRMC SNMP agent of %(node_id)s returned " "boot status value %(bootstatus)s on attempt %(times)s.", {'node_id': node.uuid, 'bootstatus': BOOT_STATUS[mutable['boot_status_value']], 'times': mutable['times']}) if _is_expected_power_state(target_state, mutable['boot_status_value']): mutable['state'] = target_state raise loopingcall.LoopingCallDone() mutable['times'] += 1 if mutable['times'] > max_retry: mutable['state'] = states.ERROR raise loopingcall.LoopingCallDone() store = {'state': None, 'times': 0, 'boot_status_value': None} timer = loopingcall.FixedIntervalLoopingCall(_wait, store) timer.start(interval=interval).wait() if store['state'] == target_state: # iRMC acknowledged the target state node.last_error = None node.power_state = (states.POWER_OFF if target_state == states.SOFT_POWER_OFF else states.POWER_ON) node.target_power_state = states.NOSTATE node.save() LOG.info('iRMC successfully set node %(node_id)s ' 'power state to %(bootstatus)s.', {'node_id': node.uuid, 'bootstatus': BOOT_STATUS[store['boot_status_value']]}) else: # iRMC failed to acknowledge the target state last_error = (_('iRMC returned unexpected boot status value %s') % BOOT_STATUS[store['boot_status_value']]) node.last_error = last_error node.power_state = states.ERROR node.target_power_state = states.NOSTATE node.save() LOG.error('iRMC failed to acknowledge the target state for node ' '%(node_id)s. Error: %(last_error)s', {'node_id': node.uuid, 'last_error': last_error}) error = _('unexpected boot status value') raise exception.IRMCOperationError(operation=target_state, error=error)
def setUp(self): super(IRMCManagementTestCase, self).setUp() self.info = irmc_common.parse_driver_info(self.node)
def test_set_secure_boot_mode_disable(self, mock_elcm): mock_elcm.set_secure_boot_mode.return_value = 'set_secure_boot_mode' info = irmc_common.parse_driver_info(self.node) irmc_common.set_secure_boot_mode(self.node, False) mock_elcm.set_secure_boot_mode.assert_called_once_with(info, False)
def test_set_secure_boot_mode_disable(self, mock_elcm): mock_elcm.set_secure_boot_mode.return_value = 'set_secure_boot_mode' info = irmc_common.parse_driver_info(self.node) irmc_common.set_secure_boot_mode(self.node, False) mock_elcm.set_secure_boot_mode.assert_called_once_with( info, False)
def _inspect_hardware(node, existing_traits=None, **kwargs): """Inspect the node and get hardware information. :param node: node object. :param existing_traits: existing traits list. :param kwargs: the dictionary of additional parameters. :raises: HardwareInspectionFailure, if unable to get essential hardware properties. :returns: a pair of dictionary and list, the dictionary contains keys as in IRMCInspect.ESSENTIAL_PROPERTIES and its inspected values, the list contains mac addresses. """ capabilities_props = set(CAPABILITIES_PROPERTIES) new_traits = list(existing_traits) if existing_traits else [] # Remove all capabilities item which will be inspected in the existing # capabilities of node if 'capabilities' in node.properties: existing_cap = node.properties['capabilities'].split(',') for item in capabilities_props: for prop in existing_cap: if item == prop.split(':')[0]: existing_cap.remove(prop) node.properties['capabilities'] = ",".join(existing_cap) # get gpu_ids, fpga_ids in ironic configuration gpu_ids = [gpu_id.lower() for gpu_id in CONF.irmc.gpu_ids] fpga_ids = [fpga_id.lower() for fpga_id in CONF.irmc.fpga_ids] # if gpu_ids = [], pci_gpu_devices will not be inspected if len(gpu_ids) == 0: capabilities_props.remove('pci_gpu_devices') # if fpga_ids = [], cpu_fpga will not be inspected if len(fpga_ids) == 0: capabilities_props.remove('cpu_fpga') try: report = irmc_common.get_irmc_report(node) props = scci.get_essential_properties( report, IRMCInspect.ESSENTIAL_PROPERTIES) d_info = irmc_common.parse_driver_info(node) capabilities = scci.get_capabilities_properties( d_info, capabilities_props, gpu_ids, fpga_ids=fpga_ids, **kwargs) if capabilities: if capabilities.get('pci_gpu_devices') == 0: capabilities.pop('pci_gpu_devices') cpu_fpga = capabilities.pop('cpu_fpga', 0) if cpu_fpga == 0 and 'CUSTOM_CPU_FPGA' in new_traits: new_traits.remove('CUSTOM_CPU_FPGA') elif cpu_fpga != 0 and 'CUSTOM_CPU_FPGA' not in new_traits: new_traits.append('CUSTOM_CPU_FPGA') if capabilities.get('trusted_boot') is False: capabilities.pop('trusted_boot') capabilities = utils.get_updated_capabilities( node.properties.get('capabilities'), capabilities) if capabilities: props['capabilities'] = capabilities macs = _get_mac_addresses(node) except (scci.SCCIInvalidInputError, scci.SCCIClientError, exception.SNMPFailure) as e: error = (_("Inspection failed for node %(node_id)s " "with the following error: %(error)s") % {'node_id': node.uuid, 'error': e}) raise exception.HardwareInspectionFailure(error=error) return props, macs, new_traits
def setUp(self): super(IRMCManagementFunctionsTestCase, self).setUp() self.info = irmc_common.parse_driver_info(self.node) irmc_management.irmc.scci.SCCIError = Exception irmc_management.irmc.scci.SCCIInvalidInputError = ValueError