674 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			674 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # (c) Copyright 2015 Hewlett Packard Enterprise Development LP
 | |
| # Copyright 2015 Universidade Federal de Campina Grande
 | |
| #
 | |
| #    Licensed under the Apache License, Version 2.0 (the "License");
 | |
| #    you may not use this file except in compliance with the License.
 | |
| #    You may obtain a copy of the License at
 | |
| #
 | |
| #        http://www.apache.org/licenses/LICENSE-2.0
 | |
| #
 | |
| #    Unless required by applicable law or agreed to in writing, software
 | |
| #    distributed under the License is distributed on an "AS IS" BASIS,
 | |
| #    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| #    See the License for the specific language governing permissions and
 | |
| #    limitations under the License.
 | |
| 
 | |
| import abc
 | |
| import json
 | |
| import six
 | |
| import time
 | |
| 
 | |
| import requests
 | |
| import retrying
 | |
| 
 | |
| from oneview_client import exceptions
 | |
| from oneview_client import ilo_utils
 | |
| from oneview_client import managers
 | |
| from oneview_client import states
 | |
| 
 | |
| SUPPORTED_ONEVIEW_VERSION = 200
 | |
| 
 | |
| WAIT_DO_REQUEST_IN_MILLISECONDS = 1000
 | |
| WAIT_TASK_IN_MILLISECONDS = 1000
 | |
| 
 | |
| GET_REQUEST_TYPE = 'GET'
 | |
| PUT_REQUEST_TYPE = 'PUT'
 | |
| POST_REQUEST_TYPE = 'POST'
 | |
| DELETE_REQUEST_TYPE = 'DELETE'
 | |
| 
 | |
| MOMENTARY_PRESS = 'MomentaryPress'
 | |
| PRESS_AND_HOLD = 'PressAndHold'
 | |
| 
 | |
| SERVER_HARDWARE_PREFIX_URI = '/rest/server-hardware/'
 | |
| SERVER_PROFILE_TEMPLATE_PREFIX_URI = '/rest/server-profile-templates/'
 | |
| SERVER_PROFILE_PREFIX_URI = '/rest/server-profiles/'
 | |
| 
 | |
| 
 | |
| @six.add_metaclass(abc.ABCMeta)
 | |
| class BaseClient(object):
 | |
| 
 | |
|     def __init__(
 | |
|         self, manager_url, username, password,
 | |
|         allow_insecure_connections=False, tls_cacert_file='',
 | |
|         max_polling_attempts=20
 | |
|     ):
 | |
|         self.manager_url = manager_url
 | |
|         self.username = username
 | |
|         self.password = password
 | |
|         self.allow_insecure_connections = allow_insecure_connections
 | |
|         self.tls_cacert_file = tls_cacert_file
 | |
|         self.max_polling_attempts = max_polling_attempts
 | |
| 
 | |
|         if self.allow_insecure_connections:
 | |
|             requests.packages.urllib3.disable_warnings(
 | |
|                 requests.packages.urllib3.exceptions.InsecureRequestWarning
 | |
|             )
 | |
| 
 | |
|         self.session_id = self.get_session()
 | |
| 
 | |
|     def verify_credentials(self):
 | |
|         return self._authenticate()
 | |
| 
 | |
|     def get_session(self):
 | |
|         response = self._authenticate()
 | |
|         return response.json().get('sessionID')
 | |
| 
 | |
|     def _authenticate(self):
 | |
|         if self.manager_url in ("", None):
 | |
|             raise exceptions.OneViewConnectionError(
 | |
|                 "Can't connect to OneView: 'manager_url' configuration"
 | |
|                 "parameter is blank")
 | |
| 
 | |
|         url = '%s/rest/login-sessions' % self.manager_url
 | |
|         body = {
 | |
|             'userName': self.username,
 | |
|             'password': self.password
 | |
|         }
 | |
|         headers = {
 | |
|             'content-type': 'application/json'
 | |
|         }
 | |
| 
 | |
|         verify_ssl = self._get_verify_connection_option()
 | |
