Add metric report definition resource for RSD2.2

Change-Id: I009e7c04f14a13394b5d89f0677b4d4793345933
This commit is contained in:
monokai 2019-01-24 14:58:15 +08:00 committed by Lin Yang
parent bedc76e7ed
commit 7372e555bd
10 changed files with 765 additions and 5 deletions

View File

@ -0,0 +1,119 @@
# 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 sushy.resources import base
from rsd_lib import utils as rsd_lib_utils
class DiscreteTriggerConditionField(base.ListField):
name = base.Field("Name")
"""This property shall contain a name for the trigger"""
trigger_value = base.Field("TriggerValue")
"""This property contains the value that sets a trigger"""
previous_value = base.Field("PreviousValue")
"""If present, this property shall contain a previous value that shall be
used in evaluating the behavior of setting the trigger.
"""
class NumericTriggerConditionField(base.ListField):
name = base.Field("Name")
"""This property shall contain a name for the trigger"""
value = base.Field("Value", adapter=rsd_lib_utils.num_or_none)
"""This property shall contain the value of the trigger"""
direction_of_crossing = base.Field("DirectionOfCrossing")
"""If present, this property shall contain the direction of crossing. If
not present, the direction is not relevant
"""
class TriggerConditionField(base.CompositeField):
dwell_interval = base.Field("DwellInterval")
"""The value shall be an ISO 8601 conformant interval during which the
triggering state shall persist before the trigger is invoked.
"""
trigger_type = base.Field("TriggerType")
"""The value of this property shall specific the type of trigger"""
discrete_trigger_conditions = DiscreteTriggerConditionField(
"DiscreteTriggerConditions")
"""A Trigger condition based on TriggerDiscreteCondition"""
filter_trigger_condition = base.Field("FilterTriggerCondition")
"""A Trigger condition based on FilterTriggerCondition"""
numeric_trigger_conditions = NumericTriggerConditionField(
"NumericTriggerConditions")
"""A Trigger condition based on NumericTriggerConditions"""
class StatusField(base.CompositeField):
state = base.Field("State")
"""The status state"""
health = base.Field("Health")
"""The status health"""
class Metric(base.ResourceBase):
identity = base.Field("Id")
"""The metric identity"""
name = base.Field('Name')
"""The metric name"""
description = base.Field('Description')
"""The metric description"""
metric_properties = base.Field("MetricProperties")
"""The report definition metric properties"""
collection_function = base.Field('CollectionFunction')
"""If present, the value shall define the function to apply over the
collection duration
"""
collection_duration = base.Field('CollectionDuration')
"""This property shall not be present if MetricDefinition.Timescope=Point
or if MetricDefintion.Duration is present. If present, the value shall
be an ISO 8601 duration of the interval over which this metric value
shall be computed.
"""
trigger_condition = TriggerConditionField("TriggerCondition")
"""If present the values define conditions that shall be met before the
event is triggered. This trigger applies to all properties defined by
the value of the MetricPropertyDeclaration property in the associated
MetricDefinition and as constrained by the MetricScope property.
"""
status = StatusField("Status")
"""The report definition status"""
def __init__(self, connector, identity, redfish_version=None):
"""A class representing a Metric
:param connector: A Connector instance
:param identity: The identity of the Metric resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(Metric, self).__init__(connector, identity, redfish_version)

View File

@ -24,6 +24,9 @@ class MetricDefinition(base.ResourceBase):
identity = base.Field('Id', required=True) identity = base.Field('Id', required=True)
"""The CPUHealth metric definition identity string""" """The CPUHealth metric definition identity string"""
description = base.Field('Description')
"""The metric definition description"""
sensor_type = base.Field('SensorType') sensor_type = base.Field('SensorType')
"""The type of sensor""" """The type of sensor"""

View File

@ -0,0 +1,177 @@
# 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 import exceptions
from sushy.resources import base
from sushy import utils
from rsd_lib.resources.v2_2.telemetry import metric
from rsd_lib.resources.v2_2.telemetry import metric_report_definition_schemas
LOG = logging.getLogger(__name__)
class ScheduleField(base.CompositeField):
recurrence_interval = base.Field("RecurrenceInterval")
"""The schedule recurrence interval"""
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")
"""The status state"""
health = base.Field("Health")
"""The status health"""
health_rollup = base.Field('HealthRollup')
"""The status health_rollup"""
class MetricReportDefinition(base.ResourceBase):
identity = base.Field("Id")
"""The metric report definition identity"""
name = base.Field('Name')
"""The metric report definition name"""
description = base.Field('Description')
"""The metric report definition description"""
schedule = ScheduleField("Schedule")
"""If present, A metric values collected starting at each scheduled
interval and for the time specified by Duration. No more than
Schedule.MaxOccurrences values shall be collected for this metric. If
not present, the corresponding metric values shall be collected when the
related metric report is retrieved.
"""
metric_report_type = base.Field("MetricReportType")
"""The value shall specify the collection type for the corresponding
metric values
"""
collection_time_scope = base.Field("CollectionTimeScope")
"""The value shall specify the time scope for collecting the corresponding
metric values
"""
report_actions = base.Field("ReportActions")
"""The value of this property shall specify the action to perform when the
metric report is generated. When a metric report is generated, place the
metric information in the resource specified by the MetricReport
property. The Volatile property will specify the behavior if
MetricReport resource already exists.
"""
volatile = base.Field("Volatile")
"""Entries in the resulting metric value properties are reused on each
scheduled interval
"""
wildcards = WildcardsField("Wildcards")
"""The property shall contain an array of wildcards and their replacements
strings, which are to appliced to the MetricProperties array property
"""
status = StatusField("Status")
"""The report definition status"""
metric_properties = base.Field("MetricProperties")
"""The report definition metric properties"""
def __init__(self, connector, identity, redfish_version=None):
"""A class representing a MetricReportDefinition
:param connector: A Connector instance
:param identity: The identity of the MetricReportDefinition resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(MetricReportDefinition, self).__init__(
connector, identity, redfish_version)
def _get_metrics_path(self):
"""Helper function to find the metrics path"""
if 'Metrics' not in self.json:
raise exceptions.MissingAttributeError(
attribute='Metrics', resource=self.path)
return utils.get_members_identities(self.json.get('Metrics'))
@property
@utils.cache_it
def metrics(self):
"""Property to provide collection to `Metric`
It is calculated once the first time it is queried. On refresh,
this property is reset.
"""
return [metric.Metric(
self._conn, path, redfish_version=self.redfish_version)
for path in self._get_metrics_path()]
def delete(self):
"""Delete report definition"""
self._conn.delete(self.path)
class MetricReportDefinitionCollection(base.ResourceCollectionBase):
@property
def _resource_type(self):
return MetricReportDefinition
def __init__(self, connector, path, redfish_version=None):
"""A class representing a ReportDefinitionCollection
:param connector: A Connector instance
:param path: The canonical path to the ReportDefinition collection
resource
:param redfish_version: The version of RedFish. Used to construct
the object according to schema of the given version.
"""
super(MetricReportDefinitionCollection, self).__init__(
connector, path, redfish_version)
def create_metric_report_definition(self, metric_report_definition_req):
"""Create a new report definition
:param metric_report_definition_req: JSON for event subscription
:returns: The uri of the new event report definition
"""
target_uri = self._path
validate(metric_report_definition_req,
metric_report_definition_schemas.report_definition_req_schema)
resp = self._conn.post(target_uri, data=metric_report_definition_req)
report_definition_url = resp.headers['Location']
LOG.info("report definition created at %s", report_definition_url)
return report_definition_url[report_definition_url.find(self._path):]

