Add missing attribute in Triggers in RSD 2.2

Change-Id: I406ad0071a85c350a9f66d1cb6aaa9483030dadc
This commit is contained in:
Lin Yang 2019-05-30 00:18:54 -07:00
parent 85afe50d6a
commit c48500785b
6 changed files with 561 additions and 436 deletions

View File

@ -20,33 +20,33 @@ from rsd_lib import common as rsd_lib_common
from rsd_lib.resources.v2_2.telemetry import metric_definition
from rsd_lib.resources.v2_2.telemetry import metric_report
from rsd_lib.resources.v2_2.telemetry import metric_report_definition
from rsd_lib.resources.v2_2.telemetry import trigger
from rsd_lib.resources.v2_2.telemetry import triggers
from rsd_lib import utils as rsd_lib_utils
class Telemetry(base.ResourceBase):
max_reports = base.Field('MaxReports', adapter=rsd_lib_utils.num_or_none)
max_reports = base.Field("MaxReports", adapter=rsd_lib_utils.num_or_none)
"""If present, the value shall specify the maximum number of metric
collectors that can be supported by this service
"""
min_collection_interval = base.Field('MinCollectionInterval')
min_collection_interval = base.Field("MinCollectionInterval")
"""If present, the value shall be an ISO 8601 duration specifying the
minimum time between collections
"""
supported_collection_functions = base.Field('SupportedCollectionFunctions')
supported_collection_functions = base.Field("SupportedCollectionFunctions")
"""If present, the value shall define the function to apply over the
collection duration
"""
status = rsd_lib_common.StatusField('Status')
status = rsd_lib_common.StatusField("Status")
"""The telemetry service status"""
def _get_metric_definitions_path(self):
"""Helper function to find the metric definitions path"""
return utils.get_sub_resource_path_by(self, 'MetricDefinitions')
return utils.get_sub_resource_path_by(self, "MetricDefinitions")
@property
@utils.cache_it
@ -57,12 +57,14 @@ class Telemetry(base.ResourceBase):
this property is reset.
"""
return metric_definition.MetricDefinitionCollection(
self._conn, self._get_metric_definitions_path(),
redfish_version=self.redfish_version)
self._conn,
self._get_metric_definitions_path(),
redfish_version=self.redfish_version,
)
def _get_metric_report_definitions_path(self):
"""Helper function to find the metric report definitions path"""
return utils.get_sub_resource_path_by(self, 'MetricReportDefinitions')
return utils.get_sub_resource_path_by(self, "MetricReportDefinitions")
@property
@utils.cache_it
@ -73,12 +75,14 @@ class Telemetry(base.ResourceBase):
this property is reset.
"""
return metric_report_definition.MetricReportDefinitionCollection(
self._conn, self._get_metric_definitions_path(),
redfish_version=self.redfish_version)
self._conn,
self._get_metric_definitions_path(),
redfish_version=self.redfish_version,
)
def _get_metric_reports_path(self):
"""Helper function to find the metric reports path"""
return utils.get_sub_resource_path_by(self, 'MetricReports')
return utils.get_sub_resource_path_by(self, "MetricReports")
@property
@utils.cache_it
@ -89,21 +93,25 @@ class Telemetry(base.ResourceBase):
this property is reset.
"""
return metric_report.MetricReportCollection(
self._conn, self._get_metric_reports_path(),
redfish_version=self.redfish_version)
self._conn,
self._get_metric_reports_path(),
redfish_version=self.redfish_version,
)
def _get_triggers_path(self):
"""Helper function to find the triggers path"""
return utils.get_sub_resource_path_by(self, 'Triggers')
return utils.get_sub_resource_path_by(self, "Triggers")
@property
@utils.cache_it
def triggers(self):
"""Property to provide reference to `TriggerCollection`
"""Property to provide reference to `TriggersCollection`
It is calculated once the first time it is queried. On refresh,
this property is reset.
"""
return trigger.TriggerCollection(
self._conn, self._get_triggers_path(),
redfish_version=self.redfish_version)
return triggers.TriggersCollection(
self._conn,
self._get_triggers_path(),
redfish_version=self.redfish_version,
)

View File

