Import sushy lib and extend it as well as show its usage for mutli-podm

As we finialized that using sushy lib as our redfish driver for podm.
This patch imports sushy lib and show how to extend it as well as create
base_podm to build up the example of releations between podm and
sushy(redfish).

Change-Id: Icbd317f2a2dfe2d0daf22b79fdf4db7eadc368b1
This commit is contained in:
hubian 2017-06-20 18:03:44 +08:00
parent 577474c9c0
commit c1d0baa164
12 changed files with 396 additions and 0 deletions

View File

@ -20,3 +20,4 @@ oslo.i18n>=2.1.0 # Apache-2.0
python-ironicclient>=1.11.0 # Apache-2.0
python-keystoneclient>=3.8.0 # Apache-2.0
stevedore>=1.20.0 # Apache-2.0
sushy>=0.1.0 # Apache-2.0

View File

View File

@ -0,0 +1,54 @@
# Copyright (c) 2016 Intel, Inc.
#
# 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 valence.redfish.sushy import sushy_instance
class PodManagerBase(object):
def __init__(self, username, password, podm_url):
self.podm_url = podm_url
self.driver = sushy_instance.RedfishInstance(username=username,
password=password,
base_url=podm_url)
def get_podm_info(self):
return self.get_resource_info_by_url(self.podm_url)
def get_resource_info_by_url(self, resource_url):
return self.driver.get_resources_by_url(resource_url)
def get_chassis_collection(self):
chassis_collection_url = self.podm_url + '/Chassis'
return self.driver.get_resources_by_url(chassis_collection_url)
def get_chassis_info(self, chassis_id):
chassis_url = self.podm_url + '/Chassis/' + chassis_id
return self.driver.get_resources_by_url(chassis_url)
def get_system_collection(self):
system_collection_url = self.podm_url + '/Systems'
return self.driver.get_resources_by_url(system_collection_url)
def get_system_info(self, system_id):
system_url = self.podm_url + '/Systems/' + system_id
return self.driver.get_resources_by_url(system_url)
def get_node_collection(self):
node_collection_url = self.podm_url + '/Nodes'
return self.driver.get_resources_by_url(node_collection_url)
def get_node_info(self, node_id):
node_url = self.podm_url + '/Nodes/' + node_id
return self.driver.get_resources_by_url(node_url)

View File

View File

@ -0,0 +1,83 @@
# 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.
import logging
from sushy.resources import base
LOG = logging.getLogger(__name__)
class Chassis(base.ResourceBase):
asset_tag = base.Field('AssetTag')
"""The chassis asset tag"""
description = base.Field('Description')
"""The chassis description"""
identity = base.Field('Id', required=True)
"""The chassis identity string"""
manufacturer = base.Field('Manufacturer')
"""The chassis manufacturer"""
name = base.Field('Name')
"""The chassis name"""
part_number = base.Field('PartNumber')
"""The chassis part number"""
serial_number = base.Field('SerialNumber')
"""The chassis serial number"""
sku = base.Field('SKU')
"""The chassis stock-keeping unit"""
chassis_type = base.Field('ChassisType')
"""The chassis type"""
oem = base.Field('Oem')
"""The chassis oem options values (dict)"""
def __init__(self, connector, identity, redfish_version=None):
"""A class representing a Chassis
:param connector: A Connector instance
:param identity: The identity of the chassis resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(Chassis, self).__init__(connector, identity, redfish_version)
def refresh(self):
super(Chassis, self).refresh()
class ChassisCollection(base.ResourceCollectionBase):
@property
def _resource_type(self):
return Chassis
def __init__(self, connector, path, redfish_version=None):
"""A class representing a ComputerchassisCollection
:param connector: A Connector instance
:param path: The canonical path to the chassis collection resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(ChassisCollection, self).__init__(connector,
path,
redfish_version)

View File

@ -0,0 +1,63 @@
#!/usr/bin/env python
# Copyright (c) 2016 Intel, Inc.
#
# 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 sushy
from sushy import exceptions
from resources import chassis
class RedfishInstance(sushy.Sushy):
def __init__(self, base_url, username, password):
"""A class representing a Sushy Object Instance
:param base_url: The base URL to the Redfish controller. It
should include scheme and authority portion of the URL.
For example: https://valence.podm:443/
:param username: User account with admin/server-profile access
privilege
:param password: User account password
"""
super(RedfishInstance, self).__init__(base_url=base_url,
username=username,
password=password)
def _get_chassis_collection_path(self):
"""Helper function to find the Chassis Collection path"""
chassis_col = self.json.get('Chassis')
if not chassis_col:
raise exceptions.MissingAttributeError(attribute='Chassis',
resource=self._path)
return chassis_col.get('@odata.id')
def get_chassis_collection(self):
"""Get the Chassis Collection object
:returns: a Chassis Collection object
"""
return chassis.ChassisCollection(self._conn,
self._get_chassis_collection_path(),
redfish_version=self.redfish_version)
def get_chassis(self, identity):
"""Given the identity return a Chassis object
:param identity: The identity of the Chassis resource
:returns: The Chassis object
"""
return chassis.Chassis(self._conn,
identity,
redfish_version=self.redfish_version)

View File

