Add PowerZone resource for RSD 2.1

Change-Id: I3d16f8a3b7424d3211e35f749711d9e694bf9800
This commit is contained in:
Lin Yang 2018-12-17 16:48:23 -08:00
parent d9c59bba76
commit 3764c4d8d0
4 changed files with 336 additions and 0 deletions

View File

@ -0,0 +1,146 @@
# Copyright 2018 Intel, 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 import base
from rsd_lib import utils as rsd_lib_utils
class StatusField(base.CompositeField):
state = base.Field('State')
health = base.Field('Health')
health_rollup = base.Field('HealthRollup')
class RackLocationField(base.CompositeField):
rack_units = base.Field('RackUnits')
"""Indicates the rack unit type"""
xlocation = base.Field('XLocation', adapter=rsd_lib_utils.int_or_none)
"""The horizontal location within uLocation, from left to right
(1.. MAXIMUM) 0 indicate not available
"""
ulocation = base.Field('ULocation', adapter=rsd_lib_utils.int_or_none)
"""The index of the top-most U of the component, from top to bottom
(1.. MAXIMUM) 0 indicate not available
"""
uheight = base.Field('UHeight', adapter=rsd_lib_utils.int_or_none)
"""The height of managed zone, e.g. 8 for 8U, 16 for 16U"""
class PowerSuppliesField(base.ListField):
name = base.Field('Name')
"""The Power Supply name"""
power_capacity_watts = base.Field(
'PowerCapacityWatts', adapter=rsd_lib_utils.int_or_none)
"""The maximum capacity of this Power Supply"""
last_power_output_watts = base.Field(
'LastPowerOutputWatts', adapter=rsd_lib_utils.int_or_none)
"""The average power output of this Power Supply"""
manufacturer = base.Field('Manufacturer')
"""The manufacturer of this Power Supply"""
model_number = base.Field('ModelNumber')
"""The model number for this Power Supply"""
firmware_revision = base.Field('FirmwareRevision')
"""The firmware version for this Power Supply"""
serial_number = base.Field('SerialNumber')
"""The serial number for this Power Supply"""
part_number = base.Field('PartNumber')
"""The part number for this Power Supply"""
status = StatusField('Status')
"""The Power supply status"""
rack_location = RackLocationField('RackLocation')
"""The PowerZone physical location"""
class PowerZone(base.ResourceBase):
identity = base.Field('Id', required=True)
"""The PowerZone identity string"""
name = base.Field('Name')
"""The PowerZone name"""
description = base.Field('Description')
"""The PowerZone description"""
status = StatusField('Status')
"""The PowerZone status"""
rack_location = RackLocationField('RackLocation')
"""The PowerZone physical location"""
max_psus_supported = base.Field(
'MaxPSUsSupported', adapter=rsd_lib_utils.int_or_none)
"""The maximum number of Power Supply Units supported by PowerZone"""
presence = base.Field('Presence')
"""Indicates the aggregated Power Supply Unit presence information
Aggregated Power Supply Unit presence format: Length of string indicate
total slot of Power Supply Units in PowerZone.
For each byte the string:
"1" means present
"0" means not present
"""
number_of_psus_present = base.Field(
'NumberOfPSUsPresent', adapter=rsd_lib_utils.int_or_none)
"""Indicates the number of existing Power Supply Units in PowerZone"""
power_consumed_watts = base.Field(
'PowerConsumedWatts', adapter=rsd_lib_utils.int_or_none)
"""The total power consumption of PowerZone, sum of trays'
power consumption
"""
power_output_watts = base.Field(
'PowerOutputWatts', adapter=rsd_lib_utils.int_or_none)
"""The total power production of PowerZone, sum of PSUs' output"""
power_capacity_watts = base.Field(
'PowerCapacityWatts', adapter=rsd_lib_utils.int_or_none)
"""The maximum power capacity supported by PowerZone"""
power_supplies = PowerSuppliesField('PowerSupplies')
"""Details of the power supplies associated with this system or device"""
class PowerZoneCollection(base.ResourceCollectionBase):
@property
def _resource_type(self):
return PowerZone
def __init__(self, connector, path, redfish_version=None):
"""A class representing a PowerZone Collection
:param connector: A Connector instance
:param path: The canonical path to the power zone collection resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(PowerZoneCollection, self).__init__(connector,
path,
redfish_version)

View File

@ -0,0 +1,50 @@
{
"@odata.context": "/redfish/v1/$metadata#Chassis/Rack/PowerZones/Members/$entity",
"@odata.id": "/redfish/v1/Chassis/Rack1/PowerZones/1",
"@odata.type": "PowerZone.v1_0_0.PowerZone",
"Id": "1",
"Name": "power zone 1",
"Description": "power zone 1 description",
"Status": {
"State": "Enabled",
"Health": "OK",
"HealthRollup": "OK"
},
"RackLocation": {
"RackUnits": "OU",
"XLocation": 0,
"ULocation": 1,
"UHeight": 8
},
"MaxPSUsSupported": 6,
"Presence": "111111",
"NumberOfPSUsPresent": 6,
"PowerConsumedWatts": 2000,
"PowerOutputWatts": 2000,
"PowerCapacityWatts": 3000,
"PowerSupplies": [
{
"Name": "Power supply 1",
"Status": {
"State": "Enabled",
"Health": "OK",
"HealthRollup": "OK"
},
"RackLocation": {
"RackUnits": "OU",
"XLocation": 0,
"ULocation": 1,
"UHeight": 8
},
"SerialNumber": "",
"Manufacturer": "",
"ModelNumber": "",
"PartNumber": "",
"FirmwareRevision": "",
"PowerCapacityWatts": 300,
"LastPowerOutputWatts": 48
}
],
"Actions": {},
"Links": {}
}

View File

@ -0,0 +1,12 @@
{
"@odata.context": "/redfish/v1/$metadata#PowerZoneCollection.PowerZoneCollection",
"@odata.id": "/redfish/v1/Chassis/Rack1/PowerZones",
"@odata.type": "#PowerZoneCollection.PowerZoneCollection",
"Name": "Power Zones Collection",
"Members@odata.count": 1,
"Members": [
{
"@odata.id": "/redfish/v1/Chassis/Rack1/PowerZones/Power1"
}
]
}

View File

@ -0,0 +1,128 @@
# 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.
import json
import mock
import testtools
from rsd_lib.resources.v2_1.chassis import power_zone
class PowerZoneTestCase(testtools.TestCase):
def setUp(self):
super(PowerZoneTestCase, self).setUp()
self.conn = mock.Mock()
with open('rsd_lib/tests/unit/json_samples/v2_1/'
'power_zone.json', 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.power_zone_inst = power_zone.PowerZone(
self.conn, '/redfish/v1/Chassis/Rack1/PowerZones/1',
redfish_version='1.1.0')
def test__parse_attributes(self):
self.power_zone_inst._parse_attributes()
self.assertEqual('1', self.power_zone_inst.identity)
self.assertEqual('power zone 1', self.power_zone_inst.name)
self.assertEqual('power zone 1 description',
self.power_zone_inst.description)
self.assertEqual('1', self.power_zone_inst.identity)
self.assertEqual('Enabled', self.power_zone_inst.status.state)
self.assertEqual('OK', self.power_zone_inst.status.health)
self.assertEqual('OK', self.power_zone_inst.status.health_rollup)
self.assertEqual('OU', self.power_zone_inst.rack_location.rack_units)
self.assertEqual(0, self.power_zone_inst.rack_location.xlocation)
self.assertEqual(1, self.power_zone_inst.rack_location.ulocation)
self.assertEqual(8, self.power_zone_inst.rack_location.uheight)
self.assertEqual(6, self.power_zone_inst.max_psus_supported)
self.assertEqual('111111', self.power_zone_inst.presence)
self.assertEqual(6, self.power_zone_inst.number_of_psus_present)
self.assertEqual(2000, self.power_zone_inst.power_consumed_watts)
self.assertEqual(2000, self.power_zone_inst.power_output_watts)
self.assertEqual(3000, self.power_zone_inst.power_capacity_watts)
self.assertEqual(
'Power supply 1', self.power_zone_inst.power_supplies[0].name)
self.assertEqual(
300, self.power_zone_inst.power_supplies[0].power_capacity_watts)
self.assertEqual(
48, self.power_zone_inst.power_supplies[0].last_power_output_watts)
self.assertEqual(
'', self.power_zone_inst.power_supplies[0].manufacturer)
self.assertEqual(
'', self.power_zone_inst.power_supplies[0].model_number)
self.assertEqual(
'', self.power_zone_inst.power_supplies[0].firmware_revision)
self.assertEqual(
'', self.power_zone_inst.power_supplies[0].serial_number)
self.assertEqual(
'', self.power_zone_inst.power_supplies[0].part_number)
self.assertEqual(
'Enabled', self.power_zone_inst.power_supplies[0].status.state)
self.assertEqual(
'OK', self.power_zone_inst.power_supplies[0].status.health)
self.assertEqual(
'OK', self.power_zone_inst.power_supplies[0].status.health_rollup)
self.assertEqual(
'OU',
self.power_zone_inst.power_supplies[0].rack_location.rack_units)
self.assertEqual(
0, self.power_zone_inst.power_supplies[0].rack_location.xlocation)
self.assertEqual(
1, self.power_zone_inst.power_supplies[0].rack_location.ulocation)
self.assertEqual(
8, self.power_zone_inst.power_supplies[0].rack_location.uheight)
class PowerZoneCollectionTestCase(testtools.TestCase):
def setUp(self):
super(PowerZoneCollectionTestCase, self).setUp()
self.conn = mock.Mock()
with open('rsd_lib/tests/unit/json_samples/v2_1/'
'power_zone_collection.json', 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.power_zone_col = power_zone.\
PowerZoneCollection(
self.conn, '/redfish/v1/Chassis/Rack1/PowerZones',
redfish_version='1.1.0')
def test__parse_attributes(self):
self.power_zone_col._parse_attributes()
self.assertEqual('1.1.0', self.power_zone_col.redfish_version)
self.assertEqual(('/redfish/v1/Chassis/Rack1/PowerZones/Power1',),
self.power_zone_col.members_identities)
@mock.patch.object(power_zone, 'PowerZone', autospec=True)
def test_get_member(self, mock_storage_subsystem):
self.power_zone_col.get_member(
'/redfish/v1/Chassis/Rack1/PowerZones/Power1')
mock_storage_subsystem.assert_called_once_with(
self.power_zone_col._conn,
'/redfish/v1/Chassis/Rack1/PowerZones/Power1',
redfish_version=self.power_zone_col.redfish_version)
@mock.patch.object(power_zone, 'PowerZone', autospec=True)
def test_get_members(self, mock_storage_subsystem):
members = self.power_zone_col.get_members()
calls = [
mock.call(self.power_zone_col._conn,
'/redfish/v1/Chassis/Rack1/PowerZones/Power1',
redfish_version=self.power_zone_col.
redfish_version)
]
mock_storage_subsystem.assert_has_calls(calls)
self.assertIsInstance(members, list)
self.assertEqual(1, len(members))