View File

@ -0,0 +1,60 @@
# 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.
report_definition_req_schema = {
'type': 'object',
'properties': {
'Name': {'type': 'string'},
'Schedule': {
'type': 'object',
'properties': {
'RecurrenceInterval': {'type': 'string'},
}
},
'MetricReportType': {
'type': 'string',
'enum': ['OnChange', 'Periodic', 'OnRequests']
},
'CollectionTimeScope': {
'type': 'string',
'enum': ['Point', 'Interval', 'StartupInterval']
},
'ReportActions': {
'type': 'array',
'items': {
'type': 'string',
'enum': ['Transmit', 'Log']
}
},
'MetricReport': {
'type': 'object',
'properties': {
'@odata.id': {'type': 'string'}
}
},
'Status': {
'type': 'object',
'properties': {
'State': {'type': 'string'},
'Health': {'type': 'string'},
'HealthRollup': {'type': 'string'}
}
},
'MetricProperties': {
'type': 'array',
'items': {'type': 'string'}
}
},
'additionalProperties': False
}

View File

@ -17,6 +17,7 @@ from sushy.resources import base
from sushy import utils from sushy import utils
from rsd_lib.resources.v2_2.telemetry import metric_definitions from rsd_lib.resources.v2_2.telemetry import metric_definitions
from rsd_lib.resources.v2_2.telemetry import metric_report_definition
from rsd_lib import utils as rsd_lib_utils from rsd_lib import utils as rsd_lib_utils
@ -61,3 +62,19 @@ class Telemetry(base.ResourceBase):
return metric_definitions.MetricDefinitionsCollection( return metric_definitions.MetricDefinitionsCollection(
self._conn, self._get_metric_definitions_path(), self._conn, self._get_metric_definitions_path(),
redfish_version=self.redfish_version) 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')
@property
@utils.cache_it
def metric_report_definitions(self):
"""Property to provide reference to `MetricReportDefinitionCollection`
It is calculated once the first time it is queried. On refresh,
this property is reset.
"""
return metric_report_definition.MetricReportDefinitionCollection(
self._conn, self._get_metric_definitions_path(),
redfish_version=self.redfish_version)

View File

@ -0,0 +1,33 @@
{
"@odata.context":"/redfish/v1/$metadata#MetricReportDefinition",
"@odata.type":"#MetricReportDefinition.1.0.0.MetricReportDefinition",
"@odata.id":"/redfish/v1/TelemetryService/MetricReportDefinitions/CPU1Metrics",
"Id":"CPUEventPublish",
"Name":"CPU1 Metric Publisher",
"Schedule":{
"RecurrenceInterval":"PT1M"
},
"MetricReportType":"Periodic",
"CollectionTimeScope":"Interval",
"ReportActions":[
"Transmit",
"Log"
],
"MetricReport":{
"@odata.id":"/redfish/v1/TelemetryService/MetricReports/TransmitCPU1Metrics"
},
"Metrics":[
{
"@odata.id":"/redfish/v1/TelemetryService/FakeMetric"
}
],
"Status":{
"State":"Enabled",
"Health":"OK"
},
"MetricProperties":[
"/redfish/v1/Systems/System1/Processors/CPU1/Metrics#/BandwidthPercent",
"/redfish/v1/Systems/System1/Processors/CPU1/Metrics#/CPUHealth",
"/redfish/v1/Systems/System1/Processors/CPU1/Metrics#/TemperatureCelsius"
]
}

View File

@ -0,0 +1,12 @@
{
"@odata.context":"/redfish/v1/$metadata#TelemetryService/MetricReportDefinitions/$entity",
"@odata.id":"/redfish/v1/TelemetryService/MetricReportDefinitions",
"@odata.type":"#MetricReportDefinitionCollection.MetricReportDefinitionCollection",
"Name":"MetricReportDefinition Collection",
"Members@odata.count":1,
"Members":[
{
"@odata.id":"/redfish/v1/TelemetryService/MetricReportDefinitions/CPU1Metrics"
}
]
}

View File

@ -38,10 +38,10 @@ class MetricDefinitionTestCase(testtools.TestCase):
self.metric_definition_inst._parse_attributes() self.metric_definition_inst._parse_attributes()
self.assertEqual('1.1.0', self.assertEqual('1.1.0',
self.metric_definition_inst.redfish_version) self.metric_definition_inst.redfish_version)
self.assertEqual('memoryTemperature', self.assertEqual('memoryTemperature', self.metric_definition_inst.name)
self.metric_definition_inst.name) self.assertEqual('1-md-6', self.metric_definition_inst.identity)
self.assertEqual('1-md-6', self.assertEqual('Metric Definition description',
self.metric_definition_inst.identity) self.metric_definition_inst.description)
self.assertEqual('Numeric', self.assertEqual('Numeric',
self.metric_definition_inst.metric_type) self.metric_definition_inst.metric_type)
self.assertEqual('Temperature', self.assertEqual('Temperature',

View File

@ -0,0 +1,276 @@
# 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 jsonschema
import mock
import testtools
from sushy import exceptions
from rsd_lib.resources.v2_2.telemetry import metric
from rsd_lib.resources.v2_2.telemetry import metric_report_definition
from rsd_lib.tests.unit.fakes import request_fakes
class ReportDefinitionTestCase(testtools.TestCase):
def setUp(self):
super(ReportDefinitionTestCase, self).setUp()
self.conn = mock.Mock()
with open(
'rsd_lib/tests/unit/json_samples/v2_2/'
'metric_report_definition.json', 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.metric_report_definition_inst = metric_report_definition.\
MetricReportDefinition(
self.conn,
'/redfish/v1/TelemetryService/MetricReportDefinitions/'
'CPU1Metrics',
redfish_version='1.1.0')
def test__parse_attributes(self):
self.metric_report_definition_inst._parse_attributes()
self.assertEqual("CPUEventPublish",
self.metric_report_definition_inst.identity)
self.assertEqual("CPU1 Metric Publisher",
self.metric_report_definition_inst.name)
self.assertEqual(None,
self.metric_report_definition_inst.description)
self.assertEqual(
"PT1M",
self.metric_report_definition_inst.schedule.recurrence_interval)
self.assertEqual("Periodic",
self.metric_report_definition_inst.metric_report_type)
self.assertEqual(
"Interval",
self.metric_report_definition_inst.collection_time_scope)
self.assertEqual(['Transmit', 'Log'],
self.metric_report_definition_inst.report_actions)
self.assertEqual(
"Enabled", self.metric_report_definition_inst.status.state)
self.assertEqual(
"OK", self.metric_report_definition_inst.status.health)
self.assertEqual(
None, self.metric_report_definition_inst.status.health_rollup)
self.assertEqual(None, self.metric_report_definition_inst.volatile)
self.assertEqual(None, self.metric_report_definition_inst.wildcards)
self.assertEqual(
[
"/redfish/v1/Systems/System1/Processors/CPU1/Metrics#"
"/BandwidthPercent",
"/redfish/v1/Systems/System1/Processors/CPU1/Metrics#"
"/CPUHealth",
"/redfish/v1/Systems/System1/Processors/CPU1/Metrics#"
"/TemperatureCelsius"
],
self.metric_report_definition_inst.metric_properties)
def test__get_metrics_path(self):
self.assertEqual(
("/redfish/v1/TelemetryService/FakeMetric",),
self.metric_report_definition_inst._get_metrics_path())
def test__get_metrics_path_missing_systems_attr(self):
self.metric_report_definition_inst._json.pop('Metrics')
with self.assertRaisesRegex(
exceptions.MissingAttributeError, 'attribute Metrics'):
self.metric_report_definition_inst._get_metrics_path()
def test_metrics(self):
# | GIVEN |
self.conn.get.return_value.json.reset_mock()
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'processor_metrics.json', 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN |
actual_metrics = self.metric_report_definition_inst.metrics
# | THEN |
self.assertIsInstance(actual_metrics, list)
self.assertIsInstance(actual_metrics[0], metric.Metric)
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_metrics,
self.metric_report_definition_inst.metrics)
self.conn.get.return_value.json.assert_not_called()
def test_metrics_on_refresh(self):
# | GIVEN |
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'processor_metrics.json', 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(
self.metric_report_definition_inst.metrics, list)
self.assertIsInstance(
self.metric_report_definition_inst.metrics[0], metric.Metric)
# On refreshing the telemetry service instance...
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'metric_report_definition.json', 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.metric_report_definition_inst.invalidate()
self.metric_report_definition_inst.refresh(force=False)
# | GIVEN |
with open('rsd_lib/tests/unit/json_samples/v2_2/'
'processor_metrics.json', 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN & THEN |
self.assertIsInstance(
self.metric_report_definition_inst.metrics, list)
self.assertIsInstance(
self.metric_report_definition_inst.metrics[0], metric.Metric)
def test_delete(self):
self.metric_report_definition_inst.delete()
self.metric_report_definition_inst._conn.delete.assert_called_once()
class ReportDefinitionCollectionTestCase(testtools.TestCase):
def setUp(self):
super(ReportDefinitionCollectionTestCase, self).setUp()
self.conn = mock.Mock()
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())
self.conn.post.return_value = request_fakes.fake_request_post(
None, headers={
"Location": "https://localhost:8443/redfish/v1/"
"TelemetryService/MetricReportDefinitions/1"})
self.report_definition_col = metric_report_definition.\
MetricReportDefinitionCollection(
self.conn,
'/redfish/v1/TelemetryService/MetricReportDefinitions',
redfish_version='1.1.0')
def test_parse_attributes(self):
self.report_definition_col._parse_attributes()
self.assertEqual("MetricReportDefinition Collection", self.
report_definition_col.name)
@mock.patch.object(
metric_report_definition, 'MetricReportDefinition', autospec=True)
def test_get_member(self, mock_metric_report_definition):
self.report_definition_col.get_member(
'/redfish/v1/TelemetryService/MetricReportDefinitions/CPU1Metrics')
mock_metric_report_definition.assert_called_once_with(
self.report_definition_col._conn,
'/redfish/v1/TelemetryService/MetricReportDefinitions/CPU1Metrics',
redfish_version=self.report_definition_col.redfish_version
)
@mock.patch.object(
metric_report_definition, 'MetricReportDefinition', autospec=True)
def test_get_members(self, mock_metric_report_definition):
members = self.report_definition_col.get_members()
self.assertEqual(mock_metric_report_definition.call_count, 1)
self.assertIsInstance(members, list)
self.assertEqual(1, len(members))
def test_create_report_definition_reqs(self):
reqs = {
'Name': 'CPU1 Metric Publisher',
'Schedule': {
'RecurrenceInterval': 'PT1M'
},
'MetricReportType': 'Periodic',
'CollectionTimeScope': 'Interval',
'ReportActions': [
'Transmit',
'Log'
],
'MetricReport': {
'@odata.id': '/redfish/v1/TelemetryService'
'/MetricReports/TransmitCPU1Metrics'
},
'Status': {
'State': 'Enabled',
'Health': 'OK'
},
'MetricProperties': [
'/redfish/v1/Systems/System1/Processors/CPU1/Metrics'
'#/BandwidthPercent',
'/redfish/v1/Systems/System1/Processors/CPU1/Metrics'
'#/CPUHealth',
'/redfish/v1/Systems/System1/Processors/CPU1/Metrics'
'#/TemperatureCelsius'
]
}
result = self.report_definition_col.create_metric_report_definition(
reqs)
self.report_definition_col._conn.post.assert_called_once_with(
'/redfish/v1/TelemetryService/MetricReportDefinitions',
data=reqs)
self.assertEqual(
result, '/redfish/v1/TelemetryService/MetricReportDefinitions/1')
def test_create_report_definition_invalid_reqs(self):
reqs = {
'Name': 'CPU1 Metric Publisher',
'Schedule': {
'RecurrenceInterval': 'PT1M'
},
'MetricReportType': 'Periodic',
'CollectionTimeScope': 'Interval',
'ReportActions': [
'Transmit',
'Log'
],
'MetricReport': {
'@odata.id': '/redfish/v1/TelemetryService/MetricReports'
'/TransmitCPU1Metrics'
},
'Status': {
'State': 'Enabled',
'Health': 'OK'
},
'MetricProperties': [
'/redfish/v1/Systems/System1/Processors/CPU1/Metrics'
'#/BandwidthPercent',
'/redfish/v1/Systems/System1/Processors/CPU1/Metrics'
'#/CPUHealth',
'/redfish/v1/Systems/System1/Processors/CPU1/Metrics'
'#/TemperatureCelsius'
]
}
# Wrong format
report_definition_req = reqs.copy()
report_definition_req.update({'ReportActions': True})
self.assertRaises(
jsonschema.exceptions.ValidationError,
self.report_definition_col.create_metric_report_definition,
report_definition_req)
# Wrong additional fields
report_definition_req = reqs.copy()
report_definition_req['Additional'] = 'AdditionalField'
self.assertRaises(
jsonschema.exceptions.ValidationError,
self.report_definition_col.create_metric_report_definition,
report_definition_req)

View File

@ -20,6 +20,7 @@ import testtools
from sushy import exceptions from sushy import exceptions
from rsd_lib.resources.v2_2.telemetry import metric_definitions from rsd_lib.resources.v2_2.telemetry import metric_definitions
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 telemetry
@ -78,7 +79,7 @@ class TelemetryTestCase(testtools.TestCase):
self.telemetry_inst.metric_definitions) self.telemetry_inst.metric_definitions)
self.conn.get.return_value.json.assert_not_called() self.conn.get.return_value.json.assert_not_called()
def test_metrics_on_refresh(self): def test_metrics_definitions_on_refresh(self):
# | GIVEN | # | GIVEN |
with open('rsd_lib/tests/unit/json_samples/v2_2/' with open('rsd_lib/tests/unit/json_samples/v2_2/'
'metric_definitions.json', 'r') as f: 'metric_definitions.json', 'r') as f:
@ -102,3 +103,65 @@ class TelemetryTestCase(testtools.TestCase):
# | WHEN & THEN | # | WHEN & THEN |
self.assertIsInstance(self.telemetry_inst.metric_definitions, self.assertIsInstance(self.telemetry_inst.metric_definitions,
metric_definitions.MetricDefinitionsCollection) metric_definitions.MetricDefinitionsCollection)
def test__get_metric_report_definitions_path_path(self):
self.assertEqual(
'/redfish/v1/TelemetryService/MetricReportDefinitions',
self.telemetry_inst._get_metric_report_definitions_path())
def test__get_metric_report_definitions_path_missing_systems_attr(self):
self.telemetry_inst._json.pop('MetricReportDefinitions')
with self.assertRaisesRegex(
exceptions.MissingAttributeError,
'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:
self.conn.get.return_value.json.return_value = json.loads(f.read())
# | WHEN |
actual_report_definitions = \
self.telemetry_inst.metric_report_definitions
# | THEN |
self.assertIsInstance(
actual_report_definitions,
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.conn.get.return_value.json.assert_not_called()
def test_metrics_report_definitions_on_refresh(self):
# | GIVEN |
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)
# 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/'
'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)