From 09f83c15ba25b6f3b13bea06b2834e61d53006eb Mon Sep 17 00:00:00 2001 From: Thiago Paiva Date: Wed, 2 Dec 2015 16:09:39 -0300 Subject: [PATCH] Implementing functions for dyn allocation Change-Id: Ib213511bdeb98e692ea556eab53feeeed108354c --- oneview_client/client.py | 35 +++ oneview_client/models.py | 3 + oneview_client/tests/test_models.py | 3 + oneview_client/tests/test_oneview_client.py | 229 ++++++++++++++++++++ 4 files changed, 270 insertions(+) diff --git a/oneview_client/client.py b/oneview_client/client.py index 2770965..1bb1454 100644 --- a/oneview_client/client.py +++ b/oneview_client/client.py @@ -360,6 +360,32 @@ class Client(object): ) 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) + + device = server_hardware.port_map.get('deviceSlots')[0] + first_physical_port = device.get('physicalPorts')[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() != \ + first_physical_port.get('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 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') @@ -392,6 +418,15 @@ class Client(object): ) raise exceptions.OneViewInconsistentResource(message) + 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) + # --- Requests --- def _prepare_and_do_request( self, uri, body={}, request_type=GET_REQUEST_TYPE diff --git a/oneview_client/models.py b/oneview_client/models.py index 93f49e8..9fc68d2 100644 --- a/oneview_client/models.py +++ b/oneview_client/models.py @@ -66,6 +66,7 @@ class ServerHardware(OneViewObject): 'processorCount': 'processor_count', 'processorCoreCount': 'processor_core_count', 'memoryMb': 'memory_mb', + 'portMap': 'port_map', } @@ -74,6 +75,8 @@ class ServerProfileTemplate(OneViewObject): 'uri': 'uri', 'serverHardwareTypeUri': 'server_hardware_type_uri', 'enclosureGroupUri': 'enclosure_group_uri', + 'connections': 'connections', + 'boot': 'boot', } diff --git a/oneview_client/tests/test_models.py b/oneview_client/tests/test_models.py index ef2af6a..eb26e5c 100644 --- a/oneview_client/tests/test_models.py +++ b/oneview_client/tests/test_models.py @@ -101,6 +101,7 @@ class Test(unittest.TestCase): 'processorCount': 'processor_count', 'processorCoreCount': 'processor_core_count', 'memoryMb': 'memory_mb', + 'portMap': 'port_map', } self.assertEqual(sh.attribute_map, sh_attribute_map) self.assertEqual(sh.uri, 'http://something.com/1111-2222-3333-4444') @@ -118,6 +119,8 @@ class Test(unittest.TestCase): 'uri': 'uri', 'serverHardwareTypeUri': 'server_hardware_type_uri', 'enclosureGroupUri': 'enclosure_group_uri', + 'boot': 'boot', + 'connections': 'connections', } self.assertEqual(spt.attribute_map, spt_attribute_map) self.assertEqual(spt.uri, 'http://something.com/1111-2222-3333-4444') diff --git a/oneview_client/tests/test_oneview_client.py b/oneview_client/tests/test_oneview_client.py index 6ea0eb9..ff7c8a3 100644 --- a/oneview_client/tests/test_oneview_client.py +++ b/oneview_client/tests/test_oneview_client.py @@ -40,6 +40,132 @@ PROPERTIES_DICT = {"cpu_arch": "x86_64", DRIVER_INFO_DICT = {'server_hardware_uri': 'fake_sh_uri', 'server_profile_template_uri': 'fake_spt_uri'} +PORT_MAP = { + "deviceSlots": [{ + "deviceName": "HP FlexFabric 10Gb 2-port 554FLB Adapter", + "deviceNumber": 9, + "location": "Flb", + "physicalPorts": [{ + "interconnectPort": 1, + "interconnectUri": ("/rest/interconnects/25352bd0-6a7a-4c1" + "d-abe1-268c306c82b8"), + "mac": "D8:9D:67:73:54:00", + "physicalInterconnectPort": 1, + "physicalInterconnectUri": ("/rest/interconnects/25352bd0-" + "6a7a-4c1d-abe1-268c306c82b8"), + "portNumber": 1, + "type": "Ethernet", + "virtualPorts": [{ + "currentAllocatedVirtualFunctionCount": (-1), + "mac": "EA:EF:C7:70:00:00", + "portFunction": "a", + "portNumber": 1, + "wwnn": None, + "wwpn": None + }, { + "currentAllocatedVirtualFunctionCount": (-1), + "mac": "D8:9D:67:73:54:01", + "portFunction": "b", + "portNumber": 2, + "wwnn": "20:00:D8:9D:67:73:54:01", + "wwpn": "10:00:D8:9D:67:73:54:01" + }, { + "currentAllocatedVirtualFunctionCount": (-1), + "mac": "D8:9D:67:73:54:02", + "portFunction": "c", + "portNumber": 3, + "wwnn": None, + "wwpn": None + }, { + "currentAllocatedVirtualFunctionCount": (-1), + "mac": "D8:9D:67:73:54:03", + "portFunction": "d", + "portNumber": 4, + "wwnn": None, + "wwpn": None + }], + "wwn": None + }, { + "interconnectPort": 1, + "interconnectUri": ("/rest/interconnects/e005478c-8b50-45c" + "7-8aae-7239df039078"), + "mac": "D8:9D:67:73:54:04", + "physicalInterconnectPort": 1, + "physicalInterconnectUri": ("/rest/interconnects/e005478c-" + "8b50-45cf-8aae-7239df039078"), + "portNumber": 2, + "type": "Ethernet", + "virtualPorts": [{ + "currentAllocatedVirtualFunctionCount": (-1), + "mac": "D8:9D:67:73:54:04", + "portFunction": "a", + "portNumber": 1, + "wwnn": None, + "wwpn": None + }, { + "currentAllocatedVirtualFunctionCount": (-1), + "mac": "D8:9D:67:73:54:05", + "portFunction": "b", + "portNumber": 2, + "wwnn": "20:00:D8:9D:67:73:54:05", + "wwpn": "10:00:D8:9D:67:73:54:05" + }, { + "currentAllocatedVirtualFunctionCount": (-1), + "mac": "D8:9D:67:73:54:06", + "portFunction": "c", + "portNumber": 3, + "wwnn": None, + "wwpn": None + }, { + "currentAllocatedVirtualFunctionCount": (-1), + "mac": "D8:9D:67:73:54:07", + "portFunction": "d", + "portNumber": 4, + "wwnn": None, + "wwpn": None + }], + "wwn": None + }], + "slotNumber": 1 + }, { + "deviceName": "HP LPe1205A 8Gb FC HBA for BladeSystem c-Class", + "deviceNumber": 1, + "location": "Mezz", + "physicalPorts": [{ + "interconnectPort": 1, + "interconnectUri": ("/rest/interconnects/efb60cdf-caf4-438" + "2-8419-7ac969504034"), + "mac": None, + "physicalInterconnectPort": 1, + "physicalInterconnectUri": ("/rest/interconnects/efb60cdf-" + "caf4-4382-8419-7ac969504034"), + "portNumber": 1, + "type": "FibreChannel", + "virtualPorts": [], + "wwn": "10:00:38:EA:A7:D3:E4:40" + }, { + "interconnectPort": 1, + "interconnectUri": ("/rest/interconnects/e4607445-0571-484" + "e-8629-8e01bdd1ea9f"), + "mac": None, + "physicalInterconnectPort": 1, + "physicalInterconnectUri": ("/rest/interconnects/e4607445-" + "0571-484e-8629-8e01bdd1ea9f"), + "portNumber": 2, + "type": "FibreChannel", + "virtualPorts": [], + "wwn": "10:00:38:EA:A7:D3:E4:41" + }], + "slotNumber": 1 + }, { + "deviceName": "", + "deviceNumber": 2, + "location": "Mezz", + "physicalPorts": [], + "slotNumber": 2 + }] +} + class TestablePort(object): @@ -516,6 +642,63 @@ class OneViewClientTestCase(unittest.TestCase): driver_info ) + @mock.patch.object(client.Client, 'get_server_hardware', + autospec=True) + def test_is_node_port_mac_compatible_with_server_hardware( + self, mock_server_hardware, mock__authenticate + ): + server_hardware_mock = ServerHardware() + setattr(server_hardware_mock, "uri", "/anyuri") + server_hardware_mock_port_map = PORT_MAP + setattr(server_hardware_mock, + "port_map", + server_hardware_mock_port_map) + + mock_server_hardware.return_value = server_hardware_mock + + oneview_client = client.Client(self.manager_url, + self.username, + self.password) + + oneview_client.is_node_port_mac_compatible_with_server_hardware( + {}, + [type('obj', (object,), {'_address': 'D8:9D:67:73:54:00'})] + ) + + mock_server_hardware.assert_called_once_with(oneview_client, {}) + + @mock.patch.object(client.Client, 'get_server_hardware', + autospec=True) + def test_is_node_port_mac_incompatible_with_server_hardware( + self, mock_server_hardware, mock__authenticate + ): + server_hardware_mock = ServerHardware() + setattr(server_hardware_mock, "uri", "/anyuri") + server_hardware_mock_port_map = PORT_MAP + setattr(server_hardware_mock, + "port_map", + server_hardware_mock_port_map) + + mock_server_hardware.return_value = server_hardware_mock + + exc_expected_msg = ( + "The ports of the node are not compatible with its server hardware" + " /anyuri." + ) + + oneview_client = client.Client(self.manager_url, + self.username, + self.password) + + self.assertRaisesRegexp( + exceptions.OneViewInconsistentResource, + exc_expected_msg, + oneview_client + .is_node_port_mac_compatible_with_server_hardware, + {}, + [type('obj', (object,), {'_address': 'AA:BB:CC:DD:EE:FF'})] + ) + @mock.patch.object(client.Client, 'get_server_profile_from_hardware', autospec=True) def test_check_node_port_mac_incompatible_with_server_profile( @@ -676,6 +859,52 @@ class OneViewClientTestCase(unittest.TestCase): driver_info ) + @mock.patch.object(client.Client, 'get_server_profile_template', + autospec=True) + @mock.patch.object(client.Client, 'get_server_hardware', autospec=True) + def test_validate_node_server_profile_template_no_primary_boot_connection( + self, mock_server_hardware, mock_server_template, mock__authenticate + ): + server_hardware_mock = ServerHardware() + setattr(server_hardware_mock, "server_hardware_type_uri", "/sht_uri") + setattr(server_hardware_mock, "enclosure_group_uri", "/eg_uri") + + profile_template_mock = ServerProfileTemplate() + setattr(profile_template_mock, "uri", "/template_uri") + setattr(profile_template_mock, "server_hardware_type_uri", "/sht_uri") + setattr(profile_template_mock, "enclosure_group_uri", "/eg_uri") + + profile_template_mock_connections = [ + {'boot': {'priority': u'NotBootable'}, + 'mac': u'56:88:7B:C0:00:0B'} + ] + setattr(profile_template_mock, + "connections", + profile_template_mock_connections) + + mock_server_template.return_value = profile_template_mock + mock_server_hardware.return_value = server_hardware_mock + + exc_expected_msg = ( + "No primary boot connection configured for server profile" + " template /template_uri." + ) + + oneview_client = client.Client(self.manager_url, + self.username, + self.password) + driver_info = { + "server_profile_template_uri": "/profile_uri" + } + + self.assertRaisesRegexp( + exceptions.OneViewInconsistentResource, + exc_expected_msg, + oneview_client + .validate_node_server_profile_template, + driver_info + ) + @mock.patch.object(client.Client, 'get_oneview_version') def test_verify_oneview_version(self, mock_get_oneview_version, mock__authenticate):