| 
 | |
|         r = requests.post(url,
 | |
|                           data=json.dumps(body),
 | |
|                           headers=headers,
 | |
|                           verify=verify_ssl)
 | |
|         if r.status_code == 400:
 | |
|             raise exceptions.OneViewNotAuthorizedException()
 | |
|         else:
 | |
|             return r
 | |
| 
 | |
|     def _get_verify_connection_option(self):
 | |
|         verify_status = False
 | |
|         user_cacert = self.tls_cacert_file
 | |
| 
 | |
|         if self.allow_insecure_connections is False:
 | |
|             if not user_cacert:
 | |
|                 verify_status = True
 | |
|             else:
 | |
|                 verify_status = user_cacert
 | |
|         return verify_status
 | |
| 
 | |
|     def verify_oneview_version(self):
 | |
|         if not self._is_oneview_version_compatible():
 | |
|             msg = ("The version of the OneView's API is unsupported. "
 | |
|                    "Supported version is '%s'" % SUPPORTED_ONEVIEW_VERSION)
 | |
|             raise exceptions.IncompatibleOneViewAPIVersion(msg)
 | |
| 
 | |
|     def _is_oneview_version_compatible(self):
 | |
|         versions = self.get_oneview_version()
 | |
|         v = SUPPORTED_ONEVIEW_VERSION
 | |
|         min_version_compatible = versions.get("minimumVersion") <= v
 | |
|         max_version_compatible = versions.get("currentVersion") >= v
 | |
|         return min_version_compatible and max_version_compatible
 | |
| 
 | |
|     def get_oneview_version(self):
 | |
|         url = '%s/rest/version' % self.manager_url
 | |
|         headers = {"Accept-Language": "en_US"}
 | |
| 
 | |
|         verify_ssl = self._get_verify_connection_option()
 | |
| 
 | |
|         try:
 | |
|             versions = requests.get(
 | |
|                 url, headers=headers, verify=verify_ssl
 | |
|             ).json()
 | |
|             return versions
 | |
|         except requests.RequestException as e:
 | |
|             raise exceptions.OneViewConnectionError(e.message)
 | |
| 
 | |
|     # --- Requests ---
 | |
|     def _prepare_and_do_request(
 | |
|         self, uri, body={}, request_type=GET_REQUEST_TYPE
 | |
|     ):
 | |
|         json_response = {}
 | |
|         try:
 | |
|             if not self.session_id:
 | |
|                 self.session_id = self.get_session()
 | |
| 
 | |
|             headers = {
 | |
|                 'content-type': 'application/json',
 | |
|                 'X-Api-Version': SUPPORTED_ONEVIEW_VERSION,
 | |
|                 'Auth': self.session_id
 | |
|             }
 | |
|             url = '%s%s' % (self.manager_url, uri)
 | |
|             body = json.dumps(body)
 | |
|             response = self._do_request(url, headers, body, request_type)
 | |
| 
 | |
|             json_response = response.json()
 | |
|         except requests.RequestException as e:
 | |
|             connection_error = str(e.message).split(':')[-1]
 | |
|             log_message = ("Can't connect to OneView: %s" % connection_error)
 | |
|             raise exceptions.OneViewConnectionError(log_message)
 | |
| 
 | |
|         return json_response
 | |
| 
 | |
|     def _do_request(self, url, headers, body, request_type):
 | |
|         verify_status = self._get_verify_connection_option()
 | |
| 
 | |
|         @retrying.retry(
 | |
|             stop_max_attempt_number=self.max_polling_attempts,
 | |
|             retry_on_result=lambda response: _check_request_status(response),
 | |
|             wait_fixed=WAIT_DO_REQUEST_IN_MILLISECONDS
 | |
|         )
 | |
|         def request(url, headers, body, request_type):
 | |
| 
 | |
|             if request_type == PUT_REQUEST_TYPE:
 | |
|                 response = requests.put(
 | |
|                     url, data=body, headers=headers, verify=verify_status
 | |
|                 )
 | |
