Add `Endpoint sub-resource to Fabric`

Add representation of the Endpoint sub-resource to Fabric resource
in sushy. A fabric endpoint represents the properties of an entity
that sends or receives protocol defined messages over a transport.

Story: #2003853
Task: #26648

Change-Id: I76c99da2aac8e0629bb468e22abd104cb29bc4ab
This commit is contained in:
Varsha
2019-04-24 02:06:31 +05:30
parent f10322a67c
commit ca8471196e
9 changed files with 522 additions and 56 deletions

View File

@@ -0,0 +1,6 @@
---
features:
- |
Exposes the ``endpoint`` sub-resource from the ``fabric`` resource.
``endpoint`` represents the properties of an entity that sends or receives
protocol defined messages over a transport.

View File

@@ -13,30 +13,87 @@
# Values come from the Redfish Fabric json-schema 1.0.4:
# http://redfish.dmtf.org/schemas/v1/Fabric.v1_0_4.json#/definitions/Fabric
# Fabric Types constants
# Protocol type constants
FABRIC_TYPE_AHCI = 'Advanced Host Controller Interface'
FABRIC_TYPE_FC = 'Fibre Channel'
FABRIC_TYPE_FCP = 'Fibre Channel Protocol for SCSI'
FABRIC_TYPE_FCoE = 'Fibre Channel over Ethernet'
FABRIC_TYPE_FICON = 'FIbre CONnection (FICON)'
FABRIC_TYPE_FTP = 'File Transfer Protocol'
FABRIC_TYPE_HTTP = 'Hypertext Transport Protocol'
FABRIC_TYPE_HTTPS = 'Secure Hypertext Transport Protocol'
FABRIC_TYPE_I2C = 'Inter-Integrated Circuit Bus'
FABRIC_TYPE_NFSv3 = 'Network File System version 3'
FABRIC_TYPE_NFSv4 = 'Network File System version 4'
FABRIC_TYPE_NVMe = 'Non-Volatile Memory Express'
FABRIC_TYPE_NVMeOverFabrics = 'NVMe over Fabrics'
FABRIC_TYPE_OEM = 'OEM specific'
FABRIC_TYPE_PCIe = 'PCI Express'
FABRIC_TYPE_RoCE = 'RDMA over Converged Ethernet Protocol'
FABRIC_TYPE_RoCEv2 = 'RDMA over Converged Ethernet Protocol Version 2'
FABRIC_TYPE_SAS = 'Serial Attached SCSI'
FABRIC_TYPE_SATA = 'Serial AT Attachment'
FABRIC_TYPE_SFTP = 'Secure File Transfer Protocol'
FABRIC_TYPE_SMB = 'Server Message Block (aka CIFS Common Internet File System)'
FABRIC_TYPE_UHCI = 'Universal Host Controller Interface'
FABRIC_TYPE_USB = 'Universal Serial Bus'
FABRIC_TYPE_iSCSI = 'Internet SCSI'
FABRIC_TYPE_iWARP = 'Internet Wide Area Remote Direct Memory Access Protocol'
PROTOCOL_TYPE_AHCI = 'Advanced Host Controller Interface'
PROTOCOL_TYPE_FC = 'Fibre Channel'
PROTOCOL_TYPE_FCP = 'Fibre Channel Protocol for SCSI'
PROTOCOL_TYPE_FCoE = 'Fibre Channel over Ethernet'
PROTOCOL_TYPE_FICON = 'FIbre CONnection (FICON)'
PROTOCOL_TYPE_FTP = 'File Transfer Protocol'
PROTOCOL_TYPE_HTTP = 'Hypertext Transport Protocol'
PROTOCOL_TYPE_HTTPS = 'Secure Hypertext Transport Protocol'
PROTOCOL_TYPE_I2C = 'Inter-Integrated Circuit Bus'
PROTOCOL_TYPE_NFSv3 = 'Network File System version 3'
PROTOCOL_TYPE_NFSv4 = 'Network File System version 4'
PROTOCOL_TYPE_NVMe = 'Non-Volatile Memory Express'
PROTOCOL_TYPE_NVMeOverFabrics = 'NVMe over Fabrics'
PROTOCOL_TYPE_OEM = 'OEM specific'
PROTOCOL_TYPE_PCIe = 'PCI Express'
PROTOCOL_TYPE_RoCE = 'RDMA over Converged Ethernet Protocol'
PROTOCOL_TYPE_RoCEv2 = 'RDMA over Converged Ethernet Protocol Version 2'
PROTOCOL_TYPE_SAS = 'Serial Attached SCSI'
PROTOCOL_TYPE_SATA = 'Serial AT Attachment'
PROTOCOL_TYPE_SFTP = 'Secure File Transfer Protocol'
PROTOCOL_TYPE_SMB = 'Server Message Block (CIFS Common Internet File System)'
PROTOCOL_TYPE_UHCI = 'Universal Host Controller Interface'
PROTOCOL_TYPE_USB = 'Universal Serial Bus'
PROTOCOL_TYPE_iSCSI = 'Internet SCSI'
PROTOCOL_TYPE_iWARP = 'Internet Wide Area Remote Direct Memory Access Protocol'
# Address origin IPv4 constants
ADDRESS_ORIGIN_IPv4_BOOTP = 'Address is provided by a BOOTP service'
ADDRESS_ORIGIN_IPv4_DHCP = 'Address is provided by a DHCPv4 service'
ADDRESS_ORIGIN_IPv4_IPv4LINKLOCAL = 'Address valid only for this segment'
ADDRESS_ORIGIN_IPv4_STATIC = 'A static address as configured by the user'
# Address origin IPv6 constants
ADDRESS_ORIGIN_IPv6_DHCPv6 = 'Address is provided by a DHCPv6 service'
ADDRESS_ORIGIN_IPv6_LINKLOCAL = 'Address valid only for this network segment'
ADDRESS_ORIGIN_IPv6_SLAAC = 'Stateless Address Auto Configuration service'
ADDRESS_ORIGIN_IPv6_STATIC = 'A static address as configured by the user'
# Address state constants
ADDRESS_STATE_DEPRECATED = 'Deprecated'
"""This address is currently within it's valid lifetime, but is now outside of
it's preferred lifetime as defined in RFC 4862."""
ADDRESS_STATE_FAILED = 'Failed'
"""This address has failed Duplicate Address Detection testing as defined in
RFC 4862 section 5.4 and is not currently in use."""
ADDRESS_STATE_PREFERRED = 'Preferred'
"""This address is currently within both it's valid and preferred lifetimes as
defined in RFC 4862."""
ADDRESS_STATE_TENTATIVE = 'Tentative'
"""This address is currently undergoing Duplicate Address Detection testing as
defined in RFC 4862 section 5.4."""
# Durable name format constants
DURABLE_NAME_FORMAT_EUI = 'IEEE-defined 64-bit Extended Unique Identifier'
DURABLE_NAME_FORMAT_FC_WWN = 'Fibre Channel World Wide Name'
DURABLE_NAME_FORMAT_NAA = 'Name Address Authority Format'
DURABLE_NAME_FORMAT_NQN = 'NVMe Qualified Name'
DURABLE_NAME_FORMAT_NSID = 'NVM Namespace Identifier'
DURABLE_NAME_FORMAT_UUID = 'Universally Unique Identifier'
DURABLE_NAME_FORMAT_iQN = 'iSCSI Qualified Name'
# Entity role constants
ENTITY_ROLE_BOTH = 'The entity is acting as both an initiator and a target'
ENTITY_ROLE_INITIATOR = 'The entity is acting as an initiator'
ENTITY_ROLE_TARGET = 'The entity is acting as a target'
# Entity type constants
ENTITY_TYPE_PCI_BRIDGE = 'PCI(e) Bridge'
ENTITY_TYPE_DISPLAY_CONTROLLER = 'Display Controller'
ENTITY_TYPE_DRIVE = 'Disk Drive'
ENTITY_TYPE_NETWORK_CONTROLLER = 'Network Controller'
ENTITY_TYPE_PROCESSOR = 'Processor Device'
ENTITY_TYPE_ROOT_COMPLEX = 'Root Complex'
ENTITY_TYPE_STORAGE_EXPANDER = 'Storage Expander'
ENTITY_TYPE_STORAGE_INITIATOR = 'Storage Initiator'
ENTITY_TYPE_VOLUME = 'Volume'

