Merge "Add `FabricCollection` and `Fabric` classes"

This commit is contained in:
Zuul 2019-04-17 21:49:18 +00:00 committed by Gerrit Code Review
commit f10322a67c
13 changed files with 347 additions and 0 deletions

View File

@ -0,0 +1,5 @@
---
features:
- |
Adds support for the Fabric resource to the library.

View File

@ -21,6 +21,7 @@ from sushy.resources.constants import * # noqa
from sushy.resources.system.constants import * # noqa
from sushy.resources.manager.constants import * # noqa
from sushy.resources.chassis.constants import * # noqa
from sushy.resources.fabric.constants import * # noqa
__all__ = ('Sushy',)
__version__ = pbr.version.VersionInfo(

View File

@ -21,6 +21,7 @@ from sushy import exceptions
from sushy.resources import base
from sushy.resources.chassis import chassis
from sushy.resources.compositionservice import compositionservice
from sushy.resources.fabric import fabric
from sushy.resources.manager import manager
from sushy.resources.registry import message_registry
from sushy.resources.registry import message_registry_file
@ -83,6 +84,9 @@ class Sushy(base.ResourceBase):
_chassis_path = base.Field(['Chassis', '@odata.id'])
"""ChassisCollection path"""
_fabrics_path = base.Field(['Fabrics', '@odata.id'])
"""FabricCollection path"""
_session_service_path = base.Field(['SessionService', '@odata.id'])
"""SessionService path"""
@ -192,6 +196,29 @@ class Sushy(base.ResourceBase):
return chassis.Chassis(self._conn, identity,
redfish_version=self.redfish_version)
def get_fabric_collection(self):
"""Get the FabricCollection object
:raises: MissingAttributeError, if the collection attribute is
not found
:returns: a FabricCollection object
"""
if not self._fabrics_path:
raise exceptions.MissingAttributeError(
attribute='Fabrics/@odata.id', resource=self._path)
return fabric.FabricCollection(self._conn, self._fabrics_path,
redfish_version=self.redfish_version)
def get_fabric(self, identity):
"""Given the identity return a Fabric object
:param identity: The identity of the Fabric resource
:returns: The Fabric object
"""
return fabric.Fabric(self._conn, identity,
redfish_version=self.redfish_version)
def get_manager_collection(self):
"""Get the ManagerCollection object

View File

View File

@ -0,0 +1,42 @@
# 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.
# 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
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'

View File

@ -0,0 +1,77 @@
# 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.
# http://redfish.dmtf.org/schemas/v1/Fabric.v1_0_4.json
from sushy.resources import base
from sushy.resources import common
from sushy.resources.fabric import mappings as fab_maps
import logging
LOG = logging.getLogger(__name__)
class Fabric(base.ResourceBase):
"""Fabric resource
The Fabric represents a simple fabric consisting of one or more
switches, zero or more endpoints, and zero or more zones.
"""
identity = base.Field('Id', required=True)
"""Identifier for the fabric"""
name = base.Field('Name', required=True)
"""The fabric name"""
description = base.Field('Description')
"""The fabric description"""
max_zones = base.Field('MaxZones')
"""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)
"""The protocol being sent over this fabric"""
def __init__(self, connector, identity, redfish_version=None):
"""A class representing a Fabric
:param connector: A Connector instance
:param identity: The identity of the Fabric resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(Fabric, self).__init__(connector, identity, redfish_version)
class FabricCollection(base.ResourceCollectionBase):
@property
def _resource_type(self):
return Fabric
def __init__(self, connector, path, redfish_version=None):
"""A class representing a FabricCollection
:param connector: A Connector instance
:param path: The canonical path to the Fabric collection resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(FabricCollection, self).__init__(connector, path,
redfish_version)

View File

@ -0,0 +1,47 @@
# Copyright 2017 Red Hat, 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.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,
}
FABRIC_TYPE_VALUE_MAP_REV = utils.revert_dictionary(FABRIC_TYPE_VALUE_MAP)

View File

@ -0,0 +1,29 @@
{
"@odata.type": "#Fabric.v1_0_3.Fabric",
"Id": "SAS",
"Name": "SAS Fabric",
"FabricType": "SAS",
"Description": "A SAS Fabric with redundant switches.",
"Status": {
"State": "Enabled",
"Health": "OK"
},
"Zones": {
"@odata.id": "/redfish/v1/Fabrics/SAS/Zones"
},
"Endpoints": {
"@odata.id": "/redfish/v1/Fabrics/SAS/Endpoints"
},
"Switches": {
"@odata.id": "/redfish/v1/Fabrics/SAS/Switches"
},
"Links": {
"Oem": {}
},
"Actions": {
"Oem": {}
},
"Oem": {},
"@odata.context": "/redfish/v1/$metadata#Fabric.Fabric",
"@odata.id": "/redfish/v1/Fabrics/SAS"
}

View File

