diff --git a/rsd_lib/resources/v2_2/ethernet_switch/ethernet_switch.py b/rsd_lib/resources/v2_2/ethernet_switch/ethernet_switch.py new file mode 100644 index 0000000..532b29e --- /dev/null +++ b/rsd_lib/resources/v2_2/ethernet_switch/ethernet_switch.py @@ -0,0 +1,57 @@ +# Copyright 2018 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 sushy.resources import base + +from rsd_lib.resources.v2_1.ethernet_switch import ethernet_switch \ + as v2_1_ethernet_switch +from rsd_lib.resources.v2_2.ethernet_switch import port + + +class EthernetSwitch(v2_1_ethernet_switch.EthernetSwitch): + + @property + def ports(self): + """Property to provide reference to `PortCollection` instance + + It is calculated once when it is queried for the first time. On + refresh, this property is reset. + """ + if self._ports is None: + self._ports = port.PortCollection( + self._conn, self._get_port_collection_path(), + redfish_version=self.redfish_version) + + return self._ports + + +class EthernetSwitchCollection(base.ResourceCollectionBase): + + @property + def _resource_type(self): + return EthernetSwitch + + def __init__(self, connector, path, redfish_version=None): + """A class representing a EthernetSwitch Collection + + :param connector: A Connector instance + :param path: The canonical path to the EthernetSwitch collection + resource + :param redfish_version: The version of RedFish. Used to construct + the object according to schema of the given version. + """ + super(EthernetSwitchCollection, self).__init__(connector, + path, + redfish_version) diff --git a/rsd_lib/resources/v2_2/ethernet_switch/port.py b/rsd_lib/resources/v2_2/ethernet_switch/port.py index 46c746a..2b9d4b7 100644 --- a/rsd_lib/resources/v2_2/ethernet_switch/port.py +++ b/rsd_lib/resources/v2_2/ethernet_switch/port.py @@ -14,6 +14,7 @@ # under the License. from sushy import exceptions +from sushy.resources import base from rsd_lib.resources.v2_1.ethernet_switch import port as v2_1_port from rsd_lib.resources.v2_2.ethernet_switch import port_metrics @@ -50,3 +51,20 @@ class Port(v2_1_port.Port): def refresh(self): super(Port, self).refresh() self._metrics = None + + +class PortCollection(base.ResourceCollectionBase): + + @property + def _resource_type(self): + return Port + + def __init__(self, connector, path, redfish_version=None): + """A class representing an Port + + :param connector: A Connector instance + :param path: The canonical path to the Port collection resource + :param redfish_version: The version of RedFish. Used to construct + the object according to schema of the given version. + """ + super(PortCollection, self).__init__(connector, path, redfish_version) diff --git a/rsd_lib/tests/unit/json_samples/v2_2/ethernet_switch.json b/rsd_lib/tests/unit/json_samples/v2_2/ethernet_switch.json new file mode 100644 index 0000000..d05a7a4 --- /dev/null +++ b/rsd_lib/tests/unit/json_samples/v2_2/ethernet_switch.json @@ -0,0 +1,42 @@ +{ + "@odata.context": "/redfish/v1/$metadata#EthernetSwitch.EthernetSwitch", + "@odata.id": "/redfish/v1/EthernetSwitches/Switch1", + "@odata.type": "#EthernetSwitch.v1_1_0.EthernetSwitch", + "Id": "Switch1", + "SwitchId": "unique switch id", + "Name": "Switch1", + "Description": "description-as-string", + "Manufacturer": "Quanta", + "Model": "ly8_rangley", + "ManufacturingDate": "02/21/2015 00:00:00", + "SerialNumber": "2M220100SL", + "PartNumber": "1LY8UZZ0007", + "FirmwareName": "ONIE", + "FirmwareVersion": "1.1", + "Role": "TOR", + "MaxACLNumber": 4, + "Status": { + "State": "Enabled", + "Health": "OK", + "HealthRollup": null + }, + "Oem": {}, + "Ports": { + "@odata.id": "/redfish/v1/EthernetSwitches/Switch1/Ports" + }, + "ACLs": { + "@odata.id": "/redfish/v1/EthernetSwitches/Switch1/ACLs" + }, + "Metrics": { + "@odata.id": "/redfish/v1/EthernetSwitches/Switch1/Metrics" + }, + "Links": { + "Chassis": { + "@odata.id": "/redfish/v1/Chassis/FabricModule1" + }, + "ManagedBy": [{ + "@odata.id": "/redfish/v1/Managers/PSME" + }] + }, + "Oem": {} +} \ No newline at end of file diff --git a/rsd_lib/tests/unit/json_samples/v2_2/ethernet_switch_collection.json b/rsd_lib/tests/unit/json_samples/v2_2/ethernet_switch_collection.json new file mode 100644 index 0000000..d0bdde0 --- /dev/null +++ b/rsd_lib/tests/unit/json_samples/v2_2/ethernet_switch_collection.json @@ -0,0 +1,11 @@ +{ + "@odata.context": "/redfish/v1/$metadata#EthernetSwitchesCollection.EthernetSwitchesCollection", + "@odata.id": "/redfish/v1/EthernetSwitches", + "@odata.type": "#EthernetSwitchesCollection.EthernetSwitchesCollection", + "Name": "Ethernet Switches Collection", + "Description": "Network Switches Collection", + "Members@odata.count": 1, + "Members": [{ + "@odata.id": "/redfish/v1/EthernetSwitches/Switch1" + }] +} \ No newline at end of file diff --git a/rsd_lib/tests/unit/json_samples/v2_2/port.json b/rsd_lib/tests/unit/json_samples/v2_2/ethernet_switch_port.json similarity index 100% rename from rsd_lib/tests/unit/json_samples/v2_2/port.json rename to rsd_lib/tests/unit/json_samples/v2_2/ethernet_switch_port.json diff --git a/rsd_lib/tests/unit/json_samples/v2_2/ethernet_switch_port_collection.json b/rsd_lib/tests/unit/json_samples/v2_2/ethernet_switch_port_collection.json new file mode 100644 index 0000000..21e15f8 --- /dev/null +++ b/rsd_lib/tests/unit/json_samples/v2_2/ethernet_switch_port_collection.json @@ -0,0 +1,11 @@ +{ + "@odata.context": "/redfish/v1/$metadata#SwitchPortsCollection.SwitchPortsCollection", + "@odata.id": "/redfish/v1/EthernetSwitches/Switch1/Ports", + "@odata.type": "#SwitchPortsCollection.SwitchPortsCollection", + "Name": "Ethernet Switch Port Collection", + "Description": "Switch Port Collection", + "Members@odata.count": 1, + "Members": [{ + "@odata.id": "/redfish/v1/EthernetSwitches/Switch1/Ports/Port1" + }] +} \ No newline at end of file diff --git a/rsd_lib/tests/unit/json_samples/v2_2/port_metrics.json b/rsd_lib/tests/unit/json_samples/v2_2/ethernet_switch_port_metrics.json similarity index 100% rename from rsd_lib/tests/unit/json_samples/v2_2/port_metrics.json rename to rsd_lib/tests/unit/json_samples/v2_2/ethernet_switch_port_metrics.json diff --git a/rsd_lib/tests/unit/resources/v2_2/ethernet_switch/test_ethernet_switch.py b/rsd_lib/tests/unit/resources/v2_2/ethernet_switch/test_ethernet_switch.py new file mode 100644 index 0000000..368eb77 --- /dev/null +++ b/rsd_lib/tests/unit/resources/v2_2/ethernet_switch/test_ethernet_switch.py @@ -0,0 +1,126 @@ +# Copyright 2018 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_2.ethernet_switch import ethernet_switch +from rsd_lib.resources.v2_2.ethernet_switch import port + + +class EthernetSwitchTestCase(testtools.TestCase): + + def setUp(self): + super(EthernetSwitchTestCase, self).setUp() + self.conn = mock.Mock() + with open('rsd_lib/tests/unit/json_samples/v2_2/' + 'ethernet_switch.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + + self.ethernet_switch_inst = ethernet_switch.EthernetSwitch( + self.conn, '/redfish/v1/EthernetSwitches/Switch1/Ports/Port1', + redfish_version='1.0.2') + + def test_ports(self): + # check for the underpath variable value + self.assertIsNone(self.ethernet_switch_inst._ports) + # | GIVEN | + self.conn.get.return_value.json.reset_mock() + with open('rsd_lib/tests/unit/json_samples/v2_2/' + 'ethernet_switch_port_collection.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN | + actual_ports = self.ethernet_switch_inst.ports + # | THEN | + self.assertIsInstance(actual_ports, + port.PortCollection) + 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_ports, + self.ethernet_switch_inst.ports) + self.conn.get.return_value.json.assert_not_called() + + def test_ports_on_refresh(self): + # | GIVEN | + with open('rsd_lib/tests/unit/json_samples/v2_2/' + 'ethernet_switch_port_collection.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN & THEN | + self.assertIsInstance(self.ethernet_switch_inst.ports, + port.PortCollection) + + # On refreshing the port instance... + with open('rsd_lib/tests/unit/json_samples/v2_2/' + 'ethernet_switch.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + self.ethernet_switch_inst.refresh() + + # | WHEN & THEN | + self.assertIsNone(self.ethernet_switch_inst._ports) + + # | GIVEN | + with open('rsd_lib/tests/unit/json_samples/v2_2/' + 'ethernet_switch_port_collection.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN & THEN | + self.assertIsInstance(self.ethernet_switch_inst.ports, + port.PortCollection) + + +class EthernetSwitchCollectionTestCase(testtools.TestCase): + + def setUp(self): + super(EthernetSwitchCollectionTestCase, self).setUp() + self.conn = mock.Mock() + + with open('rsd_lib/tests/unit/json_samples/v2_2/' + 'ethernet_switch_collection.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + + self.ethernet_switch_col = ethernet_switch.EthernetSwitchCollection( + self.conn, + 'redfish/v1/EthernetSwitches', + redfish_version='1.0.2') + + def test__parse_attributes(self): + self.ethernet_switch_col._parse_attributes() + self.assertEqual('1.0.2', self.ethernet_switch_col.redfish_version) + self.assertEqual('Ethernet Switches Collection', + self.ethernet_switch_col.name) + self.assertEqual(('/redfish/v1/EthernetSwitches/Switch1',), + self.ethernet_switch_col.members_identities) + + @mock.patch.object(ethernet_switch, 'EthernetSwitch', autospec=True) + def test_get_member(self, mock_ethernet_switch): + self.ethernet_switch_col.get_member( + '/redfish/v1/EthernetSwitches/Switch1') + + mock_ethernet_switch.assert_called_once_with( + self.ethernet_switch_col._conn, + '/redfish/v1/EthernetSwitches/Switch1', + redfish_version=self.ethernet_switch_col.redfish_version + ) + + @mock.patch.object(ethernet_switch, 'EthernetSwitch', autospec=True) + def test_get_members(self, mock_ethernet_switch): + members = self.ethernet_switch_col.get_members() + self.assertEqual(mock_ethernet_switch.call_count, 1) + self.assertIsInstance(members, list) + self.assertEqual(1, len(members)) diff --git a/rsd_lib/tests/unit/resources/v2_2/ethernet_switch/test_port.py b/rsd_lib/tests/unit/resources/v2_2/ethernet_switch/test_port.py index 8e16a1f..37b8a5c 100644 --- a/rsd_lib/tests/unit/resources/v2_2/ethernet_switch/test_port.py +++ b/rsd_lib/tests/unit/resources/v2_2/ethernet_switch/test_port.py @@ -28,8 +28,8 @@ class PortTestCase(testtools.TestCase): def setUp(self): super(PortTestCase, self).setUp() self.conn = mock.Mock() - with open('rsd_lib/tests/unit/json_samples/v2_2/port.json', - 'r') as f: + with open('rsd_lib/tests/unit/json_samples/v2_2/' + 'ethernet_switch_port.json', 'r') as f: self.conn.get.return_value.json.return_value = json.loads(f.read()) self.port_inst = port.Port( @@ -52,8 +52,8 @@ class PortTestCase(testtools.TestCase): self.assertIsNone(self.port_inst._metrics) # | GIVEN | self.conn.get.return_value.json.reset_mock() - with open('rsd_lib/tests/unit/json_samples/v2_2/port_metrics.json', - 'r') as f: + with open('rsd_lib/tests/unit/json_samples/v2_2/' + 'ethernet_switch_port_metrics.json', 'r') as f: self.conn.get.return_value.json.return_value = json.loads(f.read()) # | WHEN | actual_metrics = self.port_inst.metrics @@ -72,25 +72,68 @@ class PortTestCase(testtools.TestCase): def test_metrics_on_refresh(self): # | GIVEN | - with open('rsd_lib/tests/unit/json_samples/v2_2/port_metrics.json', - 'r') as f: + with open('rsd_lib/tests/unit/json_samples/v2_2/' + 'ethernet_switch_port_metrics.json', 'r') as f: self.conn.get.return_value.json.return_value = json.loads(f.read()) # | WHEN & THEN | self.assertIsInstance(self.port_inst.metrics, port_metrics.PortMetrics) # On refreshing the port instance... - with open('rsd_lib/tests/unit/json_samples/v2_2/port.json', - 'r') as f: + with open('rsd_lib/tests/unit/json_samples/v2_2/' + 'ethernet_switch_port.json', 'r') as f: self.conn.get.return_value.json.return_value = json.loads(f.read()) self.port_inst.refresh() # | WHEN & THEN | self.assertIsNone(self.port_inst._metrics) # | GIVEN | - with open('rsd_lib/tests/unit/json_samples/v2_2/port_metrics.json', - 'r') as f: + with open('rsd_lib/tests/unit/json_samples/v2_2/' + 'ethernet_switch_port_metrics.json', 'r') as f: self.conn.get.return_value.json.return_value = json.loads(f.read()) # | WHEN & THEN | self.assertIsInstance(self.port_inst.metrics, port_metrics.PortMetrics) + + +class PortCollectionTestCase(testtools.TestCase): + + def setUp(self): + super(PortCollectionTestCase, self).setUp() + self.conn = mock.Mock() + with open( + 'rsd_lib/tests/unit/json_samples/v2_2/' + 'ethernet_switch_port_collection.json', 'r') as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + self.port_col = port.PortCollection( + self.conn, '/redfish/v1/EthernetSwitches/Switch1/Ports', + redfish_version='1.0.2') + + def test__parse_attributes(self): + self.port_col._parse_attributes() + self.assertEqual('1.0.2', self.port_col.redfish_version) + self.assertEqual( + 'Ethernet Switch Port Collection', + self.port_col.name) + self.assertEqual( + ('/redfish/v1/EthernetSwitches/Switch1/Ports/Port1',), + self.port_col.members_identities) + + @mock.patch.object(port, 'Port', autospec=True) + def test_get_member(self, mock_port): + self.port_col.get_member( + '/redfish/v1/EthernetSwitches/Switch1/Ports/Port1') + mock_port.assert_called_once_with( + self.port_col._conn, + '/redfish/v1/EthernetSwitches/Switch1/Ports/Port1', + redfish_version=self.port_col.redfish_version) + + @mock.patch.object(port, 'Port', autospec=True) + def test_get_members(self, mock_port): + members = self.port_col.get_members() + mock_port.assert_called_with( + self.port_col._conn, + '/redfish/v1/EthernetSwitches/Switch1/Ports/Port1', + redfish_version=self.port_col.redfish_version) + self.assertIsInstance(members, list) + self.assertEqual(1, len(members)) diff --git a/rsd_lib/tests/unit/resources/v2_2/ethernet_switch/test_port_metrics.py b/rsd_lib/tests/unit/resources/v2_2/ethernet_switch/test_port_metrics.py index 2b75e63..7e63ffd 100644 --- a/rsd_lib/tests/unit/resources/v2_2/ethernet_switch/test_port_metrics.py +++ b/rsd_lib/tests/unit/resources/v2_2/ethernet_switch/test_port_metrics.py @@ -27,7 +27,7 @@ class PortMetricsTestCase(testtools.TestCase): super(PortMetricsTestCase, self).setUp() self.conn = mock.Mock() with open('rsd_lib/tests/unit/json_samples/v2_2/' - 'port_metrics.json', 'r') as f: + 'ethernet_switch_port_metrics.json', 'r') as f: self.conn.get.return_value.json.return_value = json.loads(f.read()) self.port_metrics_inst = port_metrics.PortMetrics(