@ -1,198 +0,0 @@
# 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 jsonschema import validate
import logging
from sushy.resources import base
from rsd_lib import common as rsd_lib_common
from rsd_lib.resources.v2_2.telemetry import trigger_schemas
from rsd_lib import utils as rsd_lib_utils
LOG = logging.getLogger(__name__)
class NumericTriggersField(base.ListField):
name = base.Field('Name')
"""The name of trigger"""
value = base.Field('Value', adapter=rsd_lib_utils.num_or_none)
"""This property contains the value of the trigger"""
direction_of_crossing = base.Field('DirectionOfCrossing')
"""This property contains the value of the trigger"""
dwell_tim_msec = base.Field(
'DwellTimMsec', adapter=rsd_lib_utils.num_or_none)
"""This time the excursion persists before a trigger is determined"""
severity = base.Field('Severity')
"""This property contains the value of the Severity property in the Event
message
"""
class DiscreteTriggersField(base.ListField):
name = base.Field('Name')
"""The name of trigger"""
value = base.Field('Value')
"""This property contains the value of the trigger"""
dwell_tim_msec = base.Field(
'DwellTimMsec', adapter=rsd_lib_utils.num_or_none)
"""This time the excursion persists before a trigger is determined"""
severity = base.Field('Severity')
"""This property contains the value of the Severity property in the Event
message
"""
class WildcardsField(base.ListField):
name = base.Field("Name")
"""This property shall contain a name for a Wildcard for a key"""
keys = base.Field("Keys")
"""If the value is an empty string, then the server shall substitute every
current key. Each not empty key value shall be substituted for the
wildcard
"""
class Trigger(base.ResourceBase):
identity = base.Field("Id")
"""The trigger identity"""
name = base.Field("Name")
"""The trigger name"""
description = base.Field("Description")
"""The trigger description"""
metric_type = base.Field("MetricType")
"""The type of trigger"""
trigger_actions = base.Field("TriggerActions")
"""The metric report description"""
numeric_triggers = NumericTriggersField("NumericTriggers")
"""List of numeric triggers"""
discrete_trigger_condition = base.Field("DiscreteTriggerCondition")
"""The value shall indicate how the corresponding metric"""
discrete_triggers = DiscreteTriggersField("DiscreteTriggers")
"""List of discrete triggers"""
status = rsd_lib_common.StatusField('Status')
"""The trigger status"""
wildcards = WildcardsField("Wildcards")
"""The property shall contain an array of wildcards and their replacements
strings, which are to appliced to the MetricProperties array property
"""
metric_properties = base.Field("MetricProperties")
"""The report definition metric properties"""
def delete(self):
"""Delete trigger"""
self._conn.delete(self.path)
class TriggerCollection(base.ResourceCollectionBase):
@property
def _resource_type(self):
return Trigger
def create_trigger(self, name=None, description=None, metric_type=None,
trigger_actions=None, numeric_triggers=None,
discrete_trigger_condition=None, discrete_triggers=None,
status=None, wildcards=None, metric_properties=None):
"""Create a new trigger
:param name: The trigger name
:param description: The trigger description
:param metric_type: The type of trigger
:param trigger_actions: The metric report description
:param numeric_triggers: List of numeric triggers
:param discrete_trigger_condition: The value shall indicate how the
corresponding metric
:param discrete_triggers: List of discrete triggers
:param status: The trigger status
:param wildcards: Wildcards used to replace values in MetricProperties
array property
:param metric_properties: The report definition metric properties
:returns: The uri of the new trigger
"""
target_uri = self._path
# prepare the request data of creating new trigger
data = {}
if name is not None:
data['Name'] = name
if description is not None:
data['Description'] = description
if metric_type is not None:
validate(metric_type,
trigger_schemas.metric_type_schema)
data['MetricType'] = metric_type
if trigger_actions is not None:
validate(trigger_actions,
trigger_schemas.trigger_actions_schema)
data['TriggerActions'] = trigger_actions
if numeric_triggers is not None:
validate(numeric_triggers,
trigger_schemas.numeric_triggers_schema)
data['NumericTriggers'] = numeric_triggers
if discrete_trigger_condition is not None:
validate(discrete_trigger_condition,
trigger_schemas.discrete_trigger_condition_schema)
data['DiscreteTriggerCondition'] = discrete_trigger_condition
if discrete_triggers is not None:
validate(discrete_triggers,
trigger_schemas.discrete_triggers_schema)
data['DiscreteTriggers'] = discrete_triggers
if status is not None:
validate(status,
trigger_schemas.status_schema)
data['Status'] = status
if wildcards is not None:
validate(wildcards,
trigger_schemas.wildcards_schema)
data['Wildcards'] = wildcards
if metric_properties is not None:
validate(metric_properties,
trigger_schemas.metric_properties_schema)
data['MetricProperties'] = metric_properties
# Issue POST request to create new trigger
resp = self._conn.post(target_uri, data=data)
LOG.info("Node created at %s", resp.headers['Location'])
node_url = resp.headers['Location']
return node_url[node_url.find(self._path):]

View File