|             elif request_type == POST_REQUEST_TYPE:
 | |
|                 response = requests.post(
 | |
|                     url, data=body, headers=headers, verify=verify_status
 | |
|                 )
 | |
|             elif request_type == DELETE_REQUEST_TYPE:
 | |
|                 response = requests.delete(
 | |
|                     url, headers=headers, verify=verify_status
 | |
|                 )
 | |
|             else:
 | |
|                 response = requests.get(
 | |
|                     url, headers=headers, verify=verify_status
 | |
|                 )
 | |
|             return response
 | |
|         return request(url, headers, body, request_type)
 | |
| 
 | |
|     def _wait_for_task_to_complete(self, task):
 | |
|         @retrying.retry(
 | |
|             retry_on_result=lambda task: task.get('percentComplete') < 100,
 | |
|             wait_fixed=WAIT_TASK_IN_MILLISECONDS,
 | |
|             retry_on_exception=lambda task: False
 | |
|         )
 | |
|         def wait(task):
 | |
|             uri = task.get('uri')
 | |
|             task = self._prepare_and_do_request(uri)
 | |
| 
 | |
|             task_state = task.get("taskState")
 | |
|             error_code = task.get("errorCode")
 | |
|             if (not task_state) and error_code:
 | |
|                 details = task.get("details")
 | |
|                 if error_code == "RESOURCE_NOT_FOUND":
 | |
|                     raise exceptions.OneViewResourceNotFoundError(details)
 | |
|                 else:
 | |
|                     raise exceptions.OneViewTaskError("%s - %s"
 | |
|                                                       % (error_code, details))
 | |
|             elif task_state.lower() == 'error':
 | |
|                 raise exceptions.OneViewTaskError("The task '%s' returned an "
 | |
|                                                   "error state" % uri)
 | |
|             return task
 | |
|         return wait(task)
 | |
| 
 | |
|     def _get_ilo_access(self, server_hardware_uuid):
 | |
|         uri = ("/rest/server-hardware/%s/remoteConsoleUrl"
 | |
|                % server_hardware_uuid)
 | |
|         json = self._prepare_and_do_request(uri)
 | |
|         url = json.get("remoteConsoleUrl")
 | |
|         ip_key = "addr="
 | |
|         host_ip = url[url.rfind(ip_key) + len(ip_key):]
 | |
|         host_ip = host_ip[:host_ip.find("&")]
 | |
|         session_key = "sessionkey="
 | |
|         token = url[url.rfind(session_key) + len(session_key):]
 | |
| 
 | |
|         return host_ip, token
 | |
| 
 | |
|     def get_sh_mac_from_ilo(self, server_hardware_uuid, nic_index=0):
 | |
|         host_ip, ilo_token = self._get_ilo_access(server_hardware_uuid)
 | |
|         try:
 | |
|             return ilo_utils.get_mac_from_ilo(host_ip, ilo_token, nic_index)
 | |
|         finally:
 | |
|             ilo_utils.ilo_logout(host_ip, ilo_token)
 | |
| 
 | |
| 
 | |
| class ClientV2(BaseClient):
 | |
| 
 | |
|     def __init__(
 | |
|         self, manager_url, username, password,
 | |
|         allow_insecure_connections=False, tls_cacert_file='',
 | |
|         max_polling_attempts=20
 | |
|     ):
 | |
|         super(ClientV2, self).__init__(manager_url, username, password,
 | |
|                                        allow_insecure_connections,
 | |
|                                        tls_cacert_file, max_polling_attempts)
 | |
|         # Next generation
 | |
|         self.enclosure = managers.EnclosureManager(self)
 | |
|         self.enclosure_group = managers.EnclosureGroupManager(self)
 | |
|         self.server_hardware = managers.ServerHardwareManager(self)
 | |
|         self.server_hardware_index = managers.ServerHardwareIndexManager(self)
 | |
|         self.server_hardware_type = managers.ServerHardwareTypeManager(self)
 | |
|         self.server_profile = managers.ServerProfileManager(self)
 | |