View File

@@ -0,0 +1,178 @@
# 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.
# This is referred from Redfish standard schema.
# https://redfish.dmtf.org/schemas/Endpoint.v1_3_0.json
import logging
from sushy.resources import base
from sushy.resources import common
from sushy.resources.fabric import mappings as fab_maps
from sushy import utils
LOG = logging.getLogger(__name__)
class IPv4AddressField(base.CompositeField):
address = base.Field('Address')
"""This is the IPv4 Address."""
gateway = base.Field('Gateway')
"""This is the IPv4 gateway for this address."""
subnet_mask = base.Field('SubnetMask')
"""This is the IPv4 Subnet mask."""
address_origin = base.MappedField('AddressOrigin',
fab_maps.ADDRESS_ORIGIN_IPv4_VALUE_MAP)
"""This indicates how the address was determined."""
class IPv6AddressField(base.CompositeField):
address = base.Field('Address')
"""This is the IPv6 Address."""
prefix_length = base.Field('PrefixLength', adapter=utils.int_or_none)
"""This is the IPv6 Address Prefix Length."""
address_origin = base.MappedField('AddressOrigin',
fab_maps.ADDRESS_ORIGIN_IPv6_VALUE_MAP)
"""This indicates how the address was determined."""
address_state = base.MappedField('AddressState',
fab_maps.ADDRESS_STATE_VALUE_MAP)
"""The current state of this address as defined in RFC 4862."""
class IPTransportDetailsListField(base.ListField):
"""IP transport details
This array contains details for each IP transport supported by this
endpoint. The array structure can be used to model multiple IP addresses
for this endpoint.
"""
port = base.Field('Port', adapter=utils.int_or_none)
"""The UDP or TCP port number used by the Endpoint."""
transport_protocol = base.MappedField('TransportProtocol',
fab_maps.PROTOCOL_TYPE_VALUE_MAP)
"""The protocol used by the connection entity."""
ipv4_address = IPv4AddressField('IPv4Address')
"""The IPv4 address object."""
ipv6_address = IPv6AddressField('IPv6Address')
"""The IPv6 address object."""
class PciIdField(base.CompositeField):
device_id = base.Field('DeviceId')
"""The Device ID of this PCIe function."""
subsystem_id = base.Field('SubsystemId')
"""The Subsystem ID of this PCIefunction."""
subsystem_vendor_id = base.Field('SubsystemVendorId')
"""The Subsystem Vendor ID of thisPCIe function."""
vendor_id = base.Field('VendorId')
"""The Vendor ID of this PCIe function."""
class IdentifierListField(base.ListField):
durable_name = base.Field('DurableName')
"""This indicates the world wide, persistent name of the entity."""
durable_name_format = base.MappedField('DurableNameFormat',
fab_maps.DUR_NAME_FORMAT_VALUE_MAP)
"""This represents the format of the DurableName property."""
class ConnectedEntitiesListField(base.ListField):
"""All the entities connected to this endpoint."""
pci_class_code = base.Field('PciClassCode')
"""The Class Code, Subclass code, and Programming Interface code of
this PCIe function."""
pci_function_number = base.Field('PciFunctionNumber',
adapter=utils.int_or_none)
"""The PCI ID of the connected entity."""
entity_pci_id = PciIdField('EntityPciId')
"""The PCI ID of the connected entity."""
identifiers = IdentifierListField('Identifiers')
"""Identifiers for the remote entity."""
entity_role = base.MappedField('EntityRole',
fab_maps.ENTITY_ROLE_VALUE_MAP)
"""The role of the connected entity."""
entity_type = base.MappedField('EntityType',
fab_maps.ENTITY_TYPE_VALUE_MAP)
"""The type of the connected entity."""
class Endpoint(base.ResourceBase):
"""This class represents a fabric endpoint.
It represents the properties of an entity that sends or receives protocol
defined messages over a transport.
"""
identity = base.Field('Id', required=True)
"""Identifier for the endpoint"""
name = base.Field('Name', required=True)
"""The endpoint name"""
description = base.Field('Description')
"""The endpoint description"""
status = common.StatusField('Status')
"""The endpoint status"""
host_reservation_memory_bytes = base.Field('HostReservationMemoryBytes',
adapter=utils.int_or_none)
"""The amount of memory in Bytes that the Host should allocate to connect
to this endpoint.
"""
endpoint_protocol = base.MappedField('EndpointProtocol',
fab_maps.PROTOCOL_TYPE_VALUE_MAP)
"""The protocol supported by this endpoint."""
pci_id = PciIdField('PciId')
"""The PCI ID of the endpoint."""
IP_transport_details = IPTransportDetailsListField('IPTransportDetails')
"""This array contains details for each IP transport supported by this
endpoint. The array structure can be used to model multiple IP addresses
for this endpoint."""
connected_entities = ConnectedEntitiesListField('ConnectedEntities')
"""All entities connected to this endpoint."""
class EndpointCollection(base.ResourceCollectionBase):
"""Represents a collection of endpoints associated with the fabric."""
@property
def _resource_type(self):
return Endpoint

