From ec91d38ef42a31c343379bbd8ad7998d92b54a73 Mon Sep 17 00:00:00 2001 From: monokai <2536818783@qq.com> Date: Wed, 16 Jan 2019 16:29:04 +0800 Subject: [PATCH] Add ethernet interface resource for RSD2.1 Change-Id: I02ffc2e381db7791bd1b019acbad5089f15ed024 --- .../v2_1/manager/ethernet_interface.py | 212 ++++++++++++++++++ rsd_lib/resources/v2_1/manager/manager.py | 18 ++ .../json_samples/v2_1/ethernet_interface.json | 63 ++++++ .../ethernet_interface_without_vlans.json | 61 +++++ .../v2_1/ethernrt_interface_collection.json | 12 + .../v2_1/manager/test_ethernet_interface.py | 211 +++++++++++++++++ .../resources/v2_1/manager/test_manager.py | 55 ++++- 7 files changed, 629 insertions(+), 3 deletions(-) create mode 100644 rsd_lib/resources/v2_1/manager/ethernet_interface.py create mode 100644 rsd_lib/tests/unit/json_samples/v2_1/ethernet_interface.json create mode 100644 rsd_lib/tests/unit/json_samples/v2_1/ethernet_interface_without_vlans.json create mode 100644 rsd_lib/tests/unit/json_samples/v2_1/ethernrt_interface_collection.json create mode 100644 rsd_lib/tests/unit/resources/v2_1/manager/test_ethernet_interface.py diff --git a/rsd_lib/resources/v2_1/manager/ethernet_interface.py b/rsd_lib/resources/v2_1/manager/ethernet_interface.py new file mode 100644 index 0000000..b520d90 --- /dev/null +++ b/rsd_lib/resources/v2_1/manager/ethernet_interface.py @@ -0,0 +1,212 @@ +# Copyright 2019 Intel, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# 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. + +from rsd_lib.resources.v2_1.ethernet_switch import vlan +from rsd_lib import utils as rsd_lib_utils + +from sushy import exceptions +from sushy.resources import base +from sushy import utils + + +class StatusField(base.CompositeField): + state = base.Field('State') + health = base.Field('Health') + health_rollup = base.Field('HealthRollup') + + +class IPv4AddressesField(base.ListField): + address = base.Field("Address") + """The IPv4Addresses address""" + + subnet_mask = base.Field("SubnetMask") + """The IPv4Addresses subnetmask""" + + address_origin = base.Field("AddressOrigin") + """The IPv4Addresses addressorigin""" + + gate_way = base.Field("Gateway") + """The IPv4Addresses gateway""" + + +class IPv6AddressesField(base.ListField): + address = base.Field("Address") + """The IPv4Addresses address""" + + prefix_length = base.Field("PrefixLength", + adapter=rsd_lib_utils.num_or_none) + """The prefix length of IPv6 addresses""" + + address_origin = base.Field("AddressOrigin") + """The IPv4Addresses address origin""" + + address_state = base.Field("AddressState") + """The address state of IPv6 addresses""" + + +class IPv6StaticAddressesField(base.ListField): + address = base.Field("Address") + """The IPv6 static addresses""" + + prefix_length = base.Field("PrefixLength") + """The IPv6 prefix length""" + + +class IPv6AddressPolicyTableField(base.ListField): + prefix = base.Field("Prefix") + """The IPv6 Address Policy Table prefix""" + + precedence = base.Field("Precedence", adapter=rsd_lib_utils.num_or_none) + """The IPv6 Address Policy Table precedence""" + + label = base.Field("Label", adapter=rsd_lib_utils.num_or_none) + """The IPv6 Address Policy Table label""" + + +class IntelRackScaleField(base.CompositeField): + neighbor_port = base.Field("NeighborPort", + adapter=rsd_lib_utils.get_resource_identity) + """The neighbor port of Rack ScaleIntel""" + + +class OemField(base.CompositeField): + intel_rackScale = IntelRackScaleField("Intel_RackScale") + """The Oem Intel_RackScale""" + + +class LinksField(base.CompositeField): + oem = OemField("Oem") + """"The oem of Links""" + + +class VLANField(base.CompositeField): + vlan_enable = base.Field("VLANEnable", adapter=bool) + """Whether the vlan is enable""" + + vlan_id = base.Field("VLANId", adapter=rsd_lib_utils.num_or_none) + """The vlan id""" + + +class EthernetInterface(base.ResourceBase): + identity = base.Field('Id', required=True) + """The EthernetInterface identity string""" + + name = base.Field('Name') + """The EthernetInterface identity string""" + + description = base.Field('Description') + """The EthernetInterface description""" + + status = StatusField('Status') + """The EthernetInterface Status""" + + interface_enabled = base.Field("InterfaceEnabled", adapter=bool) + """Whether the interface is enabled""" + + permanent_mac_address = base.Field("PermanentMACAddress") + """The EthernetInterface PermanentMACAddress""" + + mac_address = base.Field("MACAddress") + """The EthernetInterface MACAddress""" + + speed_mbps = base.Field("SpeedMbps", adapter=rsd_lib_utils.num_or_none) + """The EthernetInterface SpeedMbps""" + + auto_neg = base.Field("AutoNeg", adapter=bool) + """Whether the EthernetInterface is AutoNeg""" + + full_duplex = base.Field("FullDuplex", adapter=bool) + """Whether the EthernetInterface is FullDuplex""" + + mtu_size = base.Field("MTUSize", adapter=rsd_lib_utils.num_or_none) + """The EthernetInterface MTUSize""" + + host_name = base.Field("HostName") + """The EthernetInterface hostname""" + + fqdn = base.Field("FQDN") + """The EthernetInterface FQDN""" + + ipv6_default_gateway = base.Field("IPv6DefaultGateway") + """The EthernetInterface IPv6DefaultGateway""" + + max_ipv6_static_addresses = base.Field("MaxIPv6StaticAddresses", + adapter=rsd_lib_utils.num_or_none) + """The EthernetInterface MaxIPv6StaticAddresses""" + + name_servers = base.Field("NameServers") + """The EthernetInterface nameservers""" + + ipv4_addresses = IPv4AddressesField("IPv4Addresses") + """The EthernetInterface IPv4 addresses""" + + ipv6_addresses = IPv6AddressesField("IPv6Addresses") + """The EthernetInterface IPv4 addresses""" + + ipv6_static_addresses = IPv6StaticAddressesField("IPv6StaticAddresses") + """The EthernetInterface IPv6 Static Addresses""" + + ipv6_address_policy_table = IPv6AddressPolicyTableField( + "IPv6AddressPolicyTable") + """The EthernetInterface IPv6 Address Policy Table""" + + vlan = VLANField("VLAN") + """The EthernetInterface VLAN""" + + links = LinksField("Links") + """The EthernetInterface links""" + + def _get_vlan_collection_path(self): + """Helper function to find the VLANCollection path""" + try: + return utils.get_sub_resource_path_by(self, 'VLANs') + except exceptions.MissingAttributeError: + return None + + @property + @utils.cache_it + def vlans(self): + """Property to provide reference to `VLANCollection` instance + + It is calculated once when it is queried for the first time. On + refresh, this property is reset. + """ + path = self._get_vlan_collection_path() + if path: + return vlan.VLANCollection( + self._conn, path, + redfish_version=self.redfish_version) + else: + return None + + +class EthernetInterfaceCollection(base.ResourceCollectionBase): + @property + def _resource_type(self): + return EthernetInterface + + def __init__(self, connector, path, redfish_version=None): + """A class representing a EthernetInterface Collection + + :param connector: A Connector instance + :param path: The canonical path to the EthernetInterface collection + resource + :param redfish_version: The version of RedFish. Used to construct + the object according to schema of the given version. + """ + + super(EthernetInterfaceCollection, self).__init__(connector, + path, + redfish_version) diff --git a/rsd_lib/resources/v2_1/manager/manager.py b/rsd_lib/resources/v2_1/manager/manager.py index 980b676..5d9eb6a 100644 --- a/rsd_lib/resources/v2_1/manager/manager.py +++ b/rsd_lib/resources/v2_1/manager/manager.py @@ -16,6 +16,8 @@ from sushy.resources import base from sushy import utils + +from rsd_lib.resources.v2_1.manager import ethernet_interface from rsd_lib.resources.v2_1.manager import network_protocol from rsd_lib import utils as rsd_lib_utils @@ -125,6 +127,10 @@ class Manager(base.ResourceBase): """Helper function to find the network protocol path""" return utils.get_sub_resource_path_by(self, 'NetworkProtocol') + def _get_ethernet_interface_path(self): + """Helper function to find the Ethernet Interface path""" + return utils.get_sub_resource_path_by(self, 'EthernetInterfaces') + @property @utils.cache_it def network_protocol(self): @@ -137,6 +143,18 @@ class Manager(base.ResourceBase): self._conn, self._get_network_protocol_path(), redfish_version=self.redfish_version) + @property + @utils.cache_it + def ethernet_interface(self): + """Property to provide reference to `EthernetInterface` instance + + It is calculated once when it is queried for the first time. On + refresh, this property is reset. + """ + return ethernet_interface.EthernetInterfaceCollection( + self._conn, self._get_ethernet_interface_path(), + redfish_version=self.redfish_version) + class ManagerCollection(base.ResourceCollectionBase): @property diff --git a/rsd_lib/tests/unit/json_samples/v2_1/ethernet_interface.json b/rsd_lib/tests/unit/json_samples/v2_1/ethernet_interface.json new file mode 100644 index 0000000..021da96 --- /dev/null +++ b/rsd_lib/tests/unit/json_samples/v2_1/ethernet_interface.json @@ -0,0 +1,63 @@ +{ + "@odata.context":"/redfish/v1/$metadata#EthernetInterface.EthernetInterface", + "@odata.id":"/redfish/v1/Systems/System1/EthernetInterfaces/LAN1", + "@odata.type":"#EthernetInterface.v1_1_0.EthernetInterface", + "Id":"LAN1", + "Name":"Ethernet Interface", + "Description":"System NIC 1", + "Status":{ + "State":"Enabled", + "Health":"OK", + "HealthRollup":null + }, + "InterfaceEnabled":true, + "PermanentMACAddress":"AA:BB:CC:DD:EE:FF", + "MACAddress":"AA:BB:CC:DD:EE:FF", + "SpeedMbps":100, + "AutoNeg":true, + "FullDuplex":true, + "MTUSize":1500, + "HostName":"web483", + "FQDN":"web483.redfishspecification.org", + "IPv6DefaultGateway":"fe80::3ed9:2bff:fe34:600", + "MaxIPv6StaticAddresses":null, + "NameServers":[ + "names.redfishspecification.org" + ], + "IPv4Addresses":[ + { + "Address":"192.168.0.10", + "SubnetMask":"255.255.252.0", + "AddressOrigin":"Static", + "Gateway":"192.168.0.1" + } + ], + "IPv6Addresses":[ + { + "Address":"fe80::1ec1:deff:fe6f:1e24", + "PrefixLength":64, + "AddressOrigin":"Static", + "AddressState":"Preferred" + } + ], + "IPv6StaticAddresses":[ + + ], + "VLAN":null, + "VLANs": { + "@odata.id": "/redfish/v1/Managers/1/EthernetInterfaces/1/VLANs" + }, + "Oem":{ + + }, + "Links":{ + "Oem":{ + "Intel_RackScale":{ + "@odata.type":"#Intel.Oem.EthernetInterface", + "NeighborPort":{ + "@odata.id":"/redfish/v1/EthernetSwitches/1/Ports/1" + } + } + } + } +} \ No newline at end of file diff --git a/rsd_lib/tests/unit/json_samples/v2_1/ethernet_interface_without_vlans.json b/rsd_lib/tests/unit/json_samples/v2_1/ethernet_interface_without_vlans.json new file mode 100644 index 0000000..1397e27 --- /dev/null +++ b/rsd_lib/tests/unit/json_samples/v2_1/ethernet_interface_without_vlans.json @@ -0,0 +1,61 @@ +{ + "@odata.context":"/redfish/v1/$metadata#EthernetInterface.EthernetInterface", + "@odata.id":"/redfish/v1/Systems/System1/EthernetInterfaces/LAN1", + "@odata.type":"#EthernetInterface.v1_1_0.EthernetInterface", + "Id":"LAN1", + "Name":"Ethernet Interface", + "Description":"System NIC 1", + "Status":{ + "State":"Enabled", + "Health":"OK", + "HealthRollup":null + }, + "InterfaceEnabled":true, + "PermanentMACAddress":"AA:BB:CC:DD:EE:FF", + "MACAddress":"AA:BB:CC:DD:EE:FF", + "SpeedMbps":100, + "AutoNeg":true, + "FullDuplex":true, + "MTUSize":1500, + "HostName":"web483", + "FQDN":"web483.redfishspecification.org", + "IPv6DefaultGateway":"fe80::3ed9:2bff:fe34:600", + "MaxIPv6StaticAddresses":null, + "NameServers":[ + "names.redfishspecification.org" + ], + "IPv4Addresses":[ + { + "Address":"192.168.0.10", + "SubnetMask":"255.255.252.0", + "AddressOrigin":"Static", + "Gateway":"192.168.0.1" + } + ], + "IPv6Addresses":[ + { + "Address":"fe80::1ec1:deff:fe6f:1e24", + "PrefixLength":64, + "AddressOrigin":"Static", + "AddressState":"Preferred" + } + ], + "IPv6StaticAddresses":[ + + ], + "VLAN":null, + "VLANs":null, + "Oem":{ + + }, + "Links":{ + "Oem":{ + "Intel_RackScale":{ + "@odata.type":"#Intel.Oem.EthernetInterface", + "NeighborPort":{ + "@odata.id":"/redfish/v1/EthernetSwitches/1/Ports/1" + } + } + } + } +} \ No newline at end of file diff --git a/rsd_lib/tests/unit/json_samples/v2_1/ethernrt_interface_collection.json b/rsd_lib/tests/unit/json_samples/v2_1/ethernrt_interface_collection.json new file mode 100644 index 0000000..b704ef6 --- /dev/null +++ b/rsd_lib/tests/unit/json_samples/v2_1/ethernrt_interface_collection.json @@ -0,0 +1,12 @@ +{ + "@odata.context":"/redfish/v1/$metadata#Managers/Members/1/EthernetInterfaces/$entity", + "@odata.id":"/redfish/v1/Managers/1/EthernetInterfaces", + "@odata.type":"#EthernetNetworkInterface.v1_0_0.EthernetNetworkInterfaceCollection", + "Name":"Ethernet Network Interface Collection", + "Members@odata.count":1, + "Members":[ + { + "@odata.id":"/redfish/v1/Managers/1/EthernetInterfaces/1" + } + ] +} \ No newline at end of file diff --git a/rsd_lib/tests/unit/resources/v2_1/manager/test_ethernet_interface.py b/rsd_lib/tests/unit/resources/v2_1/manager/test_ethernet_interface.py new file mode 100644 index 0000000..099b1c0 --- /dev/null +++ b/rsd_lib/tests/unit/resources/v2_1/manager/test_ethernet_interface.py @@ -0,0 +1,211 @@ +# Copyright 2019 Intel, Inc. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# 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 json +import mock +import testtools + +from rsd_lib.resources.v2_1.ethernet_switch import vlan +from rsd_lib.resources.v2_1.manager import ethernet_interface + + +class EthernetInterface(testtools.TestCase): + def setUp(self): + super(EthernetInterface, self).setUp() + self.conn = mock.Mock() + with open('rsd_lib/tests/unit/json_samples/v2_1/' + 'ethernet_interface.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + + self.ethernet_interface_inst = ethernet_interface.EthernetInterface( + self.conn, + '/redfish/v1/Managers/1/EthernetInterfaces/1', + redfish_version='1.0.2') + + def test_parse_attributes(self): + self.ethernet_interface_inst._parse_attributes() + self.assertEqual("LAN1", self.ethernet_interface_inst.identity) + self.assertEqual("Ethernet Interface", self. + ethernet_interface_inst.name) + self.assertEqual("System NIC 1", self. + ethernet_interface_inst.description) + self.assertEqual("Enabled", self. + ethernet_interface_inst.status.state) + self.assertEqual("OK", self.ethernet_interface_inst.status.health) + self.assertEqual(None, self. + ethernet_interface_inst.status.health_rollup) + self.assertEqual(True, self. + ethernet_interface_inst.interface_enabled) + self.assertEqual("AA:BB:CC:DD:EE:FF", self. + ethernet_interface_inst. + permanent_mac_address) + self.assertEqual("AA:BB:CC:DD:EE:FF", self. + ethernet_interface_inst. + mac_address) + self.assertEqual(100, self. + ethernet_interface_inst.speed_mbps) + self.assertEqual(True, self.ethernet_interface_inst.auto_neg) + self.assertEqual(True, self.ethernet_interface_inst.full_duplex) + self.assertEqual(1500, self.ethernet_interface_inst.mtu_size) + self.assertEqual("web483", self. + ethernet_interface_inst.host_name) + self.assertEqual("web483.redfishspecification.org", self. + ethernet_interface_inst.fqdn) + self.assertEqual("fe80::3ed9:2bff:fe34:600", self. + ethernet_interface_inst.ipv6_default_gateway) + self.assertEqual(None, self. + ethernet_interface_inst.max_ipv6_static_addresses) + self.assertEqual((['names.redfishspecification.org']), self. + ethernet_interface_inst.name_servers) + self.assertEqual("192.168.0.10", self.ethernet_interface_inst. + ipv4_addresses[0].address) + self.assertEqual("255.255.252.0", self.ethernet_interface_inst. + ipv4_addresses[0].subnet_mask) + self.assertEqual("Static", self. + ethernet_interface_inst.ipv4_addresses[0]. + address_origin) + self.assertEqual("192.168.0.1", self.ethernet_interface_inst. + ipv4_addresses[0].gate_way) + self.assertEqual("fe80::1ec1:deff:fe6f:1e24", self. + ethernet_interface_inst.ipv6_addresses[0].address) + self.assertEqual(64, self.ethernet_interface_inst.ipv6_addresses[0]. + prefix_length) + self.assertEqual("Static", self. + ethernet_interface_inst.ipv6_addresses[0]. + address_origin) + self.assertEqual("Preferred", self. + ethernet_interface_inst.ipv6_addresses[0]. + address_state) + self.assertEqual(None, self.ethernet_interface_inst.vlan) + self.assertEqual([], + self.ethernet_interface_inst.ipv6_static_addresses) + self.assertEqual(None, + self.ethernet_interface_inst. + ipv6_address_policy_table) + self.assertEqual("/redfish/v1/EthernetSwitches/1/Ports/1", self. + ethernet_interface_inst. + links.oem.intel_rackScale.neighbor_port) + + def test__get_vlan_collection_path(self): + actual_path = self.ethernet_interface_inst._get_vlan_collection_path() + self.assertEqual('/redfish/v1/Managers/1/EthernetInterfaces/1/VLANs', + actual_path) + + def test__get_vlan_collection_path_without_vlans(self): + with open('rsd_lib/tests/unit/json_samples/v2_1/' + 'ethernet_interface_without_vlans.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + self.ethernet_interface_inst.refresh(force=True) + actual_path = self.ethernet_interface_inst._get_vlan_collection_path() + self.assertEqual(None, actual_path) + + def test_vlans(self): + # | GIVEN | + self.conn.get.return_value.json.reset_mock() + with open('rsd_lib/tests/unit/json_samples/v2_1/' + 'ethernet_switch_port_vlan_collection.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN | + actual_vlans = self.ethernet_interface_inst.vlans + # | THEN | + self.assertIsInstance(actual_vlans, + vlan.VLANCollection) + self.conn.get.return_value.json.assert_called_once_with() + + # reset mock + self.conn.get.return_value.json.reset_mock() + # | WHEN & THEN | + self.assertIs(actual_vlans, self.ethernet_interface_inst.vlans) + self.conn.get.return_value.json.assert_not_called() + + def test_vlans_on_refresh(self): + # | GIVEN | + with open('rsd_lib/tests/unit/json_samples/v2_1/' + 'ethernet_switch_port_vlan_collection.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN & THEN | + actual_vlans = self.ethernet_interface_inst.vlans + + self.assertIsInstance(actual_vlans, + vlan.VLANCollection) + + # On refreshing... + with open('rsd_lib/tests/unit/json_samples/v2_1/' + 'ethernet_interface.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads( + f.read()) + + self.ethernet_interface_inst.invalidate() + self.ethernet_interface_inst.refresh(force=False) + + # | GIVEN | + with open('rsd_lib/tests/unit/json_samples/v2_1/' + 'ethernet_switch_port_vlan_collection.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads( + f.read()) + # | WHEN & THEN | + self.assertIsInstance(actual_vlans, + vlan.VLANCollection) + + def test_without_vlans(self): + with open('rsd_lib/tests/unit/json_samples/v2_1/' + 'ethernet_interface_without_vlans.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + self.ethernet_interface_inst.refresh(force=True) + actual_vlans = self.ethernet_interface_inst.vlans + self.assertEqual(None, actual_vlans) + + +class EthernetInterfaceCollectionTestCase(testtools.TestCase): + def setUp(self): + super(EthernetInterfaceCollectionTestCase, self).setUp() + self.conn = mock.Mock() + with open('rsd_lib/tests/unit/json_samples/v2_1/' + 'ethernrt_interface_collection.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + self.ethernet_interface_col = ethernet_interface. \ + EthernetInterfaceCollection(self.conn, + '/redfish/v1/Managers/1/Ethernet' + 'Interfaces/1', + redfish_version='1.0.2') + + def test__parse_attributes(self): + self.ethernet_interface_col._parse_attributes() + self.assertEqual('1.0.2', self.ethernet_interface_col.redfish_version) + self.assertEqual(('/redfish/v1/Managers/1/EthernetInterfaces/1',), + self.ethernet_interface_col.members_identities) + + @mock.patch.object(ethernet_interface, 'EthernetInterface', autospec=True) + def test_get_member(self, mock_ethernet_interface): + self.ethernet_interface_col.get_member( + '/redfish/v1/Managers/1/EthernetInterfaces/1') + mock_ethernet_interface.assert_called_once_with( + self.ethernet_interface_col._conn, + '/redfish/v1/Managers/1/EthernetInterfaces/1', + redfish_version=self.ethernet_interface_col.redfish_version + ) + + @mock.patch.object(ethernet_interface, 'EthernetInterface', autospec=True) + def test_get_members(self, mock_ethernet_interface): + members = self.ethernet_interface_col.get_members() + calls = [ + mock.call( + self.ethernet_interface_col._conn, + '/redfish/v1/Managers/1/EthernetInterfaces/1', + redfish_version=self.ethernet_interface_col.redfish_version) + ] + mock_ethernet_interface.assert_has_calls(calls) + self.assertIsInstance(members, list) + self.assertEqual(1, len(members)) diff --git a/rsd_lib/tests/unit/resources/v2_1/manager/test_manager.py b/rsd_lib/tests/unit/resources/v2_1/manager/test_manager.py index 0b85915..9035b92 100644 --- a/rsd_lib/tests/unit/resources/v2_1/manager/test_manager.py +++ b/rsd_lib/tests/unit/resources/v2_1/manager/test_manager.py @@ -16,6 +16,7 @@ import mock from sushy.tests.unit import base +from rsd_lib.resources.v2_1.manager import ethernet_interface from rsd_lib.resources.v2_1.manager import manager from rsd_lib.resources.v2_1.manager import network_protocol @@ -75,9 +76,6 @@ class TestManager(base.TestCase): ['Telnet', 'SSH'], self.manager_inst.command_shell.connect_types_supported) self.assertEqual('1.00', self.manager_inst.firmware_version) - self.assertEqual( - '/redfish/v1/Managers/PSME/EthernetInterfaces', - self.manager_inst.ethernet_interfaces) self.assertEqual((), self.manager_inst.links.manager_for_servers) self.assertEqual( ('/redfish/v1/Chassis/FabricModule1',), @@ -135,6 +133,57 @@ class TestManager(base.TestCase): self.assertIsInstance(self.manager_inst.network_protocol, network_protocol.NetworkProtocol) + def test__get_ethernet_interface_path(self): + expected = '/redfish/v1/Managers/PSME/EthernetInterfaces' + result = self.manager_inst._get_ethernet_interface_path() + self.assertEqual(expected, result) + + def test_ethernet_interface(self): + # | GIVEN | + self.conn.get.return_value.json.reset_mock() + with open('rsd_lib/tests/unit/json_samples/v2_1/' + 'ethernet_interface.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN | + actual_ethernet_interface = self.manager_inst.ethernet_interface + # | THEN | + self.assertIsInstance(actual_ethernet_interface, + ethernet_interface.EthernetInterfaceCollection) + self.conn.get.return_value.json.assert_called_once_with() + + # reset mock + self.conn.get.return_value.json.reset_mock() + # | WHEN & THEN | + # tests for same object on invoking subsequently + self.assertIs(actual_ethernet_interface, + self.manager_inst.ethernet_interface) + self.conn.get.return_value.json.assert_not_called() + + def test_ethernet_interface_on_refresh(self): + # | GIVEN | + with open('rsd_lib/tests/unit/json_samples/v2_1/' + 'ethernet_interface.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN & THEN | + self.assertIsInstance(self.manager_inst.ethernet_interface, + ethernet_interface.EthernetInterfaceCollection) + + # On refreshing the manager instance... + with open('rsd_lib/tests/unit/json_samples/v2_1/' + 'manager.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + + self.manager_inst.invalidate() + self.manager_inst.refresh(force=False) + + # | GIVEN | + with open('rsd_lib/tests/unit/json_samples/v2_1/' + 'ethernet_interface.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN & THEN | + self.assertIsInstance(self.manager_inst.ethernet_interface, + ethernet_interface.EthernetInterfaceCollection) + class TestManagerCollection(base.TestCase):