Add Telemetry Trigger in RSD 2.2

Change-Id: I5c8713e4c8f6cb26430c45551d77b16d51710ec4
This commit is contained in:
Lin Yang 2019-02-08 10:34:19 -08:00
parent ae9d5d78d1
commit ec67bbbd59
14 changed files with 731 additions and 12 deletions

View File

@ -19,6 +19,7 @@ from sushy import utils
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 import utils as rsd_lib_utils
@ -95,3 +96,19 @@ class Telemetry(base.ResourceBase):
return metric_report.MetricReportCollection(
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')
@property
@utils.cache_it
def triggers(self):
"""Property to provide reference to `TriggerCollection`
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)

View File

@ -0,0 +1,215 @@
# 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.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 StatusField(base.CompositeField):
state = base.Field('State')
health = base.Field('Health')
health_rollup = base.Field('HealthRollup')
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 = 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 __init__(self, connector, path, redfish_version=None):
"""A class representing a TriggerCollection
:param connector: A Connector instance
:param path: The canonical path to the Trigger collection
resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(TriggerCollection, self).__init__(
connector, path, redfish_version)
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,92 @@
# Copyright (c) 2019 Intel, Corp.
#
# 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.
metric_type_schema = {
'type': 'string',
'enum': ['Numeric', 'Discrete']
}
trigger_actions_schema = {
'type': 'array',
'items': {
'type': 'string',
'enum': ['Transmit', 'Log']
}
}
numeric_triggers_schema = {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'Name': {'type': 'string'},
'Value': {'type': 'number'},
'DirectionOfCrossing': {
'type': 'string',
'enum': ['Increasing', 'Decreasing']
},
'DwellTimMsec': {'type': 'number'},
'Severity': {'type': 'string'}
},
'additionalProperties': False
}
}
discrete_trigger_condition_schema = {
'type': 'string',
'enum': ['Specified', 'Changed']
}
discrete_triggers_schema = {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'Name': {'type': 'string'},
'Value': {'type': 'string'},
'DwellTimMsec': {'type': 'number'},
'Severity': {'type': 'string'}
},
'additionalProperties': False
}
}
status_schema = {
'type': 'object',
'properties': {
'State': {'type': 'string'},
'Health': {'type': 'string'},
'HealthRollup': {'type': 'string'}
},
'additionalProperties': False
}
wildcards_schema = {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'Name': {'type': 'string'},
'Keys': {'type': 'string'}
},
'additionalProperties': False
}
}
metric_properties_schema = {
'type': 'array',
'items': {
'type': 'string'
}
}

View File

@ -0,0 +1,28 @@
{
"@odata.context": "/redfish/v1/$metadata#TelemetryService/Triggers/Members/$entity",
"@odata.id": "/redfish/v1/TelemetryService/Triggers/ProcessorMachineCheckError",
"@odata.type": "#Trigger.v1_0_0.Trigger",
"Id": "ProcessorMachineCheckError",
"Name": "Trigger for Processor Machine Check Error",
"Description": "Triggers for System1 Processor Machine Check Error",
"MetricType": "Discrete",
"TriggerActions": [
"Transmit"
],
"DiscreteTriggerCondition": "Specified",
"DiscreteTriggers": [
{
"Value": "Machine Check Exception",
"DwellTimMsec": "1",
"Severity": "Critical"
}
],
"Status": {
"State": "Enabled",
"Health": "OK"
},
"MetricProperties": [
"/redfish/v1/Systems/System1/Processors/CPU0/Metrics#/CPUHealth",
"/redfish/v1/Systems/System1/Processors/CPU1/Metrics#/CPUHealth"
]
}

View File

@ -0,0 +1,35 @@
{
"@odata.context": "/redfish/v1/$metadata#TelemetryService/Triggers/Members/$entity",
"@odata.id": "/redfish/v1/TelemetryService/Triggers/ProcessorTemperature",
"@odata.type": "#Trigger.v1_0_0.Trigger",
"Id": "ProcessorTemperature",
"Name": "Triggers for Processor Temperature Malfunction",
"Status": {
"State": "Enabled",
"Health": "OK"
},
"MetricType": "Numeric",
"TriggerActions": [
"Transmit"
],
"NumericTriggers": [
{
"Name": "UpperThresholdCritical",
"Value": "90",
"DirectionOfCrossing": "Increasing",
"DwellTimMsec": "1",
"Severity": "Critical"
},
{
"Name": "UpperThresholdNonCritical",
"Value": "75",
"DirectionOfCrossing": "Increasing",
"DwellTimMsec": "4",
"Severity": "Warning"
}
],
"MetricProperties": [
"/redfish/v1/Systems/System1/Processors/CPU0/Metrics#/TemperatureCelsius",
"/redfish/v1/Systems/System1/Processors/CPU1/Metrics#/TemperatureCelsius"
]
}