|         self.server_profile_template = managers.ServerProfileTemplateManager(
 | |
|             self
 | |
|         )
 | |
| 
 | |
| 
 | |
| class Client(BaseClient):
 | |
| 
 | |
|     def __init__(
 | |
|         self, manager_url, username, password,
 | |
|         allow_insecure_connections=False, tls_cacert_file='',
 | |
|         max_polling_attempts=20
 | |
|     ):
 | |
|         super(Client, self).__init__(manager_url, username, password,
 | |
|                                      allow_insecure_connections,
 | |
|                                      tls_cacert_file, max_polling_attempts)
 | |
|         # Next generation
 | |
|         self._enclosure_group = managers.EnclosureGroupManager(self)
 | |
|         self._server_hardware = managers.ServerHardwareManager(self)
 | |
|         self._server_profile_template = managers.ServerProfileTemplateManager(
 | |
|             self
 | |
|         )
 | |
|         self._server_profile = managers.ServerProfileManager(self)
 | |
| 
 | |
|     # --- Power Driver ---
 | |
|     def get_node_power_state(self, node_info):
 | |
|         return self.get_server_hardware(node_info).power_state
 | |
| 
 | |
|     def power_on(self, node_info):
 | |
|         if self.get_node_power_state(node_info) == \
 | |
|            states.ONEVIEW_POWER_ON:
 | |
|             ret = states.ONEVIEW_POWER_ON
 | |
|         else:
 | |
|             ret = self.set_node_power_state(
 | |
|                 node_info, states.ONEVIEW_POWER_ON
 | |
|             )
 | |
|         return ret
 | |
| 
 | |
|     def power_off(self, node_info):
 | |
|         if self.get_node_power_state(node_info) == \
 | |
|            states.ONEVIEW_POWER_OFF:
 | |
|             ret = states.ONEVIEW_POWER_OFF
 | |
|         else:
 | |
|             ret = self.set_node_power_state(
 | |
|                 node_info, states.ONEVIEW_POWER_OFF, PRESS_AND_HOLD
 | |
|             )
 | |
|         return ret
 | |
| 
 | |
|     def set_node_power_state(
 | |
|         self, node_info, state, press_type=MOMENTARY_PRESS
 | |
|     ):
 | |
|         body = {'powerState': state, 'powerControl': press_type}
 | |
|         power_state_uri = (node_info.get('server_hardware_uri') +
 | |
|                            '/powerState')
 | |
|         task = self._prepare_and_do_request(
 | |
|             uri=power_state_uri, body=body, request_type=PUT_REQUEST_TYPE
 | |
|         )
 | |
|         try:
 | |
|             self._wait_for_task_to_complete(task)
 | |
|         except exceptions.OneViewTaskError as e:
 | |
|             raise exceptions.OneViewErrorStateSettingPowerState(e.message)
 | |
| 
 | |
|         return state
 | |
| 
 | |
|     # --- Management Driver ---
 | |
|     def get_server_hardware(self, node_info):
 | |
|         uuid = node_info['server_hardware_uri'].split("/")[-1]
 | |
|         return self._server_hardware.get(uuid)
 | |
| 
 | |
|     def get_server_hardware_by_uuid(self, uuid):
 | |
|         return self._server_hardware.get(uuid)
 | |
| 
 | |
|     def get_server_profile_from_hardware(self, node_info):
 | |
|         server_hardware = self.get_server_hardware(node_info)
 | |
|         server_profile_uri = server_hardware.server_profile_uri
 | |
| 
 | |
|         if server_profile_uri is None:
 | |
|             message = (
 | |
|                 "There is no server profile assigned to"
 | |
|                 " %(server_hardware_uri)s" %
 | |
|                 {'server_hardware_uri': node_info.get('server_hardware_uri')}
 | |
|             )
 | |
|             raise exceptions.OneViewServerProfileAssociatedError(message)
 | |
| 
 | |
|         server_profile_uuid = server_profile_uri.split("/")[-1]
 | |
|         return self._server_profile.get(server_profile_uuid)
 | |
