From 681292f871f31dffaef84f811dfdfd89df23a638 Mon Sep 17 00:00:00 2001 From: sungn Date: Fri, 6 Dec 2019 16:36:52 +0800 Subject: Add energy base scenario and test files Folder of energy contains scripts of energy measurement. File __init__.py make it a module that can be imported. File energy.py contains the main function of energy measurement through redfish API. File test_energy.py test function of energy.py File energy_sample_chassis_output.txt provide a sample output of chassis query. File energy_sample_power_metrics.txt provide sample metrics of power query. This will allow users to collect data of energy consumption of baremetal machines. JIRA: YARDSTICK-1624 Co-authored by: Roland Picard Signed-off-by: sungn Change-Id: Ied86894f3dcc2536f0cb1a044f4591351e5b3270 --- yardstick/benchmark/scenarios/energy/energy.py | 139 +++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 yardstick/benchmark/scenarios/energy/energy.py (limited to 'yardstick/benchmark/scenarios/energy/energy.py') diff --git a/yardstick/benchmark/scenarios/energy/energy.py b/yardstick/benchmark/scenarios/energy/energy.py new file mode 100644 index 000000000..7440835be --- /dev/null +++ b/yardstick/benchmark/scenarios/energy/energy.py @@ -0,0 +1,139 @@ +############################################################################## +# Copyright (c) 2019 Lenovo Group Limited Co.,Ltd and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +from __future__ import print_function +from __future__ import absolute_import +import logging +import requests +import json +from yardstick.benchmark.scenarios import base + +LOG = logging.getLogger(__name__) +logging.captureWarnings(True) + + +class Energy(base.Scenario): + """Get current energy consumption of target host + + This scenario sends a REDFISH request to a host BMC + to request current energy consumption. + The response returns a number of Watts. + Usually this is an average of a rolling windows + taken from server internal sensor. + This is dependant of the server provider. + + This scenario should be used with node context + + As this scenario usually run background with other scenarios, + error of api query or data parse will not terminate task runner. + If any error occured, energy consumption will be set to -1. + + Parameters + None + """ + + __scenario_type__ = "Energy" + + def __init__(self, scenario_cfg, context_cfg): + self.scenario_cfg = scenario_cfg + self.context_cfg = context_cfg + self.target = self.context_cfg['target'] + self.setup_done = False + self.get_response = False + + def _send_request(self, url): + LOG.info("Send request to %s", url) + pod_auth = (self.target["redfish_user"], self.target["redfish_pwd"]) + response = requests.get(url, auth=pod_auth, verify=False) + return response + + def setup(self): + url = "https://{}/redfish/v1/".format(self.target["redfish_ip"]) + response = self._send_request(url) + if response.status_code != 200: + LOG.info("Don't get right response from %s", url) + self.get_response = False + else: + LOG.info("Get response from %s", url) + self.get_response = True + + self.setup_done = True + + def load_chassis_list(self): + chassis_list = [] + + # Get Chassis list + request_url = "https://" + self.target["redfish_ip"] + request_url += "/redfish/v1/Chassis/" + response = self._send_request(request_url) + if response.status_code != 200: + LOG.info("Do not get proper response from %s", request_url) + return chassis_list + + try: + chassis_data = json.loads(response.text) + except(TypeError, ValueError) as e: + LOG.info("Invalid response data, %s", e) + return chassis_list + + try: + for chassis in chassis_data['Members']: + chassis_list.append(chassis["@odata.id"]) + except KeyError as e: + LOG.info("Error data format of chassis data or invalid key.") + + return chassis_list + + def get_power(self, chassis_uri): + """Get PowerMetter values from Redfish API.""" + if chassis_uri[-1:] != '/': + chassis_uri += '/' + request_url = "https://" + self.target['redfish_ip'] + request_url += chassis_uri + request_url += "Power/" + response = self._send_request(request_url) + if response.status_code != 200: + LOG.info("Do not get proper response from %s", request_url) + power = -1 + return power + + try: + power_metrics = json.loads(response.text) + except(TypeError, ValueError) as e: + LOG.info("Invalid response data, %s", e) + power = -1 + return power + + try: + power = power_metrics["PowerControl"][0]["PowerConsumedWatts"] + except KeyError as e: + LOG.info("Error data format of power metrics or invalid key.") + power = -1 + + return power + + def run(self, result): + """execute the benchmark""" + if not self.setup_done: + self.setup() + chassis_list = self.load_chassis_list() + if not self.get_response or not chassis_list: + power = -1 + data = { + "power": power, + } + result.update(data) + else: + power = 0 + for chassis in chassis_list: + power += self.get_power(chassis) + data = { + "power": power, + } + result.update(data) -- cgit 1.2.3-korg