View File

@ -0,0 +1,27 @@
{
"@odata.context": "/redfish/v1/$metadata#TelemetryService/Triggers/$entity",
"@odata.id": "/redfish/v1/TelemetryService/Triggers",
"@odata.type": "#TriggersCollection.TriggersCollection",
"Name": "Triggers Collection",
"Members@odata.count": 6,
"Members": [
{
"@odata.id": "/redfish/v1/TelemetryService/Triggers/ProcessorCatastrophicError"
},
{
"@odata.id": "/redfish/v1/TelemetryService/Triggers/ProcessorInitializationError"
},
{
"@odata.id": "/redfish/v1/TelemetryService/Triggers/ProcessorMachineCheckError"
},
{
"@odata.id": "/redfish/v1/TelemetryService/Triggers/ProcessorPOSTFailure"
},
{
"@odata.id": "/redfish/v1/TelemetryService/Triggers/ProcessorTemperature"
},
{
"@odata.id": "/redfish/v1/TelemetryService/Triggers/ProcessorThermalTrip"
}
]
}

View File

@ -48,7 +48,7 @@ class SystemTestCase(testtools.TestCase):
self.assertEqual('/redfish/v1/Systems/437XR1138R2/Memory',
self.system_inst._get_memory_collection_path())
def test__get_memory_collection_path_missing_systems_attr(self):
def test__get_memory_collection_path_missing_attr(self):
self.system_inst._json.pop('Memory')
with self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute Memory'):
@ -105,7 +105,7 @@ class SystemTestCase(testtools.TestCase):
'/redfish/v1/Systems/437XR1138R2/Storage',
self.system_inst._get_storage_subsystem_collection_path())
def test__get_storage_collection_path_missing_systems_attr(self):
def test__get_storage_collection_path_missing_attr(self):
self.system_inst._json.pop('Storage')
with self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute Storage'):

View File

@ -76,7 +76,7 @@ class MemoryTestCase(testtools.TestCase):
self.assertEqual('/redfish/v1/Systems/System1/Memory/Dimm1/Metrics',
self.memory_inst._get_metrics_path())
def test__get_metrics_path_missing_systems_attr(self):
def test__get_metrics_path_missing_attr(self):
self.memory_inst._json.pop('Metrics')
with self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute Metrics'):

View File