| 
 | |
|     def get_server_profile_template(self, node_info):
 | |
|         uuid = node_info['server_profile_template_uri'].split("/")[-1]
 | |
|         return self._server_profile_template.get(uuid)
 | |
| 
 | |
|     def get_server_profile_template_by_uuid(self, uuid):
 | |
|         return self._server_profile_template.get(uuid)
 | |
| 
 | |
|     def get_server_profile_by_uuid(self, uuid):
 | |
|         return self._server_profile.get(uuid)
 | |
| 
 | |
|     def get_boot_order(self, node_info):
 | |
|         server_profile = self.get_server_profile_from_hardware(
 | |
|             node_info
 | |
|         )
 | |
|         return server_profile.boot.get("order")
 | |
| 
 | |
|     def set_boot_device(self, node_info, new_primary_boot_device):
 | |
|         boot_order = self.get_boot_order(node_info)
 | |
| 
 | |
|         if new_primary_boot_device is None:
 | |
|             raise exceptions.OneViewBootDeviceInvalidError()
 | |
| 
 | |
|         if new_primary_boot_device in boot_order:
 | |
|             boot_order.remove(new_primary_boot_device)
 | |
| 
 | |
|         boot_order.insert(0, new_primary_boot_device)
 | |
| 
 | |
|         server_profile = self.get_server_profile_from_hardware(
 | |
|             node_info
 | |
|         )
 | |
| 
 | |
|         manage_boot = server_profile.boot.get("manageBoot")
 | |
|         server_profile.boot = {
 | |
|             "manageBoot": manage_boot,
 | |
|             "order": boot_order
 | |
|         }
 | |
| 
 | |
|         boot_order_dict = server_profile.to_oneview_dict()
 | |
| 
 | |
|         task = self._prepare_and_do_request(
 | |
|             uri=server_profile.uri, body=boot_order_dict,
 | |
|             request_type=PUT_REQUEST_TYPE
 | |
|         )
 | |
|         try:
 | |
|             self._wait_for_task_to_complete(task)
 | |
|         except exceptions.OneViewTaskError as e:
 | |
|             raise exceptions.OneViewErrorSettingBootDevice(e.message)
 | |
| 
 | |
|     # ---- Deploy Driver ----
 | |
|     def clone_template_and_apply(self,
 | |
|                                  server_profile_name,
 | |
|                                  server_hardware_uuid,
 | |
|                                  server_profile_template_uuid):
 | |
| 
 | |
|         if not server_profile_name:
 | |
|             raise ValueError(
 | |
|                 'Missing Server Profile name.'
 | |
|             )
 | |
| 
 | |
|         if not server_hardware_uuid:
 | |
|             raise ValueError(
 | |
|                 'Missing Server Hardware uuid.'
 | |
|             )
 | |
| 
 | |
|         if not server_profile_template_uuid:
 | |
|             raise ValueError(
 | |
|                 'Missing Server Profile Template uuid.'
 | |
|             )
 | |
| 
 | |
|         server_hardware_uri = '%s%s' % (
 | |
|             SERVER_HARDWARE_PREFIX_URI,
 | |
|             server_hardware_uuid
 | |
|         )
 | |
| 
 | |
|         server_profile_template_uri = '%s%s' % (
 | |
|             SERVER_PROFILE_TEMPLATE_PREFIX_URI,
 | |
|             server_profile_template_uuid
 | |
|         )
 | |
| 
 | |
|         generate_new_profile_uri = '%s/new-profile' % (
 | |
|             server_profile_template_uri
 | |
|         )
 | |
| 
 | |
|         server_profile_from_template_json = self._prepare_and_do_request(
 | |
|             uri=generate_new_profile_uri
 | |
|         )
 | |
| 
 | |
|         server_profile_from_template_json['serverHardwareUri'] = \
 | |
|             server_hardware_uri
 | |
|         server_profile_from_template_json['name'] = server_profile_name
 | |
|         server_profile_from_template_json['serverProfileTemplateUri'] = ""
 | |
