Add patch method in EthernetSwitchPort and post method in EthernetSwitchPortCollection in RSD 2.1

Change-Id: Ia90038bb4898fde83e7a0a9e22cd51397bd71ac8
This commit is contained in:
HeyIns 2019-04-09 06:28:33 +00:00
parent 7cdaf00432
commit 4e96e0a343
3 changed files with 254 additions and 1 deletions
rsd_lib
resources/v2_1/ethernet_switch
tests/unit/resources/v2_1/ethernet_switch

@ -15,12 +15,14 @@
import logging
from jsonschema import validate
from sushy.resources import base
from sushy import utils
from rsd_lib import base as rsd_lib_base
from rsd_lib.resources.v2_1.common import ip_addresses
from rsd_lib.resources.v2_1.ethernet_switch import ethernet_switch_static_mac
from rsd_lib.resources.v2_1.ethernet_switch import schemas as port_schema
from rsd_lib.resources.v2_1.ethernet_switch import vlan_network_interface
from rsd_lib import utils as rsd_lib_utils
@ -172,9 +174,32 @@ class EthernetSwitchPort(rsd_lib_base.ResourceBase):
redfish_version=self.redfish_version,
)
def update(self, data=None):
"""Update a new Port
:param data: JSON for Port
"""
update_schema = port_schema.port_req_schema
del update_schema["required"]
if data is not None or len(data) > 0:
validate(data, update_schema)
self._conn.patch(self.path, data=data)
class EthernetSwitchPortCollection(rsd_lib_base.ResourceCollectionBase):
@property
def _resource_type(self):
return EthernetSwitchPort
def create_port(self, port_req):
"""Create a new Port
:param Port: JSON for Port
:returns: The location of the Port
"""
validate(port_req, port_schema.port_req_schema)
resp = self._conn.post(self._path, data=port_req)
port_url = resp.headers["Location"]
LOG.info("Create Port at %s", port_url)
return port_url[port_url.find(self._path):]

@ -140,3 +140,176 @@ acl_rule_req_schema = {
"required": ["Action", "Condition"],
"additionalProperties": False,
}
port_req_schema = {
"type": "object",
"properties": {
"PortId": {"type": "number"},
"LinkType": {
"type": "string",
"enum": ["Ethernet", "PCIe"],
},
"OperationalState": {
"type": "string",
"enum": ["Up", "Down"],
},
"AdministrativeState": {
"type": "string",
"enum": ["Up", "Down"],
},
"LinkSpeedMbps": {"type": ["number", "null"]},
"NeighborInfo": {
"type": "object",
"properties": {
"SwitchId": {"type": "string"},
"PortId": {"type": "string"},
"CableId": {"type": "string"},
},
"additionalProperties": False,
},
"NeighborMAC": {"type": "string"},
"FrameSize": {"type": ["number", "null"]},
"Autosense": {"type": "boolean"},
"FullDuplex": {"type": "boolean"},
"MACAddress": {"type": "string"},
"IPv4Addresses": {
"type": "array",
"items": {
"type": "object",
"properties": {
"Address": {"type": "string"},
"SubnetMask": {"type": "string"},
"AddressOrigin": {
"type": "string",
"enum": ["Static", "DHCP", "BOOTP", "IPv4LinkLocal"],
},
"Gateway": {"type": "string"},
},
"additionalProperties": False,
},
},
"IPv6Addresses": {
"type": "array",
"items": {
"type": "object",
"properties": {
"Address": {"type": "string"},
"PrefixLength": {
"type": "number",
"minimum": 1,
"maximum": 128,
},
"AddressOrigin": {
"type": "string",
"enum": ["Static", "DHCPv6", "LinkLocal", "SLAAC"],
},
"AddressState": {
"type": "string",
"enum": [
"Preferred",
"Deprecated",
"Tentative",
"Failed",
],
},
},
"additionalProperties": False,
},
},
"PortClass": {
"type": "string",
"enum": ["Physical", "Logical", "Reserved"],
},
"PortMode": {
"type": "string",
"enum": [
"LinkAggregationStatic",
"LinkAggregationDynamic",
"Unknown",
],
},
"PortType": {
"type": "string",
"enum": ["Upstream", "Downstream", "MeshPort", "Unknown"],
},
"Status": {
"type": "object",
"properties": {
"State": {
"type": "string",
"enum": [
"Enabled",
"Disabled",
"StandbyOffline",
"StandbySpare",
"InTest",
"Starting",
"Absent",
"UnavailableOffline",
"Deferring",
"Quiesced",
"Updating",
],
},
"HealthRollup": {
"type": "string",
"enum": ["OK", "Warning", "Critical"],
},
"Health": {
"type": "string",
"enum": ["OK", "Warning", "Critical"],
},
},
"additionalProperties": False,
},
"VLANs": {
"type": "object",
"properties": {"@odata.id": {"type": "string"}},
"required": ["@odata.id"],
},
"StaticMACs": {
"type": "object",
"properties": {"@odata.id": {"type": "string"}},
"required": ["@odata.id"],
},
"Links": {
"type": "object",
"properties": {
"PrimaryVLAN": {
"type": "object",
"properties": {"@odata.id": {"type": "string"}},
"required": ["@odata.id"],
},
"Switch": {
"type": "object",
"properties": {"@odata.id": {"type": "string"}},
"required": ["@odata.id"],
},
"MemberOfPort": {
"type": "object",
"properties": {"@odata.id": {"type": "string"}},
"required": ["@odata.id"],
},
"PortMembers": {
"type": "array",
"items": {
"type": "object",
"properties": {"@odata.id": {"type": "string"}},
"required": ["@odata.id"],
},
},
"ActiveACLs": {
"type": "array",
"items": {
"type": "object",
"properties": {"@odata.id": {"type": "string"}},
"required": ["@odata.id"],
},
},
},
"additionalProperties": False,
},
},
"required": ["PortId"],
"additionalProperties": False,
}

