From 1abb3f4633e16477898eef107f2be1eb58320b55 Mon Sep 17 00:00:00 2001 From: "ya.wang" Date: Wed, 15 Aug 2018 20:47:01 +0800 Subject: [PATCH] Add the functionality to support adding ports to one specific vlan Change-Id: I3e94b937ed8bcd6706bd4b75b3f6d8e31c6c5f13 --- .../resources/v2_1/ethernet_switch/schemas.py | 41 +++++++++++ .../resources/v2_1/ethernet_switch/vlan.py | 21 ++++++ .../v2_1/ethernet_switch/test_vlan.py | 70 +++++++++++++++++-- 3 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 rsd_lib/resources/v2_1/ethernet_switch/schemas.py diff --git a/rsd_lib/resources/v2_1/ethernet_switch/schemas.py b/rsd_lib/resources/v2_1/ethernet_switch/schemas.py new file mode 100644 index 0000000..20fb36d --- /dev/null +++ b/rsd_lib/resources/v2_1/ethernet_switch/schemas.py @@ -0,0 +1,41 @@ +# Copyright 2018 99cloud, 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. + +vlan_network_interface_req_schema = { + 'type': 'object', + 'properties': { + 'VLANId': {'type': 'number'}, + 'VLANEnable': {'type': 'boolean'}, + 'Oem': { + 'type': 'object', + 'properties': { + 'Intel_RackScale': { + 'type': 'object', + 'properties': { + 'Tagged': {'type': 'boolean'} + }, + 'required': ['Tagged'] + } + }, + 'required': ['Intel_RackScale'] + } + }, + 'required': [ + 'VLANId', + 'VLANEnable', + 'Oem' + ], + 'additionalProperties': False +} diff --git a/rsd_lib/resources/v2_1/ethernet_switch/vlan.py b/rsd_lib/resources/v2_1/ethernet_switch/vlan.py index 3bbb5ca..077ec8a 100644 --- a/rsd_lib/resources/v2_1/ethernet_switch/vlan.py +++ b/rsd_lib/resources/v2_1/ethernet_switch/vlan.py @@ -13,10 +13,16 @@ # License for the specific language governing permissions and limitations # under the License. +from jsonschema import validate +import logging from sushy.resources import base +from rsd_lib.resources.v2_1.ethernet_switch import schemas as \ + ethernet_switch_schemas from rsd_lib import utils as rsd_lib_utils +LOG = logging.getLogger(__name__) + class VLAN(base.ResourceBase): @@ -65,3 +71,18 @@ class VLANCollection(base.ResourceCollectionBase): the object according to schema of the given version. """ super(VLANCollection, self).__init__(connector, path, redfish_version) + + def add_vlan(self, vlan_network_interface_req): + """Add a vlan to port + + :param vlan_network_interface_req: JSON for vlan network interface + :returns: The location of the vlan network interface + """ + target_uri = self._path + validate(vlan_network_interface_req, + ethernet_switch_schemas.vlan_network_interface_req_schema) + resp = self._conn.post(target_uri, data=vlan_network_interface_req) + LOG.info("VLAN add at %s", resp.headers['Location']) + vlan_network_interface_url = resp.headers['Location'] + return vlan_network_interface_url[vlan_network_interface_url. + find(self._path):] diff --git a/rsd_lib/tests/unit/resources/v2_1/ethernet_switch/test_vlan.py b/rsd_lib/tests/unit/resources/v2_1/ethernet_switch/test_vlan.py index c2318da..039c79a 100644 --- a/rsd_lib/tests/unit/resources/v2_1/ethernet_switch/test_vlan.py +++ b/rsd_lib/tests/unit/resources/v2_1/ethernet_switch/test_vlan.py @@ -14,11 +14,12 @@ # under the License. import json - +import jsonschema import mock import testtools from rsd_lib.resources.v2_1.ethernet_switch import vlan +from rsd_lib.tests.unit.fakes import request_fakes class VLANTestCase(testtools.TestCase): @@ -52,11 +53,18 @@ class VLANCollectionTestCase(testtools.TestCase): self.conn = mock.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()) - self.vlan_col = vlan.VLANCollection( - self.conn, - '/redfish/v1/EthernetSwitches/Switch1/Ports/Port1/VLANs', - redfish_version='1.1.0') + self.conn.get.return_value = \ + request_fakes.fake_request_get(json.loads(f.read())) + self.conn.post.return_value = \ + request_fakes.fake_request_post( + None, + headers={"Location": "https://localhost:8443/redfish/v1/" + "EthernetSwitches/Switch1/" + "Ports/Port1/VLANs/VLAN1"}) + self.vlan_col = vlan.VLANCollection( + self.conn, + '/redfish/v1/EthernetSwitches/Switch1/Ports/Port1/VLANs', + redfish_version='1.1.0') def test__parse_attributes(self): self.vlan_col._parse_attributes() @@ -86,3 +94,53 @@ class VLANCollectionTestCase(testtools.TestCase): mock_vlan.assert_has_calls(calls) self.assertIsInstance(members, list) self.assertEqual(1, len(members)) + + def test_add_vlan_reqs(self): + reqs = { + 'VLANId': 101, + 'VLANEnable': True, + 'Oem': { + 'Intel_RackScale': { + 'Tagged': False + } + } + } + result = self.vlan_col.add_vlan(reqs) + self.vlan_col._conn.post.assert_called_once_with( + '/redfish/v1/EthernetSwitches/Switch1/Ports/Port1/VLANs', + data=reqs) + self.assertEqual(result, + '/redfish/v1/EthernetSwitches/Switch1/Ports/Port1/' + 'VLANs/VLAN1') + + def test_add_vlan_invalid_reqs(self): + reqs = { + 'VLANId': 101, + 'VLANEnable': True, + 'Oem': { + 'Intel_RackScale': { + 'Tagged': False + } + } + } + + # Missing filed + vlan_network_interface_req = reqs.copy() + vlan_network_interface_req.pop('VLANId') + self.assertRaises(jsonschema.exceptions.ValidationError, + self.vlan_col.add_vlan, + vlan_network_interface_req) + + # Wrong format + vlan_network_interface_req = reqs.copy() + vlan_network_interface_req.update({'VLANId': 'WrongFormat'}) + self.assertRaises(jsonschema.exceptions.ValidationError, + self.vlan_col.add_vlan, + vlan_network_interface_req) + + # Wrong additional fields + vlan_network_interface_req = reqs.copy() + vlan_network_interface_req['Additional'] = 'AdditionalField' + self.assertRaises(jsonschema.exceptions.ValidationError, + self.vlan_col.add_vlan, + vlan_network_interface_req)