def validate(self, task): """Checks required info on 'driver_info' and validates node with OneView Validates whether the 'oneview_info' property of the supplied task's node contains the required info such as server_hardware_uri, server_hardware_type, server_profile_template_uri and enclosure_group_uri. Also, checks if the server profile of the node is applied, if NICs are valid for the server profile of the node, and if the server hardware attributes (ram, memory, vcpus count) are consistent with OneView. It validates if the node is being used by Oneview. :param task: a task from TaskManager. :raises: MissingParameterValue if a required parameter is missing. :raises: InvalidParameterValue if parameters set are inconsistent with resources in OneView :raises: InvalidParameterValue if the node in use by OneView. :raises: OneViewError if not possible to get OneView's information for the given node, if not possible to retrieve Server Hardware from OneView. """ common.verify_node_info(task.node) try: common.validate_oneview_resources_compatibility(task) if deploy_utils.is_node_in_use_by_oneview(task.node): raise exception.InvalidParameterValue( _("Node %s is in use by OneView.") % task.node.uuid) except exception.OneViewError as oneview_exc: raise exception.InvalidParameterValue(oneview_exc)
def validate(self, task): """Checks required info on 'driver_info' and validates node with OneView Validates whether the 'oneview_info' property of the supplied task's node contains the required info such as server_hardware_uri, server_hardware_type, server_profile_template_uri and enclosure_group_uri. Also, checks if the server profile of the node is applied, if NICs are valid for the server profile of the node, and if the server hardware attributes (ram, memory, vcpus count) are consistent with OneView. It validates if the node is being used by Oneview. :param task: a task from TaskManager. :raises: MissingParameterValue if a required parameter is missing. :raises: InvalidParameterValue if parameters set are inconsistent with resources in OneView :raises: InvalidParameterValue if the node in use by OneView. :raises: OneViewError if not possible to get OneView's information for the given node, if not possible to retrieve Server Hardware from OneView. """ common.verify_node_info(task.node) try: common.validate_oneview_resources_compatibility( self.oneview_client, task) if deploy_utils.is_node_in_use_by_oneview(self.oneview_client, task.node): raise exception.InvalidParameterValue( _("Node %s is in use by OneView.") % task.node.uuid) except exception.OneViewError as oneview_exc: raise exception.InvalidParameterValue(oneview_exc)
def _periodic_check_nodes_taken_by_oneview(self, manager, context): """Checks if nodes in Ironic were taken by OneView users. This driver periodic task will check for nodes that were taken by OneView users while the node is in available state, set the node to maintenance mode with an appropriate maintenance reason message and move the node to manageable state. :param manager: a ConductorManager instance :param context: request context :returns: None. """ filters = { 'provision_state': states.AVAILABLE, 'maintenance': False, 'driver': self.oneview_driver } node_iter = manager.iter_nodes(filters=filters) for node_uuid, driver in node_iter: node = objects.Node.get(context, node_uuid) try: oneview_using = deploy_utils.is_node_in_use_by_oneview( self.oneview_client, node) except exception.OneViewError as e: # NOTE(xavierr): Skip this node and process the # remaining nodes. This node will be checked in # the next periodic call. LOG.error( _LE("Error while determining if node " "%(node_uuid)s is in use by OneView. " "Error: %(error)s"), { 'node_uuid': node.uuid, 'error': e }) continue if oneview_using: purpose = (_LI('Updating node %(node_uuid)s in use ' 'by OneView from %(provision_state)s state ' 'to %(target_state)s state and maintenance ' 'mode %(maintenance)s.'), { 'node_uuid': node_uuid, 'provision_state': states.AVAILABLE, 'target_state': states.MANAGEABLE, 'maintenance': True }) LOG.info(purpose) node.maintenance = True node.maintenance_reason = common.NODE_IN_USE_BY_ONEVIEW manager.update_node(context, node) manager.do_provisioning_action(context, node.uuid, 'manage')
def _periodic_check_nodes_freed_by_oneview(self, manager, context): """Checks if nodes taken by OneView users were freed. This driver periodic task will be responsible to poll the nodes that are in maintenance mode and on manageable state to check if the Server Profile was removed, indicating that the node was freed by the OneView user. If so, it'll provide the node, that will pass through the cleaning process and become available to be provisioned. :param manager: a ConductorManager instance :param context: request context :returns: None. """ filters = { 'provision_state': states.MANAGEABLE, 'maintenance': True, 'driver': self.oneview_driver } node_iter = manager.iter_nodes(fields=['maintenance_reason'], filters=filters) for node_uuid, driver, maintenance_reason in node_iter: if maintenance_reason == common.NODE_IN_USE_BY_ONEVIEW: node = objects.Node.get(context, node_uuid) try: oneview_using = deploy_utils.is_node_in_use_by_oneview( node) except exception.OneViewError as e: LOG.error( _LE("Error while determining if node " "%(node_uuid)s is in use by OneView. " "Error: %(error)s"), { 'node_uuid': node.uuid, 'error': e }) if not oneview_using: purpose = (_LI('Bringing node %(node_uuid)s back from ' 'use by OneView from %(provision_state)s ' 'state to %(target_state)s state and ' 'maintenance mode %(maintenance)s.'), { 'node_uuid': node_uuid, 'provision_state': states.MANAGEABLE, 'target_state': states.AVAILABLE, 'maintenance': False }) LOG.info(purpose) node.maintenance = False node.maintenance_reason = None manager.update_node(context, node) manager.do_provisioning_action(context, node.uuid, 'provide')
def _periodic_check_nodes_taken_by_oneview(self, manager, context): """Checks if nodes in Ironic were taken by OneView users. This driver periodic task will check for nodes that were taken by OneView users while the node is in available state, set the node to maintenance mode with an appropriate maintenance reason message and move the node to manageable state. :param manager: a ConductorManager instance :param context: request context :returns: None. """ filters = { 'provision_state': states.AVAILABLE, 'maintenance': False, 'driver': self.oneview_driver } node_iter = manager.iter_nodes(filters=filters) for node_uuid, driver in node_iter: node = objects.Node.get(context, node_uuid) try: oneview_using = deploy_utils.is_node_in_use_by_oneview( self.oneview_client, node ) except exception.OneViewError as e: # NOTE(xavierr): Skip this node and process the # remaining nodes. This node will be checked in # the next periodic call. LOG.error("Error while determining if node " "%(node_uuid)s is in use by OneView. " "Error: %(error)s", {'node_uuid': node.uuid, 'error': e}) continue if oneview_using: purpose = ('Updating node %(node_uuid)s in use ' 'by OneView from %(provision_state)s state ' 'to %(target_state)s state and maintenance ' 'mode %(maintenance)s.', {'node_uuid': node_uuid, 'provision_state': states.AVAILABLE, 'target_state': states.MANAGEABLE, 'maintenance': True}) LOG.info(purpose) node.maintenance = True node.maintenance_reason = common.NODE_IN_USE_BY_ONEVIEW manager.update_node(context, node) manager.do_provisioning_action(context, node.uuid, 'manage')
def set_power_state(self, task, power_state, timeout=None): """Set the power state of the task's node. :param task: a TaskManager instance. :param power_state: The desired power state POWER_ON, POWER_OFF or REBOOT from :mod:`ironic.common.states`. :param timeout: timeout (in seconds) positive integer (> 0) for any power state. ``None`` indicates to use default timeout. :raises: InvalidParameterValue if an invalid power state was specified. :raises: PowerStateFailure if the power couldn't be set to power_state. :raises: OneViewError if OneView fails setting the power state. """ client = common.get_hponeview_client() if deploy_utils.is_node_in_use_by_oneview(task.node): raise exception.PowerStateFailure(_( "Cannot set power state '%(power_state)s' to node %(node)s. " "The node is in use by OneView.") % {'power_state': power_state, 'node': task.node.uuid}) if power_state not in SET_POWER_STATE_MAP: raise exception.InvalidParameterValue( _("set_power_state called with invalid power state %s.") % power_state) LOG.debug('Setting power state of node %(node_uuid)s to ' '%(power_state)s', {'node_uuid': task.node.uuid, 'power_state': power_state}) server_hardware = task.node.driver_info.get('server_hardware_uri') timeout = (-1 if timeout is None else timeout) try: if power_state == states.POWER_ON: management.set_boot_device(task) client.server_hardware.update_power_state( SET_POWER_STATE_MAP.get(power_state), server_hardware, timeout=timeout) elif power_state == states.REBOOT: client.server_hardware.update_power_state( SET_POWER_STATE_MAP.get(states.POWER_OFF), server_hardware, timeout=timeout) management.set_boot_device(task) client.server_hardware.update_power_state( SET_POWER_STATE_MAP.get(states.POWER_ON), server_hardware, timeout=timeout) else: client.server_hardware.update_power_state( SET_POWER_STATE_MAP.get(power_state), server_hardware, timeout=timeout) except client_exception.HPOneViewException as exc: raise exception.OneViewError( _("Error setting power state: %s") % exc)
def test_is_node_in_use_by_oneview(self, mock_get_ov_client): """Node has a Server Profile applied by a third party user. """ fake_server_hardware = oneview_models.ServerHardware() fake_server_hardware.server_profile_uri = "/any/sp_uri" with task_manager.acquire(self.context, self.node.uuid) as task: driver_info = task.node.driver_info driver_info['dynamic_allocation'] = True task.node.driver_info = driver_info self.assertTrue(deploy_utils.is_node_in_use_by_oneview(task.node))
def test_is_node_in_use_by_oneview_no_server_profile( self, mock_get_ov_client): """Node has no Server Profile. """ fake_sh = oneview_models.ServerHardware() fake_sh.server_profile_uri = None ov_client = mock_get_ov_client.return_value ov_client.get_server_hardware_by_uuid.return_value = fake_sh with task_manager.acquire(self.context, self.node.uuid) as task: self.assertFalse(deploy_utils.is_node_in_use_by_oneview(task.node))
def test_is_node_in_use_by_oneview_no_server_profile( self, mock_get_ov_client ): """Node has no Server Profile. """ oneview_client = mock_get_ov_client() fake_sh = oneview_models.ServerHardware() fake_sh.server_profile_uri = None oneview_client.get_server_hardware_by_uuid.return_value = fake_sh with task_manager.acquire(self.context, self.node.uuid) as task: self.assertFalse( deploy_utils.is_node_in_use_by_oneview(oneview_client, task.node) )
def test_is_node_in_use_by_oneview(self, mock_get_ov_client): """Node has a Server Profile applied by a third party user. """ oneview_client = mock_get_ov_client() fake_server_hardware = oneview_models.ServerHardware() fake_server_hardware.server_profile_uri = "/any/sp_uri" with task_manager.acquire(self.context, self.node.uuid) as task: driver_info = task.node.driver_info task.node.driver_info = driver_info self.assertTrue( deploy_utils.is_node_in_use_by_oneview(oneview_client, task.node) )
def test_is_node_in_use_by_oneview_same_server_profile_applied( self, mock_get_ov_client): """Node's Server Profile uri is the same applied by ironic. """ fake_sh = oneview_models.ServerHardware() fake_sh.server_profile_uri = 'same/applied_sp_uri/' ov_client = mock_get_ov_client.return_value ov_client.get_server_hardware_by_uuid.return_value = fake_sh with task_manager.acquire(self.context, self.node.uuid) as task: driver_info = task.node.driver_info driver_info['applied_server_profile_uri'] = 'same/applied_sp_uri/' task.node.driver_info = driver_info self.assertFalse(deploy_utils.is_node_in_use_by_oneview(task.node))
def set_power_state(self, task, power_state): """Turn the current power state on or off. :param task: a TaskManager instance. :param power_state: The desired power state POWER_ON, POWER_OFF or REBOOT from :mod:`ironic.common.states`. :raises: InvalidParameterValue if an invalid power state was specified. :raises: PowerStateFailure if the power couldn't be set to power_state. :raises: OneViewError if OneView fails setting the power state. """ if deploy_utils.is_node_in_use_by_oneview(self.oneview_client, task.node): raise exception.PowerStateFailure( _("Cannot set power state '%(power_state)s' to node %(node)s. " "The node is in use by OneView.") % { 'power_state': power_state, 'node': task.node.uuid }) oneview_info = common.get_oneview_info(task.node) LOG.debug( 'Setting power state of node %(node_uuid)s to ' '%(power_state)s', { 'node_uuid': task.node.uuid, 'power_state': power_state }) try: if power_state == states.POWER_ON: management.set_boot_device(task) self.oneview_client.power_on(oneview_info) elif power_state == states.POWER_OFF: self.oneview_client.power_off(oneview_info) elif power_state == states.REBOOT: self.oneview_client.power_off(oneview_info) management.set_boot_device(task) self.oneview_client.power_on(oneview_info) else: raise exception.InvalidParameterValue( _("set_power_state called with invalid power state %s.") % power_state) except oneview_exceptions.OneViewException as exc: raise exception.OneViewError( _("Error setting power state: %s") % exc)
def test_is_node_in_use_by_oneview_same_server_profile_applied( self, mock_get_ov_client ): """Node's Server Profile uri is the same applied by ironic. """ oneview_client = mock_get_ov_client() fake_sh = oneview_models.ServerHardware() fake_sh.server_profile_uri = 'same/applied_sp_uri/' oneview_client.get_server_hardware_by_uuid.return_value = fake_sh with task_manager.acquire(self.context, self.node.uuid) as task: driver_info = task.node.driver_info driver_info['applied_server_profile_uri'] = 'same/applied_sp_uri/' task.node.driver_info = driver_info self.assertFalse( deploy_utils.is_node_in_use_by_oneview(oneview_client, task.node) )
def set_power_state(self, task, power_state): """Turn the current power state on or off. :param task: a TaskManager instance. :param power_state: The desired power state POWER_ON, POWER_OFF or REBOOT from :mod:`ironic.common.states`. :raises: InvalidParameterValue if an invalid power state was specified. :raises: PowerStateFailure if the power couldn't be set to power_state. :raises: OneViewError if OneView fails setting the power state. """ if deploy_utils.is_node_in_use_by_oneview(self.oneview_client, task.node): raise exception.PowerStateFailure(_( "Cannot set power state '%(power_state)s' to node %(node)s. " "The node is in use by OneView.") % {'power_state': power_state, 'node': task.node.uuid}) oneview_info = common.get_oneview_info(task.node) LOG.debug('Setting power state of node %(node_uuid)s to ' '%(power_state)s', {'node_uuid': task.node.uuid, 'power_state': power_state}) try: if power_state == states.POWER_ON: self.oneview_client.power_on(oneview_info) elif power_state == states.POWER_OFF: self.oneview_client.power_off(oneview_info) elif power_state == states.REBOOT: self.oneview_client.power_off(oneview_info) self.oneview_client.power_on(oneview_info) else: raise exception.InvalidParameterValue( _("set_power_state called with invalid power state %s.") % power_state) except oneview_exceptions.OneViewException as exc: raise exception.OneViewError( _("Error setting power state: %s") % exc )
def _periodic_check_nodes_freed_by_oneview(self, manager, context): """Checks if nodes taken by OneView users were freed. This driver periodic task will be responsible to poll the nodes that are in maintenance mode and on manageable state to check if the Server Profile was removed, indicating that the node was freed by the OneView user. If so, it'll provide the node, that will pass through the cleaning process and become available to be provisioned. :param manager: a ConductorManager instance :param context: request context :returns: None. """ filters = { 'provision_state': states.MANAGEABLE, 'maintenance': True, 'driver': self.oneview_driver } node_iter = manager.iter_nodes(fields=['maintenance_reason'], filters=filters) for node_uuid, driver, maintenance_reason in node_iter: if maintenance_reason == common.NODE_IN_USE_BY_ONEVIEW: node = objects.Node.get(context, node_uuid) try: oneview_using = deploy_utils.is_node_in_use_by_oneview( self.oneview_client, node ) except exception.OneViewError as e: # NOTE(xavierr): Skip this node and process the # remaining nodes. This node will be checked in # the next periodic call. LOG.error("Error while determining if node " "%(node_uuid)s is in use by OneView. " "Error: %(error)s", {'node_uuid': node.uuid, 'error': e}) continue if not oneview_using: purpose = ('Bringing node %(node_uuid)s back from ' 'use by OneView from %(provision_state)s ' 'state to %(target_state)s state and ' 'maintenance mode %(maintenance)s.', {'node_uuid': node_uuid, 'provision_state': states.MANAGEABLE, 'target_state': states.AVAILABLE, 'maintenance': False}) LOG.info(purpose) node.maintenance = False node.maintenance_reason = None manager.update_node(context, node) manager.do_provisioning_action( context, node.uuid, 'provide' )