diff --git a/ironic/drivers/modules/oneview/common.py b/ironic/drivers/modules/oneview/common.py index 56376714e1..8c16895b09 100644 --- a/ironic/drivers/modules/oneview/common.py +++ b/ironic/drivers/modules/oneview/common.py @@ -1,5 +1,6 @@ -# Copyright (2015-2017) Hewlett Packard Enterprise Development LP -# Copyright (2015-2017) Universidade Federal de Campina Grande +# Copyright 2017 Hewlett Packard Enterprise Development Company LP. +# Copyright 2015 Hewlett Packard Development Company, LP +# Copyright 2015 Universidade Federal de Campina Grande # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -18,6 +19,7 @@ from six.moves.urllib import parse from ironic.common import exception from ironic.common.i18n import _ +from ironic.common import states from ironic.conf import CONF from ironic.drivers import utils @@ -34,8 +36,6 @@ oneview_exceptions = importutils.try_import('oneview_client.exceptions') hponeview_client = importutils.try_import('hpOneView.oneview_client') redfish = importutils.try_import('redfish') -client_exception = importutils.try_import('hpOneView.exceptions') - REQUIRED_ON_DRIVER_INFO = { 'server_hardware_uri': _("Server Hardware URI. Required in driver_info."), @@ -74,7 +74,7 @@ SERVER_HARDWARE_ALLOCATION_ERROR = 'server hardware allocation error' def get_oneview_client(): - """Generate an instance of the OneView client. + """Generates an instance of the OneView client. Generates an instance of the OneView client using the imported oneview_client library. @@ -161,7 +161,7 @@ def _get_ilo_access(remote_console): def verify_node_info(node): - """Verify if fields and namespaces of a node are valid. + """Verifies if fields and namespaces of a node are valid. Verifies if the 'driver_info' field and the 'properties/capabilities' namespace exist and are not empty. @@ -185,7 +185,7 @@ def verify_node_info(node): def get_oneview_info(node): - """Get OneView information from the node. + """Gets OneView information from the node. :param: node: node object to get information from :returns: a dictionary containing: @@ -197,6 +197,7 @@ def get_oneview_info(node): OneView :raises OneViewInvalidNodeParameter: if node capabilities are malformed """ + try: capabilities_dict = utils.capabilities_to_dict( node.properties.get('capabilities', '') @@ -224,7 +225,7 @@ def get_oneview_info(node): def validate_oneview_resources_compatibility(oneview_client, task): - """Validate if the node configuration is consistent with OneView. + """Validates if the node configuration is consistent with OneView. This method calls python-oneviewclient functions to validate if the node configuration is consistent with the OneView resources it represents, @@ -237,6 +238,7 @@ def validate_oneview_resources_compatibility(oneview_client, task): :param oneview_client: an instance of the OneView client :param: task: a TaskManager instance containing the node to act on. """ + node_ports = task.ports oneview_info = get_oneview_info(task.node) @@ -265,8 +267,28 @@ def validate_oneview_resources_compatibility(oneview_client, task): raise exception.OneViewError(error=msg) +def translate_oneview_power_state(power_state): + """Translates OneView's power states strings to Ironic's format. + + :param: power_state: power state string to be translated + :returns: the power state translated + """ + + power_states_map = { + oneview_states.ONEVIEW_POWER_ON: states.POWER_ON, + oneview_states.ONEVIEW_POWERING_OFF: states.POWER_ON, + oneview_states.ONEVIEW_POWER_OFF: states.POWER_OFF, + oneview_states.ONEVIEW_POWERING_ON: states.POWER_OFF, + oneview_states.ONEVIEW_RESETTING: states.REBOOT + } + + return power_states_map.get(power_state, states.ERROR) + + def _verify_node_info(node_namespace, node_info_dict, info_required): - """Verify if info_required is present in node_namespace.""" + """Verify if info_required is present in node_namespace of the node info. + + """ missing_keys = set(info_required) - set(node_info_dict) if missing_keys: @@ -298,27 +320,35 @@ def node_has_server_profile(func): :param func: a given decorated function. """ def inner(self, *args, **kwargs): + oneview_client = self.oneview_client task = args[0] - has_server_profile(task, self.client) + has_server_profile(task, oneview_client) return func(self, *args, **kwargs) return inner -def has_server_profile(task, client): +def has_server_profile(task, oneview_client): """Checks if the node's Server Hardware has a Server Profile associated. Function to check if the Server Profile is applied to the Server Hardware. - :param client: an instance of the OneView client + :param oneview_client: an instance of the OneView client :param task: a TaskManager instance containing the node to act on. """ + oneview_info = get_oneview_info(task.node) try: - profile = task.node.driver_info.get('applied_server_profile_uri') - client.server_profiles.get(profile) - except client_exception.HPOneViewException as exc: + node_has_server_profile = ( + oneview_client.get_server_profile_from_hardware(oneview_info) + ) + except oneview_exceptions.OneViewException as oneview_exc: LOG.error( "Failed to get server profile from OneView appliance for" " node %(node)s. Error: %(message)s", - {"node": task.node.uuid, "message": exc} + {"node": task.node.uuid, "message": oneview_exc} + ) + raise exception.OneViewError(error=oneview_exc) + if not node_has_server_profile: + raise exception.OperationNotPermitted( + _("A Server Profile is not associated with node %s.") % + task.node.uuid ) - raise exception.OneViewError(error=exc) diff --git a/ironic/drivers/modules/oneview/deploy.py b/ironic/drivers/modules/oneview/deploy.py index e8fa9e92da..a6c75c79f3 100644 --- a/ironic/drivers/modules/oneview/deploy.py +++ b/ironic/drivers/modules/oneview/deploy.py @@ -1,5 +1,7 @@ -# Copyright (2016-2017) Hewlett Packard Enterprise Development LP -# Copyright (2016-2017) Universidade Federal de Campina Grande +# Copyright 2017 Hewlett Packard Enterprise Development Company LP. +# Copyright 2016 Hewlett Packard Enterprise Development LP. +# Copyright 2016 Universidade Federal de Campina Grande +# All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -43,7 +45,7 @@ class OneViewPeriodicTasks(object): @periodics.periodic(spacing=CONF.oneview.periodic_check_interval, enabled=CONF.oneview.enable_periodic_tasks) def _periodic_check_nodes_taken_by_oneview(self, manager, context): - """Check if nodes in Ironic were taken by OneView users. + """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 @@ -54,6 +56,7 @@ class OneViewPeriodicTasks(object): :param context: request context :returns: None. """ + filters = { 'provision_state': states.AVAILABLE, 'maintenance': False, @@ -67,7 +70,7 @@ class OneViewPeriodicTasks(object): try: oneview_using = deploy_utils.is_node_in_use_by_oneview( - self.client, node + self.oneview_client, node ) except exception.OneViewError as e: # NOTE(xavierr): Skip this node and process the @@ -101,7 +104,7 @@ class OneViewPeriodicTasks(object): @periodics.periodic(spacing=CONF.oneview.periodic_check_interval, enabled=CONF.oneview.enable_periodic_tasks) def _periodic_check_nodes_freed_by_oneview(self, manager, context): - """Check if nodes taken by OneView users were freed. + """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 @@ -113,6 +116,7 @@ class OneViewPeriodicTasks(object): :param context: request context :returns: None. """ + filters = { 'provision_state': states.MANAGEABLE, 'maintenance': True, @@ -128,7 +132,7 @@ class OneViewPeriodicTasks(object): try: oneview_using = deploy_utils.is_node_in_use_by_oneview( - self.client, node + self.oneview_client, node ) except exception.OneViewError as e: # NOTE(xavierr): Skip this node and process the @@ -164,7 +168,7 @@ class OneViewPeriodicTasks(object): @periodics.periodic(spacing=CONF.oneview.periodic_check_interval, enabled=CONF.oneview.enable_periodic_tasks) def _periodic_check_nodes_taken_on_cleanfail(self, manager, context): - """Check failed deploys due to Oneview users taking Server Hardware. + """Checks failed deploys due to Oneview users taking Server Hardware. This last driver periodic task will take care of nodes that would be caught on a race condition between OneView and a deploy by Ironic. In @@ -179,6 +183,7 @@ class OneViewPeriodicTasks(object): :param context: request context :returns: None. """ + filters = { 'provision_state': states.CLEANFAIL, 'driver': self.oneview_driver @@ -220,7 +225,6 @@ class OneViewIscsiDeploy(iscsi_deploy.ISCSIDeploy, OneViewPeriodicTasks): def __init__(self): super(OneViewIscsiDeploy, self).__init__() - self.client = common.get_hponeview_client() self.oneview_client = common.get_oneview_client() def get_properties(self): @@ -238,23 +242,23 @@ class OneViewIscsiDeploy(iscsi_deploy.ISCSIDeploy, OneViewPeriodicTasks): @METRICS.timer('OneViewIscsiDeploy.prepare') def prepare(self, task): - deploy_utils.prepare(self.client, task) + deploy_utils.prepare(self.oneview_client, task) super(OneViewIscsiDeploy, self).prepare(task) @METRICS.timer('OneViewIscsiDeploy.tear_down') def tear_down(self, task): if not CONF.conductor.automated_clean: - deploy_utils.tear_down(self.client, task) + deploy_utils.tear_down(self.oneview_client, task) return super(OneViewIscsiDeploy, self).tear_down(task) @METRICS.timer('OneViewIscsiDeploy.prepare_cleaning') def prepare_cleaning(self, task): - deploy_utils.prepare_cleaning(self.client, task) + deploy_utils.prepare_cleaning(self.oneview_client, task) return super(OneViewIscsiDeploy, self).prepare_cleaning(task) @METRICS.timer('OneViewIscsiDeploy.tear_down_cleaning') def tear_down_cleaning(self, task): - deploy_utils.tear_down_cleaning(self.client, task) + deploy_utils.tear_down_cleaning(self.oneview_client, task) super(OneViewIscsiDeploy, self).tear_down_cleaning(task) @@ -265,7 +269,6 @@ class OneViewAgentDeploy(agent.AgentDeploy, OneViewPeriodicTasks): def __init__(self): super(OneViewAgentDeploy, self).__init__() - self.client = common.get_hponeview_client() self.oneview_client = common.get_oneview_client() def get_properties(self): @@ -283,21 +286,21 @@ class OneViewAgentDeploy(agent.AgentDeploy, OneViewPeriodicTasks): @METRICS.timer('OneViewAgentDeploy.prepare') def prepare(self, task): - deploy_utils.prepare(self.client, task) + deploy_utils.prepare(self.oneview_client, task) super(OneViewAgentDeploy, self).prepare(task) @METRICS.timer('OneViewAgentDeploy.tear_down') def tear_down(self, task): if not CONF.conductor.automated_clean: - deploy_utils.tear_down(self.client, task) + deploy_utils.tear_down(self.oneview_client, task) return super(OneViewAgentDeploy, self).tear_down(task) @METRICS.timer('OneViewAgentDeploy.prepare_cleaning') def prepare_cleaning(self, task): - deploy_utils.prepare_cleaning(self.client, task) + deploy_utils.prepare_cleaning(self.oneview_client, task) return super(OneViewAgentDeploy, self).prepare_cleaning(task) @METRICS.timer('OneViewAgentDeploy.tear_down_cleaning') def tear_down_cleaning(self, task): - deploy_utils.tear_down_cleaning(self.client, task) + deploy_utils.tear_down_cleaning(self.oneview_client, task) super(OneViewAgentDeploy, self).tear_down_cleaning(task) diff --git a/ironic/drivers/modules/oneview/deploy_utils.py b/ironic/drivers/modules/oneview/deploy_utils.py index ad6a711e0f..41b81f2b6c 100644 --- a/ironic/drivers/modules/oneview/deploy_utils.py +++ b/ironic/drivers/modules/oneview/deploy_utils.py @@ -1,5 +1,6 @@ -# Copyright (2016-2017) Hewlett Packard Enterprise Development LP -# Copyright (2016-2017) Universidade Federal de Campina Grande +# Copyright 2016 Hewlett Packard Enterprise Development LP. +# Copyright 2016 Universidade Federal de Campina Grande +# All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -25,7 +26,6 @@ from ironic.drivers.modules.oneview import common LOG = logging.getLogger(__name__) -client_exception = importutils.try_import('hpOneView.exceptions') oneview_exception = importutils.try_import('oneview_client.exceptions') oneview_utils = importutils.try_import('oneview_client.utils') @@ -34,14 +34,14 @@ def get_properties(): return common.COMMON_PROPERTIES -def prepare(client, task): - """Apply Server Profile and update the node when preparing. +def prepare(oneview_client, task): + """Applies Server Profile and update the node when preparing. This method is responsible for applying a Server Profile to the Server Hardware and add the uri of the applied Server Profile in the node's 'applied_server_profile_uri' field on properties/capabilities. - :param client: an instance of the OneView client + :param oneview_client: an instance of the OneView client :param task: A TaskManager object :raises InstanceDeployFailure: If the node doesn't have the needed OneView informations, if Server Hardware is in use by an OneView user, or @@ -57,14 +57,14 @@ def prepare(client, task): {"instance_name": instance_display_name, "instance_uuid": instance_uuid} ) - allocate_server_hardware_to_ironic(client, task.node, + allocate_server_hardware_to_ironic(oneview_client, task.node, server_profile_name) except exception.OneViewError as e: raise exception.InstanceDeployFailure(node=task.node.uuid, reason=e) -def tear_down(client, task): +def tear_down(oneview_client, task): """Remove Server profile and update the node when tear down. This method is responsible for power a Server Hardware off, remove a Server @@ -72,26 +72,26 @@ def tear_down(client, task): Profile from the node's 'applied_server_profile_uri' in properties/capabilities. - :param client: an instance of the OneView client + :param oneview_client: an instance of the OneView client :param task: A TaskManager object :raises InstanceDeployFailure: If node has no uri of applied Server Profile, or if some error occur while deleting Server Profile. """ try: - deallocate_server_hardware_from_ironic(client, task) + deallocate_server_hardware_from_ironic(oneview_client, task.node) except exception.OneViewError as e: raise exception.InstanceDeployFailure(node=task.node.uuid, reason=e) -def prepare_cleaning(client, task): - """Apply Server Profile and update the node when preparing cleaning. +def prepare_cleaning(oneview_client, task): + """Applies Server Profile and update the node when preparing cleaning. This method is responsible for applying a Server Profile to the Server Hardware and add the uri of the applied Server Profile in the node's 'applied_server_profile_uri' field on properties/capabilities. - :param client: an instance of the OneView client + :param oneview_client: an instance of the OneView client :param task: A TaskManager object :raises NodeCleaningFailure: If the node doesn't have the needed OneView informations, if Server Hardware is in use by an OneView user, or @@ -100,7 +100,7 @@ def prepare_cleaning(client, task): """ try: server_profile_name = "Ironic Cleaning [%s]" % task.node.uuid - allocate_server_hardware_to_ironic(client, task.node, + allocate_server_hardware_to_ironic(oneview_client, task.node, server_profile_name) except exception.OneViewError as e: oneview_error = common.SERVER_HARDWARE_ALLOCATION_ERROR @@ -112,7 +112,7 @@ def prepare_cleaning(client, task): reason=e) -def tear_down_cleaning(client, task): +def tear_down_cleaning(oneview_client, task): """Remove Server profile and update the node when tear down cleaning. This method is responsible for power a Server Hardware off, remove a Server @@ -120,41 +120,18 @@ def tear_down_cleaning(client, task): Profile from the node's 'applied_server_profile_uri' in properties/capabilities. - :param client: an instance of the OneView client + :param oneview_client: an instance of the OneView client :param task: A TaskManager object :raises NodeCleaningFailure: If node has no uri of applied Server Profile, or if some error occur while deleting Server Profile. """ try: - deallocate_server_hardware_from_ironic(client, task) + deallocate_server_hardware_from_ironic(oneview_client, task.node) except exception.OneViewError as e: raise exception.NodeCleaningFailure(node=task.node.uuid, reason=e) -def _create_profile_from_template( - client, server_profile_name, - server_hardware_uri, server_profile_template): - """Create a server profile from a server profile template. - - :param client: an OneView Client instance - :param server_profile_name: the name of the new server profile - :param server_hardware_uri: the server_hardware assigned to server profile - :param server_profile_template: the server profile template id or uri - :returns: The new server profile generated with the name and server - hardware passed on parameters - :raises HPOneViewException: if the communication with OneView fails - - """ - server_profile = client.server_profile_templates.get_new_profile( - server_profile_template - ) - server_profile['name'] = server_profile_name - server_profile['serverHardwareUri'] = server_hardware_uri - server_profile['serverProfileTemplateUri'] = "" - return client.server_profiles.create(server_profile) - - def _is_node_in_use(server_hardware, applied_sp_uri, by_oneview=False): """Check if node is in use by ironic or by OneView. @@ -167,16 +144,16 @@ def _is_node_in_use(server_hardware, applied_sp_uri, by_oneview=False): False and node is in use by ironic, False otherwise. """ + operation = operator.ne if by_oneview else operator.eq - server_profile_uri = server_hardware.get('serverProfileUri') - return (server_profile_uri is not None and - operation(applied_sp_uri, server_profile_uri)) + return (server_hardware.server_profile_uri not in (None, '') and + operation(applied_sp_uri, server_hardware.server_profile_uri)) -def is_node_in_use_by_oneview(client, node): +def is_node_in_use_by_oneview(oneview_client, node): """Check if node is in use by OneView user. - :param client: an instance of the OneView client + :param oneview_client: an instance of the OneView client :param node: an ironic node object :returns: Boolean value. True if node is in use by OneView, False otherwise. @@ -185,6 +162,7 @@ def is_node_in_use_by_oneview(client, node): from OneView. """ + positive = _("Node '%s' is in use by OneView.") % node.uuid negative = _("Node '%s' is not in use by OneView.") % node.uuid @@ -194,14 +172,14 @@ def is_node_in_use_by_oneview(client, node): return _is_node_in_use(server_hardware, applied_sp_uri, by_oneview=True) - return _check_applied_server_profile(client, node, + return _check_applied_server_profile(oneview_client, node, predicate, positive, negative) -def is_node_in_use_by_ironic(client, node): +def is_node_in_use_by_ironic(oneview_client, node): """Check if node is in use by ironic in OneView. - :param client: an instance of the OneView client + :param oneview_client: an instance of the OneView client :param node: an ironic node object :returns: Boolean value. True if node is in use by ironic, False otherwise. @@ -210,6 +188,7 @@ def is_node_in_use_by_ironic(client, node): from OneView. """ + positive = _("Node '%s' is in use by Ironic.") % node.uuid negative = _("Node '%s' is not in use by Ironic.") % node.uuid @@ -219,14 +198,15 @@ def is_node_in_use_by_ironic(client, node): return _is_node_in_use(server_hardware, applied_sp_uri, by_oneview=False) - return _check_applied_server_profile(client, node, + return _check_applied_server_profile(oneview_client, node, predicate, positive, negative) -def _check_applied_server_profile(client, node, predicate, positive, negative): +def _check_applied_server_profile(oneview_client, node, + predicate, positive, negative): """Check if node is in use by ironic in OneView. - :param client: an instance of the OneView client + :param oneview_client: an instance of the OneView client :param node: an ironic node object :returns: Boolean value. True if node is in use by ironic, False otherwise. @@ -236,17 +216,25 @@ def _check_applied_server_profile(client, node, predicate, positive, negative): """ oneview_info = common.get_oneview_info(node) + + sh_uuid = oneview_utils.get_uuid_from_uri( + oneview_info.get("server_hardware_uri") + ) + try: - server_hardware = client.server_hardware.get( - oneview_info.get('server_hardware_uri') + server_hardware = oneview_client.get_server_hardware_by_uuid( + sh_uuid ) - except client_exception.HPOneViewResourceNotFound as e: + except oneview_exception.OneViewResourceNotFoundError as e: msg = (_("Error while obtaining Server Hardware from node " "%(node_uuid)s. Error: %(error)s") % {'node_uuid': node.uuid, 'error': e}) raise exception.OneViewError(error=msg) - applied_sp_uri = node.driver_info.get('applied_server_profile_uri') + applied_sp_uri = ( + node.driver_info.get('applied_server_profile_uri') + ) + result = predicate(server_hardware, applied_sp_uri) if result: @@ -258,14 +246,13 @@ def _check_applied_server_profile(client, node, predicate, positive, negative): def _add_applied_server_profile_uri_field(node, applied_profile): - """Add the applied Server Profile uri to a node. + """Adds the applied Server Profile uri to a node. :param node: an ironic node object - :param applied_profile: the server_profile that will be applied to node """ driver_info = node.driver_info - driver_info['applied_server_profile_uri'] = applied_profile.get('uri') + driver_info['applied_server_profile_uri'] = applied_profile.uri node.driver_info = driver_info node.save() @@ -282,11 +269,11 @@ def _del_applied_server_profile_uri_field(node): node.save() -def allocate_server_hardware_to_ironic(client, node, +def allocate_server_hardware_to_ironic(oneview_client, node, server_profile_name): """Allocate Server Hardware to ironic. - :param client: an instance of the OneView client + :param oneview_client: an instance of the OneView client :param node: an ironic node object :param server_profile_name: a formatted string with the Server Profile name @@ -294,18 +281,27 @@ def allocate_server_hardware_to_ironic(client, node, Hardware to ironic """ - node_in_use_by_oneview = is_node_in_use_by_oneview(client, node) + node_in_use_by_oneview = is_node_in_use_by_oneview(oneview_client, node) if not node_in_use_by_oneview: + oneview_info = common.get_oneview_info(node) + applied_sp_uri = node.driver_info.get('applied_server_profile_uri') - sh_uri = oneview_info.get("server_hardware_uri") - spt_uri = oneview_info.get("server_profile_template_uri") - server_hardware = client.server_hardware.get(sh_uri) + + sh_uuid = oneview_utils.get_uuid_from_uri( + oneview_info.get("server_hardware_uri") + ) + spt_uuid = oneview_utils.get_uuid_from_uri( + oneview_info.get("server_profile_template_uri") + ) + server_hardware = oneview_client.get_server_hardware_by_uuid(sh_uuid) # Don't have Server Profile on OneView but has # `applied_server_profile_uri` on driver_info - if not server_hardware.get('serverProfileUri') and applied_sp_uri: + if (server_hardware.server_profile_uri in (None, '') and + applied_sp_uri is not (None, '')): + _del_applied_server_profile_uri_field(node) LOG.info( "Inconsistent 'applied_server_profile_uri' parameter " @@ -316,10 +312,8 @@ def allocate_server_hardware_to_ironic(client, node, # applied_server_profile_uri exists and is equal to Server profile # applied on Hardware. Do not apply again. - if ( - applied_sp_uri and server_hardware.get('serverProfileUri') and - server_hardware.get('serverProfileUri') == applied_sp_uri - ): + if (applied_sp_uri and server_hardware.server_profile_uri and + server_hardware.server_profile_uri == applied_sp_uri): LOG.info( "The Server Profile %(applied_sp_uri)s was already applied " "by ironic on node %(node_uuid)s. Reusing.", @@ -328,8 +322,8 @@ def allocate_server_hardware_to_ironic(client, node, return try: - applied_profile = _create_profile_from_template( - client, server_profile_name, sh_uri, spt_uri + applied_profile = oneview_client.clone_template_and_apply( + server_profile_name, sh_uuid, spt_uuid ) _add_applied_server_profile_uri_field(node, applied_profile) @@ -337,41 +331,46 @@ def allocate_server_hardware_to_ironic(client, node, "Server Profile %(server_profile_uuid)s was successfully" " applied to node %(node_uuid)s.", {"node_uuid": node.uuid, - "server_profile_uuid": applied_profile.get('uri')} + "server_profile_uuid": applied_profile.uri} ) - except client_exception.HPOneViewInvalidResource as e: + except oneview_exception.OneViewServerProfileAssignmentError as e: LOG.error("An error occurred during allocating server " "hardware to ironic during prepare: %s", e) raise exception.OneViewError(error=e) else: - msg = _("Node %s is already in use by OneView.") % node.uuid + msg = (_("Node %s is already in use by OneView.") % + node.uuid) + raise exception.OneViewError(error=msg) -def deallocate_server_hardware_from_ironic(client, task): +def deallocate_server_hardware_from_ironic(oneview_client, node): """Deallocate Server Hardware from ironic. - :param client: an instance of the OneView client - :param task: a TaskManager object + :param oneview_client: an instance of the OneView client + :param node: an ironic node object :raises OneViewError: if an error occurs while deallocating the Server Hardware to ironic """ - node = task.node - if is_node_in_use_by_ironic(client, node): + + if is_node_in_use_by_ironic(oneview_client, node): + oneview_info = common.get_oneview_info(node) - server_profile_uri = oneview_info.get('applied_server_profile_uri') + server_profile_uuid = oneview_utils.get_uuid_from_uri( + oneview_info.get('applied_server_profile_uri') + ) try: - task.driver.power.set_power_state(task, states.POWER_OFF) - client.server_profiles.delete(server_profile_uri) + oneview_client.power_off(oneview_info) + oneview_client.delete_server_profile(server_profile_uuid) _del_applied_server_profile_uri_field(node) - LOG.info("Server Profile %(server_profile_uri)s was deleted " + LOG.info("Server Profile %(server_profile_uuid)s was deleted " "from node %(node_uuid)s in OneView.", - {'server_profile_uri': server_profile_uri, + {'server_profile_uuid': server_profile_uuid, 'node_uuid': node.uuid}) - except client_exception.HPOneViewException as e: + except (ValueError, oneview_exception.OneViewException) as e: msg = (_("Error while deleting applied Server Profile from node " "%(node_uuid)s. Error: %(error)s") % {'node_uuid': node.uuid, 'error': e}) diff --git a/ironic/drivers/modules/oneview/inspect.py b/ironic/drivers/modules/oneview/inspect.py index 5aa87e9bb5..dafc87ae29 100644 --- a/ironic/drivers/modules/oneview/inspect.py +++ b/ironic/drivers/modules/oneview/inspect.py @@ -1,5 +1,6 @@ -# Copyright (2016-2017) Hewlett Packard Enterprise Development LP -# Copyright (2016-2017) Universidade Federal de Campina Grande +# Copyright 2016 Hewlett Packard Enterprise Development LP. +# Copyright 2016 Universidade Federal de Campina Grande +# All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -36,7 +37,6 @@ class OneViewInspect(inspector.Inspector): def __init__(self): super(OneViewInspect, self).__init__() - self.client = common.get_hponeview_client() self.oneview_client = common.get_oneview_client() def get_properties(self): @@ -44,7 +44,7 @@ class OneViewInspect(inspector.Inspector): @METRICS.timer('OneViewInspect.validate') def validate(self, task): - """Check required info on 'driver_info' and validates node with OneView. + """Checks required info on 'driver_info' and validates node with OneView Validates whether the 'driver_info' property of the supplied task's node contains the required info such as server_hardware_uri, @@ -56,6 +56,7 @@ class OneViewInspect(inspector.Inspector): :raises: InvalidParameterValue if parameters set are inconsistent with resources in OneView """ + common.verify_node_info(task.node) try: @@ -96,11 +97,12 @@ class OneViewInspect(inspector.Inspector): state_after = task.node.provision_state # inspection finished - if state_before == states.INSPECTING and state_after in [ + if ( + state_before == states.INSPECTING and state_after in [ states.MANAGEABLE, states.INSPECTFAIL - ]: + ] + ): deploy_utils.deallocate_server_hardware_from_ironic( - self.client, task.node - ) + self.oneview_client, task.node) return result diff --git a/ironic/drivers/modules/oneview/management.py b/ironic/drivers/modules/oneview/management.py index b7b18c8cae..04f87d593c 100644 --- a/ironic/drivers/modules/oneview/management.py +++ b/ironic/drivers/modules/oneview/management.py @@ -1,5 +1,6 @@ -# Copyright (2015-2017) Hewlett Packard Enterprise Development LP -# Copyright (2015-2017) Universidade Federal de Campina Grande +# Copyright 2017 Hewlett Packard Enterprise Development Company LP. +# Copyright 2015 Hewlett Packard Development Company, LP +# Copyright 2015 Universidade Federal de Campina Grande # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -25,59 +26,22 @@ from ironic.drivers import base from ironic.drivers.modules.oneview import common from ironic.drivers.modules.oneview import deploy_utils -client_exception = importutils.try_import('hpOneView.exceptions') -oneview_exceptions = importutils.try_import('oneview_client.exceptions') - LOG = logging.getLogger(__name__) + METRICS = metrics_utils.get_metrics_logger(__name__) -BOOT_DEVICE_MAP_ONEVIEW = { - boot_devices.CDROM: 'CD', +BOOT_DEVICE_MAPPING_TO_OV = { boot_devices.DISK: 'HardDisk', - boot_devices.PXE: 'PXE' + boot_devices.PXE: 'PXE', + boot_devices.CDROM: 'CD', } -BOOT_DEVICE_MAP_ONEVIEW_REV = { - v: k for k, v in BOOT_DEVICE_MAP_ONEVIEW.items()} - -BOOT_DEVICE_MAP_ILO = { - boot_devices.CDROM: 'Cd', - boot_devices.DISK: 'Hdd', - boot_devices.PXE: 'Pxe' +BOOT_DEVICE_OV_TO_GENERIC = { + v: k + for k, v in BOOT_DEVICE_MAPPING_TO_OV.items() } -BOOT_DEVICE_MAP_ILO_REV = { - v: k for k, v in BOOT_DEVICE_MAP_ILO.items()} - - -def set_onetime_boot(task): - """Set onetime boot to server hardware. - - Change the onetime boot option of an OneView server hardware. - - :param task: a task from TaskManager. - """ - driver_internal_info = task.node.driver_internal_info - next_boot_device = driver_internal_info.get('next_boot_device') - - if next_boot_device: - boot_device = next_boot_device.get('boot_device') - persistent = next_boot_device.get('persistent') - - if not persistent: - client = common.get_hponeview_client() - server_hardware = task.node.driver_info.get('server_hardware_uri') - ilo_client = common.get_ilorest_client(client, server_hardware) - boot_device = BOOT_DEVICE_MAP_ILO.get(boot_device) - path = '/rest/v1/Systems/1' - body = { - "Boot": { - "BootSourceOverrideTarget": boot_device, - "BootSourceOverrideEnabled": "Once" - } - } - headers = {"Content-Type": "application/json"} - ilo_client.patch(path=path, body=body, headers=headers) +oneview_exceptions = importutils.try_import('oneview_client.exceptions') def set_boot_device(task): @@ -88,10 +52,12 @@ def set_boot_device(task): :param task: a task from TaskManager. :raises: InvalidParameterValue if an invalid boot device is specified. + :raises: OperationNotPermitted if the server has no server profile or + if the server is already powered on. :raises: OneViewError if the communication with OneView fails """ - client = common.get_hponeview_client() - common.has_server_profile(task, client) + oneview_client = common.get_oneview_client() + common.has_server_profile(task, oneview_client) driver_internal_info = task.node.driver_internal_info next_boot_device = driver_internal_info.get('next_boot_device') @@ -99,7 +65,7 @@ def set_boot_device(task): boot_device = next_boot_device.get('boot_device') persistent = next_boot_device.get('persistent') - if boot_device not in sorted(BOOT_DEVICE_MAP_ONEVIEW): + if boot_device not in sorted(BOOT_DEVICE_MAPPING_TO_OV): raise exception.InvalidParameterValue( _("Invalid boot device %s specified.") % boot_device) @@ -108,23 +74,16 @@ def set_boot_device(task): {"boot_device": boot_device, "persistent": persistent, "node": task.node.uuid}) - profile = task.node.driver_info.get('applied_server_profile_uri') - boot_device = BOOT_DEVICE_MAP_ONEVIEW.get(boot_device) - try: - server_profile = client.server_profiles.get(profile) - boot = server_profile.get('boot') - order = boot.get('order') - order.remove(boot_device) - order.insert(0, boot_device) - boot['order'] = order - server_profile['boot'] = boot - client.server_profiles.update(server_profile, profile) - set_onetime_boot(task) + oneview_info = common.get_oneview_info(task.node) + device_to_oneview = BOOT_DEVICE_MAPPING_TO_OV.get(boot_device) + oneview_client.set_boot_device(oneview_info, + device_to_oneview, + onetime=not persistent) driver_internal_info.pop('next_boot_device', None) task.node.driver_internal_info = driver_internal_info task.node.save() - except client_exception.HPOneViewException as oneview_exc: + except oneview_exceptions.OneViewException as oneview_exc: msg = (_( "Error setting boot device on OneView. Error: %s") % oneview_exc @@ -142,7 +101,6 @@ class OneViewManagement(base.ManagementInterface): def __init__(self): super(OneViewManagement, self).__init__() - self.client = common.get_hponeview_client() self.oneview_client = common.get_oneview_client() def get_properties(self): @@ -150,7 +108,7 @@ class OneViewManagement(base.ManagementInterface): @METRICS.timer('OneViewManagement.validate') def validate(self, task): - """Check required info on 'driver_info' and validates node with OneView. + """Checks required info on 'driver_info' and validates node with OneView Validates whether the 'driver_info' property of the supplied task's node contains the required info such as server_hardware_uri, @@ -164,6 +122,7 @@ class OneViewManagement(base.ManagementInterface): :raises: InvalidParameterValue if parameters set are inconsistent with resources in OneView """ + common.verify_node_info(task.node) try: @@ -171,7 +130,7 @@ class OneViewManagement(base.ManagementInterface): self.oneview_client, task) if not deploy_utils.is_node_in_use_by_ironic( - self.client, task.node + self.oneview_client, task.node ): raise exception.InvalidParameterValue( _("Node %s is not in use by ironic.") % task.node.uuid) @@ -180,19 +139,20 @@ class OneViewManagement(base.ManagementInterface): @METRICS.timer('OneViewManagement.get_supported_boot_devices') def get_supported_boot_devices(self, task): - """Get a list of the supported boot devices. + """Gets a list of the supported boot devices. :param task: a task from TaskManager. :returns: A list with the supported boot devices defined in :mod:`ironic.common.boot_devices`. """ - return sorted(BOOT_DEVICE_MAP_ONEVIEW) + + return sorted(BOOT_DEVICE_MAPPING_TO_OV.keys()) @METRICS.timer('OneViewManagement.set_boot_device') @task_manager.require_exclusive_lock @common.node_has_server_profile def set_boot_device(self, task, device, persistent=False): - """Set the boot device for a node. + """Set the next boot device to the node. Sets the boot device to the node next_boot_device on driver_internal_info namespace. The operation will be @@ -239,6 +199,8 @@ class OneViewManagement(base.ManagementInterface): :mod:`ironic.common.boot_devices` [PXE, DISK, CDROM] :persistent: Whether the boot device will persist to all future boots or not, None if it is unknown. + :raises: OperationNotPermitted if no Server Profile is associated with + the node :raises: InvalidParameterValue if the boot device is unknown :raises: OneViewError if the communication with OneView fails """ @@ -248,27 +210,26 @@ class OneViewManagement(base.ManagementInterface): if next_boot_device: return next_boot_device - driver_info = task.node.driver_info - server_profile = driver_info.get('applied_server_profile_uri') + oneview_info = common.get_oneview_info(task.node) try: - profile = self.client.server_profiles.get(server_profile) - except client_exception.HPOneViewException as exc: - msg = _("Error getting boot device from OneView. Error: %s") % exc + boot_order = self.oneview_client.get_boot_order(oneview_info) + except oneview_exceptions.OneViewException as oneview_exc: + msg = (_( + "Error getting boot device from OneView. Error: %s") + % oneview_exc + ) raise exception.OneViewError(msg) - boot = profile.get('boot') - boot_order = boot.get('order') primary_device = boot_order[0] - - if primary_device not in BOOT_DEVICE_MAP_ONEVIEW_REV: + if primary_device not in BOOT_DEVICE_OV_TO_GENERIC: raise exception.InvalidParameterValue( - _("Unsupported boot device %(device)s for node: %(node)s") + _("Unsupported boot Device %(device)s for Node: %(node)s") % {"device": primary_device, "node": task.node.uuid} ) boot_device = { - 'boot_device': BOOT_DEVICE_MAP_ONEVIEW_REV.get(primary_device), + 'boot_device': BOOT_DEVICE_OV_TO_GENERIC.get(primary_device), 'persistent': True, } diff --git a/ironic/drivers/modules/oneview/power.py b/ironic/drivers/modules/oneview/power.py index 575d1a98fa..7637c38c54 100644 --- a/ironic/drivers/modules/oneview/power.py +++ b/ironic/drivers/modules/oneview/power.py @@ -1,5 +1,6 @@ -# Copyright (2015-2017) Hewlett Packard Enterprise Development LP -# Copyright (2015-2017) Universidade Federal de Campina Grande +# Copyright 2017 Hewlett Packard Enterprise Development Company LP. +# Copyright 2015 Hewlett Packard Development Company, LP +# Copyright 2015 Universidade Federal de Campina Grande # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -26,40 +27,17 @@ from ironic.drivers.modules.oneview import common from ironic.drivers.modules.oneview import deploy_utils from ironic.drivers.modules.oneview import management -client_exception = importutils.try_import('hpOneView.exceptions') -oneview_exceptions = importutils.try_import('oneview_client.exceptions') - LOG = logging.getLogger(__name__) + METRICS = metrics_utils.get_metrics_logger(__name__) -POWER_ON = {'powerState': 'On'} -POWER_OFF = {'powerState': 'Off', 'powerControl': 'PressAndHold'} -REBOOT = {'powerState': 'On', 'powerControl': 'ColdBoot'} -SOFT_REBOOT = {'powerState': 'On', 'powerControl': 'Reset'} -SOFT_POWER_OFF = {'powerState': 'Off', 'powerControl': 'PressAndHold'} - -GET_POWER_STATE_MAP = { - 'On': states.POWER_ON, - 'Off': states.POWER_OFF, - 'Resetting': states.REBOOT, - 'PoweringOff': states.POWER_ON, - 'PoweringOn': states.POWER_OFF -} - -SET_POWER_STATE_MAP = { - states.POWER_ON: POWER_ON, - states.POWER_OFF: POWER_OFF, - states.REBOOT: REBOOT, - states.SOFT_REBOOT: SOFT_REBOOT, - states.SOFT_POWER_OFF: SOFT_POWER_OFF -} +oneview_exceptions = importutils.try_import('oneview_client.exceptions') class OneViewPower(base.PowerInterface): def __init__(self): super(OneViewPower, self).__init__() - self.client = common.get_hponeview_client() self.oneview_client = common.get_oneview_client() def get_properties(self): @@ -67,7 +45,7 @@ class OneViewPower(base.PowerInterface): @METRICS.timer('OneViewPower.validate') def validate(self, task): - """Check required info on 'driver_info' and validates node with OneView. + """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, @@ -90,21 +68,19 @@ class OneViewPower(base.PowerInterface): common.verify_node_info(task.node) try: - if deploy_utils.is_node_in_use_by_oneview( - self.client, task.node - ): + 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) - - common.validate_oneview_resources_compatibility( - self.oneview_client, task - ) except exception.OneViewError as oneview_exc: raise exception.InvalidParameterValue(oneview_exc) @METRICS.timer('OneViewPower.get_power_state') def get_power_state(self, task): - """Get the current power state. + """Gets the current power state. :param task: a TaskManager instance. :returns: one of :mod:`ironic.common.states` POWER_OFF, @@ -112,24 +88,25 @@ class OneViewPower(base.PowerInterface): :raises: OneViewError if fails to retrieve power state of OneView resource """ - server_hardware = task.node.driver_info.get('server_hardware_uri') + oneview_info = common.get_oneview_info(task.node) + try: - server_hardware = self.client.server_hardware.get(server_hardware) - except client_exception.HPOneViewException as exc: + power_state = self.oneview_client.get_node_power_state( + oneview_info + ) + except oneview_exceptions.OneViewException as oneview_exc: LOG.error( "Error getting power state for node %(node)s. Error:" "%(error)s", - {'node': task.node.uuid, 'error': exc} + {'node': task.node.uuid, 'error': oneview_exc} ) - raise exception.OneViewError(error=exc) - else: - power_state = server_hardware.get('powerState') - return GET_POWER_STATE_MAP.get(power_state) + raise exception.OneViewError(error=oneview_exc) + return common.translate_oneview_power_state(power_state) @METRICS.timer('OneViewPower.set_power_state') @task_manager.require_exclusive_lock def set_power_state(self, task, power_state): - """Set the power state of the task's node. + """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 @@ -138,53 +115,47 @@ class OneViewPower(base.PowerInterface): :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.client, task.node): + 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}) - if power_state not in SET_POWER_STATE_MAP: - raise exception.InvalidParameterValue( - _("set_power_state called with invalid power state %s.") - % power_state) + 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}) - server_hardware = task.node.driver_info.get('server_hardware_uri') - try: if power_state == states.POWER_ON: management.set_boot_device(task) - self.client.server_hardware.update_power_state( - SET_POWER_STATE_MAP.get(power_state), server_hardware) + 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.client.server_hardware.update_power_state( - SET_POWER_STATE_MAP.get(states.POWER_OFF), server_hardware) + self.oneview_client.power_off(oneview_info) management.set_boot_device(task) - self.client.server_hardware.update_power_state( - SET_POWER_STATE_MAP.get(states.POWER_ON), server_hardware) + self.oneview_client.power_on(oneview_info) else: - self.client.server_hardware.update_power_state( - SET_POWER_STATE_MAP.get(power_state), server_hardware) - except client_exception.HPOneViewException as exc: + 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) + _("Error setting power state: %s") % exc + ) @METRICS.timer('OneViewPower.reboot') @task_manager.require_exclusive_lock def reboot(self, task): - """Reboot the node. + """Reboot the node :param task: a TaskManager instance. :raises: PowerStateFailure if the final state of the node is not POWER_ON. """ - current_power_state = self.get_power_state(task) - if current_power_state == states.POWER_ON: - self.set_power_state(task, states.REBOOT) - else: - self.set_power_state(task, states.POWER_ON) + + self.set_power_state(task, states.REBOOT) diff --git a/ironic/drivers/oneview.py b/ironic/drivers/oneview.py index 27038a46de..f032173a5f 100644 --- a/ironic/drivers/oneview.py +++ b/ironic/drivers/oneview.py @@ -1,5 +1,5 @@ -# Copyright (2015-2017) Hewlett Packard Enterprise Development LP -# Copyright (2015-2017) Universidade Federal de Campina Grande +# Copyright 2015 Hewlett Packard Development Company, LP +# Copyright 2015 Universidade Federal de Campina Grande # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -13,7 +13,9 @@ # License for the specific language governing permissions and limitations # under the License. -"""OneView Driver and supporting meta-classes.""" +""" +OneView Driver and supporting meta-classes. +""" from oslo_utils import importutils from ironic.common import exception @@ -71,11 +73,6 @@ class AgentPXEOneViewDriver(base.BaseDriver): driver=self.__class__.__name__, reason=_("Unable to import python-oneviewclient library")) - if not importutils.try_import('hpOneView.oneview_client'): - raise exception.DriverLoadError( - driver=self.__class__.__name__, - reason=_("Unable to import hpOneView library")) - # Checks connectivity to OneView and version compatibility on driver # initialization oneview_client = common.get_oneview_client() @@ -104,11 +101,6 @@ class ISCSIPXEOneViewDriver(base.BaseDriver): driver=self.__class__.__name__, reason=_("Unable to import python-oneviewclient library")) - if not importutils.try_import('hpOneView.oneview_client'): - raise exception.DriverLoadError( - driver=self.__class__.__name__, - reason=_("Unable to import hpOneView library")) - # Checks connectivity to OneView and version compatibility on driver # initialization oneview_client = common.get_oneview_client() diff --git a/ironic/tests/unit/drivers/modules/oneview/test_common.py b/ironic/tests/unit/drivers/modules/oneview/test_common.py index 751e5a0d32..5fa2a8553a 100644 --- a/ironic/tests/unit/drivers/modules/oneview/test_common.py +++ b/ironic/tests/unit/drivers/modules/oneview/test_common.py @@ -1,5 +1,5 @@ -# Copyright (2015-2017) Hewlett Packard Enterprise Development LP -# Copyright (2015-2017) Universidade Federal de Campina Grande +# Copyright 2015 Hewlett Packard Development Company, LP +# Copyright 2015 Universidade Federal de Campina Grande # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -17,6 +17,7 @@ import mock from oslo_utils import importutils from ironic.common import exception +from ironic.common import states from ironic.conductor import task_manager from ironic.drivers.modules.oneview import common from ironic.tests.unit.conductor import mgr_utils @@ -78,7 +79,7 @@ class OneViewCommonTestCase(db_base.DbTestCase): common.get_hponeview_client() mock_hponeview_client.assert_called_once_with(self.config) - def test__get_ilo_access(self): + def test_get_ilo_access(self): url = ("hplocons://addr=1.2.3.4&sessionkey" + "=a79659e3b3b7c8209c901ac3509a6719") remote_console = {'remoteConsoleUrl': url} @@ -239,10 +240,29 @@ class OneViewCommonTestCase(db_base.DbTestCase): {"a": '', "b": None, "c": "something"}, ["a", "b", "c"]) + def _test_translate_oneview_states(self, power_state_to_translate, + expected_translated_power_state): + translated_power_state = common.translate_oneview_power_state( + power_state_to_translate) + self.assertEqual(translated_power_state, + expected_translated_power_state) + + def test_all_scenarios_for_translate_oneview_states(self): + self._test_translate_oneview_states( + oneview_states.ONEVIEW_POWERING_OFF, states.POWER_ON) + self._test_translate_oneview_states( + oneview_states.ONEVIEW_POWER_OFF, states.POWER_OFF) + self._test_translate_oneview_states( + oneview_states.ONEVIEW_POWERING_ON, states.POWER_OFF) + self._test_translate_oneview_states( + oneview_states.ONEVIEW_RESETTING, states.REBOOT) + self._test_translate_oneview_states("anything", states.ERROR) + @mock.patch.object(common, 'get_oneview_client', spec_set=True, autospec=True) def test_validate_oneview_resources_compatibility( - self, mock_get_ov_client): + self, mock_get_ov_client + ): """Validate compatibility of resources. 1) Check validate_node_server_profile_template method is called diff --git a/ironic/tests/unit/drivers/modules/oneview/test_deploy.py b/ironic/tests/unit/drivers/modules/oneview/test_deploy.py index 233ea487ff..03db42d404 100644 --- a/ironic/tests/unit/drivers/modules/oneview/test_deploy.py +++ b/ironic/tests/unit/drivers/modules/oneview/test_deploy.py @@ -1,5 +1,7 @@ -# Copyright (2016-2017) Hewlett Packard Enterprise Development LP -# Copyright (2016-2017) Universidade Federal de Campina Grande +# Copyright 2017 Hewlett Packard Enterprise Development Company LP. +# Copyright 2016 Hewlett Packard Enterprise Development LP. +# Copyright 2016 Universidade Federal de Campina Grande +# All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -85,7 +87,6 @@ class OneViewDriverDeploy(deploy.OneViewPeriodicTasks): oneview_driver = 'fake_oneview' def __init__(self): - self.client = mock.MagicMock() self.oneview_client = mock.MagicMock() @@ -100,6 +101,7 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.config(password='password', group='oneview') mgr_utils.mock_the_extension_manager(driver='fake_oneview') + self.driver = driver_factory.get_driver('fake_oneview') self.deploy = OneViewDriverDeploy() self.os_primary = mock.MagicMock(spec=METHODS) @@ -110,7 +112,8 @@ class OneViewPeriodicTasks(db_base.DbTestCase): ) def test_node_manageable_maintenance_when_in_use_by_oneview( - self, mock_is_node_in_use_by_oneview, mock_node_get): + self, mock_is_node_in_use_by_oneview, mock_node_get + ): mock_node_get.get.return_value = self.node _setup_node_in_available_state(self.node) self.os_primary.iter_nodes.return_value = nodes_taken_by_oneview @@ -119,7 +122,7 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.os_primary, self.context ) mock_is_node_in_use_by_oneview.assert_called_once_with( - self.deploy.client, self.node + self.deploy.oneview_client, self.node ) self.assertTrue(self.os_primary.update_node.called) self.assertTrue(self.os_primary.do_provisioning_action.called) @@ -128,7 +131,8 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.node.maintenance_reason) def test_node_stay_available_when_not_in_use_by_oneview( - self, mock_is_node_in_use_by_oneview, mock_node_get): + self, mock_is_node_in_use_by_oneview, mock_node_get + ): mock_node_get.get.return_value = self.node _setup_node_in_available_state(self.node) mock_node_get.return_value = self.node @@ -138,7 +142,7 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.os_primary, self.context ) mock_is_node_in_use_by_oneview.assert_called_once_with( - self.deploy.client, self.node + self.deploy.oneview_client, self.node ) self.assertFalse(self.os_primary.update_node.called) self.assertFalse(self.os_primary.do_provisioning_action.called) @@ -146,7 +150,8 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.assertIsNone(self.node.maintenance_reason) def test_node_stay_available_when_raise_exception( - self, mock_is_node_in_use_by_oneview, mock_node_get): + self, mock_is_node_in_use_by_oneview, mock_node_get + ): mock_node_get.get.return_value = self.node _setup_node_in_available_state(self.node) side_effect = exception.OneViewError('boom') @@ -156,7 +161,7 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.os_primary, self.context ) mock_is_node_in_use_by_oneview.assert_called_once_with( - self.deploy.client, self.node + self.deploy.oneview_client, self.node ) self.assertFalse(self.os_primary.update_node.called) self.assertFalse(self.os_primary.do_provisioning_action.called) @@ -165,7 +170,8 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.node.maintenance_reason) def test_node_available_when_not_in_use_by_oneview( - self, mock_is_node_in_use_by_oneview, mock_node_get): + self, mock_is_node_in_use_by_oneview, mock_node_get + ): mock_node_get.get.return_value = self.node _setup_node_in_manageable_state(self.node) self.os_primary.iter_nodes.return_value = nodes_freed_by_oneview @@ -174,7 +180,7 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.os_primary, self.context ) mock_is_node_in_use_by_oneview.assert_called_once_with( - self.deploy.client, self.node + self.deploy.oneview_client, self.node ) self.assertTrue(self.os_primary.update_node.called) self.assertTrue(self.os_primary.do_provisioning_action.called) @@ -182,7 +188,8 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.assertIsNone(self.node.maintenance_reason) def test_node_stay_manageable_when_in_use_by_oneview( - self, mock_is_node_in_use_by_oneview, mock_node_get): + self, mock_is_node_in_use_by_oneview, mock_node_get + ): mock_node_get.get.return_value = self.node _setup_node_in_manageable_state(self.node) mock_is_node_in_use_by_oneview.return_value = True @@ -191,7 +198,7 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.os_primary, self.context ) mock_is_node_in_use_by_oneview.assert_called_once_with( - self.deploy.client, self.node + self.deploy.oneview_client, self.node ) self.assertFalse(self.os_primary.update_node.called) self.assertFalse(self.os_primary.do_provisioning_action.called) @@ -200,7 +207,8 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.node.maintenance_reason) def test_node_stay_manageable_maintenance_when_raise_exception( - self, mock_is_node_in_use_by_oneview, mock_node_get): + self, mock_is_node_in_use_by_oneview, mock_node_get + ): mock_node_get.get.return_value = self.node _setup_node_in_manageable_state(self.node) side_effect = exception.OneViewError('boom') @@ -210,7 +218,7 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.os_primary, self.context ) mock_is_node_in_use_by_oneview.assert_called_once_with( - self.deploy.client, self.node + self.deploy.oneview_client, self.node ) self.assertFalse(self.os_primary.update_node.called) self.assertFalse(self.os_primary.do_provisioning_action.called) @@ -219,7 +227,8 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.node.maintenance_reason) def test_node_manageable_maintenance_when_oneview_error( - self, mock_is_node_in_use_by_oneview, mock_node_get): + self, mock_is_node_in_use_by_oneview, mock_node_get + ): mock_node_get.get.return_value = self.node _setup_node_in_cleanfailed_state_with_oneview_error(self.node) self.os_primary.iter_nodes.return_value = nodes_taken_on_cleanfail @@ -234,7 +243,8 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.assertNotIn('oneview_error', self.node.driver_internal_info) def test_node_stay_clean_failed_when_no_oneview_error( - self, mock_is_node_in_use_by_oneview, mock_node_get): + self, mock_is_node_in_use_by_oneview, mock_node_get + ): mock_node_get.get.return_value = self.node _setup_node_in_cleanfailed_state_without_oneview_error(self.node) self.os_primary.iter_nodes.return_value = \ @@ -250,7 +260,7 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.assertNotIn('oneview_error', self.node.driver_internal_info) -@mock.patch.object(common, 'get_hponeview_client') +@mock.patch.object(common, 'get_oneview_client', spec_set=True, autospec=True) class OneViewIscsiDeployTestCase(db_base.DbTestCase): def setUp(self): @@ -278,99 +288,111 @@ class OneViewIscsiDeployTestCase(db_base.DbTestCase): expected = common.COMMON_PROPERTIES self.assertEqual(expected, self.driver.deploy.get_properties()) - @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'validate', autospec=True) + @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'validate', + spec_set=True, autospec=True) def test_validate(self, iscsi_deploy_validate_mock, mock_get_ov_client): - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: task.driver.deploy.validate(task) iscsi_deploy_validate_mock.assert_called_once_with(mock.ANY, task) - @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'prepare', autospec=True) + @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'prepare', + spec_set=True, autospec=True) @mock.patch.object(deploy_utils, 'allocate_server_hardware_to_ironic') - def test_prepare( - self, allocate_server_hardware_mock, iscsi_deploy_prepare_mock, - mock_get_ov_client): + def test_prepare(self, allocate_server_hardware_mock, + iscsi_deploy_prepare_mock, mock_get_ov_client): self.node.provision_state = states.DEPLOYING self.node.save() - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: task.driver.deploy.prepare(task) iscsi_deploy_prepare_mock.assert_called_once_with(mock.ANY, task) self.assertTrue(allocate_server_hardware_mock.called) - @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'prepare', autospec=True) - def test_prepare_active_node( - self, iscsi_deploy_prepare_mock, mock_get_ov_client): - """Ensure nodes in running states are not inadvertently changed.""" + @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'prepare', + spec_set=True, autospec=True) + def test_prepare_active_node(self, iscsi_deploy_prepare_mock, + mock_get_ov_client): + """Ensure nodes in running states are not inadvertently changed""" test_states = list(states.STABLE_STATES) - test_states.extend([ - states.CLEANING, - states.CLEANWAIT, - states.INSPECTING - ]) + test_states.extend([states.CLEANING, + states.CLEANWAIT, + states.INSPECTING]) for state in test_states: self.node.provision_state = state self.node.save() iscsi_deploy_prepare_mock.reset_mock() - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: task.driver.deploy.prepare(task) iscsi_deploy_prepare_mock.assert_called_once_with( mock.ANY, task) - @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'deploy', autospec=True) + @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'deploy', + spec_set=True, autospec=True) def test_deploy(self, iscsi_deploy_mock, mock_get_ov_client): - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: task.driver.deploy.deploy(task) iscsi_deploy_mock.assert_called_once_with(mock.ANY, task) - @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'tear_down', autospec=True) + @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'tear_down', spec_set=True, + autospec=True) def test_tear_down(self, iscsi_tear_down_mock, mock_get_ov_client): iscsi_tear_down_mock.return_value = states.DELETED - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: returned_state = task.driver.deploy.tear_down(task) iscsi_tear_down_mock.assert_called_once_with(mock.ANY, task) self.assertEqual(states.DELETED, returned_state) - @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'tear_down', autospec=True) + @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'tear_down', spec_set=True, + autospec=True) @mock.patch.object(deploy_utils, 'deallocate_server_hardware_from_ironic') def test_tear_down_with_automated_clean_disabled( - self, deallocate_server_hardware_mock, iscsi_tear_down_mock, - mock_get_ov_client): + self, deallocate_server_hardware_mock, + iscsi_tear_down_mock, mock_get_ov_client + ): CONF.conductor.automated_clean = False iscsi_tear_down_mock.return_value = states.DELETED - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: returned_state = task.driver.deploy.tear_down(task) iscsi_tear_down_mock.assert_called_once_with(mock.ANY, task) self.assertEqual(states.DELETED, returned_state) self.assertTrue(deallocate_server_hardware_mock.called) @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'prepare_cleaning', - autospec=True) + spec_set=True, autospec=True) @mock.patch.object(deploy_utils, 'allocate_server_hardware_to_ironic') - def test_prepare_cleaning( - self, allocate_server_hardware_mock, iscsi_prep_clean_mock, - mock_get_ov_client): + def test_prepare_cleaning(self, allocate_server_hardware_mock, + iscsi_prep_clean_mock, mock_get_ov_client): iscsi_prep_clean_mock.return_value = states.CLEANWAIT - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: ret = task.driver.deploy.prepare_cleaning(task) self.assertEqual(states.CLEANWAIT, ret) iscsi_prep_clean_mock.assert_called_once_with(mock.ANY, task) self.assertTrue(allocate_server_hardware_mock.called) @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'tear_down_cleaning', - autospec=True) + spec_set=True, autospec=True) @mock.patch.object(deploy_utils, 'deallocate_server_hardware_from_ironic') def test_tear_down_cleaning( - self, deallocate_server_hardware_mock, iscsi_tear_down_clean_mock, - mock_get_ov_client): + self, deallocate_server_hardware_mock, iscsi_tear_down_clean_mock, + mock_get_ov_client + ): iscsi_tear_down_clean_mock.return_value = states.CLEANWAIT - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: task.driver.deploy.tear_down_cleaning(task) iscsi_tear_down_clean_mock.assert_called_once_with(mock.ANY, task) self.assertTrue(deallocate_server_hardware_mock.called) -@mock.patch.object(common, 'get_hponeview_client') +@mock.patch.object(common, 'get_oneview_client', spec_set=True, autospec=True) class OneViewAgentDeployTestCase(db_base.DbTestCase): def setUp(self): super(OneViewAgentDeployTestCase, self).setUp() @@ -397,28 +419,32 @@ class OneViewAgentDeployTestCase(db_base.DbTestCase): expected = common.COMMON_PROPERTIES self.assertEqual(expected, self.driver.deploy.get_properties()) - @mock.patch.object(agent.AgentDeploy, 'validate', autospec=True) + @mock.patch.object(agent.AgentDeploy, 'validate', + spec_set=True, autospec=True) def test_validate(self, agent_deploy_validate_mock, mock_get_ov_client): - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: task.driver.deploy.validate(task) agent_deploy_validate_mock.assert_called_once_with(mock.ANY, task) - @mock.patch.object(agent.AgentDeploy, 'prepare', autospec=True) + @mock.patch.object(agent.AgentDeploy, 'prepare', + spec_set=True, autospec=True) @mock.patch.object(deploy_utils, 'allocate_server_hardware_to_ironic') - def test_prepare( - self, allocate_server_hardware_mock, agent_deploy_prepare_mock, - mock_get_ov_client): + def test_prepare(self, allocate_server_hardware_mock, + agent_deploy_prepare_mock, mock_get_ov_client): self.node.provision_state = states.DEPLOYING self.node.save() - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: task.driver.deploy.prepare(task) agent_deploy_prepare_mock.assert_called_once_with(mock.ANY, task) self.assertTrue(allocate_server_hardware_mock.called) - @mock.patch.object(agent.AgentDeploy, 'prepare', autospec=True) - def test_prepare_active_node( - self, agent_deploy_prepare_mock, mock_get_ov_client): - """Ensure nodes in running states are not inadvertently changed.""" + @mock.patch.object(agent.AgentDeploy, 'prepare', + spec_set=True, autospec=True) + def test_prepare_active_node(self, agent_deploy_prepare_mock, + mock_get_ov_client): + """Ensure nodes in running states are not inadvertently changed""" test_states = list(states.STABLE_STATES) test_states.extend([states.CLEANING, states.CLEANWAIT, @@ -427,14 +453,17 @@ class OneViewAgentDeployTestCase(db_base.DbTestCase): self.node.provision_state = state self.node.save() agent_deploy_prepare_mock.reset_mock() - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: task.driver.deploy.prepare(task) agent_deploy_prepare_mock.assert_called_once_with( mock.ANY, task) - @mock.patch.object(agent.AgentDeploy, 'deploy', autospec=True) + @mock.patch.object(agent.AgentDeploy, 'deploy', + spec_set=True, autospec=True) def test_deploy(self, agent_deploy_mock, mock_get_ov_client): - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: task.driver.deploy.deploy(task) agent_deploy_mock.assert_called_once_with(mock.ANY, task) @@ -442,35 +471,41 @@ class OneViewAgentDeployTestCase(db_base.DbTestCase): autospec=True) @mock.patch.object(deploy_utils, 'deallocate_server_hardware_from_ironic') def test_tear_down_with_automated_clean_disabled( - self, deallocate_server_hardware_mock, agent_tear_down_mock, - mock_get_ov_client): + self, deallocate_server_hardware_mock, + agent_tear_down_mock, mock_get_ov_client + ): CONF.conductor.automated_clean = False agent_tear_down_mock.return_value = states.DELETED - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: returned_state = task.driver.deploy.tear_down(task) agent_tear_down_mock.assert_called_once_with(mock.ANY, task) self.assertEqual(states.DELETED, returned_state) self.assertTrue(deallocate_server_hardware_mock.called) - @mock.patch.object(agent.AgentDeploy, 'prepare_cleaning', autospec=True) + @mock.patch.object(agent.AgentDeploy, 'prepare_cleaning', + spec_set=True, autospec=True) @mock.patch.object(deploy_utils, 'allocate_server_hardware_to_ironic') - def test_prepare_cleaning( - self, allocate_server_hardware_mock, - agent_prep_clean_mock, mock_get_ov_client): + def test_prepare_cleaning(self, allocate_server_hardware_mock, + agent_prep_clean_mock, mock_get_ov_client): agent_prep_clean_mock.return_value = states.CLEANWAIT - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: ret = task.driver.deploy.prepare_cleaning(task) self.assertEqual(states.CLEANWAIT, ret) agent_prep_clean_mock.assert_called_once_with(mock.ANY, task) self.assertTrue(allocate_server_hardware_mock.called) - @mock.patch.object(agent.AgentDeploy, 'tear_down_cleaning', autospec=True) + @mock.patch.object(agent.AgentDeploy, 'tear_down_cleaning', + spec_set=True, autospec=True) @mock.patch.object(deploy_utils, 'deallocate_server_hardware_from_ironic') def test_tear_down_cleaning( - self, deallocate_server_hardware_mock, - agent_tear_down_clean_mock, mock_get_ov_client): + self, deallocate_server_hardware_mock, agent_tear_down_clean_mock, + mock_get_ov_client + ): agent_tear_down_clean_mock.return_value = states.CLEANWAIT - with task_manager.acquire(self.context, self.node.uuid) as task: + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: task.driver.deploy.tear_down_cleaning(task) agent_tear_down_clean_mock.assert_called_once_with(mock.ANY, task) self.assertTrue(deallocate_server_hardware_mock.called) diff --git a/ironic/tests/unit/drivers/modules/oneview/test_deploy_utils.py b/ironic/tests/unit/drivers/modules/oneview/test_deploy_utils.py index 44929456a6..783e29005a 100644 --- a/ironic/tests/unit/drivers/modules/oneview/test_deploy_utils.py +++ b/ironic/tests/unit/drivers/modules/oneview/test_deploy_utils.py @@ -1,5 +1,6 @@ -# Copyright (2016-2017) Hewlett Packard Enterprise Development LP -# Copyright (2016-2017) Universidade Federal de Campina Grande +# Copyright 2016 Hewlett Packard Enterprise Development LP. +# Copyright 2016 Universidade Federal de Campina Grande +# All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -31,7 +32,7 @@ from ironic.tests.unit.objects import utils as obj_utils oneview_models = importutils.try_import('oneview_client.models') -@mock.patch.object(common, 'get_hponeview_client') +@mock.patch.object(common, 'get_oneview_client', spec_set=True, autospec=True) class OneViewDeployUtilsTestCase(db_base.DbTestCase): def setUp(self): @@ -49,296 +50,394 @@ class OneViewDeployUtilsTestCase(db_base.DbTestCase): driver_info=db_utils.get_test_oneview_driver_info(), ) self.info = common.get_oneview_info(self.node) - deploy_utils.is_node_in_use_by_oneview = mock.Mock(return_value=False) - deploy_utils.is_node_in_use_by_ironic = mock.Mock(return_value=True) # Tests for prepare - def test_prepare_node_is_in_use_by_oneview(self, mock_oneview_client): - """`prepare` behavior when the node has a Profile on OneView.""" - client = mock_oneview_client() - deploy_utils.is_node_in_use_by_oneview.return_value = True + def test_prepare_node_is_in_use_by_oneview(self, mock_get_ov_client): + """`prepare` behavior when the node already has a Profile on OneView. + + """ + oneview_client = mock_get_ov_client() + + fake_server_hardware = oneview_models.ServerHardware() + fake_server_hardware.server_profile_uri = "/any/sp_uri" + oneview_client.get_server_hardware.return_value = fake_server_hardware + with task_manager.acquire(self.context, self.node.uuid) as task: + driver_info = task.node.driver_info + task.node.driver_info = driver_info task.node.provision_state = states.DEPLOYING self.assertRaises( exception.InstanceDeployFailure, deploy_utils.prepare, - client, + oneview_client, task ) @mock.patch.object(objects.Node, 'save') def test_prepare_node_is_successfuly_allocated_to_ironic( - self, mock_save, mock_oneview_client): - """`prepare` behavior when the node is free from OneView standpoint.""" + self, mock_node_save, mock_get_ov_client + ): + """`prepare` behavior when the node is free from OneView standpoint. + + """ + 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: task.node.provision_state = states.DEPLOYING - deploy_utils.prepare(mock_oneview_client(), task) - self.assertTrue(mock_save.called) + deploy_utils.prepare(oneview_client, task) + self.assertTrue(oneview_client.clone_template_and_apply.called) + self.assertTrue(oneview_client.get_server_profile_from_hardware) # Tests for tear_down - def test_tear_down(self, mock_oneview_client): - """`tear_down` behavior when node already has Profile applied.""" - client = mock_oneview_client() + def test_tear_down(self, mock_get_ov_client): + """`tear_down` behavior when node already has Profile applied + + """ + sp_uri = '/rest/server-profiles/1234556789' + ov_client = mock_get_ov_client() + fake_sh = oneview_models.ServerHardware() + fake_sh.server_profile_uri = 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: - task.node.driver_info['applied_server_profile_uri'] = ( + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = \ '/rest/server-profiles/1234556789' - ) + task.node.driver_info = driver_info + self.assertIn( 'applied_server_profile_uri', task.node.driver_info ) - deploy_utils.tear_down(client, task) + deploy_utils.tear_down(ov_client, task) self.assertNotIn( 'applied_server_profile_uri', task.node.driver_info ) - self.assertTrue(client.server_profiles.delete.called) + self.assertTrue( + ov_client.delete_server_profile.called + ) # Tests for prepare_cleaning @mock.patch.object(objects.Node, 'save') def test_prepare_cleaning_when_node_does_not_have_sp_applied( - self, mock_save, mock_oneview_client): - """`prepare_cleaning` behavior when node is free.""" + self, mock_node_save, mock_get_ov_client + ): + """`prepare_cleaning` behavior when node is free + + """ + 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( - 'applied_server_profile_uri' in task.node.driver_info - ) - deploy_utils.prepare_cleaning(mock_oneview_client(), task) - self.assertTrue( - 'applied_server_profile_uri' in task.node.driver_info - ) + deploy_utils.prepare_cleaning(oneview_client, task) + self.assertTrue(oneview_client.clone_template_and_apply.called) @mock.patch.object(objects.Node, 'save') def test_prepare_cleaning_when_node_has_sp_applied( - self, mock_node_save, mock_oneview_client): - """`prepare_cleaning` behavior when node has Profile applied.""" - client = mock_oneview_client() - client.server_hardware.get.return_value = { - 'serverProfileUri': 'same/sp_applied' - } + self, mock_node_save, mock_get_ov_client + ): + """`prepare_cleaning` behavior when node already has Profile applied + + """ + oneview_client = mock_get_ov_client() + + fake_sh = oneview_models.ServerHardware() + fake_sh.server_profile_uri = 'same/sp_applied' + oneview_client.get_server_hardware_by_uuid.return_value = fake_sh + with task_manager.acquire(self.context, self.node.uuid) as task: - task.node.driver_info['applied_server_profile_uri'] = ( - 'same/sp_applied' - ) - deploy_utils.prepare_cleaning(client, task) - self.assertFalse(mock_node_save.called) + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = 'same/sp_applied' + task.node.driver_info = driver_info + + deploy_utils.prepare_cleaning(oneview_client, task) + self.assertFalse(oneview_client.clone_template_and_apply.called) def test_prepare_cleaning_node_is_in_use_by_oneview( - self, mock_oneview_client): - """`prepare_cleaning` behavior when node has Profile on OneView.""" - deploy_utils.is_node_in_use_by_oneview.return_value = True + self, mock_get_ov_client + ): + """`prepare_cleaning` behavior when node has Server Profile on OneView + + """ + oneview_client = mock_get_ov_client() + + fake_server_hardware = oneview_models.ServerHardware() + fake_server_hardware.server_profile_uri = "/any/sp_uri" + oneview_client.get_server_hardware.return_value = fake_server_hardware with task_manager.acquire(self.context, self.node.uuid) as task: + driver_info = task.node.driver_info + task.node.driver_info = driver_info + task.node.provision_state = states.DEPLOYING self.assertRaises( exception.NodeCleaningFailure, deploy_utils.prepare_cleaning, - mock_oneview_client(), + oneview_client, task ) # Tests for tear_down_cleaning - def test_tear_down_cleaning(self, mock_oneview_client): - """Check if Server Profile was deleted and its uri removed.""" - client = mock_oneview_client() + def test_tear_down_cleaning(self, mock_get_ov_client): + """Checks if Server Profile was deleted and its uri removed + + """ + sp_uri = '/rest/server-profiles/1234556789' + ov_client = mock_get_ov_client() + fake_sh = oneview_models.ServerHardware() + fake_sh.server_profile_uri = 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: - task.node.driver_info['applied_server_profile_uri'] = ( + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = \ '/rest/server-profiles/1234556789' - ) - self.assertTrue( - 'applied_server_profile_uri' in task.node.driver_info - ) - deploy_utils.tear_down_cleaning(client, task) - self.assertFalse( - 'applied_server_profile_uri' in task.node.driver_info - ) - self.assertTrue(client.server_profiles.delete.called) + task.node.driver_info = driver_info + + self.assertIn('applied_server_profile_uri', task.node.driver_info) + deploy_utils.tear_down_cleaning(ov_client, task) + self.assertNotIn('applied_server_profile_uri', + task.node.driver_info) + self.assertTrue(ov_client.delete_server_profile.called) # Tests for is_node_in_use_by_oneview - def test_is_node_in_use_by_oneview(self, mock_oneview_client): - """Node has a Server Profile applied by a third party user.""" - server_hardware = { - 'serverProfileUri': '/rest/server-profile/123456789' - } + 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: - task.node.driver_info['applied_server_profile_uri'] = ( - '/rest/server-profile/987654321' - ) + driver_info = task.node.driver_info + task.node.driver_info = driver_info self.assertTrue( - deploy_utils._is_node_in_use( - server_hardware, - task.node.driver_info['applied_server_profile_uri'], - by_oneview=True - ) + deploy_utils.is_node_in_use_by_oneview(oneview_client, + task.node) ) def test_is_node_in_use_by_oneview_no_server_profile( - self, mock_oneview_client): - """Node has no Server Profile.""" - server_hardware = {'serverProfileUri': None} + 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: - task.node.driver_info['applied_server_profile_uri'] = ( - '/rest/server-profile/123456789' - ) self.assertFalse( - deploy_utils._is_node_in_use( - server_hardware, - task.node.driver_info['applied_server_profile_uri'], - by_oneview=True - ) + 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_oneview_client): - """Check if node's Server Profile uri is the same applied by ironic.""" - server_hardware = { - 'serverProfileUri': '/rest/server-profile/123456789' - } + 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: - task.node.driver_info['applied_server_profile_uri'] = ( - '/rest/server-profile/123456789' - ) + 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( - server_hardware, - task.node.driver_info['applied_server_profile_uri'], - by_oneview=True - ) + deploy_utils.is_node_in_use_by_oneview(oneview_client, + task.node) ) # Tests for is_node_in_use_by_ironic - def test_is_node_in_use_by_ironic(self, mock_oneview_client): - """Node has a Server Profile applied by ironic.""" - server_hardware = {'serverProfileUri': 'same/applied_sp_uri/'} + def test_is_node_in_use_by_ironic(self, mock_get_ov_client): + """Node has a Server Profile 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: - task.node.driver_info['applied_server_profile_uri'] = ( - 'same/applied_sp_uri/' - ) + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = 'same/applied_sp_uri/' + task.node.driver_info = driver_info self.assertTrue( - deploy_utils._is_node_in_use( - server_hardware, - task.node.driver_info['applied_server_profile_uri'], - by_oneview=False - ) + deploy_utils.is_node_in_use_by_ironic(ov_client, task.node) ) def test_is_node_in_use_by_ironic_no_server_profile( - self, mock_oneview_client): - """Node has no Server Profile.""" - server_hardware = {'serverProfileUri': None} - with task_manager.acquire(self.context, self.node.uuid) as task: - task.node.driver_info['applied_server_profile_uri'] = ( - '/applied_sp_uri/' - ) - self.assertFalse( - deploy_utils._is_node_in_use( - server_hardware, - task.node.driver_info['applied_server_profile_uri'], - by_oneview=False - ) - ) + self, mock_get_ov_client + ): + """Node has no Server Profile. - def test__create_profile_from_template(self, mock_oneview_client): - """Check if the server_profile was created from template.""" - server_hardware_uri = "server_hardware/12456789" - sp_template_uri = "server_profile_template_uri/13245798" - client = mock_oneview_client() - client.server_profile_templates.get_new_profile.return_value = {} - server_profile = {"name": "server_profile_name", - "serverHardwareUri": server_hardware_uri, - "serverProfileTemplateUri": ""} - deploy_utils._create_profile_from_template( - client, - "server_profile_name", - server_hardware_uri, - sp_template_uri - ) - client.server_profiles.create.assert_called_with( - 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_ironic(ov_client, task.node) + ) # Tests for _add_applied_server_profile_uri_field - @mock.patch.object(objects.Node, 'save') - def test__add_applied_server_profile_uri_field( - self, save, mock_oneview_client): - """Check if applied_server_profile_uri was added to driver_info.""" - server_profile = {'uri': 'any/applied_sp_uri/'} + def test__add_applied_server_profile_uri_field(self, mock_get_ov_client): + """Checks if applied_server_profile_uri was added to driver_info. + + """ with task_manager.acquire(self.context, self.node.uuid) as task: - task.node.driver_info.pop('applied_server_profile_uri', None) - self.assertNotIn( - 'applied_server_profile_uri', task.node.driver_info - ) + driver_info = task.node.driver_info + task.node.driver_info = driver_info + fake_server_profile = oneview_models.ServerProfile() + fake_server_profile.uri = 'any/applied_sp_uri/' + + self.assertNotIn('applied_server_profile_uri', + task.node.driver_info) deploy_utils._add_applied_server_profile_uri_field( task.node, - server_profile + fake_server_profile ) self.assertIn('applied_server_profile_uri', task.node.driver_info) # Tests for _del_applied_server_profile_uri_field - @mock.patch.object(objects.Node, 'save') - def test__del_applied_server_profile_uri_field( - self, save, mock_oneview_client): - """Check if applied_server_profile_uri was removed from driver_info.""" + def test__del_applied_server_profile_uri_field(self, mock_get_ov_client): + """Checks if applied_server_profile_uri was removed from driver_info. + + """ with task_manager.acquire(self.context, self.node.uuid) as task: - task.node.driver_info['applied_server_profile_uri'] = ( - 'any/applied_sp_uri/' - ) + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = 'any/applied_sp_uri/' + task.node.driver_info = driver_info + self.assertIn('applied_server_profile_uri', task.node.driver_info) deploy_utils._del_applied_server_profile_uri_field(task.node) - self.assertNotIn( - 'applied_server_profile_uri', task.node.driver_info - ) + self.assertNotIn('applied_server_profile_uri', + task.node.driver_info) # Tests for allocate_server_hardware_to_ironic @mock.patch.object(objects.Node, 'save') def test_allocate_server_hardware_to_ironic( - self, mock_node_save, mock_oneview_client): - """Check if a Profile was created and its uri is in driver_info.""" - client = mock_oneview_client() - server_hardware = {'serverProfileUri': None} - client.server_hardware.get.return_value = server_hardware + self, mock_node_save, mock_get_ov_client + ): + """Checks if a Server Profile was created and its uri is in driver_info. + + """ + 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: deploy_utils.allocate_server_hardware_to_ironic( - client, task.node, 'serverProfileName' + oneview_client, task.node, 'serverProfileName' ) - self.assertTrue(mock_node_save.called) + self.assertTrue(oneview_client.clone_template_and_apply.called) self.assertIn('applied_server_profile_uri', task.node.driver_info) @mock.patch.object(objects.Node, 'save') + @mock.patch.object(deploy_utils, + '_del_applied_server_profile_uri_field') def test_allocate_server_hardware_to_ironic_node_has_server_profile( - self, mock_node_save, mock_oneview_client): - """Test profile allocation when applied_server_profile_uri exists. + self, mock_delete_applied_sp, mock_node_save, mock_get_ov_client + ): + """Tests server profile allocation when applied_server_profile_uri exists. This test consider that no Server Profile is applied on the Server Hardware but the applied_server_profile_uri remained on the node. Thus, the conductor should remove the value and apply a new server profile to use the node. """ - client = mock_oneview_client() - server_hardware = {'serverProfileUri': None} - client.server_hardware.get.return_value = server_hardware + 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: - task.node.driver_info['applied_server_profile_uri'] = ( - 'any/applied_sp_uri/' - ) + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = 'any/applied_sp_uri/' + task.node.driver_info = driver_info + deploy_utils.allocate_server_hardware_to_ironic( - client, task.node, 'serverProfileName' + oneview_client, task.node, 'serverProfileName' ) - self.assertTrue(mock_node_save.called) + self.assertTrue(mock_delete_applied_sp.called) # Tests for deallocate_server_hardware_from_ironic @mock.patch.object(objects.Node, 'save') def test_deallocate_server_hardware_from_ironic( - self, mock_node_save, mock_oneview_client): - client = mock_oneview_client() - server_hardware = {'serverProfileUri': 'any/applied_sp_uri/'} - client.server_hardware.get.return_value = server_hardware + self, mock_node_save, mock_get_ov_client + ): + oneview_client = mock_get_ov_client() + + fake_sh = oneview_models.ServerHardware() + fake_sh.server_profile_uri = 'any/applied_sp_uri/' + oneview_client.get_server_hardware_by_uuid.return_value = fake_sh + mock_get_ov_client.return_value = oneview_client + with task_manager.acquire(self.context, self.node.uuid) as task: - task.node.driver_info['applied_server_profile_uri'] = ( - 'any/applied_sp_uri/' - ) + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = 'any/applied_sp_uri/' + task.node.driver_info = driver_info + deploy_utils.deallocate_server_hardware_from_ironic( - client, task + oneview_client, task.node ) - self.assertTrue(client.server_profiles.delete.called) + self.assertTrue(oneview_client.delete_server_profile.called) self.assertNotIn( 'applied_server_profile_uri', task.node.driver_info ) + + @mock.patch.object(objects.Node, 'save') + def test_deallocate_server_hardware_from_ironic_missing_profile_uuid( + self, mock_node_save, mock_get_ov_client + ): + """Test for case when server profile application fails. + + Due to an error when applying Server Profile in OneView, + the node will have no Server Profile uuid in the + 'applied_server_profile_uri' namespace. When the method + tested is called without Server Profile uuid, the client + will raise a ValueError when trying to delete the profile, + this error is converted to an OneViewError. + """ + + ov_client = mock_get_ov_client.return_value + fake_sh = oneview_models.ServerHardware() + fake_sh.server_profile_uri = 'any/applied_sp_uri/' + ov_client.get_server_hardware_by_uuid.return_value = fake_sh + ov_client.delete_server_profile.side_effect = ValueError + mock_get_ov_client.return_value = ov_client + + with task_manager.acquire(self.context, self.node.uuid) as task: + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = 'any/applied_sp_uri/' + task.node.driver_info = driver_info + self.assertRaises( + exception.OneViewError, + deploy_utils.deallocate_server_hardware_from_ironic, + ov_client, + task.node + ) + self.assertTrue(ov_client.delete_server_profile.called) + self.assertIn( + 'applied_server_profile_uri', task.node.driver_info + ) diff --git a/ironic/tests/unit/drivers/modules/oneview/test_inspect.py b/ironic/tests/unit/drivers/modules/oneview/test_inspect.py index f42f978708..d676b5e74e 100644 --- a/ironic/tests/unit/drivers/modules/oneview/test_inspect.py +++ b/ironic/tests/unit/drivers/modules/oneview/test_inspect.py @@ -1,5 +1,6 @@ -# Copyright (2016-2017) Hewlett Packard Enterprise Development LP -# Copyright (2016-2017) Universidade Federal de Campina Grande +# Copyright 2016 Hewlett Packard Enterprise Development LP. +# Copyright 2016 Universidade Federal de Campina Grande +# All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -24,6 +25,8 @@ from ironic.tests.unit.db import utils as db_utils from ironic.tests.unit.objects import utils as obj_utils +@mock.patch.object( + oneview_common, 'get_oneview_client', spec_set=True, autospec=True) class AgentPXEOneViewInspectTestCase(db_base.DbTestCase): def setUp(self): @@ -37,14 +40,15 @@ class AgentPXEOneViewInspectTestCase(db_base.DbTestCase): driver_info=db_utils.get_test_oneview_driver_info(), ) - def test_get_properties(self): + def test_get_properties(self, mock_get_ov_client): expected = deploy_utils.get_properties() with task_manager.acquire(self.context, self.node.uuid, shared=True) as task: self.assertEqual(expected, task.driver.inspect.get_properties()) - @mock.patch.object(oneview_common, 'verify_node_info') - def test_validate(self, mock_verify_node_info): + @mock.patch.object(oneview_common, 'verify_node_info', spec_set=True, + autospec=True) + def test_validate(self, mock_verify_node_info, mock_get_ov_client): self.config(enabled=False, group='inspector') with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: @@ -52,13 +56,16 @@ class AgentPXEOneViewInspectTestCase(db_base.DbTestCase): mock_verify_node_info.assert_called_once_with(task.node) @mock.patch.object(deploy_utils, 'allocate_server_hardware_to_ironic') - def test_inspect_hardware(self, mock_allocate_server_hardware_to_ironic): + def test_inspect_hardware(self, mock_allocate_server_hardware_to_ironic, + mock_get_ov_client): with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: task.driver.inspect.inspect_hardware(task) self.assertTrue(mock_allocate_server_hardware_to_ironic.called) +@mock.patch.object( + oneview_common, 'get_oneview_client', spec_set=True, autospec=True) class ISCSIPXEOneViewInspectTestCase(db_base.DbTestCase): def setUp(self): @@ -72,14 +79,15 @@ class ISCSIPXEOneViewInspectTestCase(db_base.DbTestCase): driver_info=db_utils.get_test_oneview_driver_info(), ) - def test_get_properties(self): + def test_get_properties(self, mock_get_ov_client): expected = deploy_utils.get_properties() with task_manager.acquire(self.context, self.node.uuid, shared=True) as task: self.assertEqual(expected, task.driver.inspect.get_properties()) - @mock.patch.object(oneview_common, 'verify_node_info') - def test_validate(self, mock_verify_node_info): + @mock.patch.object(oneview_common, 'verify_node_info', spec_set=True, + autospec=True) + def test_validate(self, mock_verify_node_info, mock_get_ov_client): self.config(enabled=False, group='inspector') with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: @@ -87,7 +95,8 @@ class ISCSIPXEOneViewInspectTestCase(db_base.DbTestCase): mock_verify_node_info.assert_called_once_with(task.node) @mock.patch.object(deploy_utils, 'allocate_server_hardware_to_ironic') - def test_inspect_hardware(self, mock_allocate_server_hardware_to_ironic): + def test_inspect_hardware(self, mock_allocate_server_hardware_to_ironic, + mock_get_ov_client): with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: task.driver.inspect.inspect_hardware(task) diff --git a/ironic/tests/unit/drivers/modules/oneview/test_management.py b/ironic/tests/unit/drivers/modules/oneview/test_management.py index a8be001ed4..151a9adfa2 100644 --- a/ironic/tests/unit/drivers/modules/oneview/test_management.py +++ b/ironic/tests/unit/drivers/modules/oneview/test_management.py @@ -1,5 +1,6 @@ -# Copyright (2015-2017) Hewlett Packard Enterprise Development LP -# Copyright (2015-2017) Universidade Federal de Campina Grande +# Copyright 2017 Hewlett Packard Enterprise Development Company LP. +# Copyright 2015 Hewlett Packard Development Company, LP +# Copyright 2015 Universidade Federal de Campina Grande # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -22,7 +23,6 @@ from ironic.common import driver_factory from ironic.common import exception from ironic.conductor import task_manager from ironic.drivers.modules.oneview import common -from ironic.drivers.modules.oneview import deploy_utils from ironic.drivers.modules.oneview import management from ironic.tests.unit.conductor import mgr_utils from ironic.tests.unit.db import base as db_base @@ -30,12 +30,11 @@ from ironic.tests.unit.db import utils as db_utils from ironic.tests.unit.objects import utils as obj_utils -client_exception = importutils.try_import('hpOneView.exceptions') oneview_exceptions = importutils.try_import('oneview_client.exceptions') oneview_models = importutils.try_import('oneview_client.models') -@mock.patch.object(common, 'get_hponeview_client') +@mock.patch.object(common, 'get_oneview_client', spect_set=True, autospec=True) class OneViewManagementDriverFunctionsTestCase(db_base.DbTestCase): def setUp(self): @@ -54,10 +53,26 @@ class OneViewManagementDriverFunctionsTestCase(db_base.DbTestCase): ) self.info = common.get_oneview_info(self.node) - @mock.patch.object(common, 'get_ilorest_client') - def test_set_boot_device( - self, mock_get_ilo_client, mock_get_ov_client): - ilo_client = mock_get_ilo_client() + def test_set_boot_device(self, mock_get_ov_client): + oneview_client = mock_get_ov_client() + + with task_manager.acquire(self.context, self.node.uuid) as task: + driver_internal_info = task.node.driver_internal_info + next_boot_device = {'boot_device': boot_devices.PXE, + 'persistent': False} + driver_internal_info['next_boot_device'] = next_boot_device + task.node.driver_internal_info = driver_internal_info + management.set_boot_device(task) + oneview_client.set_boot_device.assert_called_once_with( + self.info, + management.BOOT_DEVICE_MAPPING_TO_OV[boot_devices.PXE], + onetime=True + ) + driver_internal_info = task.node.driver_internal_info + self.assertNotIn('next_boot_device', driver_internal_info) + + def test_set_boot_device_persistent(self, mock_get_ov_client): + oneview_client = mock_get_ov_client() with task_manager.acquire(self.context, self.node.uuid) as task: driver_internal_info = task.node.driver_internal_info @@ -66,49 +81,16 @@ class OneViewManagementDriverFunctionsTestCase(db_base.DbTestCase): driver_internal_info['next_boot_device'] = next_boot_device task.node.driver_internal_info = driver_internal_info management.set_boot_device(task) - self.assertFalse(ilo_client.called) - patch = ilo_client.patch - self.assertFalse(patch.called) - driver_internal_info = task.node.driver_internal_info - self.assertNotIn('next_boot_device', driver_internal_info) - - @mock.patch.object(common, 'get_ilorest_client') - def test_set_boot_device_not_persistent( - self, mock_get_ilo_client, mock_get_ov_client): - ilo_client = mock_get_ilo_client() - client = mock_get_ov_client() - server_profile = {'boot': {'order': - list(management.BOOT_DEVICE_MAP_ONEVIEW_REV)}} - client.server_profiles.get.return_value = server_profile - boot_device_map_ilo = management.BOOT_DEVICE_MAP_ILO - boot_device = boot_device_map_ilo.get(boot_devices.PXE) - path = '/rest/v1/Systems/1' - body = { - "Boot": { - "BootSourceOverrideTarget": boot_device, - "BootSourceOverrideEnabled": "Once" - } - } - headers = {"Content-Type": "application/json"} - with task_manager.acquire(self.context, self.node.uuid) as task: - driver_info = task.node.driver_info - profile_uri = driver_info.get('applied_server_profile_uri') - driver_internal_info = task.node.driver_internal_info - next_boot_device = {'boot_device': boot_devices.PXE, - 'persistent': False} - driver_internal_info['next_boot_device'] = next_boot_device - task.node.driver_internal_info = driver_internal_info - management.set_boot_device(task) - update = client.server_profiles.update - update.assert_called_once_with(server_profile, profile_uri) - patch = ilo_client.patch - patch.assert_called_once_with( - path=path, body=body, headers=headers) + oneview_client.set_boot_device.assert_called_once_with( + self.info, + management.BOOT_DEVICE_MAPPING_TO_OV[boot_devices.PXE], + onetime=False + ) driver_internal_info = task.node.driver_internal_info self.assertNotIn('next_boot_device', driver_internal_info) def test_set_boot_device_invalid_device(self, mock_get_ov_client): - client = mock_get_ov_client() + oneview_client = mock_get_ov_client() with task_manager.acquire(self.context, self.node.uuid) as task: driver_internal_info = task.node.driver_internal_info @@ -119,14 +101,30 @@ class OneViewManagementDriverFunctionsTestCase(db_base.DbTestCase): self.assertRaises(exception.InvalidParameterValue, management.set_boot_device, task) - self.assertFalse(client.set_boot_device.called) + self.assertFalse(oneview_client.set_boot_device.called) self.assertIn('next_boot_device', driver_internal_info) def test_set_boot_device_fail_to_get_server_profile( self, mock_get_ov_client): - client = mock_get_ov_client() - exc = client_exception.HPOneViewException() - client.server_profiles.get.side_effect = exc + oneview_client = mock_get_ov_client() + oneview_client.get_server_profile_from_hardware.side_effect = \ + oneview_exceptions.OneViewException() + + with task_manager.acquire(self.context, self.node.uuid) as task: + driver_internal_info = task.node.driver_internal_info + next_boot_device = {'boot_device': 'disk', + 'persistent': True} + driver_internal_info['next_boot_device'] = next_boot_device + task.node.driver_internal_info = driver_internal_info + self.assertRaises(exception.OneViewError, + management.set_boot_device, + task) + self.assertFalse(oneview_client.set_boot_device.called) + self.assertIn('next_boot_device', driver_internal_info) + + def test_set_boot_device_without_server_profile(self, mock_get_ov_client): + oneview_client = mock_get_ov_client() + oneview_client.get_server_profile_from_hardware.return_value = False with task_manager.acquire(self.context, self.node.uuid) as task: driver_internal_info = task.node.driver_internal_info @@ -134,50 +132,20 @@ class OneViewManagementDriverFunctionsTestCase(db_base.DbTestCase): 'persistent': True} driver_internal_info['next_boot_device'] = next_boot_device task.node.driver_internal_info = driver_internal_info - self.assertRaises( - exception.OneViewError, + expected_msg = ( + 'A Server Profile is not associated with node %s.' + % self.node.uuid + ) + self.assertRaisesRegex( + exception.OperationNotPermitted, + expected_msg, management.set_boot_device, task ) self.assertIn('next_boot_device', driver_internal_info) - @mock.patch.object(common, 'get_ilorest_client') - def test_set_onetime_boot_persistent( - self, mock_iloclient, mock_get_ov_client): - ilo_client = mock_iloclient() - driver_internal_info = self.node.driver_internal_info - next_boot_device = {'device': 'disk', 'persistent': False} - driver_internal_info['next_boot_device'] = next_boot_device - with task_manager.acquire(self.context, self.node.uuid) as task: - management.set_onetime_boot(task) - self.assertFalse(ilo_client.called) - self.assertFalse(ilo_client.patch.called) - @mock.patch.object(common, 'get_ilorest_client') - def test_set_onetime_boot_not_persistent( - self, mock_iloclient, mock_get_ov_client): - ilo_client = mock_iloclient() - boot_device = management.BOOT_DEVICE_MAP_ILO.get(boot_devices.DISK) - path = '/rest/v1/Systems/1' - body = { - "Boot": { - "BootSourceOverrideTarget": boot_device, - "BootSourceOverrideEnabled": "Once" - } - } - headers = {"Content-Type": "application/json"} - with task_manager.acquire(self.context, self.node.uuid) as task: - driver_internal_info = task.node.driver_internal_info - next_boot_device = {'boot_device': 'disk', 'persistent': False} - driver_internal_info['next_boot_device'] = next_boot_device - task.node.driver_internal_info = driver_internal_info - management.set_onetime_boot(task) - self.assertTrue(mock_iloclient.called) - ilo_client.patch.assert_called_with( - path=path, body=body, headers=headers) - - -@mock.patch.object(common, 'get_hponeview_client') +@mock.patch.object(common, 'get_oneview_client', spect_set=True, autospec=True) class OneViewManagementDriverTestCase(db_base.DbTestCase): def setUp(self): @@ -196,33 +164,66 @@ class OneViewManagementDriverTestCase(db_base.DbTestCase): ) self.info = common.get_oneview_info(self.node) - @mock.patch.object(deploy_utils, 'is_node_in_use_by_ironic') - @mock.patch.object(common, 'validate_oneview_resources_compatibility') - def test_validate(self, mock_validate, mock_ironic_node, mock_ovclient): - mock_ironic_node.return_value = True + @mock.patch.object(common, 'validate_oneview_resources_compatibility', + spect_set=True, autospec=True) + def test_validate(self, mock_validate, mock_get_ov_client): + oneview_client = mock_get_ov_client() + self.driver.management.oneview_client = oneview_client + + fake_server_hardware = oneview_models.ServerHardware() + fake_server_hardware.server_profile_uri = 'any/applied_sp_uri/' + + oneview_client.get_server_hardware_by_uuid.return_value = ( + fake_server_hardware + ) + mock_get_ov_client.return_value = oneview_client + + driver_info = self.node.driver_info + driver_info['applied_server_profile_uri'] = 'any/applied_sp_uri/' + + self.node.driver_info = driver_info + self.node.save() + with task_manager.acquire(self.context, self.node.uuid) as task: task.driver.management.validate(task) self.assertTrue(mock_validate.called) - @mock.patch.object(deploy_utils, 'is_node_in_use_by_ironic') - @mock.patch.object(common, 'validate_oneview_resources_compatibility') - def test_validate_for_node_not_in_use_by_ironic( - self, mock_validate, mock_ironic_node, mock_ovclient): - mock_ironic_node.return_value = False + @mock.patch.object(common, 'validate_oneview_resources_compatibility', + spect_set=True, autospec=True) + def test_validate_for_node_not_in_use_by_ironic(self, + mock_validate, + mock_get_ov_client): + oneview_client = mock_get_ov_client() + + fake_server_hardware = oneview_models.ServerHardware() + fake_server_hardware.server_profile_uri = 'any/applied_sp_uri/' + + oneview_client.get_server_hardware_by_uuid.return_value = ( + fake_server_hardware + ) + mock_get_ov_client.return_value = oneview_client + + driver_info = self.node.driver_info + driver_info['applied_server_profile_uri'] = 'other/applied_sp_uri/' + + self.node.driver_info = driver_info + self.node.save() + with task_manager.acquire(self.context, self.node.uuid) as task: self.assertRaises(exception.InvalidParameterValue, task.driver.management.validate, task) def test_validate_fail(self, mock_get_ov_client): - node = obj_utils.create_test_node( - self.context, uuid=uuidutils.generate_uuid(), - id=999, driver='fake_oneview' - ) + node = obj_utils.create_test_node(self.context, + uuid=uuidutils.generate_uuid(), + id=999, + driver='fake_oneview') with task_manager.acquire(self.context, node.uuid) as task: self.assertRaises(exception.MissingParameterValue, task.driver.management.validate, task) - @mock.patch.object(common, 'validate_oneview_resources_compatibility') + @mock.patch.object(common, 'validate_oneview_resources_compatibility', + spect_set=True, autospec=True) def test_validate_fail_exception(self, mock_validate, mock_get_ov_client): mock_validate.side_effect = exception.OneViewError('message') with task_manager.acquire(self.context, self.node.uuid) as task: @@ -267,33 +268,35 @@ class OneViewManagementDriverTestCase(db_base.DbTestCase): def test_get_supported_boot_devices(self, mock_get_ov_client): with task_manager.acquire(self.context, self.node.uuid) as task: - expected = [ - boot_devices.PXE, boot_devices.DISK, boot_devices.CDROM - ] + expected = [boot_devices.PXE, boot_devices.DISK, + boot_devices.CDROM] self.assertItemsEqual( expected, task.driver.management.get_supported_boot_devices(task), ) def test_get_boot_device(self, mock_get_ov_client): - client = mock_get_ov_client() - self.driver.management.client = client - device_mapping = management.BOOT_DEVICE_MAP_ONEVIEW.items() + device_mapping = management.BOOT_DEVICE_MAPPING_TO_OV + oneview_client = mock_get_ov_client() + self.driver.management.oneview_client = oneview_client + with task_manager.acquire(self.context, self.node.uuid) as task: # For each known device on OneView, Ironic should return its # counterpart value - for ironic_device, oneview_device in device_mapping: - profile = {'boot': {'order': [oneview_device]}} - client.server_profiles.get.return_value = profile - expected = {'boot_device': ironic_device, 'persistent': True} + for device_ironic, device_ov in device_mapping.items(): + oneview_client.get_boot_order.return_value = [device_ov] + expected_response = { + 'boot_device': device_ironic, + 'persistent': True + } response = self.driver.management.get_boot_device(task) - self.assertEqual(expected, response) - self.assertTrue(client.server_profiles.get.called) + self.assertEqual(expected_response, response) + oneview_client.get_boot_order.assert_called_with(self.info) def test_get_boot_device_from_next_boot_device( self, mock_get_ov_client): - client = mock_get_ov_client() - self.driver.management.client = client + oneview_client = mock_get_ov_client() + self.driver.management.oneview_client = oneview_client with task_manager.acquire(self.context, self.node.uuid) as task: driver_internal_info = task.node.driver_internal_info @@ -307,27 +310,26 @@ class OneViewManagementDriverTestCase(db_base.DbTestCase): } response = self.driver.management.get_boot_device(task) self.assertEqual(expected_response, response) - self.assertFalse(client.get_boot_order.called) + self.assertFalse(oneview_client.get_boot_order.called) def test_get_boot_device_fail(self, mock_get_ov_client): - client = mock_get_ov_client() - self.driver.management.client = client - exc = client_exception.HPOneViewException() - client.server_profiles.get.side_effect = exc + oneview_client = mock_get_ov_client() + oneview_client.get_boot_order.side_effect = \ + oneview_exceptions.OneViewException() + self.driver.management.oneview_client = oneview_client + with task_manager.acquire(self.context, self.node.uuid) as task: - self.assertRaises( - exception.OneViewError, - self.driver.management.get_boot_device, - task - ) - self.assertTrue(client.server_profiles.get.called) + self.assertRaises(exception.OneViewError, + self.driver.management.get_boot_device, + task) + oneview_client.get_boot_order.assert_called_with(self.info) def test_get_boot_device_unknown_device(self, mock_get_ov_client): - client = mock_get_ov_client() - order = ['Eggs', 'Bacon'] - profile = {'boot': {'order': order}} - client.server_profiles.get.return_value = profile - self.driver.management.client = client + oneview_client = mock_get_ov_client() + oneview_client.get_boot_order.return_value = ["spam", + "bacon"] + self.driver.management.oneview_client = oneview_client + with task_manager.acquire(self.context, self.node.uuid) as task: self.assertRaises( exception.InvalidParameterValue, diff --git a/ironic/tests/unit/drivers/modules/oneview/test_power.py b/ironic/tests/unit/drivers/modules/oneview/test_power.py index e2c1358c6f..5ed1aa4887 100644 --- a/ironic/tests/unit/drivers/modules/oneview/test_power.py +++ b/ironic/tests/unit/drivers/modules/oneview/test_power.py @@ -1,5 +1,7 @@ -# Copyright (2015-2017) Hewlett Packard Enterprise Development LP -# Copyright (2015-2017) Universidade Federal de Campina Grande +# -*- encoding: utf-8 -*- +# +# Copyright 2015 Hewlett Packard Development Company, LP +# Copyright 2015 Universidade Federal de Campina Grande # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -24,18 +26,20 @@ from ironic.conductor import task_manager from ironic.drivers.modules.oneview import common from ironic.drivers.modules.oneview import deploy_utils from ironic.drivers.modules.oneview import management -from ironic.drivers.modules.oneview import power from ironic.tests.unit.conductor import mgr_utils from ironic.tests.unit.db import base as db_base from ironic.tests.unit.db import utils as db_utils from ironic.tests.unit.objects import utils as obj_utils -client_exception = importutils.try_import('hpOneView.exceptions') oneview_models = importutils.try_import('oneview_client.models') oneview_exceptions = importutils.try_import('oneview_client.exceptions') +POWER_ON = 'On' +POWER_OFF = 'Off' +ERROR = 'error' -@mock.patch.object(common, 'get_hponeview_client') + +@mock.patch.object(common, 'get_oneview_client', spec_set=True, autospec=True) class OneViewPowerDriverTestCase(db_base.DbTestCase): def setUp(self): @@ -53,199 +57,274 @@ class OneViewPowerDriverTestCase(db_base.DbTestCase): driver_info=db_utils.get_test_oneview_driver_info(), ) self.info = common.get_oneview_info(self.node) - deploy_utils.is_node_in_use_by_oneview = mock.Mock(return_value=False) - @mock.patch.object(common, 'validate_oneview_resources_compatibility') - def test_validate(self, mock_validate, mock_get_ov_client): + @mock.patch.object(common, 'validate_oneview_resources_compatibility', + spect_set=True, autospec=True) + @mock.patch.object(deploy_utils, 'is_node_in_use_by_oneview', + spect_set=True, autospec=True) + def test_power_interface_validate(self, mock_is_node_in_use_by_oneview, + mock_validate, mock_get_ov_client): + mock_is_node_in_use_by_oneview.return_value = False with task_manager.acquire(self.context, self.node.uuid) as task: task.driver.power.validate(task) self.assertTrue(mock_validate.called) - def test_validate_missing_parameter(self, mock_get_ov_client): - node = obj_utils.create_test_node( - self.context, uuid=uuidutils.generate_uuid(), - id=999, driver='fake_oneview') + def test_power_interface_validate_fail(self, mock_get_ov_client): + node = obj_utils.create_test_node(self.context, + uuid=uuidutils.generate_uuid(), + id=999, + driver='fake_oneview') with task_manager.acquire(self.context, node.uuid) as task: - self.assertRaises( - exception.MissingParameterValue, - task.driver.power.validate, - task) + self.assertRaises(exception.MissingParameterValue, + task.driver.power.validate, task) - @mock.patch.object(common, 'validate_oneview_resources_compatibility') - def test_validate_exception(self, mock_validate, mock_get_ov_client): + @mock.patch.object(common, 'validate_oneview_resources_compatibility', + spect_set=True, autospec=True) + def test_power_interface_validate_fail_exception(self, mock_validate, + mock_get_ov_client): mock_validate.side_effect = exception.OneViewError('message') with task_manager.acquire(self.context, self.node.uuid) as task: - self.assertRaises( - exception.InvalidParameterValue, - task.driver.power.validate, - task) + self.assertRaises(exception.InvalidParameterValue, + task.driver.power.validate, + task) - def test_validate_node_in_use_by_oneview(self, mock_get_ov_client): - deploy_utils.is_node_in_use_by_oneview.return_value = True + @mock.patch.object(common, 'validate_oneview_resources_compatibility', + spect_set=True, autospec=True) + @mock.patch.object(deploy_utils, 'is_node_in_use_by_oneview', + spect_set=True, autospec=True) + def test_power_validate_fail_node_used_by_oneview( + self, mock_is_node_in_use_by_oneview, mock_validate, + mock_get_ov_client): + mock_validate.return_value = True + mock_is_node_in_use_by_oneview.return_value = True with task_manager.acquire(self.context, self.node.uuid) as task: - self.assertRaises( - exception.InvalidParameterValue, - task.driver.power.validate, - task) + self.assertRaises(exception.InvalidParameterValue, + task.driver.power.validate, + task) - def test_get_properties(self, mock_get_ov_client): + @mock.patch.object(common, 'validate_oneview_resources_compatibility', + spect_set=True, autospec=True) + @mock.patch.object(deploy_utils, 'is_node_in_use_by_oneview', + spect_set=True, autospec=True) + def test_validate_fail_node_in_use_by_oneview( + self, mock_is_node_in_use_by_oneview, mock_validate, + mock_get_ov_client): + mock_validate.return_value = True + mock_is_node_in_use_by_oneview.side_effect = ( + exception.OneViewError('message')) + with task_manager.acquire(self.context, self.node.uuid) as task: + self.assertRaises(exception.InvalidParameterValue, + task.driver.power.validate, + task) + + def test_power_interface_get_properties(self, mock_get_ov_client): expected = common.COMMON_PROPERTIES - self.assertEqual(expected, self.driver.power.get_properties()) + self.assertItemsEqual(expected, self.driver.power.get_properties()) def test_get_power_state(self, mock_get_ov_client): - client = mock_get_ov_client() - server_hardware = {'powerState': 'On'} - client.server_hardware.get.return_value = server_hardware - self.driver.power.client = client + oneview_client = mock_get_ov_client() + oneview_client.get_node_power_state.return_value = POWER_ON + self.driver.power.oneview_client = oneview_client + with task_manager.acquire(self.context, self.node.uuid) as task: - power_state = self.driver.power.get_power_state(task) - self.assertEqual(states.POWER_ON, power_state) + self.driver.power.get_power_state(task) + oneview_client.get_node_power_state.assert_called_once_with(self.info) def test_get_power_state_fail(self, mock_get_ov_client): - client = mock_get_ov_client() - exc = client_exception.HPOneViewException() - client.server_hardware.get.side_effect = exc - self.driver.power.client = client + oneview_client = mock_get_ov_client() + oneview_client.get_node_power_state.side_effect = \ + oneview_exceptions.OneViewException() + self.driver.power.oneview_client = oneview_client + with task_manager.acquire(self.context, self.node.uuid) as task: self.assertRaises( exception.OneViewError, self.driver.power.get_power_state, - task) + task + ) @mock.patch.object(management, 'set_boot_device') - def test_set_power_on(self, mock_set_boot_device, mock_get_ov_client): - client = mock_get_ov_client() - self.driver.power.client = client - server_hardware = self.node.driver_info.get('server_hardware_uri') + def test_set_power_on( + self, mock_set_boot_device, mock_get_ov_client): + + sp_uri = '/any/server-profile' + oneview_client = mock_get_ov_client() + fake_sh = oneview_models.ServerHardware() + fake_sh.server_profile_uri = sp_uri + oneview_client = mock_get_ov_client.return_value + oneview_client.get_server_hardware_by_uuid.return_value = fake_sh + oneview_client.power_on.return_value = POWER_ON + self.driver.power.oneview_client = oneview_client + with task_manager.acquire(self.context, self.node.uuid) as task: + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = sp_uri + task.node.driver_info = driver_info self.driver.power.set_power_state(task, states.POWER_ON) - self.assertTrue(mock_set_boot_device.called) - update = client.server_hardware.update_power_state - update.assert_called_once_with(power.POWER_ON, server_hardware) + mock_set_boot_device.assert_called_once_with(task) + self.info['applied_server_profile_uri'] = sp_uri + oneview_client.power_on.assert_called_once_with(self.info) @mock.patch.object(management, 'set_boot_device') - def test_set_power_off(self, mock_set_boot_device, mock_get_ov_client): - client = mock_get_ov_client() - self.driver.power.client = client - server_hardware = self.node.driver_info.get('server_hardware_uri') + def test_set_power_off( + self, mock_set_boot_device, mock_get_ov_client): + + sp_uri = '/any/server-profile' + oneview_client = mock_get_ov_client() + fake_sh = oneview_models.ServerHardware() + fake_sh.server_profile_uri = sp_uri + oneview_client = mock_get_ov_client.return_value + oneview_client.get_server_hardware_by_uuid.return_value = fake_sh + oneview_client.power_off.return_value = POWER_OFF + self.driver.power.oneview_client = oneview_client + with task_manager.acquire(self.context, self.node.uuid) as task: + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = sp_uri + task.node.driver_info = driver_info self.driver.power.set_power_state(task, states.POWER_OFF) self.assertFalse(mock_set_boot_device.called) - update = client.server_hardware.update_power_state - update.assert_called_once_with(power.POWER_OFF, server_hardware) + self.info['applied_server_profile_uri'] = sp_uri + oneview_client.power_off.assert_called_once_with(self.info) @mock.patch.object(management, 'set_boot_device') - def test_set_power_reboot(self, mock_set_boot_device, mock_get_ov_client): - client = mock_get_ov_client() - self.driver.power.client = client - server_hardware = self.node.driver_info.get('server_hardware_uri') - with task_manager.acquire(self.context, self.node.uuid) as task: - self.driver.power.set_power_state(task, states.REBOOT) - calls = [mock.call(power.POWER_OFF, server_hardware), - mock.call(power.POWER_ON, server_hardware)] - update = client.server_hardware.update_power_state - update.assert_has_calls(calls) + def test_set_power_on_fail( + self, mock_set_boot_device, mock_get_ov_client): + + sp_uri = '/any/server-profile' + oneview_client = mock_get_ov_client() + fake_sh = oneview_models.ServerHardware() + fake_sh.server_profile_uri = sp_uri + oneview_client.get_server_hardware_by_uuid.return_value = fake_sh + exc = oneview_exceptions.OneViewException() + oneview_client.power_on.side_effect = exc + self.driver.power.oneview_client = oneview_client - @mock.patch.object(management, 'set_boot_device') - def test_set_power_on_fail(self, mock_set_boot_device, mock_get_ov_client): - client = mock_get_ov_client() - exc = client_exception.HPOneViewException() - client.server_hardware.update_power_state.side_effect = exc - self.driver.power.client = client with task_manager.acquire(self.context, self.node.uuid) as task: - self.assertRaises( - exception.OneViewError, - self.driver.power.set_power_state, - task, - states.POWER_ON) + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = sp_uri + task.node.driver_info = driver_info + self.assertRaises(exception.OneViewError, + self.driver.power.set_power_state, task, + states.POWER_ON) mock_set_boot_device.assert_called_once_with(task) + self.info['applied_server_profile_uri'] = sp_uri + oneview_client.power_on.assert_called_once_with(self.info) @mock.patch.object(management, 'set_boot_device') def test_set_power_off_fail( self, mock_set_boot_device, mock_get_ov_client): - client = mock_get_ov_client() - exc = client_exception.HPOneViewException() - client.server_hardware.update_power_state.side_effect = exc - self.driver.power.client = client - with task_manager.acquire(self.context, self.node.uuid) as task: - self.assertRaises( - exception.OneViewError, - self.driver.power.set_power_state, - task, - states.POWER_OFF) - self.assertFalse(mock_set_boot_device.called) - @mock.patch.object(management, 'set_boot_device') - def test_reboot_fail_with_hardware_on( - self, mock_set_boot_device, mock_get_ov_client): - client = mock_get_ov_client() - server_hardware = {'powerState': 'On'} - client.server_hardware.get.return_value = server_hardware - self.driver.power.client = client - exc = client_exception.HPOneViewException() - client.server_hardware.update_power_state.side_effect = exc - self.driver.power.client = client - with task_manager.acquire(self.context, self.node.uuid) as task: - self.assertRaises( - exception.OneViewError, - self.driver.power.reboot, - task) - self.assertFalse(mock_set_boot_device.called) + sp_uri = '/any/server-profile' + oneview_client = mock_get_ov_client() + fake_sh = oneview_models.ServerHardware() + fake_sh.server_profile_uri = sp_uri + oneview_client.get_server_hardware_by_uuid.return_value = fake_sh + exc = oneview_exceptions.OneViewException() + oneview_client.power_off.side_effect = exc + self.driver.power.oneview_client = oneview_client - @mock.patch.object(management, 'set_boot_device') - def test_reboot_fail_with_hardware_off( - self, mock_set_boot_device, mock_get_ov_client): - client = mock_get_ov_client() - server_hardware = {'powerState': 'Off'} - client.server_hardware.get.return_value = server_hardware - self.driver.power.client = client - exc = client_exception.HPOneViewException() - client.server_hardware.update_power_state.side_effect = exc - self.driver.power.client = client with task_manager.acquire(self.context, self.node.uuid) as task: - self.assertRaises( - exception.OneViewError, - self.driver.power.reboot, - task) - mock_set_boot_device.assert_called_once_with(task) + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = sp_uri + task.node.driver_info = driver_info + self.assertRaises(exception.OneViewError, + self.driver.power.set_power_state, task, + states.POWER_OFF) + self.assertFalse(mock_set_boot_device.called) + self.info['applied_server_profile_uri'] = sp_uri + oneview_client.power_off.assert_called_once_with(self.info) @mock.patch.object(management, 'set_boot_device') def test_set_power_invalid_state( self, mock_set_boot_device, mock_get_ov_client): + + sp_uri = '/any/server-profile' + oneview_client = mock_get_ov_client() + fake_sh = oneview_models.ServerHardware() + fake_sh.server_profile_uri = sp_uri + oneview_client.get_server_hardware_by_uuid.return_value = fake_sh + exc = oneview_exceptions.OneViewException() + oneview_client.power_off.side_effect = exc + self.driver.power.oneview_client = oneview_client + with task_manager.acquire(self.context, self.node.uuid) as task: - self.assertRaises( - exception.InvalidParameterValue, - self.driver.power.set_power_state, - task, - 'fake_state') + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = sp_uri + task.node.driver_info = driver_info + self.assertRaises(exception.InvalidParameterValue, + self.driver.power.set_power_state, task, + 'fake state') self.assertFalse(mock_set_boot_device.called) @mock.patch.object(management, 'set_boot_device') - def test_set_power_reboot_with_hardware_on( + def test_set_power_reboot( self, mock_set_boot_device, mock_get_ov_client): - client = mock_get_ov_client() - server_hardware = {'powerState': 'On'} - client.server_hardware.get.return_value = server_hardware - self.driver.power.client = client - server_hardware = self.node.driver_info.get('server_hardware_uri') + + sp_uri = '/any/server-profile' + oneview_client = mock_get_ov_client() + fake_sh = oneview_models.ServerHardware() + fake_sh.server_profile_uri = sp_uri + oneview_client.get_server_hardware_by_uuid.return_value = fake_sh + oneview_client.power_off.return_value = POWER_OFF + oneview_client.power_on.return_value = POWER_ON + self.driver.power.oneview_client = oneview_client + with task_manager.acquire(self.context, self.node.uuid) as task: - self.driver.power.reboot(task) - calls = [mock.call(power.POWER_OFF, server_hardware), - mock.call(power.POWER_ON, server_hardware)] - update = client.server_hardware.update_power_state - update.assert_has_calls(calls) + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = sp_uri + task.node.driver_info = driver_info + self.driver.power.set_power_state(task, states.REBOOT) mock_set_boot_device.assert_called_once_with(task) + self.info['applied_server_profile_uri'] = sp_uri + oneview_client.power_off.assert_called_once_with(self.info) + oneview_client.power_off.assert_called_once_with(self.info) + oneview_client.power_on.assert_called_once_with(self.info) @mock.patch.object(management, 'set_boot_device') - def test_set_power_reboot_with_hardware_off( + def test_reboot( self, mock_set_boot_device, mock_get_ov_client): - client = mock_get_ov_client() - server_hardware = {'powerState': 'Off'} - client.server_hardware.get.return_value = server_hardware - self.driver.power.client = client - server_hardware = self.node.driver_info.get('server_hardware_uri') + + sp_uri = '/any/server-profile' + oneview_client = mock_get_ov_client() + fake_sh = oneview_models.ServerHardware() + fake_sh.server_profile_uri = sp_uri + oneview_client.get_server_hardware_by_uuid.return_value = fake_sh + oneview_client.power_off.return_value = POWER_OFF + oneview_client.power_on.return_value = POWER_ON + self.driver.power.oneview_client = oneview_client + with task_manager.acquire(self.context, self.node.uuid) as task: + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = sp_uri + task.node.driver_info = driver_info self.driver.power.reboot(task) - update = client.server_hardware.update_power_state - update.assert_called_once_with(power.POWER_ON, server_hardware) mock_set_boot_device.assert_called_once_with(task) + self.info['applied_server_profile_uri'] = sp_uri + oneview_client.power_off.assert_called_once_with(self.info) + oneview_client.power_on.assert_called_once_with(self.info) + + @mock.patch.object(management, 'set_boot_device') + def test_reboot_fail( + self, mock_set_boot_device, mock_get_ov_client): + + sp_uri = '/any/server-profile' + oneview_client = mock_get_ov_client() + fake_sh = oneview_models.ServerHardware() + fake_sh.server_profile_uri = sp_uri + oneview_client.get_server_hardware_by_uuid.return_value = fake_sh + exc = oneview_exceptions.OneViewException() + oneview_client.power_off.side_effect = exc + self.driver.power.oneview_client = oneview_client + + with task_manager.acquire(self.context, + self.node.uuid) as task: + driver_info = task.node.driver_info + driver_info['applied_server_profile_uri'] = sp_uri + task.node.driver_info = driver_info + self.assertRaises(exception.OneViewError, + self.driver.power.reboot, task) + self.assertFalse(mock_set_boot_device.called) + self.info['applied_server_profile_uri'] = sp_uri + oneview_client.power_off.assert_called_once_with(self.info) + self.assertFalse(oneview_client.power_on.called)