View File

@@ -15,7 +15,9 @@
from sushy.resources import base
from sushy.resources import common
from sushy.resources.fabric import endpoint as fab_endpoint
from sushy.resources.fabric import mappings as fab_maps
from sushy import utils
import logging
@@ -38,14 +40,14 @@ class Fabric(base.ResourceBase):
description = base.Field('Description')
"""The fabric description"""
max_zones = base.Field('MaxZones')
max_zones = base.Field('MaxZones', adapter=utils.int_or_none)
"""The maximum number of zones the switch can currently configure"""
status = common.StatusField('Status')
"""The fabric status"""
fabric_type = base.MappedField('FabricType',
fab_maps.FABRIC_TYPE_VALUE_MAP)
fab_maps.PROTOCOL_TYPE_VALUE_MAP)
"""The protocol being sent over this fabric"""
def __init__(self, connector, identity, redfish_version=None):
@@ -58,6 +60,13 @@ class Fabric(base.ResourceBase):
"""
super(Fabric, self).__init__(connector, identity, redfish_version)
@property
@utils.cache_it
def endpoints(self):
return fab_endpoint.EndpointCollection(
self._conn, utils.get_sub_resource_path_by(self, 'Endpoints'),
redfish_version=self.redfish_version)
class FabricCollection(base.ResourceCollectionBase):

View File

@@ -16,32 +16,89 @@
from sushy.resources.fabric import constants as fab_cons
from sushy import utils
FABRIC_TYPE_VALUE_MAP = {
'AHCI': fab_cons.FABRIC_TYPE_AHCI,
'FC': fab_cons.FABRIC_TYPE_FC,
'FCP': fab_cons.FABRIC_TYPE_FCP,
'FCoE': fab_cons.FABRIC_TYPE_FCoE,
'FICON': fab_cons.FABRIC_TYPE_FICON,
'FTP': fab_cons.FABRIC_TYPE_FTP,
'HTTP': fab_cons.FABRIC_TYPE_HTTP,
'HTTPS': fab_cons.FABRIC_TYPE_HTTPS,
'I2C': fab_cons.FABRIC_TYPE_I2C,
'NFSv3': fab_cons.FABRIC_TYPE_NFSv3,
'NFSv4': fab_cons.FABRIC_TYPE_NFSv4,
'NVMe': fab_cons.FABRIC_TYPE_NVMe,
'NVMeOverFabrics': fab_cons.FABRIC_TYPE_NVMeOverFabrics,
'OEM': fab_cons.FABRIC_TYPE_OEM,
'PCIe': fab_cons.FABRIC_TYPE_PCIe,
'RoCE': fab_cons.FABRIC_TYPE_RoCE,
'RoCEv2': fab_cons.FABRIC_TYPE_RoCEv2,
'SAS': fab_cons.FABRIC_TYPE_SAS,
'SATA': fab_cons.FABRIC_TYPE_SATA,
'SFTP': fab_cons.FABRIC_TYPE_SFTP,
'SMB': fab_cons.FABRIC_TYPE_SMB,
'UHCI': fab_cons.FABRIC_TYPE_UHCI,
'USB': fab_cons.FABRIC_TYPE_USB,
'iSCSI': fab_cons.FABRIC_TYPE_iSCSI,
'iWARP': fab_cons.FABRIC_TYPE_iWARP,
PROTOCOL_TYPE_VALUE_MAP = {
'AHCI': fab_cons.PROTOCOL_TYPE_AHCI,
'FC': fab_cons.PROTOCOL_TYPE_FC,
'FCP': fab_cons.PROTOCOL_TYPE_FCP,
'FCoE': fab_cons.PROTOCOL_TYPE_FCoE,
'FICON': fab_cons.PROTOCOL_TYPE_FICON,
'FTP': fab_cons.PROTOCOL_TYPE_FTP,
'HTTP': fab_cons.PROTOCOL_TYPE_HTTP,
'HTTPS': fab_cons.PROTOCOL_TYPE_HTTPS,
'I2C': fab_cons.PROTOCOL_TYPE_I2C,
'NFSv3': fab_cons.PROTOCOL_TYPE_NFSv3,
'NFSv4': fab_cons.PROTOCOL_TYPE_NFSv4,
'NVMe': fab_cons.PROTOCOL_TYPE_NVMe,
'NVMeOverFabrics': fab_cons.PROTOCOL_TYPE_NVMeOverFabrics,
'OEM': fab_cons.PROTOCOL_TYPE_OEM,
'PCIe': fab_cons.PROTOCOL_TYPE_PCIe,
'RoCE': fab_cons.PROTOCOL_TYPE_RoCE,
'RoCEv2': fab_cons.PROTOCOL_TYPE_RoCEv2,
'SAS': fab_cons.PROTOCOL_TYPE_SAS,
'SATA': fab_cons.PROTOCOL_TYPE_SATA,
'SFTP': fab_cons.PROTOCOL_TYPE_SFTP,
'SMB': fab_cons.PROTOCOL_TYPE_SMB,
'UHCI': fab_cons.PROTOCOL_TYPE_UHCI,
'USB': fab_cons.PROTOCOL_TYPE_USB,
'iSCSI': fab_cons.PROTOCOL_TYPE_iSCSI,
'iWARP': fab_cons.PROTOCOL_TYPE_iWARP,
}
FABRIC_TYPE_VALUE_MAP_REV = utils.revert_dictionary(FABRIC_TYPE_VALUE_MAP)
ADDRESS_ORIGIN_IPv4_VALUE_MAP = {
'BOOTP': fab_cons.ADDRESS_ORIGIN_IPv4_BOOTP,
'DHCP': fab_cons.ADDRESS_ORIGIN_IPv4_DHCP,
'IPv4LinkLocal': fab_cons.ADDRESS_ORIGIN_IPv4_IPv4LINKLOCAL,
'Static': fab_cons.ADDRESS_ORIGIN_IPv4_STATIC,
}
ADDRESS_ORIGIN_IPv6_VALUE_MAP = {
'DHCPv6': fab_cons.ADDRESS_ORIGIN_IPv6_DHCPv6,
'LinkLocal': fab_cons.ADDRESS_ORIGIN_IPv6_LINKLOCAL,
'SLAAC': fab_cons.ADDRESS_ORIGIN_IPv6_SLAAC,
'Static': fab_cons.ADDRESS_ORIGIN_IPv6_STATIC,
}
ADDRESS_STATE_VALUE_MAP = {
'Deprecated': fab_cons.ADDRESS_STATE_DEPRECATED,
'Failed': fab_cons.ADDRESS_STATE_FAILED,
'Preferred': fab_cons.ADDRESS_STATE_PREFERRED,
'Tentative': fab_cons.ADDRESS_STATE_TENTATIVE,
}
DUR_NAME_FORMAT_VALUE_MAP = {
'EUI': fab_cons.DURABLE_NAME_FORMAT_EUI,
'FC_WWN': fab_cons.DURABLE_NAME_FORMAT_FC_WWN,
'NAA': fab_cons.DURABLE_NAME_FORMAT_NAA,
'NQN': fab_cons.DURABLE_NAME_FORMAT_NQN,
'NSID': fab_cons.DURABLE_NAME_FORMAT_NSID,
'UUID': fab_cons.DURABLE_NAME_FORMAT_UUID,
'iQN': fab_cons.DURABLE_NAME_FORMAT_iQN,
}
ENTITY_ROLE_VALUE_MAP = {
'Both': fab_cons.ENTITY_ROLE_BOTH,
'Initiator': fab_cons.ENTITY_ROLE_INITIATOR,
'Target': fab_cons.ENTITY_ROLE_TARGET,
}
ENTITY_ROLE_VALUE_MAP_REV = utils.revert_dictionary(ENTITY_ROLE_VALUE_MAP)
ENTITY_TYPE_VALUE_MAP = {
'Bridge': fab_cons.ENTITY_TYPE_PCI_BRIDGE,
'DisplayController': fab_cons.ENTITY_TYPE_DISPLAY_CONTROLLER,
'Drive': fab_cons.ENTITY_TYPE_DRIVE,
'NetworkController': fab_cons.ENTITY_TYPE_NETWORK_CONTROLLER,
'Processor': fab_cons.ENTITY_TYPE_PROCESSOR,
'RootComplex': fab_cons.ENTITY_TYPE_ROOT_COMPLEX,
'StorageExpander': fab_cons.ENTITY_TYPE_STORAGE_EXPANDER,
'StorageInitiator': fab_cons.ENTITY_TYPE_STORAGE_INITIATOR,
'Volume': fab_cons.ENTITY_TYPE_VOLUME,
}
ENTITY_TYPE_VALUE_MAP_REV = utils.revert_dictionary(ENTITY_TYPE_VALUE_MAP)

View File

@@ -0,0 +1,40 @@
{
"@odata.type":"#Endpoint.v1_1_0.Endpoint",
"Id":"Drive1",
"Name":"SAS Drive",
"Description":"The SAS Drive in Enclosure 2 Bay 0",
"EndpointProtocol":"SAS",
"ConnectedEntities":[
{
"EntityType":"Drive",
"EntityRole":"Target",
"Identifiers":[
{
"DurableNameFormat":"NAA",
"DurableName":"32ADF365C6C1B7C3"
}
],
"Oem":{}
}
],
"Links":
{
"MutuallyExclusiveEndpoints":[
{
"@odata.id":"/redfish/v1/Fabrics/SAS/Endpoints/Enclosure2"
}
],
"Ports":[
{
"@odata.id":"/redfish/v1/Fabrics/SAS/Switches/Switch1/Ports/8"
},
{
"@odata.id":"/redfish/v1/Fabrics/SAS/Switches/Switch2/Ports/8"
}
],
"Oem":{}
},
"Oem":{},
"@odata.context":"/redfish/v1/$metadata#Endpoint.Endpoint",
"@odata.id":"/redfish/v1/Fabrics/SAS/Endpoints/Drive1"
}

View File

@@ -0,0 +1,13 @@
{
"@odata.type": "#EndpointCollection.EndpointCollection",
"Name": "Endpoint Collection",
"Members@odata.count": 1,
"Members": [
{
"@odata.id": "/redfish/v1/Fabrics/SAS/Endpoints/Drive1"
}
],
"Oem": {},
"@odata.context": "/redfish/v1/$metadata#EndpointCollection.EndpointCollection",
"@odata.id": "/redfish/v1/Fabrics/SAS/Endpoints"
}

View File

@@ -0,0 +1,48 @@
# 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 sushy
from sushy.resources.fabric import endpoint
from sushy.tests.unit import base
class EndpointTestCase(base.TestCase):
def setUp(self):
super(EndpointTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'endpoint.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.fab_endpoint = endpoint.Endpoint(
self.conn, '/redfish/v1/Fabrics/SAS/Endpoints/Drive1',
redfish_version='1.0.2')
def test__parse_atrtributes(self):
self.fab_endpoint._parse_attributes()
self.assertEqual('Drive1', self.fab_endpoint.identity)
self.assertEqual('SAS Drive', self.fab_endpoint.name)
self.assertEqual(sushy.PROTOCOL_TYPE_SAS,
self.fab_endpoint.endpoint_protocol)
self.assertEqual(sushy.ENTITY_TYPE_DRIVE,
self.fab_endpoint.connected_entities[0].entity_type)
self.assertEqual(sushy.ENTITY_ROLE_TARGET,
self.fab_endpoint.connected_entities[0].entity_role)
con_entity = self.fab_endpoint.connected_entities[0]
self.assertEqual(sushy.DURABLE_NAME_FORMAT_NAA,
con_entity.identifiers[0].durable_name_format)
self.assertEqual('32ADF365C6C1B7C3',
con_entity.identifiers[0].durable_name)

View File

@@ -17,6 +17,7 @@ import json
import mock
import sushy
from sushy.resources.fabric import endpoint
from sushy.resources.fabric import fabric
from sushy.tests.unit import base
@@ -41,11 +42,68 @@ class FabricTestCase(base.TestCase):
self.assertEqual('SAS Fabric', self.fabric.name)
self.assertEqual('A SAS Fabric with redundant switches.',
self.fabric.description)
self.assertEqual(sushy.FABRIC_TYPE_SAS,
self.assertEqual(sushy.PROTOCOL_TYPE_SAS,
self.fabric.fabric_type)
self.assertEqual(sushy.STATE_ENABLED, self.fabric.status.state)
self.assertEqual(sushy.HEALTH_OK, self.fabric.status.health)
def test_endpoints(self):
# | GIVEN |
with open('sushy/tests/unit/json_samples/'
'endpoint_collection.json') as f:
endpoint_collection_return_value = json.load(f)
with open('sushy/tests/unit/json_samples/'
'endpoint.json') as f:
endpoint_return_value = json.load(f)
self.conn.get.return_value.json.side_effect = [
endpoint_collection_return_value, endpoint_return_value]
# | WHEN |
actual_endpoints = self.fabric.endpoints
# | THEN |
self.assertIsInstance(actual_endpoints,
endpoint.EndpointCollection)
self.assertEqual(actual_endpoints.name, 'Endpoint Collection')
member = actual_endpoints.get_member(
'/redfish/v1/Fabrics/SAS/Endpoints/Drive1')
self.assertEqual(member.name, "SAS Drive")
self.assertEqual(member.endpoint_protocol, sushy.PROTOCOL_TYPE_SAS)
def test_endpoints_on_refresh(self):
# | GIVEN |
with open('sushy/tests/unit/json_samples/'
'endpoint_collection.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
# | WHEN & THEN |
endpts = self.fabric.endpoints
self.assertIsInstance(endpts, endpoint.EndpointCollection)
# On refreshing the fabric instance...
with open('sushy/tests/unit/json_samples/fabric.json', 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.fabric.invalidate()
self.fabric.refresh(force=False)
# | WHEN & THEN |
self.assertTrue(endpts._is_stale)
# | GIVEN |
with open('sushy/tests/unit/json_samples/'
'endpoint_collection.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
# | WHEN & THEN |
self.assertIsInstance(self.fabric.endpoints,
endpoint.EndpointCollection)
self.assertFalse(endpts._is_stale)
class FabricCollectionTestCase(base.TestCase):