| 
 | |
|         post_profile_task = self._prepare_and_do_request(
 | |
|             uri=SERVER_PROFILE_PREFIX_URI,
 | |
|             body=server_profile_from_template_json,
 | |
|             request_type=POST_REQUEST_TYPE
 | |
|         )
 | |
| 
 | |
|         try:
 | |
|             complete_task = self._wait_for_task_to_complete(
 | |
|                 post_profile_task
 | |
|             )
 | |
|         except exceptions.OneViewTaskError as e:
 | |
|             raise exceptions.OneViewServerProfileAssignmentError(e.message)
 | |
| 
 | |
|         server_profile_uri = complete_task.get('associatedResource')\
 | |
|             .get('resourceUri')
 | |
| 
 | |
|         uuid = server_profile_uri.split("/")[-1]
 | |
|         server_profile = self.get_server_profile_by_uuid(uuid)
 | |
| 
 | |
|         return server_profile
 | |
| 
 | |
|     def delete_server_profile(self, uuid):
 | |
|         if not uuid:
 | |
|             raise ValueError('Missing Server Profile uuid.')
 | |
| 
 | |
|         delete_profile_task = self._prepare_and_do_request(
 | |
|             uri='%s%s' % (SERVER_PROFILE_PREFIX_URI, uuid),
 | |
|             request_type=DELETE_REQUEST_TYPE
 | |
|         )
 | |
|         try:
 | |
|             complete_task = self._wait_for_task_to_complete(
 | |
|                 delete_profile_task
 | |
|             )
 | |
|         except exceptions.OneViewTaskError as e:
 | |
|             raise exceptions.OneViewServerProfileDeletionError(e.message)
 | |
| 
 | |
|         return complete_task.get('associatedResource').get('resourceUri')
 | |
| 
 | |
|     # ---- Node Validate ----
 | |
|     def validate_node_server_hardware(
 | |
|         self, node_info, node_memorymb, node_cpus
 | |
|     ):
 | |
|         node_sh_uri = node_info.get('server_hardware_uri')
 | |
|         server_hardware = self.get_server_hardware(node_info)
 | |
|         server_hardware_cpus = (server_hardware.processor_core_count
 | |
|                                 * server_hardware.processor_count)
 | |
|         if server_hardware.memory_mb != node_memorymb:
 | |
|             message = (
 | |
|                 "Node memory_mb is inconsistent with OneView's"
 | |
|                 " server hardware %(server_hardware_uri)s memoryMb."
 | |
|                 % {'server_hardware_uri': node_sh_uri}
 | |
|             )
 | |
|             raise exceptions.OneViewInconsistentResource(message)
 | |
|         elif server_hardware_cpus != node_cpus:
 | |
|             message = (
 | |
|                 "Node cpus is inconsistent with OneView's"
 | |
|                 " server hardware %(server_hardware_uri)s cpus."
 | |
|                 % {'server_hardware_uri': node_sh_uri}
 | |
|             )
 | |
|             raise exceptions.OneViewInconsistentResource(message)
 | |
| 
 | |
|     def validate_node_server_hardware_type(self, node_info):
 | |
|         node_sht_uri = node_info.get('server_hardware_type_uri')
 | |
|         server_hardware = self.get_server_hardware(node_info)
 | |
|         server_hardware_sht_uri = server_hardware.server_hardware_type_uri
 | |
| 
 | |
|         if server_hardware_sht_uri != node_sht_uri:
 | |
|             message = (
 | |
|                 "Node server_hardware_type_uri is inconsistent"
 | |
|                 " with OneView's server hardware %(server_hardware_uri)s"
 | |
|                 " serverHardwareTypeUri." %
 | |
|                 {'server_hardware_uri': node_info.get('server_hardware_uri')}
 | |
|             )
 | |
|             raise exceptions.OneViewInconsistentResource(message)
 | |
| 
 | |
|     def check_server_profile_is_applied(self, node_info):
 | |
|         self.get_server_profile_from_hardware(node_info)
 | |
| 
 | |