@ -0,0 +1,219 @@
# 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 jsonschema import validate
import logging
from sushy.resources import base
from rsd_lib import base as rsd_lib_base
from rsd_lib.resources.v2_2.telemetry import trigger_schemas
from rsd_lib import utils as rsd_lib_utils
LOG = logging.getLogger(__name__)
class DiscreteTriggerCollectionField(base.ListField):
"""DiscreteTrigger field
A discrete trigger.
"""
name = base.Field("Name")
"""The name of trigger."""
value = base.Field("Value")
"""This property contains the value of the trigger."""
dwell_tim_msec = base.Field(
"DwellTimMsec", adapter=rsd_lib_utils.num_or_none
)
"""This time the excursion persists before a trigger is determined."""
severity = base.Field("Severity")
"""This property contains the value of the Severity property in the Event
message.
"""
class WildcardCollectionField(base.ListField):
"""Wildcard field
Wildcards used to replace values in MetricProperties array property.
"""
name = base.Field("Name")
"""The name of Wildcard."""
values = base.Field("Values")
"""An array of values to substitute for the wildcard."""
class NumericTriggerCollectionField(base.ListField):
"""NumericTrigger field
A numeric trigger.
"""
name = base.Field("Name")
"""The name of trigger."""
value = base.Field("Value", adapter=rsd_lib_utils.num_or_none)
"""This property contains the value of the trigger."""
direction_of_crossing = base.Field("DirectionOfCrossing")
"""This property contains the value of the trigger."""
dwell_tim_msec = base.Field(
"DwellTimMsec", adapter=rsd_lib_utils.num_or_none
)
"""This time the excursion persists before a trigger is determined."""
severity = base.Field("Severity")
"""This property contains the value of the Severity property in the Event
message.
"""
class Triggers(rsd_lib_base.ResourceBase):
"""Triggers resource class
This is the schema definition for a Triggers.
"""
metric_type = base.Field("MetricType")
"""The type of trigger."""
trigger_actions = base.Field("TriggerActions")
"""This property specifies what action is perform when the MetricTrigger
occurs.
"""
numeric_triggers = NumericTriggerCollectionField("NumericTriggers")
"""List of numeric triggers."""
discrete_trigger_condition = base.Field("DiscreteTriggerCondition")
"""The type of trigger."""
discrete_triggers = DiscreteTriggerCollectionField("DiscreteTriggers")
"""List of discrete triggers."""
status = rsd_lib_base.StatusField("Status")
"""This indicates the known state of the resource, such as if it is
enabled.
"""
wildcards = WildcardCollectionField("Wildcards")
"""Wildcards used to replace values in MetricProperties array property."""
metric_properties = base.Field("MetricProperties")
"""A collection of URI for the properties on which this metric definition
is defined.
"""
def delete(self):
"""Delete trigger"""
self._conn.delete(self.path)
class TriggersCollection(rsd_lib_base.ResourceCollectionBase):
@property
def _resource_type(self):
return Triggers
def create_trigger(
self,
name=None,
description=None,
metric_type=None,
trigger_actions=None,
numeric_triggers=None,
discrete_trigger_condition=None,
discrete_triggers=None,
status=None,
wildcards=None,
metric_properties=None,
):
"""Create a new trigger
:param name: The trigger name
:param description: The trigger description
:param metric_type: The type of trigger
:param trigger_actions: The metric report description
:param numeric_triggers: List of numeric triggers
:param discrete_trigger_condition: The value shall indicate how the
corresponding metric
:param discrete_triggers: List of discrete triggers
:param status: The trigger status
:param wildcards: Wildcards used to replace values in MetricProperties
array property
:param metric_properties: The report definition metric properties
:returns: The uri of the new trigger
"""
target_uri = self._path
# prepare the request data of creating new trigger
data = {}
if name is not None:
data["Name"] = name
if description is not None:
data["Description"] = description
if metric_type is not None:
validate(metric_type, trigger_schemas.metric_type_schema)
data["MetricType"] = metric_type
if trigger_actions is not None:
validate(trigger_actions, trigger_schemas.trigger_actions_schema)
data["TriggerActions"] = trigger_actions
if numeric_triggers is not None:
validate(numeric_triggers, trigger_schemas.numeric_triggers_schema)
data["NumericTriggers"] = numeric_triggers
if discrete_trigger_condition is not None:
validate(
discrete_trigger_condition,
trigger_schemas.discrete_trigger_condition_schema,
)
data["DiscreteTriggerCondition"] = discrete_trigger_condition
if discrete_triggers is not None:
validate(
discrete_triggers, trigger_schemas.discrete_triggers_schema
)
data["DiscreteTriggers"] = discrete_triggers
if status is not None:
validate(status, trigger_schemas.status_schema)
data["Status"] = status
if wildcards is not None:
validate(wildcards, trigger_schemas.wildcards_schema)
data["Wildcards"] = wildcards
if metric_properties is not None:
validate(
metric_properties, trigger_schemas.metric_properties_schema
)
data["MetricProperties"] = metric_properties
# Issue POST request to create new trigger
resp = self._conn.post(target_uri, data=data)
LOG.info("Node created at %s", resp.headers["Location"])
node_url = resp.headers["Location"]
return node_url[node_url.find(self._path):]

View File