@ -60,7 +60,7 @@ class ProcessorTestCase(testtools.TestCase):
self.assertEqual('/redfish/v1/Systems/System1/Processors/CPU1/Metrics',
self.processor_inst._get_metrics_path())
def test__get_metrics_path_missing_systems_attr(self):
def test__get_metrics_path_missing_attr(self):
self.processor_inst._json.get('Oem').get('Intel_RackScale')\
.pop('Metrics')
with self.assertRaisesRegex(exceptions.MissingAttributeError,

View File

@ -49,7 +49,7 @@ class SystemTestCase(testtools.TestCase):
self.assertEqual('/redfish/v1/Systems/System2/Metrics',
self.system_inst._get_metrics_path())
def test__get_metrics_path_missing_systems_attr(self):
def test__get_metrics_path_missing_attr(self):
self.system_inst._json.get('Oem').get('Intel_RackScale').pop('Metrics')
with self.assertRaisesRegex(exceptions.MissingAttributeError,
'attribute Oem/Intel_RackScale/Metrics'):

View File

@ -96,7 +96,7 @@ class MetricReportTestCase(testtools.TestCase):
'/redfish/v1/TelemetryService/MetricReportDefinitions/CPU1Metrics',
self.metric_report_inst._get_metric_report_definition_path())
def test__get_metric_report_definition_path_missing_systems_attr(self):
def test__get_metric_report_definition_path_missing_attr(self):
self.metric_report_inst._json.pop('MetricReportDefinition')
with self.assertRaisesRegex(
exceptions.MissingAttributeError,
@ -164,7 +164,7 @@ class MetricReportCollectionTestCase(testtools.TestCase):
'metric_report_collection.json', 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.metric_report_col = metric_report. MetricReportCollection(
self.metric_report_col = metric_report.MetricReportCollection(
self.conn, '/redfish/v1/TelemetryService/MetricReports',
redfish_version='1.1.0')

View File

@ -85,7 +85,7 @@ class ReportDefinitionTestCase(testtools.TestCase):
("/redfish/v1/TelemetryService/FakeMetric",),
self.metric_report_definition_inst._get_metrics_path())
def test__get_metrics_path_missing_systems_attr(self):
def test__get_metrics_path_missing_attr(self):
self.metric_report_definition_inst._json.pop('Metrics')
with self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute Metrics'):
@ -146,7 +146,7 @@ class ReportDefinitionTestCase(testtools.TestCase):
'/redfish/v1/TelemetryService/MetricReports/TransmitCPU1Metrics',
self.metric_report_definition_inst._get_metric_report_path())
def test__get_metric_report_path_missing_systems_attr(self):
def test__get_metric_report_path_missing_attr(self):
self.metric_report_definition_inst._json.pop('MetricReport')
with self.assertRaisesRegex(exceptions.MissingAttributeError,
'attribute MetricReport'):

View File