|     def validate_node_enclosure_group(self, node_info):
 | |
|         server_hardware = self.get_server_hardware(node_info)
 | |
|         sh_enclosure_group_uri = server_hardware.enclosure_group_uri
 | |
|         node_enclosure_group_uri = node_info.get('enclosure_group_uri')
 | |
| 
 | |
|         if node_enclosure_group_uri not in ('', 'None', None):
 | |
|             if sh_enclosure_group_uri != node_enclosure_group_uri:
 | |
|                 message = (
 | |
|                     "Node enclosure_group_uri '%(node_enclosure_group_uri)s' "
 | |
|                     "is inconsistent with OneView's server hardware "
 | |
|                     "serverGroupUri '%(sh_enclosure_group_uri)s' of "
 | |
|                     "ServerHardware %(server_hardware)s"
 | |
|                     % {
 | |
|                         'node_enclosure_group_uri': node_enclosure_group_uri,
 | |
|                         'sh_enclosure_group_uri': sh_enclosure_group_uri,
 | |
|                         'server_hardware': server_hardware.uuid,
 | |
|                     }
 | |
|                 )
 | |
|                 raise exceptions.OneViewInconsistentResource(message)
 | |
| 
 | |
|     def is_node_port_mac_compatible_with_server_profile(
 | |
|         self, node_info, ports
 | |
|     ):
 | |
|         server_profile = self.get_server_profile_from_hardware(
 | |
|             node_info
 | |
|         )
 | |
| 
 | |
|         if server_profile.connections:
 | |
|             primary_boot_connection = None
 | |
| 
 | |
|             for connection in server_profile.connections:
 | |
|                 boot = connection.get('boot')
 | |
|                 if (boot is not None and
 | |
|                    boot.get('priority').lower() == 'primary'):
 | |
|                     primary_boot_connection = connection
 | |
| 
 | |
|             if primary_boot_connection is None:
 | |
|                 message = (
 | |
|                     "No primary boot connection configured for server profile"
 | |
|                     " %s." % server_profile.uri
 | |
|                 )
 | |
|                 raise exceptions.OneViewInconsistentResource(message)
 | |
| 
 | |
|             mac = primary_boot_connection.get('mac')
 | |
| 
 | |
|         else:
 | |
|             # If no connections on Server Profile, the connections are not
 | |
|             # being managed or the server is rack based. In both cases, fall
 | |
|             # back to 1st nic from iLO
 | |
|             server_hardware = self.get_server_hardware(node_info)
 | |
|             mac = self.get_sh_mac_from_ilo(server_hardware.uuid, nic_index=0)
 | |
| 
 | |
|         is_mac_address_compatible = True
 | |
|         for port in ports:
 | |
|             port_address = port.__dict__.get('_obj_address')
 | |
|             if port_address is None:
 | |
|                 port_address = port.__dict__.get('_address')
 | |
|             if port_address.lower() != mac.lower():
 | |
|                 is_mac_address_compatible = False
 | |
| 
 | |
|         if (not is_mac_address_compatible) or len(ports) == 0:
 | |
|             message = (
 | |
|                 "The ports of the node are not compatible with its"
 | |
|                 " server profile %(server_profile_uri)s." %
 | |
|                 {'server_profile_uri': server_profile.uri}
 | |
|             )
 | |
|             raise exceptions.OneViewInconsistentResource(message)
 | |
| 
 | |
|     def is_node_port_mac_compatible_with_server_hardware(
 | |
|         self, node_info, ports
 | |
|     ):
 | |
|         server_hardware = self.get_server_hardware(node_info)
 | |
|         try:
 | |
|             mac = server_hardware.get_mac(nic_index=0)
 | |
|         except exceptions.OneViewException:
 | |
|             mac = self.get_sh_mac_from_ilo(server_hardware.uuid, nic_index=0)
 | |
| 
 | |
|         is_mac_address_compatible = True
 | |
|         for port in ports:
 | |
|             port_address = port.__dict__.get('_obj_address')
 | |
|             if port_address is None:
 | |