@ -23,263 +23,327 @@ from rsd_lib.resources.v2_2.telemetry import metric_definition
from rsd_lib.resources.v2_2.telemetry import metric_report
from rsd_lib.resources.v2_2.telemetry import metric_report_definition
from rsd_lib.resources.v2_2.telemetry import telemetry
from rsd_lib.resources.v2_2.telemetry import trigger
from rsd_lib.resources.v2_2.telemetry import triggers
class TelemetryTestCase(testtools.TestCase):
def setUp(self):
super(TelemetryTestCase, self).setUp()
self.conn = mock.Mock()
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'telemetry_service.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/telemetry_service.json", "r"
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.telemetry_inst = telemetry.Telemetry(
self.conn, '/redfish/v1/TelemetryService',
redfish_version='1.1.0')
self.conn, "/redfish/v1/TelemetryService", redfish_version="1.1.0"
)
def test__parse_attributes(self):
self.telemetry_inst._parse_attributes()
self.assertEqual('1.1.0', self.telemetry_inst.redfish_version)
self.assertEqual('Enabled', self.telemetry_inst.status.state)
self.assertEqual('OK', self.telemetry_inst.status.health)
self.assertEqual("1.1.0", self.telemetry_inst.redfish_version)
self.assertEqual("Enabled", self.telemetry_inst.status.state)
self.assertEqual("OK", self.telemetry_inst.status.health)
self.assertEqual(None, self.telemetry_inst.status.health_rollup)
self.assertEqual(None, self.telemetry_inst.max_reports)
self.assertEqual(None, self.telemetry_inst.min_collection_interval)
self.assertEqual(
None, self.telemetry_inst.supported_collection_functions)
None, self.telemetry_inst.supported_collection_functions
)
def test__get_metric_definitions_path(self):
self.assertEqual('/redfish/v1/TelemetryService/MetricDefinitions',
self.telemetry_inst._get_metric_definitions_path())
self.assertEqual(
"/redfish/v1/TelemetryService/MetricDefinitions",
self.telemetry_inst._get_metric_definitions_path(),
)
def test__get_metric_definitions_path_missing_attr(self):
self.telemetry_inst._json.pop('MetricDefinitions')
self.telemetry_inst._json.pop("MetricDefinitions")
with self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute MetricDefinitions'):
exceptions.MissingAttributeError, "attribute MetricDefinitions"
):
self.telemetry_inst._get_metric_definitions_path()
def test_metric_definitions(self):
# | GIVEN |
self.conn.get.return_value.json.reset_mock()
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'metric_definition_collection.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/"
"metric_definition_collection.json",
"r",
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN |
actual_metric_definitions = self.telemetry_inst.metric_definitions
# | THEN |
self.assertIsInstance(actual_metric_definitions,
metric_definition.MetricDefinitionCollection)
self.assertIsInstance(
actual_metric_definitions,
metric_definition.MetricDefinitionCollection,
)
self.conn.get.return_value.json.assert_called_once_with()
# reset mock
self.conn.get.return_value.json.reset_mock()
# | WHEN & THEN |
# tests for same object on invoking subsequently
self.assertIs(actual_metric_definitions,
self.telemetry_inst.metric_definitions)
self.assertIs(
actual_metric_definitions, self.telemetry_inst.metric_definitions
)
self.conn.get.return_value.json.assert_not_called()
def test_metric_definitions_on_refresh(self):
# | GIVEN |
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'metric_definition_collection.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/"
"metric_definition_collection.json",
"r",
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(self.telemetry_inst.metric_definitions,
metric_definition.MetricDefinitionCollection)
self.assertIsInstance(
self.telemetry_inst.metric_definitions,
metric_definition.MetricDefinitionCollection,
)
# On refreshing the telemetry service instance...
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'telemetry_service.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/telemetry_service.json", "r"
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.telemetry_inst.invalidate()
self.telemetry_inst.refresh(force=False)
# | GIVEN |
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'metric_definition_collection.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/"
"metric_definition_collection.json",
"r",
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(self.telemetry_inst.metric_definitions,
metric_definition.MetricDefinitionCollection)
self.assertIsInstance(
self.telemetry_inst.metric_definitions,
metric_definition.MetricDefinitionCollection,
)
def test__get_metric_report_definitions_path_path(self):
self.assertEqual(
'/redfish/v1/TelemetryService/MetricReportDefinitions',
self.telemetry_inst._get_metric_report_definitions_path())
"/redfish/v1/TelemetryService/MetricReportDefinitions",
self.telemetry_inst._get_metric_report_definitions_path(),
)
def test__get_metric_report_definitions_path_missing_attr(self):
self.telemetry_inst._json.pop('MetricReportDefinitions')
self.telemetry_inst._json.pop("MetricReportDefinitions")
with self.assertRaisesRegex(
exceptions.MissingAttributeError,
'attribute MetricReportDefinitions'):
"attribute MetricReportDefinitions",
):
self.telemetry_inst._get_metric_report_definitions_path()
def test_metric_report_definitions(self):
# | GIVEN |
self.conn.get.return_value.json.reset_mock()
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'metric_report_definition_collection.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/"
"metric_report_definition_collection.json",
"r",
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN |
actual_report_definitions = \
actual_report_definitions = (
self.telemetry_inst.metric_report_definitions
)
# | THEN |
self.assertIsInstance(
actual_report_definitions,
metric_report_definition.MetricReportDefinitionCollection)
metric_report_definition.MetricReportDefinitionCollection,
)
self.conn.get.return_value.json.assert_called_once_with()
# reset mock
self.conn.get.return_value.json.reset_mock()
# | WHEN & THEN |
# tests for same object on invoking subsequently
self.assertIs(actual_report_definitions,
self.telemetry_inst.metric_report_definitions)
self.assertIs(
actual_report_definitions,
self.telemetry_inst.metric_report_definitions,
)
self.conn.get.return_value.json.assert_not_called()
def test_metric_report_definitions_on_refresh(self):
# | GIVEN |
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'metric_report_definition_collection.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/"
"metric_report_definition_collection.json",
"r",
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(
self.telemetry_inst.metric_report_definitions,
metric_report_definition.MetricReportDefinitionCollection)
metric_report_definition.MetricReportDefinitionCollection,
)
# On refreshing the telemetry service instance...
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'telemetry_service.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/telemetry_service.json", "r"
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.telemetry_inst.invalidate()
self.telemetry_inst.refresh(force=False)
# | GIVEN |
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'metric_report_definition_collection.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/"
"metric_report_definition_collection.json",
"r",
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(
self.telemetry_inst.metric_report_definitions,
metric_report_definition.MetricReportDefinitionCollection)
metric_report_definition.MetricReportDefinitionCollection,
)
def test__get_metric_reports_path_path(self):
self.assertEqual(
'/redfish/v1/TelemetryService/MetricReports',
self.telemetry_inst._get_metric_reports_path())
"/redfish/v1/TelemetryService/MetricReports",
self.telemetry_inst._get_metric_reports_path(),
)
def test__get_metric_reports_path_missing_attr(self):
self.telemetry_inst._json.pop('MetricReports')
with self.assertRaisesRegex(exceptions.MissingAttributeError,
'attribute MetricReports'):
self.telemetry_inst._json.pop("MetricReports")
with self.assertRaisesRegex(
exceptions.MissingAttributeError, "attribute MetricReports"
):
self.telemetry_inst._get_metric_reports_path()
def test_metric_reports(self):
# | GIVEN |
self.conn.get.return_value.json.reset_mock()
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'metric_report_collection.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/"
"metric_report_collection.json",
"r",
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN |
actual_metric_reports = self.telemetry_inst.metric_reports
# | THEN |
self.assertIsInstance(
actual_metric_reports, metric_report.MetricReportCollection)
actual_metric_reports, metric_report.MetricReportCollection
)
self.conn.get.return_value.json.assert_called_once_with()
# reset mock
self.conn.get.return_value.json.reset_mock()
# | WHEN & THEN |
# tests for same object on invoking subsequently
self.assertIs(actual_metric_reports,
self.telemetry_inst.metric_reports)
self.assertIs(
actual_metric_reports, self.telemetry_inst.metric_reports
)
self.conn.get.return_value.json.assert_not_called()
def test_metric_reports_on_refresh(self):
# | GIVEN |
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'metric_report_collection.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/"
"metric_report_collection.json",
"r",
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(
self.telemetry_inst.metric_reports,
metric_report.MetricReportCollection)
metric_report.MetricReportCollection,
)
# On refreshing the telemetry service instance...
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'telemetry_service.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/telemetry_service.json", "r"
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.telemetry_inst.invalidate()
self.telemetry_inst.refresh(force=False)
# | GIVEN |
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'metric_report_collection.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/"
"metric_report_collection.json",
"r",
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(
self.telemetry_inst.metric_reports,
metric_report.MetricReportCollection)
metric_report.MetricReportCollection,
)
def test__get_triggers_path_path(self):
self.assertEqual(
'/redfish/v1/TelemetryService/Triggers',
self.telemetry_inst._get_triggers_path())
"/redfish/v1/TelemetryService/Triggers",
self.telemetry_inst._get_triggers_path(),
)
def test__get_triggers_path_missing_attr(self):
self.telemetry_inst._json.pop('Triggers')
with self.assertRaisesRegex(exceptions.MissingAttributeError,
'attribute Triggers'):
self.telemetry_inst._json.pop("Triggers")
with self.assertRaisesRegex(
exceptions.MissingAttributeError, "attribute Triggers"
):
self.telemetry_inst._get_triggers_path()
def test_triggers(self):
# | GIVEN |
self.conn.get.return_value.json.reset_mock()
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'trigger_collection.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/triggers_collection.json",
"r",
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN |
actual_triggers = self.telemetry_inst.triggers
# | THEN |
self.assertIsInstance(
actual_triggers, trigger.TriggerCollection)
self.assertIsInstance(actual_triggers, triggers.TriggersCollection)
self.conn.get.return_value.json.assert_called_once_with()
# reset mock
self.conn.get.return_value.json.reset_mock()
# | WHEN & THEN |
# tests for same object on invoking subsequently
self.assertIs(actual_triggers,
self.telemetry_inst.triggers)
self.assertIs(actual_triggers, self.telemetry_inst.triggers)
self.conn.get.return_value.json.assert_not_called()
def test_triggers_on_refresh(self):
# | GIVEN |
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'trigger_collection.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/triggers_collection.json",
"r",
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(
self.telemetry_inst.triggers, trigger.TriggerCollection)
self.telemetry_inst.triggers, triggers.TriggersCollection
)
# On refreshing the telemetry service instance...
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'telemetry_service.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/telemetry_service.json", "r"
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.telemetry_inst.invalidate()
self.telemetry_inst.refresh(force=False)
# | GIVEN |
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'trigger_collection.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/triggers_collection.json",
"r",
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(
self.telemetry_inst.triggers, trigger.TriggerCollection)
self.telemetry_inst.triggers, triggers.TriggersCollection
)

