Add chassis missing property and unitest

Change-Id: I1b968801b937ef4a3e92e678fe8934fa215ebac7
This commit is contained in:
monokai 2019-03-08 11:11:54 +08:00 committed by Lin Yang
parent 7754b87ba3
commit 113cbeaa8e
5 changed files with 293 additions and 0 deletions

View File

@ -16,6 +16,7 @@
from sushy.resources import base
from sushy import utils
from rsd_lib.resources.v2_1.chassis import log_services
from rsd_lib.resources.v2_1.chassis import power
from rsd_lib.resources.v2_1.chassis import power_zone
from rsd_lib.resources.v2_1.chassis import thermal
@ -54,6 +55,22 @@ class LinksField(base.CompositeField):
adapter=utils.get_members_identities)
"""The Ethernet switches contained in this chassis"""
drives = base.Field("Drives", adapter=utils.get_members_identities)
""""An array of references to the disk drives located in this Chassis"""
storage = base.Field("Storage", adapter=utils.get_members_identities)
"""An array of references to the storage subsystems connected to or inside
this Chassis
"""
cooled_by = base.Field("CooledBy",
adapter=utils.get_members_identities)
"""An array of ID[s] of resources that cool this chassis"""
powered_by = base.Field("PoweredBy",
adapter=utils.get_members_identities)
"""An array of ID[s] of resources that power this chassis"""
class LocationField(base.CompositeField):
identity = base.Field('Id')
@ -83,6 +100,18 @@ class OemField(base.CompositeField):
"""Provides info about the geographical location of this chassis"""
class PhysicalSecurityField(base.CompositeField):
intrusion_sensor_number = base.Field("IntrusionSensorNumber",
adapter=rsd_lib_utils.num_or_none)
""""The physical security intrusion sensor number"""
intrusion_sensor = base.Field("IntrusionSensor")
""""The physical security intrusion sensor"""
intrusion_sensor_rearm = base.Field("IntrusionSensorReArm")
""""The physical security intrusion sensor rearm"""
class Chassis(base.ResourceBase):
identity = base.Field('Id', required=True)
"""The chassis identity string"""
@ -126,6 +155,12 @@ class Chassis(base.ResourceBase):
links = LinksField('Links')
"""The link section of chassis"""
power_state = base.Field("PowerState")
"""The chassis power state"""
physical_security = PhysicalSecurityField("PhysicalSecurity")
"""The chassis physical security"""
def __init__(self, connector, identity, redfish_version=None):
"""A class representing a Chassis
@ -200,6 +235,22 @@ class Chassis(base.ResourceBase):
self._conn, self._get_thermal_path(),
redfish_version=self.redfish_version)
def _get_log_service_collection_path(self):
"""Helper function to find the LogServices path"""
return utils.get_sub_resource_path_by(self, 'LogServices')
@property
@utils.cache_it
def log_services(self):
"""Property to provide reference to `LogServices` instance
It is calculated once when it is queried for the first time. On
refresh, this property is reset.
"""
return log_services.LogServicesCollection(
self._conn, self._get_log_service_collection_path(),
redfish_version=self.redfish_version)
def update(self, asset_tag=None, location_id=None):
"""Update AssetTag and Location->Id properties

View File

