diff --git a/ironic/drivers/modules/oneview/common.py b/ironic/drivers/modules/oneview/common.py index 2e7e1ab77f..1f44ba1709 100644 --- a/ironic/drivers/modules/oneview/common.py +++ b/ironic/drivers/modules/oneview/common.py @@ -21,7 +21,6 @@ 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,6 +33,7 @@ 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."), @@ -281,24 +281,6 @@ 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 of the node info. @@ -334,35 +316,31 @@ 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, oneview_client) + ensure_server_profile(task) return func(self, *args, **kwargs) return inner -def has_server_profile(task, oneview_client): +def ensure_server_profile(task): """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 oneview_client: an instance of the OneView client :param task: a TaskManager instance containing the node to act on. + :raises: OneViewError if failed to get server profile from OneView """ - oneview_info = get_oneview_info(task.node) + oneview_client = get_hponeview_client() try: - node_has_server_profile = ( - oneview_client.get_server_profile_from_hardware(oneview_info) - ) - except oneview_exceptions.OneViewException as oneview_exc: + profile_uri = task.node.driver_info.get('applied_server_profile_uri') + oneview_client.server_profiles.get(profile_uri) + except client_exception.HPOneViewException as exc: LOG.error( - "Failed to get server profile from OneView appliance for" - " node %(node)s. Error: %(message)s", - {"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 + "Failed to get server profile: %(profile)s from OneView appliance " + "for node %(node)s. Error: %(message)s", { + "profile": profile_uri, + "node": task.node.uuid, + "message": exc + } ) + raise exception.OneViewError(error=exc) diff --git a/ironic/drivers/modules/oneview/deploy.py b/ironic/drivers/modules/oneview/deploy.py index a7d7bff8d3..b4857901e0 100644 --- a/ironic/drivers/modules/oneview/deploy.py +++ b/ironic/drivers/modules/oneview/deploy.py @@ -67,9 +67,7 @@ class OneViewPeriodicTasks(object): node = objects.Node.get(context, node_uuid) try: - oneview_using = deploy_utils.is_node_in_use_by_oneview( - self.oneview_client, node - ) + oneview_using = deploy_utils.is_node_in_use_by_oneview(node) except exception.OneViewError as e: # NOTE(xavierr): Skip this node and process the # remaining nodes. This node will be checked in @@ -130,7 +128,7 @@ class OneViewPeriodicTasks(object): try: oneview_using = deploy_utils.is_node_in_use_by_oneview( - self.oneview_client, node + node ) except exception.OneViewError as e: # NOTE(xavierr): Skip this node and process the @@ -240,23 +238,23 @@ class OneViewIscsiDeploy(iscsi_deploy.ISCSIDeploy, OneViewPeriodicTasks): @METRICS.timer('OneViewIscsiDeploy.prepare') def prepare(self, task): - deploy_utils.prepare(self.oneview_client, task) + deploy_utils.prepare(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.oneview_client, task) + deploy_utils.tear_down(task) return super(OneViewIscsiDeploy, self).tear_down(task) @METRICS.timer('OneViewIscsiDeploy.prepare_cleaning') def prepare_cleaning(self, task): - deploy_utils.prepare_cleaning(self.oneview_client, task) + deploy_utils.prepare_cleaning(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.oneview_client, task) + deploy_utils.tear_down_cleaning(task) super(OneViewIscsiDeploy, self).tear_down_cleaning(task) @@ -284,21 +282,21 @@ class OneViewAgentDeploy(agent.AgentDeploy, OneViewPeriodicTasks): @METRICS.timer('OneViewAgentDeploy.prepare') def prepare(self, task): - deploy_utils.prepare(self.oneview_client, task) + deploy_utils.prepare(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.oneview_client, task) + deploy_utils.tear_down(task) return super(OneViewAgentDeploy, self).tear_down(task) @METRICS.timer('OneViewAgentDeploy.prepare_cleaning') def prepare_cleaning(self, task): - deploy_utils.prepare_cleaning(self.oneview_client, task) + deploy_utils.prepare_cleaning(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.oneview_client, task) + deploy_utils.tear_down_cleaning(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 5cb088c340..db17d0cdba 100644 --- a/ironic/drivers/modules/oneview/deploy_utils.py +++ b/ironic/drivers/modules/oneview/deploy_utils.py @@ -27,20 +27,20 @@ LOG = logging.getLogger(__name__) oneview_exception = importutils.try_import('oneview_client.exceptions') oneview_utils = importutils.try_import('oneview_client.utils') +client_exception = importutils.try_import('hpOneView.exceptions') def get_properties(): return common.COMMON_PROPERTIES -def prepare(oneview_client, task): +def prepare(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 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 @@ -56,14 +56,13 @@ def prepare(oneview_client, task): {"instance_name": instance_display_name, "instance_uuid": instance_uuid} ) - allocate_server_hardware_to_ironic(oneview_client, task.node, - server_profile_name) + allocate_server_hardware_to_ironic(task.node, server_profile_name) except exception.OneViewError as e: raise exception.InstanceDeployFailure(node=task.node.uuid, reason=e) -def tear_down(oneview_client, task): +def tear_down(task): """Remove Server profile and update the node when tear down. This method is responsible for power a Server Hardware off, remove a Server @@ -71,26 +70,24 @@ def tear_down(oneview_client, task): Profile from the node's 'applied_server_profile_uri' in properties/capabilities. - :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(oneview_client, task.node) + deallocate_server_hardware_from_ironic(task) except exception.OneViewError as e: raise exception.InstanceDeployFailure(node=task.node.uuid, reason=e) -def prepare_cleaning(oneview_client, task): +def prepare_cleaning(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 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 @@ -99,8 +96,7 @@ def prepare_cleaning(oneview_client, task): """ try: server_profile_name = "Ironic Cleaning [%s]" % task.node.uuid - allocate_server_hardware_to_ironic(oneview_client, task.node, - server_profile_name) + allocate_server_hardware_to_ironic(task.node, server_profile_name) except exception.OneViewError as e: oneview_error = common.SERVER_HARDWARE_ALLOCATION_ERROR driver_internal_info = task.node.driver_internal_info @@ -111,7 +107,7 @@ def prepare_cleaning(oneview_client, task): reason=e) -def tear_down_cleaning(oneview_client, task): +def tear_down_cleaning(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 @@ -119,49 +115,75 @@ def tear_down_cleaning(oneview_client, task): Profile from the node's 'applied_server_profile_uri' in properties/capabilities. - :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(oneview_client, task.node) + deallocate_server_hardware_from_ironic(task) except exception.OneViewError as e: raise exception.NodeCleaningFailure(node=task.node.uuid, reason=e) +def _create_profile_from_template( + oneview_client, server_profile_name, + server_hardware_uri, server_profile_template): + """Create a server profile from a server profile template. + + :param oneview_client: an HPE 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 OneViewError: if the communication with OneView fails + + """ + server_profile = oneview_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'] = "" + try: + return oneview_client.server_profiles.create(server_profile) + except client_exception.HPOneViewException as e: + msg = (_("Error while creating a Server Profile for Server Hardware: " + "%(sh_uri)s. Error: %(error)s") % + {'sh_uri': server_hardware_uri, 'error': e}) + raise exception.OneViewError(error=msg) + + def _is_node_in_use(server_hardware, applied_sp_uri, by_oneview=False): """Check if node is in use by ironic or by OneView. + :param server_hardware: Server Hardware object. + :param applied_sp_uri: Server Profile URI applied in the node. :param by_oneview: Boolean value. True when want to verify if node is in use by OneView. False to verify if node is in use by ironic. - :param node: an ironic node object :returns: Boolean value. True if by_oneview param is also True and node is in use by OneView, False otherwise. True if by_oneview param is False and node is in use by ironic, False otherwise. - """ - operation = operator.ne if by_oneview else operator.eq - return (server_hardware.server_profile_uri not in (None, '') and - operation(applied_sp_uri, server_hardware.server_profile_uri)) + server_profile_uri = server_hardware.get('serverProfileUri') + return (server_profile_uri and + operation(applied_sp_uri, server_profile_uri)) -def is_node_in_use_by_oneview(oneview_client, node): +def is_node_in_use_by_oneview(node): """Check if node is in use by OneView user. - :param oneview_client: an instance of the OneView client - :param node: an ironic node object + :param node: an ironic node object. :returns: Boolean value. True if node is in use by OneView, False otherwise. :raises OneViewError: if not possible to get OneView's informations for the given node, if not possible to retrieve Server Hardware from OneView. - """ - + oneview_client = common.get_hponeview_client() positive = _("Node '%s' is in use by OneView.") % node.uuid negative = _("Node '%s' is not in use by OneView.") % node.uuid @@ -175,19 +197,17 @@ def is_node_in_use_by_oneview(oneview_client, node): predicate, positive, negative) -def is_node_in_use_by_ironic(oneview_client, node): +def is_node_in_use_by_ironic(node): """Check if node is in use by ironic in OneView. - :param oneview_client: an instance of the OneView client - :param node: an ironic node object + :param node: an ironic node object. :returns: Boolean value. True if node is in use by ironic, False otherwise. :raises OneViewError: if not possible to get OneView's information for the given node, if not possible to retrieve Server Hardware from OneView. - """ - + oneview_client = common.get_hponeview_client() positive = _("Node '%s' is in use by Ironic.") % node.uuid negative = _("Node '%s' is not in use by Ironic.") % node.uuid @@ -215,25 +235,17 @@ def _check_applied_server_profile(oneview_client, node, """ oneview_info = common.get_oneview_info(node) - - sh_uuid = oneview_utils.get_uuid_from_uri( - oneview_info.get("server_hardware_uri") - ) - try: - server_hardware = oneview_client.get_server_hardware_by_uuid( - sh_uuid + server_hardware = oneview_client.server_hardware.get( + oneview_info.get('server_hardware_uri') ) - except oneview_exception.OneViewResourceNotFoundError as e: + except client_exception.HPOneViewResourceNotFound 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: @@ -248,10 +260,10 @@ def _add_applied_server_profile_uri_field(node, applied_profile): """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.uri + driver_info['applied_server_profile_uri'] = applied_profile.get('uri') node.driver_info = driver_info node.save() @@ -268,38 +280,35 @@ def _del_applied_server_profile_uri_field(node): node.save() -def allocate_server_hardware_to_ironic(oneview_client, node, - server_profile_name): +def allocate_server_hardware_to_ironic(node, server_profile_name): """Allocate Server Hardware to ironic. - :param oneview_client: an instance of the OneView client - :param node: an ironic node object + :param node: an ironic node object. :param server_profile_name: a formatted string with the Server Profile - name + name. :raises OneViewError: if an error occurs while allocating the Server - Hardware to ironic - + Hardware to ironic or the node is already in use by OneView. """ - node_in_use_by_oneview = is_node_in_use_by_oneview(oneview_client, node) + oneview_client = common.get_hponeview_client() + node_in_use_by_oneview = is_node_in_use_by_oneview(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 = oneview_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) + if not server_hardware: + msg = _("An error occurred during allocating server hardware to " + "ironic. Server hardware: %s not found.") % sh_uri + raise exception.OneViewError(error=msg) # Don't have Server Profile on OneView but has # `applied_server_profile_uri` on driver_info - if (server_hardware.server_profile_uri in (None, '') and - applied_sp_uri is not (None, '')): + if not server_hardware.get('serverProfileUri') and applied_sp_uri: _del_applied_server_profile_uri_field(node) LOG.info( @@ -311,8 +320,8 @@ def allocate_server_hardware_to_ironic(oneview_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.server_profile_uri and - server_hardware.server_profile_uri == applied_sp_uri): + if (applied_sp_uri and server_hardware.get( + 'serverProfileUri') == applied_sp_uri): LOG.info( "The Server Profile %(applied_sp_uri)s was already applied " "by ironic on node %(node_uuid)s. Reusing.", @@ -321,8 +330,8 @@ def allocate_server_hardware_to_ironic(oneview_client, node, return try: - applied_profile = oneview_client.clone_template_and_apply( - server_profile_name, sh_uuid, spt_uuid + applied_profile = _create_profile_from_template( + oneview_client, server_profile_name, sh_uri, spt_uri ) _add_applied_server_profile_uri_field(node, applied_profile) @@ -330,46 +339,42 @@ def allocate_server_hardware_to_ironic(oneview_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.uri} + "server_profile_uuid": applied_profile.get('uri')} ) - except oneview_exception.OneViewServerProfileAssignmentError as e: + except client_exception.HPOneViewInvalidResource 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(oneview_client, node): +def deallocate_server_hardware_from_ironic(task): """Deallocate Server Hardware from ironic. - :param oneview_client: an instance of the OneView client - :param node: an ironic node object + :param task: a TaskManager object :raises OneViewError: if an error occurs while deallocating the Server Hardware to ironic """ + node = task.node + oneview_client = common.get_hponeview_client() - if is_node_in_use_by_ironic(oneview_client, node): - + if is_node_in_use_by_ironic(node): oneview_info = common.get_oneview_info(node) - server_profile_uuid = oneview_utils.get_uuid_from_uri( - oneview_info.get('applied_server_profile_uri') - ) + server_profile_uri = oneview_info.get('applied_server_profile_uri') try: - oneview_client.power_off(oneview_info) - oneview_client.delete_server_profile(server_profile_uuid) + task.driver.power.set_power_state(task, states.POWER_OFF) + oneview_client.server_profiles.delete(server_profile_uri) _del_applied_server_profile_uri_field(node) LOG.info("Server Profile %(server_profile_uuid)s was deleted " "from node %(node_uuid)s in OneView.", - {'server_profile_uuid': server_profile_uuid, + {'server_profile_uri': server_profile_uri, 'node_uuid': node.uuid}) - except (ValueError, oneview_exception.OneViewException) as e: + except client_exception.HPOneViewException 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 a44626cb3e..3bc0ecc614 100644 --- a/ironic/drivers/modules/oneview/inspect.py +++ b/ironic/drivers/modules/oneview/inspect.py @@ -68,7 +68,7 @@ class OneViewInspect(inspector.Inspector): def inspect_hardware(self, task): profile_name = 'Ironic Inspecting [%s]' % task.node.uuid deploy_utils.allocate_server_hardware_to_ironic( - self.oneview_client, task.node, profile_name + task.node, profile_name ) return super(OneViewInspect, self).inspect_hardware(task) @@ -96,12 +96,9 @@ 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.oneview_client, task.node) + ]: + deploy_utils.deallocate_server_hardware_from_ironic(task.node) return result diff --git a/ironic/drivers/modules/oneview/management.py b/ironic/drivers/modules/oneview/management.py index f1f7cb37aa..489215716e 100644 --- a/ironic/drivers/modules/oneview/management.py +++ b/ironic/drivers/modules/oneview/management.py @@ -25,22 +25,68 @@ from ironic.drivers import base from ironic.drivers.modules.oneview import common from ironic.drivers.modules.oneview import deploy_utils -LOG = logging.getLogger(__name__) +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_MAPPING_TO_OV = { - boot_devices.DISK: 'HardDisk', - boot_devices.PXE: 'PXE', +BOOT_DEVICE_MAP_ONEVIEW = { boot_devices.CDROM: 'CD', + boot_devices.DISK: 'HardDisk', + boot_devices.PXE: 'PXE' } -BOOT_DEVICE_OV_TO_GENERIC = { - v: k - for k, v in BOOT_DEVICE_MAPPING_TO_OV.items() +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' } -oneview_exceptions = importutils.try_import('oneview_client.exceptions') +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 not next_boot_device: + return + + boot_device = next_boot_device.get('boot_device') + persistent = next_boot_device.get('persistent') + + if persistent: + return + + server_hardware = task.node.driver_info.get('server_hardware_uri') + ilo_client = common.get_ilorest_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"} + try: + ilo_client.patch(path=path, body=body, headers=headers) + except Exception as e: + msg = (_("Error while trying to set onetime boot on Server Hardware: " + "%(sh_uri)s. Error: %(error)s") % + {'sh_uri': server_hardware, 'error': e}) + raise exception.OneViewError(error=msg) def set_boot_device(task): @@ -51,12 +97,10 @@ 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 """ - oneview_client = common.get_oneview_client() - common.has_server_profile(task, oneview_client) + oneview_client = common.get_hponeview_client() + common.ensure_server_profile(task) driver_internal_info = task.node.driver_internal_info next_boot_device = driver_internal_info.get('next_boot_device') @@ -64,7 +108,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_MAPPING_TO_OV): + if boot_device not in sorted(BOOT_DEVICE_MAP_ONEVIEW): raise exception.InvalidParameterValue( _("Invalid boot device %s specified.") % boot_device) @@ -73,16 +117,24 @@ 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: - 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) + server_profile = oneview_client.server_profiles.get(profile) + boot = server_profile.get('boot', {}) + order = boot.get('order', []) + if boot_device in order: + order.remove(boot_device) + order.insert(0, boot_device) + boot['order'] = order + server_profile['boot'] = boot + oneview_client.server_profiles.update(server_profile, profile) + set_onetime_boot(task) driver_internal_info.pop('next_boot_device', None) task.node.driver_internal_info = driver_internal_info task.node.save() - except oneview_exceptions.OneViewException as oneview_exc: + except client_exception.HPOneViewException as oneview_exc: msg = (_( "Error setting boot device on OneView. Error: %s") % oneview_exc @@ -128,9 +180,7 @@ class OneViewManagement(base.ManagementInterface): common.validate_oneview_resources_compatibility( self.oneview_client, task) - if not deploy_utils.is_node_in_use_by_ironic( - self.oneview_client, task.node - ): + if not deploy_utils.is_node_in_use_by_ironic(task.node): raise exception.InvalidParameterValue( _("Node %s is not in use by ironic.") % task.node.uuid) except exception.OneViewError as oneview_exc: @@ -145,7 +195,7 @@ class OneViewManagement(base.ManagementInterface): in :mod:`ironic.common.boot_devices`. """ - return sorted(BOOT_DEVICE_MAPPING_TO_OV.keys()) + return sorted(BOOT_DEVICE_MAP_ONEVIEW) @METRICS.timer('OneViewManagement.set_boot_device') @task_manager.require_exclusive_lock @@ -198,37 +248,43 @@ 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 """ + oneview_client = common.get_hponeview_client() driver_internal_info = task.node.driver_internal_info next_boot_device = driver_internal_info.get('next_boot_device') if next_boot_device: return next_boot_device - oneview_info = common.get_oneview_info(task.node) + driver_info = task.node.driver_info + server_profile = driver_info.get('applied_server_profile_uri') try: - 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 - ) + profile = oneview_client.server_profiles.get(server_profile) + primary_device = None + boot = profile.get('boot', {}) + boot_order = boot.get('order', []) + if boot_order: + primary_device = boot_order[0] + except client_exception.HPOneViewException as exc: + msg = _("Error on node: %(node)s while getting Server Profile: " + "%(profile)s of the from OneView. Error: %(error)s.") % { + 'profile': server_profile, + 'node': task.node.uuid, + 'error': exc + } raise exception.OneViewError(msg) - primary_device = boot_order[0] - if primary_device not in BOOT_DEVICE_OV_TO_GENERIC: + if primary_device not in BOOT_DEVICE_MAP_ONEVIEW_REV: 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_OV_TO_GENERIC.get(primary_device), + 'boot_device': BOOT_DEVICE_MAP_ONEVIEW_REV.get(primary_device), 'persistent': True, } diff --git a/ironic/drivers/modules/oneview/power.py b/ironic/drivers/modules/oneview/power.py index af542e039e..41b96861a5 100644 --- a/ironic/drivers/modules/oneview/power.py +++ b/ironic/drivers/modules/oneview/power.py @@ -26,11 +26,34 @@ 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__) -oneview_exceptions = importutils.try_import('oneview_client.exceptions') +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 +} class OneViewPower(base.PowerInterface): @@ -68,10 +91,9 @@ class OneViewPower(base.PowerInterface): try: common.validate_oneview_resources_compatibility( - self.oneview_client, task) - - if deploy_utils.is_node_in_use_by_oneview(self.oneview_client, - task.node): + self.oneview_client, task + ) + if deploy_utils.is_node_in_use_by_oneview(task.node): raise exception.InvalidParameterValue( _("Node %s is in use by OneView.") % task.node.uuid) except exception.OneViewError as oneview_exc: @@ -87,20 +109,21 @@ class OneViewPower(base.PowerInterface): :raises: OneViewError if fails to retrieve power state of OneView resource """ - oneview_info = common.get_oneview_info(task.node) - + oneview_client = common.get_hponeview_client() + server_hardware = task.node.driver_info.get('server_hardware_uri') try: - power_state = self.oneview_client.get_node_power_state( - oneview_info - ) - except oneview_exceptions.OneViewException as oneview_exc: + server_hardware = oneview_client.server_hardware.get( + server_hardware) + except client_exception.HPOneViewException as exc: LOG.error( "Error getting power state for node %(node)s. Error:" "%(error)s", - {'node': task.node.uuid, 'error': oneview_exc} + {'node': task.node.uuid, 'error': exc} ) - raise exception.OneViewError(error=oneview_exc) - return common.translate_oneview_power_state(power_state) + raise exception.OneViewError(error=exc) + else: + power_state = server_hardware.get('powerState') + return GET_POWER_STATE_MAP.get(power_state) @METRICS.timer('OneViewPower.set_power_state') @task_manager.require_exclusive_lock @@ -114,38 +137,50 @@ 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.oneview_client, - task.node): + oneview_client = common.get_hponeview_client() + + if deploy_utils.is_node_in_use_by_oneview(task.node): raise exception.PowerStateFailure(_( "Cannot set power state '%(power_state)s' to node %(node)s. " "The node is in use by OneView.") % {'power_state': power_state, 'node': task.node.uuid}) - oneview_info = common.get_oneview_info(task.node) + if power_state not in SET_POWER_STATE_MAP: + raise exception.InvalidParameterValue( + _("set_power_state called with invalid power state %(state)s " + "on node: %(node)s") % { + 'state': power_state, + 'node': task.node.uuid + }) 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.oneview_client.power_on(oneview_info) - elif power_state == states.POWER_OFF: - self.oneview_client.power_off(oneview_info) + oneview_client.server_hardware.update_power_state( + SET_POWER_STATE_MAP.get(power_state), server_hardware) elif power_state == states.REBOOT: - self.oneview_client.power_off(oneview_info) + oneview_client.server_hardware.update_power_state( + SET_POWER_STATE_MAP.get(states.POWER_OFF), server_hardware) management.set_boot_device(task) - self.oneview_client.power_on(oneview_info) + oneview_client.server_hardware.update_power_state( + SET_POWER_STATE_MAP.get(states.POWER_ON), server_hardware) else: - raise exception.InvalidParameterValue( - _("set_power_state called with invalid power state %s.") - % power_state) - except oneview_exceptions.OneViewException as exc: + oneview_client.server_hardware.update_power_state( + SET_POWER_STATE_MAP.get(power_state), server_hardware) + except client_exception.HPOneViewException as exc: raise exception.OneViewError( - _("Error setting power state: %s") % exc - ) + _("Failed to setting power state on node: %(node)s. " + "Error: %(error)s.") % { + 'node': task.node.uuid, + 'error': exc + }) @METRICS.timer('OneViewPower.reboot') @task_manager.require_exclusive_lock @@ -156,5 +191,8 @@ class OneViewPower(base.PowerInterface): :raises: PowerStateFailure if the final state of the node is not POWER_ON. """ - - self.set_power_state(task, states.REBOOT) + 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) diff --git a/ironic/drivers/oneview.py b/ironic/drivers/oneview.py index 9567928be2..1a7bf93f5a 100644 --- a/ironic/drivers/oneview.py +++ b/ironic/drivers/oneview.py @@ -73,6 +73,16 @@ 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")) + + if not importutils.try_import('redfish'): + raise exception.DriverLoadError( + driver=self.__class__.__name__, + reason=_("Unable to import python-ilorest-library")) + # Checks connectivity to OneView and version compatibility on driver # initialization oneview_client = common.get_oneview_client() @@ -101,6 +111,16 @@ 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")) + + if not importutils.try_import('redfish'): + raise exception.DriverLoadError( + driver=self.__class__.__name__, + reason=_("Unable to import python-ilorest-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 56e29395c3..5ed590fb06 100644 --- a/ironic/tests/unit/drivers/modules/oneview/test_common.py +++ b/ironic/tests/unit/drivers/modules/oneview/test_common.py @@ -17,7 +17,6 @@ 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 @@ -26,7 +25,6 @@ from ironic.tests.unit.db import utils as db_utils from ironic.tests.unit.objects import utils as obj_utils hponeview_client = importutils.try_import('hpOneView.oneview_client') -oneview_states = importutils.try_import('oneview_client.states') class OneViewCommonTestCase(db_base.DbTestCase): @@ -258,24 +256,6 @@ 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( diff --git a/ironic/tests/unit/drivers/modules/oneview/test_deploy.py b/ironic/tests/unit/drivers/modules/oneview/test_deploy.py index b49edd7495..098a54f640 100644 --- a/ironic/tests/unit/drivers/modules/oneview/test_deploy.py +++ b/ironic/tests/unit/drivers/modules/oneview/test_deploy.py @@ -99,7 +99,6 @@ 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) @@ -119,9 +118,7 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.deploy._periodic_check_nodes_taken_by_oneview( self.os_primary, self.context ) - mock_is_node_in_use_by_oneview.assert_called_once_with( - self.deploy.oneview_client, self.node - ) + mock_is_node_in_use_by_oneview.assert_called_once_with(self.node) self.assertTrue(self.os_primary.update_node.called) self.assertTrue(self.os_primary.do_provisioning_action.called) self.assertTrue(self.node.maintenance) @@ -139,9 +136,7 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.deploy._periodic_check_nodes_taken_by_oneview( self.os_primary, self.context ) - mock_is_node_in_use_by_oneview.assert_called_once_with( - self.deploy.oneview_client, self.node - ) + mock_is_node_in_use_by_oneview.assert_called_once_with(self.node) self.assertFalse(self.os_primary.update_node.called) self.assertFalse(self.os_primary.do_provisioning_action.called) self.assertFalse(self.node.maintenance) @@ -158,9 +153,7 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.deploy._periodic_check_nodes_taken_by_oneview( self.os_primary, self.context ) - mock_is_node_in_use_by_oneview.assert_called_once_with( - self.deploy.oneview_client, self.node - ) + mock_is_node_in_use_by_oneview.assert_called_once_with(self.node) self.assertFalse(self.os_primary.update_node.called) self.assertFalse(self.os_primary.do_provisioning_action.called) self.assertFalse(self.node.maintenance) @@ -177,9 +170,7 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.deploy._periodic_check_nodes_freed_by_oneview( self.os_primary, self.context ) - mock_is_node_in_use_by_oneview.assert_called_once_with( - self.deploy.oneview_client, self.node - ) + mock_is_node_in_use_by_oneview.assert_called_once_with(self.node) self.assertTrue(self.os_primary.update_node.called) self.assertTrue(self.os_primary.do_provisioning_action.called) self.assertFalse(self.node.maintenance) @@ -195,9 +186,7 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.deploy._periodic_check_nodes_freed_by_oneview( self.os_primary, self.context ) - mock_is_node_in_use_by_oneview.assert_called_once_with( - self.deploy.oneview_client, self.node - ) + mock_is_node_in_use_by_oneview.assert_called_once_with(self.node) self.assertFalse(self.os_primary.update_node.called) self.assertFalse(self.os_primary.do_provisioning_action.called) self.assertTrue(self.node.maintenance) @@ -215,9 +204,7 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.deploy._periodic_check_nodes_freed_by_oneview( self.os_primary, self.context ) - mock_is_node_in_use_by_oneview.assert_called_once_with( - self.deploy.oneview_client, self.node - ) + mock_is_node_in_use_by_oneview.assert_called_once_with(self.node) self.assertFalse(self.os_primary.update_node.called) self.assertFalse(self.os_primary.do_provisioning_action.called) self.assertTrue(self.node.maintenance) @@ -245,8 +232,8 @@ class OneViewPeriodicTasks(db_base.DbTestCase): ): 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 = \ - nodes_taken_on_cleanfail_no_info + self.os_primary.iter_nodes.return_value = ( + nodes_taken_on_cleanfail_no_info) self.deploy._periodic_check_nodes_taken_on_cleanfail( self.os_primary, self.context ) @@ -258,7 +245,6 @@ class OneViewPeriodicTasks(db_base.DbTestCase): self.assertNotIn('oneview_error', self.node.driver_internal_info) -@mock.patch.object(common, 'get_oneview_client', spec_set=True, autospec=True) class OneViewIscsiDeployTestCase(db_base.DbTestCase): def setUp(self): @@ -282,35 +268,32 @@ class OneViewIscsiDeployTestCase(db_base.DbTestCase): node_id=self.node.id) self.info = common.get_oneview_info(self.node) - def test_get_properties(self, mock_get_ov_client): + def test_get_properties(self): expected = common.COMMON_PROPERTIES self.assertEqual(expected, self.driver.deploy.get_properties()) @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'validate', spec_set=True, autospec=True) - def test_validate(self, iscsi_deploy_validate_mock, mock_get_ov_client): + def test_validate(self, iscsi_deploy_validate): 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) + iscsi_deploy_validate.assert_called_once_with(mock.ANY, task) - @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'prepare', - spec_set=True, autospec=True) + @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'prepare', 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): + iscsi_deploy_prepare_mock): self.node.provision_state = states.DEPLOYING self.node.save() - with task_manager.acquire(self.context, self.node.uuid, - shared=False) as task: + with task_manager.acquire(self.context, self.node.uuid) 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', spec_set=True, autospec=True) - def test_prepare_active_node(self, iscsi_deploy_prepare_mock, - mock_get_ov_client): + def test_prepare_active_node(self, iscsi_deploy_prepare_mock): """Ensure nodes in running states are not inadvertently changed""" test_states = list(states.STABLE_STATES) test_states.extend([states.CLEANING, @@ -328,7 +311,7 @@ class OneViewIscsiDeployTestCase(db_base.DbTestCase): @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'deploy', spec_set=True, autospec=True) - def test_deploy(self, iscsi_deploy_mock, mock_get_ov_client): + def test_deploy(self, iscsi_deploy_mock): with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: task.driver.deploy.deploy(task) @@ -336,7 +319,7 @@ class OneViewIscsiDeployTestCase(db_base.DbTestCase): @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): + def test_tear_down(self, iscsi_tear_down_mock): iscsi_tear_down_mock.return_value = states.DELETED with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: @@ -348,9 +331,7 @@ class OneViewIscsiDeployTestCase(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, - iscsi_tear_down_mock, mock_get_ov_client - ): + self, deallocate_server_hardware_mock, iscsi_tear_down_mock): CONF.conductor.automated_clean = False iscsi_tear_down_mock.return_value = states.DELETED @@ -364,8 +345,8 @@ class OneViewIscsiDeployTestCase(db_base.DbTestCase): @mock.patch.object(iscsi_deploy.ISCSIDeploy, '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, - iscsi_prep_clean_mock, mock_get_ov_client): + def test_prepare_cleaning( + self, allocate_server_hardware_mock, iscsi_prep_clean_mock): iscsi_prep_clean_mock.return_value = states.CLEANWAIT with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: @@ -378,9 +359,7 @@ class OneViewIscsiDeployTestCase(db_base.DbTestCase): 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): iscsi_tear_down_clean_mock.return_value = states.CLEANWAIT with task_manager.acquire(self.context, self.node.uuid, @@ -390,7 +369,6 @@ class OneViewIscsiDeployTestCase(db_base.DbTestCase): self.assertTrue(deallocate_server_hardware_mock.called) -@mock.patch.object(common, 'get_oneview_client', spec_set=True, autospec=True) class OneViewAgentDeployTestCase(db_base.DbTestCase): def setUp(self): super(OneViewAgentDeployTestCase, self).setUp() @@ -413,13 +391,13 @@ class OneViewAgentDeployTestCase(db_base.DbTestCase): node_id=self.node.id) self.info = common.get_oneview_info(self.node) - def test_get_properties(self, mock_get_ov_client): + def test_get_properties(self): expected = common.COMMON_PROPERTIES self.assertEqual(expected, self.driver.deploy.get_properties()) @mock.patch.object(agent.AgentDeploy, 'validate', spec_set=True, autospec=True) - def test_validate(self, agent_deploy_validate_mock, mock_get_ov_client): + def test_validate(self, agent_deploy_validate_mock): with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: task.driver.deploy.validate(task) @@ -428,8 +406,8 @@ class OneViewAgentDeployTestCase(db_base.DbTestCase): @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): self.node.provision_state = states.DEPLOYING self.node.save() with task_manager.acquire(self.context, self.node.uuid, @@ -440,8 +418,7 @@ class OneViewAgentDeployTestCase(db_base.DbTestCase): @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): + def test_prepare_active_node(self, agent_deploy_prepare_mock): """Ensure nodes in running states are not inadvertently changed""" test_states = list(states.STABLE_STATES) test_states.extend([states.CLEANING, @@ -459,7 +436,7 @@ class OneViewAgentDeployTestCase(db_base.DbTestCase): @mock.patch.object(agent.AgentDeploy, 'deploy', spec_set=True, autospec=True) - def test_deploy(self, agent_deploy_mock, mock_get_ov_client): + def test_deploy(self, agent_deploy_mock): with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: task.driver.deploy.deploy(task) @@ -469,9 +446,7 @@ 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): CONF.conductor.automated_clean = False agent_tear_down_mock.return_value = states.DELETED with task_manager.acquire(self.context, self.node.uuid, @@ -484,8 +459,8 @@ class OneViewAgentDeployTestCase(db_base.DbTestCase): @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): agent_prep_clean_mock.return_value = states.CLEANWAIT with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: @@ -498,9 +473,7 @@ class OneViewAgentDeployTestCase(db_base.DbTestCase): 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): agent_tear_down_clean_mock.return_value = states.CLEANWAIT with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: 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 fe94e74b9d..cd2548ff13 100644 --- a/ironic/tests/unit/drivers/modules/oneview/test_deploy_utils.py +++ b/ironic/tests/unit/drivers/modules/oneview/test_deploy_utils.py @@ -14,6 +14,7 @@ # under the License. import mock + from oslo_utils import importutils from ironic.common import driver_factory @@ -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_oneview_client', spec_set=True, autospec=True) +@mock.patch.object(common, 'get_hponeview_client') class OneViewDeployUtilsTestCase(db_base.DbTestCase): def setUp(self): @@ -49,394 +50,292 @@ 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_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 - + def test_prepare_node_is_in_use_by_oneview(self, mock_oneview_client): + """`prepare` behavior when the node has a Profile on OneView.""" + deploy_utils.is_node_in_use_by_oneview.return_value = True 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, - oneview_client, task ) @mock.patch.object(objects.Node, 'save') def test_prepare_node_is_successfuly_allocated_to_ironic( - 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 + self, mock_save, mock_oneview_client): + """`prepare` behavior when the node is free from OneView standpoint.""" with task_manager.acquire(self.context, self.node.uuid) as task: task.node.provision_state = states.DEPLOYING - deploy_utils.prepare(oneview_client, task) - self.assertTrue(oneview_client.clone_template_and_apply.called) - self.assertTrue(oneview_client.get_server_profile_from_hardware) + deploy_utils.prepare(task) + self.assertTrue(mock_save.called) # Tests for tear_down - 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 - + def test_tear_down(self, mock_oneview_client): + """`tear_down` behavior when node already has Profile applied.""" + oneview_client = mock_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'] = \ + task.node.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(ov_client, task) - self.assertNotIn( - 'applied_server_profile_uri', task.node.driver_info + self.assertTrue( + 'applied_server_profile_uri' in task.node.driver_info ) - self.assertTrue( - ov_client.delete_server_profile.called - ) + deploy_utils.tear_down(task) + self.assertFalse( + 'applied_server_profile_uri' in task.node.driver_info + ) + self.assertTrue(oneview_client.server_profiles.delete.called) # Tests for prepare_cleaning @mock.patch.object(objects.Node, 'save') def test_prepare_cleaning_when_node_does_not_have_sp_applied( - 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 + self, mock_save, mock_oneview_client): + """`prepare_cleaning` behavior when node is free.""" with task_manager.acquire(self.context, self.node.uuid) as task: - deploy_utils.prepare_cleaning(oneview_client, task) - self.assertTrue(oneview_client.clone_template_and_apply.called) + self.assertFalse( + 'applied_server_profile_uri' in task.node.driver_info + ) + deploy_utils.prepare_cleaning(task) + self.assertTrue( + 'applied_server_profile_uri' in task.node.driver_info + ) @mock.patch.object(objects.Node, 'save') def test_prepare_cleaning_when_node_has_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 - + self, mock_node_save, mock_oneview_client): + """`prepare_cleaning` behavior when node has Profile applied.""" + oneview_client = mock_oneview_client() + oneview_client.server_hardware.get.return_value = { + 'serverProfileUri': 'same/sp_applied' + } with task_manager.acquire(self.context, self.node.uuid) as task: - 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) + task.node.driver_info['applied_server_profile_uri'] = ( + 'same/sp_applied' + ) + deploy_utils.prepare_cleaning(task) + self.assertFalse(mock_node_save.called) def test_prepare_cleaning_node_is_in_use_by_oneview( - 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 + self, mock_oneview_client): + """`prepare_cleaning` behavior when node has Profile on OneView.""" + deploy_utils.is_node_in_use_by_oneview.return_value = True 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, - oneview_client, task ) # Tests for tear_down_cleaning - 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 - + def test_tear_down_cleaning(self, mock_oneview_client): + """Check if Server Profile was deleted and its uri removed.""" + oneview_client = mock_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'] = \ + task.node.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_cleaning(ov_client, task) - self.assertNotIn('applied_server_profile_uri', - task.node.driver_info) - self.assertTrue(ov_client.delete_server_profile.called) + ) + self.assertTrue( + 'applied_server_profile_uri' in task.node.driver_info + ) + deploy_utils.tear_down_cleaning(task) + self.assertFalse( + 'applied_server_profile_uri' in task.node.driver_info + ) + self.assertTrue(oneview_client.server_profiles.delete.called) # Tests for is_node_in_use_by_oneview - 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" - + 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' + } 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.driver_info['applied_server_profile_uri'] = ( + '/rest/server-profile/987654321' + ) self.assertTrue( - deploy_utils.is_node_in_use_by_oneview(oneview_client, - task.node) + deploy_utils._is_node_in_use( + server_hardware, + task.node.driver_info['applied_server_profile_uri'], + by_oneview=True + ) ) def test_is_node_in_use_by_oneview_no_server_profile( - self, mock_get_ov_client - ): - """Node has no Server Profile. - - """ - oneview_client = mock_get_ov_client() - - fake_sh = oneview_models.ServerHardware() - fake_sh.server_profile_uri = None - oneview_client.get_server_hardware_by_uuid.return_value = fake_sh + 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'] = ( + '/rest/server-profile/123456789' + ) self.assertFalse( - deploy_utils.is_node_in_use_by_oneview(oneview_client, - task.node) + deploy_utils._is_node_in_use( + server_hardware, + task.node.driver_info['applied_server_profile_uri'], + by_oneview=True + ) ) def test_is_node_in_use_by_oneview_same_server_profile_applied( - self, mock_get_ov_client - ): - """Node's Server Profile uri is the same applied by ironic. - - """ - oneview_client = mock_get_ov_client() - - fake_sh = oneview_models.ServerHardware() - fake_sh.server_profile_uri = 'same/applied_sp_uri/' - oneview_client.get_server_hardware_by_uuid.return_value = fake_sh - + self, mock_oneview_client): + """Check if node's Server Profile uri is the same applied by ironic.""" + server_hardware = { + 'serverProfileUri': '/rest/server-profile/123456789' + } with task_manager.acquire(self.context, self.node.uuid) as task: - driver_info = task.node.driver_info - driver_info['applied_server_profile_uri'] = 'same/applied_sp_uri/' - task.node.driver_info = driver_info + task.node.driver_info['applied_server_profile_uri'] = ( + '/rest/server-profile/123456789' + ) self.assertFalse( - deploy_utils.is_node_in_use_by_oneview(oneview_client, - task.node) + deploy_utils._is_node_in_use( + server_hardware, + task.node.driver_info['applied_server_profile_uri'], + by_oneview=True + ) ) # Tests for is_node_in_use_by_ironic - 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 - + 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/'} with task_manager.acquire(self.context, self.node.uuid) as task: - driver_info = task.node.driver_info - driver_info['applied_server_profile_uri'] = 'same/applied_sp_uri/' - task.node.driver_info = driver_info + task.node.driver_info['applied_server_profile_uri'] = ( + 'same/applied_sp_uri/' + ) self.assertTrue( - deploy_utils.is_node_in_use_by_ironic(ov_client, task.node) + deploy_utils._is_node_in_use( + server_hardware, + task.node.driver_info['applied_server_profile_uri'], + by_oneview=False + ) ) def test_is_node_in_use_by_ironic_no_server_profile( - self, mock_get_ov_client - ): - """Node has no Server Profile. - - """ - fake_sh = oneview_models.ServerHardware() - fake_sh.server_profile_uri = None - - ov_client = mock_get_ov_client.return_value - ov_client.get_server_hardware_by_uuid.return_value = fake_sh - + 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_by_ironic(ov_client, task.node) + deploy_utils._is_node_in_use( + server_hardware, + task.node.driver_info['applied_server_profile_uri'], + by_oneview=False + ) ) + 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" + oneview_client = mock_oneview_client() + oneview_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( + oneview_client, + "server_profile_name", + server_hardware_uri, + sp_template_uri + ) + oneview_client.server_profiles.create.assert_called_with( + server_profile) + # Tests for _add_applied_server_profile_uri_field - def test__add_applied_server_profile_uri_field(self, mock_get_ov_client): - """Checks if applied_server_profile_uri was added to driver_info. - - """ + @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/'} with task_manager.acquire(self.context, self.node.uuid) as task: - 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) + task.node.driver_info.pop('applied_server_profile_uri', None) + self.assertNotIn( + 'applied_server_profile_uri', task.node.driver_info + ) deploy_utils._add_applied_server_profile_uri_field( task.node, - fake_server_profile + server_profile ) self.assertIn('applied_server_profile_uri', task.node.driver_info) # Tests for _del_applied_server_profile_uri_field - def test__del_applied_server_profile_uri_field(self, mock_get_ov_client): - """Checks if applied_server_profile_uri was removed from driver_info. - - """ + @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.""" 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 - + task.node.driver_info['applied_server_profile_uri'] = ( + 'any/applied_sp_uri/' + ) 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_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 + self, mock_node_save, mock_oneview_client): + """Check if a Profile was created and its uri is in driver_info.""" + oneview_client = mock_oneview_client() + server_hardware = {'serverProfileUri': None} + oneview_client.server_hardware.get.return_value = server_hardware with task_manager.acquire(self.context, self.node.uuid) as task: deploy_utils.allocate_server_hardware_to_ironic( - oneview_client, task.node, 'serverProfileName' + task.node, 'serverProfileName' ) - self.assertTrue(oneview_client.clone_template_and_apply.called) + self.assertTrue(mock_node_save.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_delete_applied_sp, mock_node_save, mock_get_ov_client - ): - """Tests server profile allocation when applied_server_profile_uri exists. + self, mock_node_save, mock_oneview_client): + """Test 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. """ - 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 + oneview_client = mock_oneview_client() + server_hardware = {'serverProfileUri': None} + oneview_client.server_hardware.get.return_value = server_hardware 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 - - deploy_utils.allocate_server_hardware_to_ironic( - oneview_client, task.node, 'serverProfileName' + task.node.driver_info['applied_server_profile_uri'] = ( + 'any/applied_sp_uri/' ) - self.assertTrue(mock_delete_applied_sp.called) + deploy_utils.allocate_server_hardware_to_ironic( + task.node, 'serverProfileName' + ) + self.assertTrue(mock_node_save.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_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 - + self, mock_node_save, mock_oneview_client): + oneview_client = mock_oneview_client() + server_hardware = {'serverProfileUri': 'any/applied_sp_uri/'} + oneview_client.server_hardware.get.return_value = server_hardware 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 - - deploy_utils.deallocate_server_hardware_from_ironic( - oneview_client, task.node + task.node.driver_info['applied_server_profile_uri'] = ( + 'any/applied_sp_uri/' ) - 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 + deploy_utils.deallocate_server_hardware_from_ironic(task) + self.assertTrue(mock_node_save.called) + self.assertTrue( + 'applied_server_profile_uri' not in 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 ebc01b1013..9f7b439185 100644 --- a/ironic/tests/unit/drivers/modules/oneview/test_inspect.py +++ b/ironic/tests/unit/drivers/modules/oneview/test_inspect.py @@ -24,8 +24,6 @@ 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): @@ -39,15 +37,14 @@ class AgentPXEOneViewInspectTestCase(db_base.DbTestCase): driver_info=db_utils.get_test_oneview_driver_info(), ) - def test_get_properties(self, mock_get_ov_client): + def test_get_properties(self): 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', spec_set=True, - autospec=True) - def test_validate(self, mock_verify_node_info, mock_get_ov_client): + @mock.patch.object(oneview_common, 'verify_node_info') + def test_validate(self, mock_verify_node_info): self.config(enabled=False, group='inspector') with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: @@ -55,16 +52,13 @@ 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, - mock_get_ov_client): + def test_inspect_hardware(self, mock_allocate_server_hardware_to_ironic): 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): @@ -78,15 +72,14 @@ class ISCSIPXEOneViewInspectTestCase(db_base.DbTestCase): driver_info=db_utils.get_test_oneview_driver_info(), ) - def test_get_properties(self, mock_get_ov_client): + def test_get_properties(self): 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', spec_set=True, - autospec=True) - def test_validate(self, mock_verify_node_info, mock_get_ov_client): + @mock.patch.object(oneview_common, 'verify_node_info') + def test_validate(self, mock_verify_node_info): self.config(enabled=False, group='inspector') with task_manager.acquire(self.context, self.node.uuid, shared=False) as task: @@ -94,8 +87,7 @@ 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, - mock_get_ov_client): + def test_inspect_hardware(self, mock_allocate_server_hardware_to_ironic): 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 1e88f8fb53..f640099727 100644 --- a/ironic/tests/unit/drivers/modules/oneview/test_management.py +++ b/ironic/tests/unit/drivers/modules/oneview/test_management.py @@ -22,6 +22,7 @@ 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 @@ -29,11 +30,12 @@ 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_oneview_client', spect_set=True, autospec=True) +@mock.patch.object(common, 'get_hponeview_client') class OneViewManagementDriverFunctionsTestCase(db_base.DbTestCase): def setUp(self): @@ -52,26 +54,10 @@ class OneViewManagementDriverFunctionsTestCase(db_base.DbTestCase): ) self.info = common.get_oneview_info(self.node) - 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() + @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() with task_manager.acquire(self.context, self.node.uuid) as task: driver_internal_info = task.node.driver_internal_info @@ -80,16 +66,49 @@ 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) - oneview_client.set_boot_device.assert_called_once_with( - self.info, - management.BOOT_DEVICE_MAPPING_TO_OV[boot_devices.PXE], - onetime=False - ) + 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) 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): - oneview_client = mock_get_ov_client() + client = mock_get_ov_client() with task_manager.acquire(self.context, self.node.uuid) as task: driver_internal_info = task.node.driver_internal_info @@ -100,30 +119,14 @@ class OneViewManagementDriverFunctionsTestCase(db_base.DbTestCase): self.assertRaises(exception.InvalidParameterValue, management.set_boot_device, task) - self.assertFalse(oneview_client.set_boot_device.called) + self.assertFalse(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): - 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 + client = mock_get_ov_client() + exc = client_exception.HPOneViewException() + client.server_profiles.get.side_effect = exc with task_manager.acquire(self.context, self.node.uuid) as task: driver_internal_info = task.node.driver_internal_info @@ -131,20 +134,49 @@ class OneViewManagementDriverFunctionsTestCase(db_base.DbTestCase): 'persistent': True} driver_internal_info['next_boot_device'] = next_boot_device task.node.driver_internal_info = driver_internal_info - expected_msg = ( - 'A Server Profile is not associated with node %s.' - % self.node.uuid - ) - self.assertRaisesRegex( - exception.OperationNotPermitted, - expected_msg, + self.assertRaises( + exception.OneViewError, 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_oneview_client', spect_set=True, autospec=True) class OneViewManagementDriverTestCase(db_base.DbTestCase): def setUp(self): @@ -152,6 +184,8 @@ class OneViewManagementDriverTestCase(db_base.DbTestCase): self.config(manager_url='https://1.2.3.4', group='oneview') self.config(username='user', group='oneview') self.config(password='password', group='oneview') + self.config(tls_cacert_file='ca_file', group='oneview') + self.config(allow_insecure_connections=False, group='oneview') mgr_utils.mock_the_extension_manager(driver="fake_oneview") self.driver = driver_factory.get_driver("fake_oneview") @@ -163,79 +197,44 @@ class OneViewManagementDriverTestCase(db_base.DbTestCase): ) self.info = common.get_oneview_info(self.node) - @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() - + @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_ironic_node.return_value = True with task_manager.acquire(self.context, self.node.uuid) as task: task.driver.management.validate(task) self.assertTrue(mock_validate.called) - @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() - + @mock.patch.object(deploy_utils, 'is_node_in_use_by_ironic') + def test_validate_for_node_not_in_use_by_ironic(self, mock_ironic_node): + mock_ironic_node.return_value = False 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') + def test_validate_fail(self): + 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', - spect_set=True, autospec=True) - def test_validate_fail_exception(self, mock_validate, mock_get_ov_client): + @mock.patch.object(common, 'validate_oneview_resources_compatibility') + def test_validate_fail_exception(self, mock_validate): mock_validate.side_effect = exception.OneViewError('message') with task_manager.acquire(self.context, self.node.uuid) as task: self.assertRaises(exception.InvalidParameterValue, task.driver.management.validate, task) - def test_get_properties(self, mock_get_ov_client): + def test_get_properties(self): expected = common.COMMON_PROPERTIES self.assertItemsEqual(expected, self.driver.management.get_properties()) - def test_set_boot_device_persistent_true(self, mock_get_ov_client): + def test_set_boot_device_persistent_true(self): with task_manager.acquire(self.context, self.node.uuid) as task: task.driver.management.set_boot_device( task, boot_devices.PXE, True) @@ -246,7 +245,7 @@ class OneViewManagementDriverTestCase(db_base.DbTestCase): next_boot_device.get('boot_device'), boot_devices.PXE) self.assertTrue(next_boot_device.get('persistent')) - def test_set_boot_device_persistent_false(self, mock_get_ov_client): + def test_set_boot_device_persistent_false(self): with task_manager.acquire(self.context, self.node.uuid) as task: task.driver.management.set_boot_device( task, boot_devices.PXE, False) @@ -257,7 +256,7 @@ class OneViewManagementDriverTestCase(db_base.DbTestCase): next_boot_device.get('boot_device'), boot_devices.PXE) self.assertFalse(next_boot_device.get('persistent')) - def test_set_boot_device_invalid_device(self, mock_get_ov_client): + def test_set_boot_device_invalid_device(self): with task_manager.acquire(self.context, self.node.uuid) as task: self.assertRaises(exception.InvalidParameterValue, task.driver.management.set_boot_device, @@ -265,38 +264,32 @@ class OneViewManagementDriverTestCase(db_base.DbTestCase): driver_internal_info = task.node.driver_internal_info self.assertNotIn('next_boot_device', driver_internal_info) - def test_get_supported_boot_devices(self, mock_get_ov_client): + def test_get_supported_boot_devices(self): 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), ) + @mock.patch.object(common, 'get_hponeview_client') def test_get_boot_device(self, mock_get_ov_client): - device_mapping = management.BOOT_DEVICE_MAPPING_TO_OV - oneview_client = mock_get_ov_client() - self.driver.management.oneview_client = oneview_client - + client = mock_get_ov_client() + device_mapping = management.BOOT_DEVICE_MAP_ONEVIEW.items() with task_manager.acquire(self.context, self.node.uuid) as task: # For each known device on OneView, Ironic should return its # counterpart value - 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 - } + 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} response = self.driver.management.get_boot_device(task) - 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): - oneview_client = mock_get_ov_client() - self.driver.management.oneview_client = oneview_client + self.assertEqual(expected, response) + self.assertTrue(client.server_profiles.get.called) + def test_get_boot_device_from_next_boot_device(self): 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.DISK, @@ -309,26 +302,21 @@ class OneViewManagementDriverTestCase(db_base.DbTestCase): } response = self.driver.management.get_boot_device(task) self.assertEqual(expected_response, response) - self.assertFalse(oneview_client.get_boot_order.called) + @mock.patch.object(common, 'get_hponeview_client') def test_get_boot_device_fail(self, mock_get_ov_client): - oneview_client = mock_get_ov_client() - oneview_client.get_boot_order.side_effect = \ - oneview_exceptions.OneViewException() - self.driver.management.oneview_client = oneview_client - + client = mock_get_ov_client() + exc = client_exception.HPOneViewException() + client.server_profiles.get.side_effect = exc with task_manager.acquire(self.context, self.node.uuid) as task: - 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): - oneview_client = mock_get_ov_client() - oneview_client.get_boot_order.return_value = ["spam", - "bacon"] - self.driver.management.oneview_client = oneview_client + self.assertRaises( + exception.OneViewError, + self.driver.management.get_boot_device, + task + ) + self.assertTrue(client.server_profiles.get.called) + def test_get_boot_device_unknown_device(self): with task_manager.acquire(self.context, self.node.uuid) as task: self.assertRaises( exception.InvalidParameterValue, @@ -336,7 +324,7 @@ class OneViewManagementDriverTestCase(db_base.DbTestCase): task ) - def test_get_sensors_data_not_implemented(self, mock_get_ov_client): + def test_get_sensors_data_not_implemented(self): with task_manager.acquire(self.context, self.node.uuid) as task: self.assertRaises( NotImplementedError, diff --git a/ironic/tests/unit/drivers/modules/oneview/test_power.py b/ironic/tests/unit/drivers/modules/oneview/test_power.py index 4c0df08d0a..6a8afc2954 100644 --- a/ironic/tests/unit/drivers/modules/oneview/test_power.py +++ b/ironic/tests/unit/drivers/modules/oneview/test_power.py @@ -24,20 +24,17 @@ 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_oneview_client', spec_set=True, autospec=True) class OneViewPowerDriverTestCase(db_base.DbTestCase): def setUp(self): @@ -45,6 +42,8 @@ class OneViewPowerDriverTestCase(db_base.DbTestCase): self.config(manager_url='https://1.2.3.4', group='oneview') self.config(username='user', group='oneview') self.config(password='password', group='oneview') + self.config(tls_cacert_file='ca_file', group='oneview') + self.config(allow_insecure_connections=False, group='oneview') mgr_utils.mock_the_extension_manager(driver='fake_oneview') self.driver = driver_factory.get_driver('fake_oneview') @@ -55,274 +54,197 @@ 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', - 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 + @mock.patch.object(common, 'validate_oneview_resources_compatibility') + def test_validate(self, mock_validate): with task_manager.acquire(self.context, self.node.uuid) as task: task.driver.power.validate(task) self.assertTrue(mock_validate.called) - 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') + def test_validate_missing_parameter(self): + 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', - spect_set=True, autospec=True) - def test_power_interface_validate_fail_exception(self, mock_validate, - mock_get_ov_client): + @mock.patch.object(common, 'validate_oneview_resources_compatibility') + def test_validate_exception(self, mock_validate): 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) - @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 + def test_validate_node_in_use_by_oneview(self): + deploy_utils.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) - @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): + def test_get_properties(self): expected = common.COMMON_PROPERTIES - self.assertItemsEqual(expected, self.driver.power.get_properties()) + self.assertEqual(expected, self.driver.power.get_properties()) + @mock.patch.object(common, 'get_hponeview_client') def test_get_power_state(self, mock_get_ov_client): - oneview_client = mock_get_ov_client() - oneview_client.get_node_power_state.return_value = POWER_ON - self.driver.power.oneview_client = oneview_client - + client = mock_get_ov_client() + server_hardware = {'powerState': 'On'} + client.server_hardware.get.return_value = server_hardware with task_manager.acquire(self.context, self.node.uuid) as task: - self.driver.power.get_power_state(task) - oneview_client.get_node_power_state.assert_called_once_with(self.info) + power_state = self.driver.power.get_power_state(task) + self.assertEqual(states.POWER_ON, power_state) + @mock.patch.object(common, 'get_hponeview_client') def test_get_power_state_fail(self, mock_get_ov_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 - + client = mock_get_ov_client() + exc = client_exception.HPOneViewException() + client.server_hardware.get.side_effect = exc 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(common, 'get_hponeview_client') @mock.patch.object(management, 'set_boot_device') - 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 - + def test_set_power_on(self, mock_set_boot_device, mock_get_ov_client): + client = mock_get_ov_client() + server_hardware = self.node.driver_info.get('server_hardware_uri') 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) - 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) + 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.patch.object(common, 'get_hponeview_client') @mock.patch.object(management, 'set_boot_device') - 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 - + def test_set_power_off(self, mock_set_boot_device, mock_get_ov_client): + client = mock_get_ov_client() + server_hardware = self.node.driver_info.get('server_hardware_uri') 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) - self.info['applied_server_profile_uri'] = sp_uri - oneview_client.power_off.assert_called_once_with(self.info) + update = client.server_hardware.update_power_state + update.assert_called_once_with(power.POWER_OFF, server_hardware) + @mock.patch.object(common, 'get_hponeview_client') @mock.patch.object(management, 'set_boot_device') - 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 - + def test_set_power_reboot(self, mock_set_boot_device, mock_get_ov_client): + client = mock_get_ov_client() + server_hardware = self.node.driver_info.get('server_hardware_uri') 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.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) + 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) + @mock.patch.object(common, 'get_hponeview_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 + 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) + mock_set_boot_device.assert_called_once_with(task) + + @mock.patch.object(common, 'get_hponeview_client') @mock.patch.object(management, 'set_boot_device') def test_set_power_off_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 - + client = mock_get_ov_client() + exc = client_exception.HPOneViewException() + client.server_hardware.update_power_state.side_effect = exc 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.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: - 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.assertRaises( + exception.OneViewError, + self.driver.power.set_power_state, + task, + states.POWER_OFF) self.assertFalse(mock_set_boot_device.called) + @mock.patch.object(common, 'get_hponeview_client') @mock.patch.object(management, 'set_boot_device') - def test_set_power_reboot( + def test_reboot_fail_with_hardware_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.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 - + client = mock_get_ov_client() + server_hardware = {'powerState': 'On'} + client.server_hardware.get.return_value = server_hardware + 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: - 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) + self.assertRaises( + exception.OneViewError, + self.driver.power.reboot, + task) + self.assertFalse(mock_set_boot_device.called) + + @mock.patch.object(common, 'get_hponeview_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 + exc = client_exception.HPOneViewException() + client.server_hardware.update_power_state.side_effect = exc + 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) - 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_reboot( - 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 - oneview_client.power_off.return_value = POWER_OFF - oneview_client.power_on.return_value = POWER_ON - self.driver.power.oneview_client = oneview_client - + def test_set_power_invalid_state(self, mock_set_boot_device): + with task_manager.acquire(self.context, self.node.uuid) as task: + self.assertRaises( + exception.InvalidParameterValue, + self.driver.power.set_power_state, + task, + 'fake_state') + self.assertFalse(mock_set_boot_device.called) + + @mock.patch.object(common, 'get_hponeview_client') + @mock.patch.object(management, 'set_boot_device') + def test_set_power_reboot_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 + server_hardware = self.node.driver_info.get('server_hardware_uri') 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) + 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) 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(common, 'get_hponeview_client') @mock.patch.object(management, 'set_boot_device') - def test_reboot_fail( + def test_set_power_reboot_with_hardware_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.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) + client = mock_get_ov_client() + server_hardware = {'powerState': 'Off'} + client.server_hardware.get.return_value = server_hardware + server_hardware = self.node.driver_info.get('server_hardware_uri') + with task_manager.acquire(self.context, self.node.uuid) as task: + 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) diff --git a/ironic/tests/unit/drivers/third_party_driver_mock_specs.py b/ironic/tests/unit/drivers/third_party_driver_mock_specs.py index 2574743c93..8126f7add5 100644 --- a/ironic/tests/unit/drivers/third_party_driver_mock_specs.py +++ b/ironic/tests/unit/drivers/third_party_driver_mock_specs.py @@ -162,6 +162,10 @@ HPE_ONEVIEW_STATES_SPEC = ( 'ONEVIEW_ERROR', ) +REDFISH_SPEC = ( + 'redfish', +) + SUSHY_CONSTANTS_SPEC = ( 'BOOT_SOURCE_TARGET_PXE', 'BOOT_SOURCE_TARGET_HDD', diff --git a/ironic/tests/unit/drivers/third_party_driver_mocks.py b/ironic/tests/unit/drivers/third_party_driver_mocks.py index 28e3741987..f813a69c07 100644 --- a/ironic/tests/unit/drivers/third_party_driver_mocks.py +++ b/ironic/tests/unit/drivers/third_party_driver_mocks.py @@ -116,6 +116,14 @@ if 'ironic.drivers.oneview' in sys.modules: six.moves.reload_module(sys.modules['ironic.drivers.modules.oneview']) +redfish = importutils.try_import('redfish') +if not redfish: + redfish = mock.MagicMock(spec_set=mock_specs.REDFISH_SPEC) + sys.modules['redfish'] = redfish +if 'ironic.drivers.oneview' in sys.modules: + six.moves.reload_module(sys.modules['ironic.drivers.modules.oneview']) + + # attempt to load the external 'python-dracclient' library, which is required # by the optional drivers.modules.drac module dracclient = importutils.try_import('dracclient')