View File

@ -17,188 +17,223 @@ import json
import mock
import testtools
from rsd_lib.resources.v2_2.telemetry import trigger
from rsd_lib.resources.v2_2.telemetry import triggers
from rsd_lib.tests.unit.fakes import request_fakes
class TriggerTestCase(testtools.TestCase):
class TriggersTestCase(testtools.TestCase):
def setUp(self):
super(TriggerTestCase, self).setUp()
super(TriggersTestCase, self).setUp()
self.conn = mock.Mock()
with open('rsd_lib/tests/unit/json_samples/v2_2/numeric_trigger.json',
'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/numeric_trigger.json", "r"
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.trigger_inst = trigger.Trigger(
self.triggers_inst = triggers.Triggers(
self.conn,
'/redfish/v1/TelemetryService/Triggers/ProcessorTemperature',
redfish_version='1.1.0')
"/redfish/v1/TelemetryService/Triggers/ProcessorTemperature",
redfish_version="1.1.0",
)
def test__parse_attributes(self):
self.trigger_inst._parse_attributes()
self.assertEqual("ProcessorTemperature", self.trigger_inst.identity)
self.assertEqual("Triggers for Processor Temperature Malfunction",
self.trigger_inst.name)
self.assertEqual(None, self.trigger_inst.description)
self.triggers_inst._parse_attributes()
self.assertEqual("ProcessorTemperature", self.triggers_inst.identity)
self.assertEqual(
"Triggers for Processor Temperature Malfunction",
self.triggers_inst.name,
)
self.assertEqual(None, self.triggers_inst.description)
self.assertEqual('Enabled', self.trigger_inst.status.state)
self.assertEqual('OK', self.trigger_inst.status.health)
self.assertEqual(None, self.trigger_inst.status.health_rollup)
self.assertEqual("Enabled", self.triggers_inst.status.state)
self.assertEqual("OK", self.triggers_inst.status.health)
self.assertEqual(None, self.triggers_inst.status.health_rollup)
self.assertEqual('Numeric', self.trigger_inst.metric_type)
self.assertEqual(["Transmit"], self.trigger_inst.trigger_actions)
self.assertEqual(None, self.trigger_inst.discrete_trigger_condition)
self.assertEqual(None, self.trigger_inst.discrete_triggers)
self.assertEqual(None, self.trigger_inst.wildcards)
self.assertEqual("Numeric", self.triggers_inst.metric_type)
self.assertEqual(["Transmit"], self.triggers_inst.trigger_actions)
self.assertEqual(None, self.triggers_inst.discrete_trigger_condition)
self.assertEqual(None, self.triggers_inst.discrete_triggers)
self.assertEqual(None, self.triggers_inst.wildcards)
self.assertEqual(
[
"/redfish/v1/Systems/System1/Processors/CPU0/Metrics#/"
"TemperatureCelsius",
"/redfish/v1/Systems/System1/Processors/CPU1/Metrics#/"
"TemperatureCelsius"
"TemperatureCelsius",
],
self.trigger_inst.metric_properties)
self.triggers_inst.metric_properties,
)
self.assertEqual(
'UpperThresholdCritical',
self.trigger_inst.numeric_triggers[0].name)
self.assertEqual(90, self.trigger_inst.numeric_triggers[0].value)
"UpperThresholdCritical",
self.triggers_inst.numeric_triggers[0].name,
)
self.assertEqual(90, self.triggers_inst.numeric_triggers[0].value)
self.assertEqual(
'Increasing',
self.trigger_inst.numeric_triggers[0].direction_of_crossing)
"Increasing",
self.triggers_inst.numeric_triggers[0].direction_of_crossing,
)
self.assertEqual(
1, self.trigger_inst.numeric_triggers[0].dwell_tim_msec)
1, self.triggers_inst.numeric_triggers[0].dwell_tim_msec
)
self.assertEqual(
'Critical', self.trigger_inst.numeric_triggers[0].severity)
"Critical", self.triggers_inst.numeric_triggers[0].severity
)
self.assertEqual(
'UpperThresholdNonCritical',
self.trigger_inst.numeric_triggers[1].name)
self.assertEqual(75, self.trigger_inst.numeric_triggers[1].value)
"UpperThresholdNonCritical",
self.triggers_inst.numeric_triggers[1].name,
)
self.assertEqual(75, self.triggers_inst.numeric_triggers[1].value)
self.assertEqual(
'Increasing',
self.trigger_inst.numeric_triggers[1].direction_of_crossing)
"Increasing",
self.triggers_inst.numeric_triggers[1].direction_of_crossing,
)
self.assertEqual(
4, self.trigger_inst.numeric_triggers[1].dwell_tim_msec)
4, self.triggers_inst.numeric_triggers[1].dwell_tim_msec
)
self.assertEqual(
'Warning', self.trigger_inst.numeric_triggers[1].severity)
"Warning", self.triggers_inst.numeric_triggers[1].severity
)
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'discrete_trigger.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/discrete_trigger.json", "r"
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.trigger_inst.refresh()
self.triggers_inst.refresh()
self.assertEqual(
"ProcessorMachineCheckError", self.trigger_inst.identity)
self.assertEqual("Trigger for Processor Machine Check Error",
self.trigger_inst.name)
"ProcessorMachineCheckError", self.triggers_inst.identity
)
self.assertEqual(
"Trigger for Processor Machine Check Error",
self.triggers_inst.name,
)
self.assertEqual(
"Triggers for System1 Processor Machine Check Error",
self.trigger_inst.description)
self.triggers_inst.description,
)
self.assertEqual('Enabled', self.trigger_inst.status.state)
self.assertEqual('OK', self.trigger_inst.status.health)
self.assertEqual(None, self.trigger_inst.status.health_rollup)
self.assertEqual("Enabled", self.triggers_inst.status.state)
self.assertEqual("OK", self.triggers_inst.status.health)
self.assertEqual(None, self.triggers_inst.status.health_rollup)
self.assertEqual('Discrete', self.trigger_inst.metric_type)
self.assertEqual(["Transmit"], self.trigger_inst.trigger_actions)
self.assertEqual("Discrete", self.triggers_inst.metric_type)
self.assertEqual(["Transmit"], self.triggers_inst.trigger_actions)
self.assertEqual(
'Specified', self.trigger_inst.discrete_trigger_condition)
self.assertEqual(
None, self.trigger_inst.numeric_triggers)
self.assertEqual(None, self.trigger_inst.wildcards)
"Specified", self.triggers_inst.discrete_trigger_condition
)
self.assertEqual(None, self.triggers_inst.numeric_triggers)
self.assertEqual(None, self.triggers_inst.wildcards)
self.assertEqual(
[
"/redfish/v1/Systems/System1/Processors/CPU0/Metrics#/"
"CPUHealth",
"/redfish/v1/Systems/System1/Processors/CPU1/Metrics#/"
"CPUHealth"
"CPUHealth",
],
self.trigger_inst.metric_properties)
self.triggers_inst.metric_properties,
)
self.assertEqual(None, self.trigger_inst.discrete_triggers[0].name)
self.assertEqual(None, self.triggers_inst.discrete_triggers[0].name)
self.assertEqual(
"Machine Check Exception",
self.trigger_inst.discrete_triggers[0].value)
self.triggers_inst.discrete_triggers[0].value,
)
self.assertEqual(
1, self.trigger_inst.discrete_triggers[0].dwell_tim_msec)
1, self.triggers_inst.discrete_triggers[0].dwell_tim_msec
)
self.assertEqual(
'Critical', self.trigger_inst.discrete_triggers[0].severity)
"Critical", self.triggers_inst.discrete_triggers[0].severity
)
def test_delete(self):
self.trigger_inst.delete()
self.trigger_inst._conn.delete.assert_called_once_with(
self.trigger_inst.path)
self.triggers_inst.delete()
self.triggers_inst._conn.delete.assert_called_once_with(
self.triggers_inst.path
)
class TriggerCollectionTestCase(testtools.TestCase):
class TriggersCollectionTestCase(testtools.TestCase):
def setUp(self):
super(TriggerCollectionTestCase, self).setUp()
super(TriggersCollectionTestCase, self).setUp()
self.conn = mock.Mock()
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'trigger_collection.json', 'r') as f:
with open(
"rsd_lib/tests/unit/json_samples/v2_2/triggers_collection.json",
"r",
) as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.conn.post.return_value = request_fakes.fake_request_post(
None, headers={
None,
headers={
"Location": "https://localhost:8443/redfish/v1/"
"TelemetryService/Triggers/2"})
self.trigger_col = trigger.TriggerCollection(
self.conn, '/redfish/v1/TelemetryService/Triggers',
redfish_version='1.1.0')
def test_parse_attributes(self):
self.trigger_col._parse_attributes()
self.assertEqual("Triggers Collection", self.trigger_col.name)
@mock.patch.object(trigger, 'Trigger', autospec=True)
def test_get_member(self, mock_trigger):
self.trigger_col.get_member(
'/redfish/v1/TelemetryService/Triggers/ProcessorCatastrophicError')
mock_trigger.assert_called_once_with(
self.trigger_col._conn,
'/redfish/v1/TelemetryService/Triggers/ProcessorCatastrophicError',
redfish_version=self.trigger_col.redfish_version
"TelemetryService/Triggers/2"
},
)
@mock.patch.object(trigger, 'Trigger', autospec=True)
self.triggers_col = triggers.TriggersCollection(
self.conn,
"/redfish/v1/TelemetryService/Triggers",
redfish_version="1.1.0",
)
def test_parse_attributes(self):
self.triggers_col._parse_attributes()
self.assertEqual("Triggers Collection", self.triggers_col.name)
@mock.patch.object(triggers, "Triggers", autospec=True)
def test_get_member(self, mock_trigger):
self.triggers_col.get_member(
"/redfish/v1/TelemetryService/Triggers/ProcessorCatastrophicError"
)
mock_trigger.assert_called_once_with(
self.triggers_col._conn,
"/redfish/v1/TelemetryService/Triggers/ProcessorCatastrophicError",
redfish_version=self.triggers_col.redfish_version,
)
@mock.patch.object(triggers, "Triggers", autospec=True)
def test_get_members(self, mock_trigger):
members = self.trigger_col.get_members()
members = self.triggers_col.get_members()
calls = [
mock.call(
self.trigger_col._conn,
'/redfish/v1/TelemetryService/Triggers/'
'ProcessorCatastrophicError',
redfish_version=self.trigger_col.redfish_version),
self.triggers_col._conn,
"/redfish/v1/TelemetryService/Triggers/"
"ProcessorCatastrophicError",
redfish_version=self.triggers_col.redfish_version,
),
mock.call(
self.trigger_col._conn,
'/redfish/v1/TelemetryService/Triggers/'
'ProcessorInitializationError',
redfish_version=self.trigger_col.redfish_version),
self.triggers_col._conn,
"/redfish/v1/TelemetryService/Triggers/"
"ProcessorInitializationError",
redfish_version=self.triggers_col.redfish_version,
),
mock.call(
self.trigger_col._conn,
'/redfish/v1/TelemetryService/Triggers/'
'ProcessorMachineCheckError',
redfish_version=self.trigger_col.redfish_version),
self.triggers_col._conn,
"/redfish/v1/TelemetryService/Triggers/"
"ProcessorMachineCheckError",
redfish_version=self.triggers_col.redfish_version,
),
mock.call(
self.trigger_col._conn,
'/redfish/v1/TelemetryService/Triggers/ProcessorPOSTFailure',
redfish_version=self.trigger_col.redfish_version),
self.triggers_col._conn,
"/redfish/v1/TelemetryService/Triggers/ProcessorPOSTFailure",
redfish_version=self.triggers_col.redfish_version,
),
mock.call(
self.trigger_col._conn,
'/redfish/v1/TelemetryService/Triggers/ProcessorTemperature',
redfish_version=self.trigger_col.redfish_version),
self.triggers_col._conn,
"/redfish/v1/TelemetryService/Triggers/ProcessorTemperature",
redfish_version=self.triggers_col.redfish_version,
),
mock.call(
self.trigger_col._conn,
'/redfish/v1/TelemetryService/Triggers/ProcessorThermalTrip',
redfish_version=self.trigger_col.redfish_version)
self.triggers_col._conn,
"/redfish/v1/TelemetryService/Triggers/ProcessorThermalTrip",
redfish_version=self.triggers_col.redfish_version,
),
]
mock_trigger.assert_has_calls(calls)
self.assertEqual(mock_trigger.call_count, 6)
@ -209,40 +244,37 @@ class TriggerCollectionTestCase(testtools.TestCase):
reqs = {
"Name": "Trigger for Processor Machine Check Error",
"Description": "Triggers for System1 Processor Machine Check "
"Error",
"Error",
"MetricType": "Discrete",
"TriggerActions": [
"Transmit"
],
"TriggerActions": ["Transmit"],
"DiscreteTriggerCondition": "Specified",
"DiscreteTriggers": [
{
"Value": "Machine Check Exception",
"DwellTimMsec": 1,
"Severity": "Critical"
"Severity": "Critical",
}
],
"Status": {
"State": "Enabled",
"Health": "OK"
},
"Status": {"State": "Enabled", "Health": "OK"},
"MetricProperties": [
"/redfish/v1/Systems/System1/Processors/CPU0/Metrics#/"
"CPUHealth",
"/redfish/v1/Systems/System1/Processors/CPU1/Metrics#/"
"CPUHealth"
]
"CPUHealth",
],
}
result = self.trigger_col.create_trigger(
name=reqs['Name'], description=reqs['Description'],
metric_type=reqs['MetricType'],
trigger_actions=reqs['TriggerActions'],
discrete_trigger_condition=reqs['DiscreteTriggerCondition'],
discrete_triggers=reqs['DiscreteTriggers'], status=reqs['Status'],
metric_properties=reqs['MetricProperties'],)
self.trigger_col._conn.post.assert_called_once_with(
'/redfish/v1/TelemetryService/Triggers',
data=reqs)
self.assertEqual(
result, '/redfish/v1/TelemetryService/Triggers/2')
result = self.triggers_col.create_trigger(
name=reqs["Name"],
description=reqs["Description"],
metric_type=reqs["MetricType"],
trigger_actions=reqs["TriggerActions"],
discrete_trigger_condition=reqs["DiscreteTriggerCondition"],
discrete_triggers=reqs["DiscreteTriggers"],
status=reqs["Status"],
metric_properties=reqs["MetricProperties"],
)
self.triggers_col._conn.post.assert_called_once_with(
"/redfish/v1/TelemetryService/Triggers", data=reqs
)
self.assertEqual(result, "/redfish/v1/TelemetryService/Triggers/2")