X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=functest%2Fenergy%2Fenergy.py;h=a26522119db48c94cc959a0fc063c59be3e5b355;hb=67363022f2139fea4049743bc00b32cf8e5f453e;hp=71b7123930ed78df34f3db3203b1bbee2fd56f3a;hpb=c14a40a88ff496f981e61837f605027e65b2c345;p=functest.git diff --git a/functest/energy/energy.py b/functest/energy/energy.py index 71b712393..a26522119 100644 --- a/functest/energy/energy.py +++ b/functest/energy/energy.py @@ -12,10 +12,27 @@ import json import logging -import urllib +import traceback + +from functools import wraps import requests +from six.moves import urllib + +from functest.utils import env -import functest.utils.functest_utils as ft_utils + +def finish_session(current_scenario): + """Finish a recording session.""" + if current_scenario is None: + EnergyRecorder.stop() + else: + EnergyRecorder.logger.debug("Restoring previous scenario (%s/%s)", + current_scenario["scenario"], + current_scenario["step"]) + EnergyRecorder.submit_scenario( + current_scenario["scenario"], + current_scenario["step"] + ) def enable_recording(method): @@ -30,6 +47,7 @@ def enable_recording(method): .. note:: "method" should belong to a class having a "case_name" attribute """ + @wraps(method) def wrapper(*args): """ Record energy during method execution (implementation). @@ -38,14 +56,13 @@ def enable_recording(method): """ current_scenario = EnergyRecorder.get_current_scenario() EnergyRecorder.start(args[0].case_name) - return_value = method(*args) - if current_scenario is None: - EnergyRecorder.stop() - else: - EnergyRecorder.submit_scenario( - current_scenario["scenario"], - current_scenario["step"] - ) + try: + return_value = method(*args) + finish_session(current_scenario) + except Exception as exc: # pylint: disable=broad-except + EnergyRecorder.logger.exception(exc) + finish_session(current_scenario) + raise exc return return_value return wrapper @@ -62,6 +79,9 @@ class EnergyRecorder(object): # Default initial step INITIAL_STEP = "running" + # Default connection timeout + CONNECTION_TIMEOUT = 4 + @staticmethod def load_config(): """ @@ -74,35 +94,47 @@ class EnergyRecorder(object): # 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) + assert env.get('NODE_NAME') + assert env.get('ENERGY_RECORDER_API_URL') + environment = env.get('NODE_NAME') + energy_recorder_uri = env.get( + 'ENERGY_RECORDER_API_URL') # Creds - user = ft_utils.get_functest_config( - "energy_recorder.api_user") - password = ft_utils.get_functest_config( - "energy_recorder.api_password") + creds_usr = env.get("ENERGY_RECORDER_API_USER") + creds_pass = env.get("ENERGY_RECORDER_API_PASSWORD") + + uri_comp = "/recorders/environment/" + uri_comp += urllib.parse.quote_plus(environment) - if user != "" and password != "": - energy_recorder_api_auth = (user, password) + if creds_usr and creds_pass: + energy_recorder_api_auth = (creds_usr, creds_pass) else: energy_recorder_api_auth = None + try: + resp = requests.get(energy_recorder_uri + "/monitoring/ping", + auth=energy_recorder_api_auth, + headers={ + 'content-type': 'application/json' + }, + timeout=EnergyRecorder.CONNECTION_TIMEOUT) + api_available = json.loads(resp.text)["status"] == "OK" + EnergyRecorder.logger.info( + "API recorder available at : %s", + energy_recorder_uri + uri_comp) + except Exception as exc: # pylint: disable=broad-except + EnergyRecorder.logger.info( + "Energy recorder API is not available, cause=%s", + str(exc)) + api_available = False # Final config EnergyRecorder.energy_recorder_api = { - "uri": energy_recorder_uri, - "auth": energy_recorder_api_auth + "uri": energy_recorder_uri + uri_comp, + "auth": energy_recorder_api_auth, + "available": api_available } + return EnergyRecorder.energy_recorder_api["available"] @staticmethod def submit_scenario(scenario, step): @@ -114,36 +146,43 @@ class EnergyRecorder(object): param step: Step name :type step: string """ - return_status = True try: - EnergyRecorder.logger.debug("Submitting scenario") + return_status = True # Ensure that connectyvity settings are loaded - EnergyRecorder.load_config() - - # Create API payload - payload = { - "step": 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 EnergyRecorder.load_config(): + EnergyRecorder.logger.debug("Submitting scenario (%s/%s)", + scenario, step) + + # Create API payload + payload = { + "step": step, + "scenario": scenario } - ) - if response.status_code != 200: - log_msg = "Error while submitting scenario\n{}" - log_msg = log_msg.format(response.text) - EnergyRecorder.logger.info(log_msg) - return_status = False + # 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' + }, + timeout=EnergyRecorder.CONNECTION_TIMEOUT + ) + if response.status_code != 200: + EnergyRecorder.logger.error( + "Error while submitting scenario\n%s", + response.text) + return_status = False + except requests.exceptions.ConnectionError: + EnergyRecorder.logger.warning( + "submit_scenario: Unable to connect energy recorder API") + 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 submitting scenarion to energy recorder API" + EnergyRecorder.logger.info( + "Error while submitting scenarion to energy recorder API\n%s", + traceback.format_exc() ) return_status = False return return_status @@ -158,17 +197,19 @@ class EnergyRecorder(object): """ return_status = True try: - EnergyRecorder.logger.debug("Starting recording") - return_status = EnergyRecorder.submit_scenario( - scenario, - EnergyRecorder.INITIAL_STEP - ) + if EnergyRecorder.load_config(): + EnergyRecorder.logger.debug("Starting recording") + return_status = EnergyRecorder.submit_scenario( + scenario, + EnergyRecorder.INITIAL_STEP + ) 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" + EnergyRecorder.logger.info( + "Error while starting energy recorder API\n%s", + traceback.format_exc() ) return_status = False return return_status @@ -176,30 +217,36 @@ class EnergyRecorder(object): @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 + if EnergyRecorder.load_config(): + EnergyRecorder.logger.debug("Stopping recording") + + # 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' + }, + timeout=EnergyRecorder.CONNECTION_TIMEOUT + ) + if response.status_code != 200: + EnergyRecorder.logger.error( + "Error while stating energy recording session\n%s", + response.text) + return_status = False + except requests.exceptions.ConnectionError: + EnergyRecorder.logger.warning( + "stop: Unable to connect energy recorder API") + 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" + EnergyRecorder.logger.info( + "Error while stoping energy recorder API\n%s", + traceback.format_exc() ) return_status = False return return_status @@ -207,36 +254,42 @@ class EnergyRecorder(object): @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() + if EnergyRecorder.load_config(): + EnergyRecorder.logger.debug("Setting step") - # 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' + # Create API payload + payload = { + "step": step, } - ) - 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 + + # 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' + }, + timeout=EnergyRecorder.CONNECTION_TIMEOUT + ) + if response.status_code != 200: + EnergyRecorder.logger.error( + "Error while setting current step of testcase\n%s", + response.text) + return_status = False + except requests.exceptions.ConnectionError: + EnergyRecorder.logger.warning( + "set_step: Unable to connect energy recorder API") + 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" + EnergyRecorder.logger.info( + "Error while setting step on energy recorder API\n%s", + traceback.format_exc() ) return_status = False return return_status @@ -244,38 +297,40 @@ class EnergyRecorder(object): @staticmethod def get_current_scenario(): """Get current running scenario (if any, None else).""" - EnergyRecorder.logger.debug("Getting current scenario") return_value = None - print "In get current" try: # Ensure that connectyvity settings are loaded - EnergyRecorder.load_config() - - # Call API get running scenario - response = requests.get( - EnergyRecorder.energy_recorder_api["uri"], - auth=EnergyRecorder.energy_recorder_api["auth"] - ) - if response.status_code == 200: - return_value = json.loads(response.text) - elif response.status_code == 404: - log_msg = "No current running scenario at {}" - log_msg = log_msg.format( - EnergyRecorder.energy_recorder_api["uri"]) - EnergyRecorder.logger.error(log_msg) - print log_msg - return_value = None - else: - log_msg = "Error while getting current scenario\n{}" - log_msg = log_msg.format(response.text) - EnergyRecorder.logger.error(log_msg) - print log_msg - return_value = None + if EnergyRecorder.load_config(): + EnergyRecorder.logger.debug("Getting current scenario") + + # Call API get running scenario + response = requests.get( + EnergyRecorder.energy_recorder_api["uri"], + auth=EnergyRecorder.energy_recorder_api["auth"], + timeout=EnergyRecorder.CONNECTION_TIMEOUT + ) + if response.status_code == 200: + return_value = json.loads(response.text) + elif response.status_code == 404: + EnergyRecorder.logger.info( + "No current running scenario at %s", + EnergyRecorder.energy_recorder_api["uri"]) + return_value = None + else: + EnergyRecorder.logger.error( + "Error while getting current scenario\n%s", + response.text) + return_value = None + except requests.exceptions.ConnectionError: + EnergyRecorder.logger.warning( + "get_currernt_sceario: Unable to connect energy recorder API") + return_value = None except Exception: # pylint: disable=broad-except # Default exception handler to ensure that method # is safe for caller - EnergyRecorder.logger.exception( + EnergyRecorder.logger.info( "Error while getting current scenario from energy recorder API" + "\n%s", traceback.format_exc() ) return_value = None return return_value