@ -0,0 +1,73 @@
{
"@odata.context": "/redfish/v1/$metadata#Chassis/Members/$entity",
"@odata.id": "/redfish/v1/Chassis/Chassis1",
"@odata.type": "#Chassis.1.0.0.Chassis",
"AssetTag": "FlexChassis1",
"ChassisType": "Drawer",
"Description": "this is a chassis",
"Id": "Chassis1",
"IndicatorLED": "On",
"Links": {
"ComputerSystems": [
{
"@odata.id": "/redfish/v1/Systems/system1"
},
{
"@odata.id": "/redfish/v1/Systems/system2"
},
{
"@odata.id": "/redfish/v1/Systems/system3"
},
{
"@odata.id": "/redfish/v1/Systems/system4"
}
],
"ContainedBy": {
"@odata.id": "/redfish/v1/Chassis/Rack1"
},
"Contains": [
{
"@odata.id": "/redfish/v1/Chassis/Chassis1"
}
],
"ManagedBy": [
{
"@odata.id": "/redfish/v1/Managers/manager1"
}
],
"ManagersIn": [
{
"@odata.id": "/redfish/v1/Managers/manager1"
}
],
"Oem": { },
"Switches": [
{
"@odata.id": "/redfish/v1/EthernetSwitches/switch1"
}
]
},
"Manufacturer": "Intel Corporaion",
"Model": "Lenovo FLEX 8731",
"Name": "FLEX-1",
"Oem": {
"Intel:RackScale": {
"@odata.type": "#Intel.Oem.Chassis",
"Location": {
"Rack": "Rack1",
"UHeight": "10 U",
"ULocation": "25 U",
"UWidth": "1 U"
},
"UUID": "e1c2d764-5c72-36d6-9945-a78255edab51"
}
},
"PartNumber": "5c72-36d6",
"SKU": "e1c2d764-5c72",
"SerialNumber": "a78255edab51",
"Status": {
"Health": "OK",
"HealthRollup": "OK",
"State": "Enabled"
}
}

View File

@ -0,0 +1,34 @@
{
"@odata.context": "/redfish/v1/$metadata#Chassis",
"@odata.id": "/redfish/v1/Chassis",
"@odata.type": "#ChassisCollection.ChassisCollection",
"Members": [
{
"@odata.id": "/redfish/v1/Chassis/Rack1"
},
{
"@odata.id": "/redfish/v1/Chassis/Rack2"
},
{
"@odata.id": "/redfish/v1/Chassis/Chassis1"
},
{
"@odata.id": "/redfish/v1/Chassis/Chassis2"
},
{
"@odata.id": "/redfish/v1/Chassis/Drawer1"
},
{
"@odata.id": "/redfish/v1/Chassis/Drawer2"
},
{
"@odata.id": "/redfish/v1/Chassis/NVMEChassis1"
},
{
"@odata.id": "/redfish/v1/Chassis/NVMEChassis2"
}
],
"Members@odata.count": 8,
"Name": "Chassis Collection"
}

View File

@ -0,0 +1,88 @@
# 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
from sushy.tests.unit import base
from valence.redfish.sushy.resources import chassis
class TestChassis(base.TestCase):
def setUp(self):
super(TestChassis, self).setUp()
self.conn = mock.Mock()
with open('valence/tests/unit/redfish/sushy/json_samples/chassis.json',
'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.chassis_inst = chassis.Chassis(self.conn,
'/redfish/v1/Chassis/chassis1',
redfish_version='1.0.2')
def test_parse_attributes(self):
self.chassis_inst._parse_attributes()
self.assertEqual('1.0.2', self.chassis_inst.redfish_version)
self.assertEqual('FlexChassis1', self.chassis_inst.asset_tag)
self.assertEqual('Drawer', self.chassis_inst.chassis_type)
self.assertEqual('this is a chassis', self.chassis_inst.description)
self.assertEqual('Chassis1', self.chassis_inst.identity)
self.assertEqual('Intel Corporaion', self.chassis_inst.manufacturer)
self.assertEqual('FLEX-1', self.chassis_inst.name)
self.assertEqual('5c72-36d6', self.chassis_inst.part_number)
self.assertEqual('a78255edab51', self.chassis_inst.serial_number)
self.assertEqual('e1c2d764-5c72', self.chassis_inst.sku)
self.assertEqual('e1c2d764-5c72-36d6-9945-a78255edab51',
self.chassis_inst.oem['Intel:RackScale']['UUID'])
class TestChassisCollection(base.TestCase):
def setUp(self):
super(TestChassisCollection, self).setUp()
self.conn = mock.Mock()
with open('valence/tests/unit/redfish/sushy/json_samples/'
'chassis_collection.json', 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.chassis_col = chassis.ChassisCollection(self.conn,
'/redfish/v1/Systems',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.chassis_col._parse_attributes()
self.assertEqual('1.0.2', self.chassis_col.redfish_version)
self.assertEqual('Chassis Collection', self.chassis_col.name)
self.assertIn('/redfish/v1/Chassis/Chassis1',
self.chassis_col.members_identities)
@mock.patch.object(chassis, 'Chassis', autospec=True)
def test_get_member(self, mock_chassis):
self.chassis_col.get_member('/redfish/v1/Chassis/Chassis1')
mock_chassis.assert_called_once_with(
self.chassis_col._conn,
'/redfish/v1/Chassis/Chassis1',
redfish_version=self.chassis_col.redfish_version
)
@mock.patch.object(chassis, 'Chassis', autospec=True)
def test_get_members(self, mock_chassis):
members = self.chassis_col.get_members()
self.assertEqual(mock_chassis.call_count, 8)
self.assertIsInstance(members, list)
self.assertEqual(8, len(members))