From 57b3a9e6b836b33201cf4e2630fd228032e657e4 Mon Sep 17 00:00:00 2001 From: Benoit HERARD Date: Thu, 27 Apr 2017 11:23:00 +0200 Subject: Add Energy recording support It adds helpers to send notifications to Energy recording API and related unit tests. It requires a dedicated section in functest config file to set connectivity parameters to Energy recording API. It is using shared API Recording at http://161.105.253.100:8888 Change-Id: Idcb74d1bf7341ccce7cc1c3926f22338ce24f714 Signed-off-by: Benoit HERARD --- functest/energy/__init__.py | 0 functest/energy/energy.py | 203 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 functest/energy/__init__.py create mode 100644 functest/energy/energy.py (limited to 'functest/energy') diff --git a/functest/energy/__init__.py b/functest/energy/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/functest/energy/energy.py b/functest/energy/energy.py new file mode 100644 index 000000000..a20c79926 --- /dev/null +++ b/functest/energy/energy.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +# Copyright (c) 2017 Orange 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 + +"""This module manages calls to Energy recording API.""" + +import json +import logging +import urllib +import requests + +import functest.utils.functest_utils as ft_utils + + +def enable_recording(method): + """ + Decorator to record energy during "method" exection. + + param method: Method to suround with start and stop + :type method: function + + .. note:: "method" should belong to a class having a "case_name" + attribute + """ + def wrapper(*args): + """Wrapper for decorator to handle method arguments.""" + EnergyRecorder.start(args[0].case_name) + return_value = method(*args) + EnergyRecorder.stop() + return return_value + return wrapper + + +# Class to manage energy recording sessions +class EnergyRecorder(object): + """Manage Energy recording session.""" + + logger = logging.getLogger(__name__) + # Energy recording API connectivity settings + # see load_config method + energy_recorder_api = None + + # Default initial step + INITIAL_STEP = "starting" + + @staticmethod + def load_config(): + """ + Load connectivity settings from yaml. + + Load connectivity settings to Energy recording API + Use functest global config yaml file + (see functest_utils.get_functest_config) + """ + # Singleton pattern for energy_recorder_api static member + # Load only if not previouly done + if EnergyRecorder.energy_recorder_api is None: + environment = ft_utils.get_pod_name() + + # API URL + energy_recorder_uri = ft_utils.get_functest_config( + "energy_recorder.api_url") + assert energy_recorder_uri + assert environment + + energy_recorder_uri += "/recorders/environment/" + energy_recorder_uri += urllib.quote_plus(environment) + EnergyRecorder.logger.debug( + "API recorder at: " + energy_recorder_uri) + + # Creds + user = ft_utils.get_functest_config( + "energy_recorder.api_user") + password = ft_utils.get_functest_config( + "energy_recorder.api_password") + + if user != "" and password != "": + energy_recorder_api_auth = (user, password) + else: + energy_recorder_api_auth = None + + # Final config + EnergyRecorder.energy_recorder_api = { + "uri": energy_recorder_uri, + "auth": energy_recorder_api_auth + } + + @staticmethod + def start(scenario): + """ + Start a recording session for scenario. + + param scenario: Starting scenario + :type scenario: string + """ + return_status = True + try: + EnergyRecorder.logger.debug("Starting recording") + # Ensure that connectyvity settings are loaded + EnergyRecorder.load_config() + + # Create API payload + payload = { + "step": EnergyRecorder.INITIAL_STEP, + "scenario": scenario + } + # Call API to start energy recording + response = requests.post( + EnergyRecorder.energy_recorder_api["uri"], + data=json.dumps(payload), + auth=EnergyRecorder.energy_recorder_api["auth"], + headers={ + 'content-type': 'application/json' + } + ) + if response.status_code != 200: + log_msg = "Error while starting energy recording session\n{}" + log_msg = log_msg.format(response.text) + EnergyRecorder.logger.info(log_msg) + return_status = False + + except Exception: # pylint: disable=broad-except + # Default exception handler to ensure that method + # is safe for caller + EnergyRecorder.logger.exception( + "Error while starting energy recorder API" + ) + return_status = False + return return_status + + @staticmethod + def stop(): + """Stop current recording session.""" + EnergyRecorder.logger.debug("Stopping recording") + return_status = True + try: + # Ensure that connectyvity settings are loaded + EnergyRecorder.load_config() + + # Call API to stop energy recording + response = requests.delete( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + headers={ + 'content-type': 'application/json' + } + ) + if response.status_code != 200: + log_msg = "Error while stating energy recording session\n{}" + log_msg = log_msg.format(response.text) + EnergyRecorder.logger.error(log_msg) + return_status = False + except Exception: # pylint: disable=broad-except + # Default exception handler to ensure that method + # is safe for caller + EnergyRecorder.logger.exception( + "Error while stoping energy recorder API" + ) + return_status = False + return return_status + + @staticmethod + def set_step(step): + """Notify energy recording service of current step of the testcase.""" + EnergyRecorder.logger.debug("Setting step") + return_status = True + try: + # Ensure that connectyvity settings are loaded + EnergyRecorder.load_config() + + # Create API payload + payload = { + "step": step, + } + + # Call API to define step + response = requests.post( + EnergyRecorder.energy_recorder_api["uri"] + "/step", + data=json.dumps(payload), + auth=EnergyRecorder.energy_recorder_api["auth"], + headers={ + 'content-type': 'application/json' + } + ) + if response.status_code != 200: + log_msg = "Error while setting current step of testcase\n{}" + log_msg = log_msg.format(response.text) + EnergyRecorder.logger.error(log_msg) + return_status = False + except Exception: # pylint: disable=broad-except + # Default exception handler to ensure that method + # is safe for caller + EnergyRecorder.logger.exception( + "Error while setting step on energy recorder API" + ) + return_status = False + return return_status -- cgit 1.2.3-korg