@ -23,6 +23,7 @@ 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
class TelemetryTestCase(testtools.TestCase):
@ -53,7 +54,7 @@ class TelemetryTestCase(testtools.TestCase):
self.assertEqual('/redfish/v1/TelemetryService/MetricDefinitions',
self.telemetry_inst._get_metric_definitions_path())
def test__get_metric_definitions_path_missing_systems_attr(self):
def test__get_metric_definitions_path_missing_attr(self):
self.telemetry_inst._json.pop('MetricDefinitions')
with self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute MetricDefinitions'):
@ -110,7 +111,7 @@ class TelemetryTestCase(testtools.TestCase):
'/redfish/v1/TelemetryService/MetricReportDefinitions',
self.telemetry_inst._get_metric_report_definitions_path())
def test__get_metric_report_definitions_path_missing_systems_attr(self):
def test__get_metric_report_definitions_path_missing_attr(self):
self.telemetry_inst._json.pop('MetricReportDefinitions')
with self.assertRaisesRegex(
exceptions.MissingAttributeError,
@ -172,7 +173,7 @@ class TelemetryTestCase(testtools.TestCase):
'/redfish/v1/TelemetryService/MetricReports',
self.telemetry_inst._get_metric_reports_path())
def test__get_metric_reports_path_missing_systems_attr(self):
def test__get_metric_reports_path_missing_attr(self):
self.telemetry_inst._json.pop('MetricReports')
with self.assertRaisesRegex(exceptions.MissingAttributeError,
'attribute MetricReports'):
@ -225,3 +226,60 @@ class TelemetryTestCase(testtools.TestCase):
self.assertIsInstance(
self.telemetry_inst.metric_reports,
metric_report.MetricReportCollection)
def test__get_triggers_path_path(self):
self.assertEqual(
'/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._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:
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.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.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:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(
self.telemetry_inst.triggers, trigger.TriggerCollection)
# On refreshing the telemetry service instance...
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:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(
self.telemetry_inst.triggers, trigger.TriggerCollection)

View File

@ -0,0 +1,247 @@
# 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.
import json
import mock
import testtools
from rsd_lib.resources.v2_2.telemetry import trigger
from rsd_lib.tests.unit.fakes import request_fakes
class TriggerTestCase(testtools.TestCase):
def setUp(self):
super(TriggerTestCase, self).setUp()
self.conn = mock.Mock()
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.conn,
'/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.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('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(
[
"/redfish/v1/Systems/System1/Processors/CPU0/Metrics#/"
"TemperatureCelsius",
"/redfish/v1/Systems/System1/Processors/CPU1/Metrics#/"
"TemperatureCelsius"
],
self.trigger_inst.metric_properties)
self.assertEqual(
'UpperThresholdCritical',
self.trigger_inst.numeric_triggers[0].name)
self.assertEqual(90, self.trigger_inst.numeric_triggers[0].value)
self.assertEqual(
'Increasing',
self.trigger_inst.numeric_triggers[0].direction_of_crossing)
self.assertEqual(
1, self.trigger_inst.numeric_triggers[0].dwell_tim_msec)
self.assertEqual(
'Critical', self.trigger_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)
self.assertEqual(
'Increasing',
self.trigger_inst.numeric_triggers[1].direction_of_crossing)
self.assertEqual(
4, self.trigger_inst.numeric_triggers[1].dwell_tim_msec)
self.assertEqual(
'Warning', self.trigger_inst.numeric_triggers[1].severity)
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.assertEqual(
"ProcessorMachineCheckError", self.trigger_inst.identity)
self.assertEqual("Trigger for Processor Machine Check Error",
self.trigger_inst.name)
self.assertEqual(
"Triggers for System1 Processor Machine Check Error",
self.trigger_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('Discrete', self.trigger_inst.metric_type)
self.assertEqual(["Transmit"], self.trigger_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)
self.assertEqual(
[
"/redfish/v1/Systems/System1/Processors/CPU0/Metrics#/"
"CPUHealth",
"/redfish/v1/Systems/System1/Processors/CPU1/Metrics#/"
"CPUHealth"
],
self.trigger_inst.metric_properties)
self.assertEqual(None, self.trigger_inst.discrete_triggers[0].name)
self.assertEqual(
"Machine Check Exception",
self.trigger_inst.discrete_triggers[0].value)
self.assertEqual(
1, self.trigger_inst.discrete_triggers[0].dwell_tim_msec)
self.assertEqual(
'Critical', self.trigger_inst.discrete_triggers[0].severity)
def test_delete(self):
self.trigger_inst.delete()
self.trigger_inst._conn.delete.assert_called_once()
class TriggerCollectionTestCase(testtools.TestCase):
def setUp(self):
super(TriggerCollectionTestCase, self).setUp()
self.conn = mock.Mock()
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'trigger_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={
"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
)
@mock.patch.object(trigger, 'Trigger', autospec=True)
def test_get_members(self, mock_trigger):
members = self.trigger_col.get_members()
calls = [
mock.call(
self.trigger_col._conn,
'/redfish/v1/TelemetryService/Triggers/'
'ProcessorCatastrophicError',
redfish_version=self.trigger_col.redfish_version),
mock.call(
self.trigger_col._conn,
'/redfish/v1/TelemetryService/Triggers/'
'ProcessorInitializationError',
redfish_version=self.trigger_col.redfish_version),
mock.call(
self.trigger_col._conn,
'/redfish/v1/TelemetryService/Triggers/'
'ProcessorMachineCheckError',
redfish_version=self.trigger_col.redfish_version),
mock.call(
self.trigger_col._conn,
'/redfish/v1/TelemetryService/Triggers/ProcessorPOSTFailure',
redfish_version=self.trigger_col.redfish_version),
mock.call(
self.trigger_col._conn,
'/redfish/v1/TelemetryService/Triggers/ProcessorTemperature',
redfish_version=self.trigger_col.redfish_version),
mock.call(
self.trigger_col._conn,
'/redfish/v1/TelemetryService/Triggers/ProcessorThermalTrip',
redfish_version=self.trigger_col.redfish_version)
]
mock_trigger.assert_has_calls(calls)
self.assertEqual(mock_trigger.call_count, 6)
self.assertIsInstance(members, list)
self.assertEqual(6, len(members))
def test_create_trigger(self):
reqs = {
"Name": "Trigger for Processor Machine Check Error",
"Description": "Triggers for System1 Processor Machine Check "
"Error",
"MetricType": "Discrete",
"TriggerActions": [
"Transmit"
],
"DiscreteTriggerCondition": "Specified",
"DiscreteTriggers": [
{
"Value": "Machine Check Exception",
"DwellTimMsec": 1,
"Severity": "Critical"
}
],
"Status": {
"State": "Enabled",
"Health": "OK"
},
"MetricProperties": [
"/redfish/v1/Systems/System1/Processors/CPU0/Metrics#/"
"CPUHealth",
"/redfish/v1/Systems/System1/Processors/CPU1/Metrics#/"
"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')