@ -0,0 +1,96 @@
# Copyright 2019 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 rsd_lib import utils as rsd_lib_utils
from sushy.resources import base
from sushy import utils
class LinksField(base.CompositeField):
OriginOfCondition = base.Field("OriginOfCondition",
adapter=utils.get_members_identities)
"""The URI of the resource that caused the log entry"""
class LogEntry(base.ResourceBase):
identity = base.Field('Id', required=True)
"""The log entry identity string"""
description = base.Field('Description')
"""The log entry description"""
name = base.Field('Name')
"""The log entry name"""
severity = base.Field("Severity")
"""The severity of the log entry"""
created = base.Field("Created")
"""The time the log entry was created"""
entry_type = base.Field("EntryType")
""""The type of log entry"""
oem_record_format = base.Field("OemRecordFormat")
"""The log entry oem record format"""
entry_code = base.Field("EntryCode")
"""The log entry code"""
sensor_type = base.Field("SensorType")
"""The log entry sensor type"""
sensor_number = base.Field("SensorNumber",
adapter=rsd_lib_utils.num_or_none)
"""The log entry sensor number"""
message = base.Field("Message")
"""The log entry message"""
message_id = base.Field("MessageId")
"""The log entry message id"""
message_args = base.Field("MessageArgs")
"""The log entry message args"""
links = LinksField("Links")
"""The log entry links"""
event_type = base.Field("EventType")
"""The type of an event recorded in this log"""
event_id = base.Field("EventId")
"""A unique instance identifier of an event"""
event_timestamp = base.Field("EventTimestamp")
"""Time the event occurred"""
class LogEntryCollection(base.ResourceCollectionBase):
@property
def _resource_type(self):
return LogEntry
def __init__(self, connector, path, redfish_version=None):
"""A class representing a LogEntry Collection
:param connector: A Connector instance
:param path: The canonical path to the LogEntry Collection resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(LogEntryCollection, self).__init__(connector,
path,
redfish_version)

View File

@ -0,0 +1,105 @@
# Copyright 2019 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 rsd_lib.resources.v2_1.chassis import log_entry
from rsd_lib import utils as rsd_lib_utils
from sushy.resources import base
from sushy import utils
class StatusField(base.CompositeField):
state = base.Field('State')
health = base.Field('Health')
health_rollup = base.Field('HealthRollup')
class LogService(base.ResourceBase):
identity = base.Field('Id', required=True)
"""The log service identity string"""
description = base.Field('Description')
"""The log service description"""
name = base.Field('Name')
"""The log service name"""
status = StatusField("Status")
"""The log service status"""
service_enabled = base.Field("ServiceEnabled", adapter=bool)
"""This indicates whether this service is enabled"""
max_number_of_records = base.Field("MaxNumberOfRecords",
adapter=rsd_lib_utils.num_or_none)
"""The maximum number of log entries this service can have"""
overwrite_policy = base.Field("OverWritePolicy")
"""The overwrite policy for this service that
takes place when the log is full
"""
date_time = base.Field("DateTime")
"""The current DateTime (with offset) for the log
service, used to set or read time
"""
date_time_local_offset = base.Field("DateTimeLocalOffset")
"""The time offset from UTC that the DateTime
property is set to in format: +06:00
"""
def __init__(self, connector, identity, redfish_version=None):
"""A class representing a LogService
:param connector: A Connector instance
:param identity: The identity of the log service resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(LogService, self).__init__(connector, identity, redfish_version)
def _get_entry_collection_path(self):
"""Helper function to find the LogEntryCollection path"""
return utils.get_sub_resource_path_by(self, 'Entries')
@property
@utils.cache_it
def log_entries(self):
"""Property to provide reference to `LogEntryCollection` instance
It is calculated once when it is queried for the first time. On
refresh, this property is reset.
"""
return log_entry.LogEntryCollection(
self._conn, self._get_entry_collection_path(),
redfish_version=self.redfish_version)
class LogServicesCollection(base.ResourceCollectionBase):
@property
def _resource_type(self):
return LogService
def __init__(self, connector, path, redfish_version=None):
"""A class representing a LogService Collection
:param connector: A Connector instance
:param path: The canonical path to the LogService Collection resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(LogServicesCollection, self).__init__(connector,
path,
redfish_version)

View File

@ -13,6 +13,12 @@
"PartNumber": "part-number-as-string",
"AssetTag": "FlexChassis1",
"IndicatorLED": "Unknown",
"PowerState": "On",
"PhysicalSecurity": {
"IntrusionSensorNumber": 1,
"IntrusionSensor": 2,
"IntrusionSensorReArm": 3
},
"Status": {
"State": "Enabled",
"Health": "OK"
@ -64,6 +70,26 @@
"@odata.id": "/redfish/v1/Systems/system4"
}
],
"Drives": [
{
"@odata.id": "/redfish/v1/Drives/1"
}
],
"Storage": [
{
"@odata.id": "/redfish/v1/Storage/1"
}
],
"CooledBy": [
{
"@odata.id": "/redfish/v1/Cool/1"
}
],
"PoweredBy": [
{
"@odata.id": "/redfish/v1/Power/1"
}
],
"ManagedBy": [
{
"@odata.id": "/redfish/v1/Managers/RMM"

View File

@ -80,6 +80,21 @@ class TestChassis(base.TestCase):
self.chassis_inst.oem.rack_supports_disaggregated_power_cooling)
self.assertEqual('Unique ID', self.chassis_inst.oem.uuid)
self.assertEqual('54.348103, 18.645172', self.chassis_inst.oem.geo_tag)
self.assertEqual('On', self.chassis_inst.power_state)
self.assertEqual(
1, self.chassis_inst.physical_security.intrusion_sensor_number)
self.assertEqual(
2, self.chassis_inst.physical_security.intrusion_sensor)
self.assertEqual(
3, self.chassis_inst.physical_security.intrusion_sensor_rearm)
self.assertEqual(('/redfish/v1/Drives/1',),
self.chassis_inst.links.drives)
self.assertEqual(('/redfish/v1/Storage/1',),
self.chassis_inst.links.storage)
self.assertEqual(('/redfish/v1/Cool/1',),
self.chassis_inst.links.cooled_by)
self.assertEqual(('/redfish/v1/Power/1',),
self.chassis_inst.links.powered_by)
def test__get_power_zone_collection_path(self):
expected = '/redfish/v1/Chassis/Rack1/PowerZones'