|                 port_address = port.__dict__.get('_address')
 | |
| 
 | |
|             if port_address.lower() != mac:
 | |
|                 is_mac_address_compatible = False
 | |
| 
 | |
|         if (not is_mac_address_compatible) or len(ports) == 0:
 | |
|             message = (
 | |
|                 "The ports of the node are not compatible with its"
 | |
|                 " server hardware %(server_hardware_uri)s." %
 | |
|                 {'server_hardware_uri': server_hardware.uri}
 | |
|             )
 | |
|             raise exceptions.OneViewInconsistentResource(message)
 | |
| 
 | |
|     def validate_node_server_profile_template(self, node_info):
 | |
|         node_spt_uri = node_info.get('server_profile_template_uri')
 | |
| 
 | |
|         server_profile_template = self.get_server_profile_template(node_info)
 | |
|         spt_server_hardware_type_uri = server_profile_template \
 | |
|             .server_hardware_type_uri
 | |
|         spt_enclosure_group_uri = server_profile_template.enclosure_group_uri
 | |
| 
 | |
|         server_hardware = self.get_server_hardware(node_info)
 | |
|         sh_server_hardware_type_uri = server_hardware.server_hardware_type_uri
 | |
|         sh_enclosure_group_uri_uri = server_hardware.enclosure_group_uri
 | |
|         if spt_server_hardware_type_uri != sh_server_hardware_type_uri:
 | |
|             message = (
 | |
|                 "Server profile template %(spt_uri)s serverHardwareTypeUri is"
 | |
|                 " inconsistent with server hardware %(server_hardware_uri)s"
 | |
|                 " serverHardwareTypeUri." %
 | |
|                 {'spt_uri': node_spt_uri,
 | |
|                  'server_hardware_uri': node_info.get('server_hardware_uri')}
 | |
|             )
 | |
|             raise exceptions.OneViewInconsistentResource(message)
 | |
|         if spt_enclosure_group_uri != sh_enclosure_group_uri_uri:
 | |
|             message = (
 | |
|                 "Server profile template %(spt_uri)s enclosureGroupUri is"
 | |
|                 " inconsistent with server hardware %(server_hardware_uri)s"
 | |
|                 " serverGroupUri." %
 | |
|                 {'spt_uri': node_spt_uri,
 | |
|                  'server_hardware_uri': node_info.get('server_hardware_uri')}
 | |
|             )
 | |
|             raise exceptions.OneViewInconsistentResource(message)
 | |
| 
 | |
|     def validate_spt_boot_connections(self, uuid):
 | |
|         server_profile_template = self.get_server_profile_template_by_uuid(
 | |
|             uuid
 | |
|         )
 | |
| 
 | |
|         for connection in server_profile_template.connections:
 | |
|             boot = connection.get('boot')
 | |
|             if boot is not None and boot.get('priority').lower() != 'primary':
 | |
|                 message = (
 | |
|                     "No primary boot connection configured for server profile"
 | |
|                     " template %s." % server_profile_template.uri
 | |
|                 )
 | |
|                 raise exceptions.OneViewInconsistentResource(message)
 | |
| 
 | |
| 
 | |
| def _check_request_status(response):
 | |
|     repeat = False
 | |
|     status = response.status_code
 | |
| 
 | |
|     if status == 401:
 | |
|         raise exceptions.OneViewNotAuthorizedException()
 | |
|     elif status == 404:
 | |
|         raise exceptions.OneViewResourceNotFoundError()
 | |
|     elif status in (408, 409,):
 | |
|         time.sleep(10)
 | |
|         repeat = True
 | |
|     elif status == 500:
 | |
|         raise exceptions.OneViewInternalServerError()
 | |
|     # Any other unexpected status are logged
 | |
|     elif status not in (200, 202,):
 | |
|         message = (
 | |
|             "OneView appliance returned an unknown response status: %s"
 | |
|             % status
 | |
|         )
 | |
|         raise exceptions.UnknowOneViewResponseError(message)
 | |
|     return repeat
 | 