@ -0,0 +1,16 @@
{
"@odata.type": "#FabricCollection.FabricCollection",
"Name": "Fabric Collection",
"Members@odata.count": 2,
"Members": [
{
"@odata.id": "/redfish/v1/Fabrics/SAS1"
},
{
"@odata.id": "/redfish/v1/Fabrics/SAS2"
}
],
"@odata.context": "/redfish/v1/$metadata#FabricCollection.FabricCollection",
"@odata.id": "/redfish/v1/Fabrics",
"@Redfish.Copyright": "Copyright 2014-2017 Distributed Management Task Force, Inc. (DMTF). For the full DMTF copyright policy, see http://www.dmtf.org/about/policies/copyright."
}

View File

@ -21,6 +21,9 @@
"Managers": {
"@odata.id": "/redfish/v1/Managers"
},
"Fabrics": {
"@odata.id": "/redfish/v1/Fabrics"
},
"Tasks": {
"@odata.id": "/redfish/v1/TaskService"
},

View File

@ -0,0 +1,79 @@
# -*- coding: utf-8 -*-
# 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 fabric
from sushy.tests.unit import base
class FabricTestCase(base.TestCase):
def setUp(self):
super(FabricTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/fabric.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.fabric = fabric.Fabric(self.conn, '/redfish/v1/Fabrics/SAS',
redfish_version='1.0.3')
def test__parse_attributes(self):
# | WHEN |
self.fabric._parse_attributes()
# | THEN |
self.assertEqual('1.0.3', self.fabric.redfish_version)
self.assertEqual('SAS', self.fabric.identity)
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.fabric.fabric_type)
self.assertEqual(sushy.STATE_ENABLED, self.fabric.status.state)
self.assertEqual(sushy.HEALTH_OK, self.fabric.status.health)
class FabricCollectionTestCase(base.TestCase):
def setUp(self):
super(FabricCollectionTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy/tests/unit/json_samples/'
'fabric_collection.json') as f:
self.conn.get.return_value.json.return_value = json.load(f)
self.fabric = fabric.FabricCollection(
self.conn, '/redfish/v1/Fabrics', redfish_version='1.0.3')
@mock.patch.object(fabric, 'Fabric', autospec=True)
def test_get_member(self, fabric_mock):
self.fabric.get_member('/redfish/v1/Fabrics/SAS1')
fabric_mock.assert_called_once_with(
self.fabric._conn, '/redfish/v1/Fabrics/SAS1',
redfish_version=self.fabric.redfish_version)
@mock.patch.object(fabric, 'Fabric', autospec=True)
def test_get_members(self, fabric_mock):
members = self.fabric.get_members()
calls = [
mock.call(self.fabric._conn, '/redfish/v1/Fabrics/SAS1',
redfish_version=self.fabric.redfish_version),
mock.call(self.fabric._conn, '/redfish/v1/Fabrics/SAS2',
redfish_version=self.fabric.redfish_version)
]
fabric_mock.assert_has_calls(calls)
self.assertIsInstance(members, list)
self.assertEqual(2, len(members))

View File

@ -22,6 +22,7 @@ from sushy import exceptions
from sushy import main
from sushy.resources.chassis import chassis
from sushy.resources.compositionservice import compositionservice
from sushy.resources.fabric import fabric
from sushy.resources.manager import manager
from sushy.resources.registry import message_registry_file
from sushy.resources.sessionservice import session
@ -67,6 +68,7 @@ class MainTestCase(base.TestCase):
self.assertEqual('/redfish/v1/Systems', self.root._systems_path)
self.assertEqual('/redfish/v1/Managers', self.root._managers_path)
self.assertEqual('/redfish/v1/Chassis', self.root._chassis_path)
self.assertEqual('/redfish/v1/Fabrics', self.root._fabrics_path)
self.assertEqual('/redfish/v1/SessionService',
self.root._session_service_path)
self.assertEqual('/redfish/v1/CompositionService',
@ -118,6 +120,20 @@ class MainTestCase(base.TestCase):
self.root._conn, '/redfish/v1/Chassis',
redfish_version=self.root.redfish_version)
@mock.patch.object(fabric, 'Fabric', autospec=True)
def test_get_fabric(self, mock_fabric):
self.root.get_fabric('fake-fabric-id')
mock_fabric.assert_called_once_with(
self.root._conn, 'fake-fabric-id',
redfish_version=self.root.redfish_version)
@mock.patch.object(fabric, 'FabricCollection', autospec=True)
def test_get_fabric_collection(self, fabric_collection_mock):
self.root.get_fabric_collection()
fabric_collection_mock.assert_called_once_with(
self.root._conn, '/redfish/v1/Fabrics',
redfish_version=self.root.redfish_version)
@mock.patch.object(manager, 'ManagerCollection', autospec=True)
def test_get_manager_collection(self, ManagerCollection_mock):
self.root.get_manager_collection()
@ -205,6 +221,11 @@ class BareMinimumMainTestCase(base.TestCase):
exceptions.MissingAttributeError,
'Chassis/@odata.id', self.root.get_chassis_collection)
def test_get_fabric_collection_when_fabrics_attr_absent(self):
self.assertRaisesRegex(
exceptions.MissingAttributeError,
'Fabrics/@odata.id', self.root.get_fabric_collection)
def test_get_session_service_when_sessionservice_attr_absent(self):
self.assertRaisesRegex(
exceptions.MissingAttributeError,