@ -21,6 +21,7 @@ import testtools
from rsd_lib.resources.v2_1.ethernet_switch import ethernet_switch_port
from rsd_lib.resources.v2_1.ethernet_switch import ethernet_switch_static_mac
from rsd_lib.resources.v2_1.ethernet_switch import vlan_network_interface
from rsd_lib.tests.unit.fakes import request_fakes
class EthernetSwitchPortTestCase(testtools.TestCase):
@ -239,6 +240,31 @@ class EthernetSwitchPortTestCase(testtools.TestCase):
vlan_network_interface.VLanNetworkInterfaceCollection,
)
def test_update(self):
data = {
"AdministrativeState": "Up",
"LinkSpeedMbps": 1000,
"FrameSize": 1500,
"Autosense": False,
"Links": {
"PrimaryVLAN": {
"@odata.id": "/redfish/v1/EthernetSwitches/"
"Switch1/Ports/Port11/VLans/VLan1"
},
"PortMembers": [
{"@odata.id": "/redfish/v1/EthernetSwitches/"
"Switch1/Ports/Port10"},
{"@odata.id": "/redfish/v1/EthernetSwitches/"
"Switch1/Ports/Port12"},
],
},
}
self.port_inst.update(data)
self.port_inst._conn.patch.assert_called_once_with(
"/redfish/v1/EthernetSwitches/Switch1/Ports/Port1",
data=data,
)
class EthernetSwitchPortCollectionTestCase(testtools.TestCase):
def setUp(self):
@ -250,9 +276,16 @@ class EthernetSwitchPortCollectionTestCase(testtools.TestCase):
"r",
) as f:
self.conn.get.return_value.json.return_value = 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"
},
)
self.port_col = ethernet_switch_port.EthernetSwitchPortCollection(
self.conn,
"/redfish/v1/EthernetSwitches/Ports",
"/redfish/v1/EthernetSwitches/Switch1/Ports",
redfish_version="1.0.2",
)
@ -290,3 +323,25 @@ class EthernetSwitchPortCollectionTestCase(testtools.TestCase):
)
self.assertIsInstance(members, list)
self.assertEqual(1, len(members))
def test_create_port_reqs(self):
reqs = {
"PortId": 1,
"PortMode": "LinkAggregationStatic",
"Links": {
"PortMembers": [
{"@odata.id": "/redfish/v1/EthernetSwitches/"
"Switch1/Ports/Port10"},
{"@odata.id": "/redfish/v1/EthernetSwitches/"
"Switch1/Ports/Port11"},
],
},
}
result = self.port_col.create_port(reqs)
self.port_col._conn.post.assert_called_once_with(
"/redfish/v1/EthernetSwitches/Switch1/Ports", data=reqs
)
self.assertEqual(
result,
"/redfish/v1/EthernetSwitches/Switch1/Ports/Port1",
)