Add decorators in testcases for energy recording.
[functest.git] / functest / energy / energy.py
index a20c799..372c1d3 100644 (file)
 import json
 import logging
 import urllib
+
+from functools import wraps
 import requests
 
 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.submit_scenario(
+            current_scenario["scenario"],
+            current_scenario["step"]
+        )
+
+
 def enable_recording(method):
     """
+    Record energy during method execution.
+
     Decorator to record energy during "method" exection.
 
         param method: Method to suround with start and stop
@@ -28,11 +43,21 @@ def enable_recording(method):
         .. note:: "method" should belong to a class having a "case_name"
                   attribute
     """
+    @wraps(method)
     def wrapper(*args):
-        """Wrapper for decorator to handle method arguments."""
+        """
+        Record energy during method execution (implementation).
+
+        Wrapper for decorator to handle method arguments.
+        """
+        current_scenario = EnergyRecorder.get_current_scenario()
         EnergyRecorder.start(args[0].case_name)
-        return_value = method(*args)
-        EnergyRecorder.stop()
+        try:
+            return_value = method(*args)
+            finish_session(current_scenario)
+        except Exception:  # pylint: disable=broad-except
+            finish_session(current_scenario)
+            raise
         return return_value
     return wrapper
 
@@ -47,7 +72,7 @@ class EnergyRecorder(object):
     energy_recorder_api = None
 
     # Default initial step
-    INITIAL_STEP = "starting"
+    INITIAL_STEP = "running"
 
     @staticmethod
     def load_config():
@@ -92,22 +117,24 @@ class EnergyRecorder(object):
             }
 
     @staticmethod
-    def start(scenario):
+    def submit_scenario(scenario, step):
         """
-        Start a recording session for scenario.
+        Submit a complet scenario definition to Energy recorder API.
 
-            param scenario: Starting scenario
+            param scenario: Scenario name
             :type scenario: string
+            param step: Step name
+            :type step: string
         """
         return_status = True
         try:
-            EnergyRecorder.logger.debug("Starting recording")
+            EnergyRecorder.logger.debug("Submitting scenario")
             # Ensure that connectyvity settings are loaded
             EnergyRecorder.load_config()
 
             # Create API payload
             payload = {
-                "step": EnergyRecorder.INITIAL_STEP,
+                "step": step,
                 "scenario": scenario
             }
             # Call API to start energy recording
@@ -120,10 +147,34 @@ class EnergyRecorder(object):
                 }
             )
             if response.status_code != 200:
-                log_msg = "Error while starting energy recording session\n{}"
+                log_msg = "Error while submitting scenario\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 submitting scenarion to energy recorder API"
+            )
+            return_status = False
+        return return_status
+
+    @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")
+            return_status = EnergyRecorder.submit_scenario(
+                scenario,
+                EnergyRecorder.INITIAL_STEP
+            )
 
         except Exception:  # pylint: disable=broad-except
             # Default exception handler to ensure that method
@@ -201,3 +252,39 @@ class EnergyRecorder(object):
             )
             return_status = False
         return return_status
+
+    @staticmethod
+    def get_current_scenario():
+        """Get current running scenario (if any, None else)."""
+        EnergyRecorder.logger.debug("Getting current scenario")
+        return_value = None
+        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)
+                return_value = None
+            else:
+                log_msg = "Error while getting current scenario\n{}"
+                log_msg = log_msg.format(response.text)
+                EnergyRecorder.logger.error(log_msg)
+                return_value = None
+        except Exception:  # pylint: disable=broad-except
+            # Default exception handler to ensure that method
+            # is safe for caller
+            EnergyRecorder.logger.exception(
+                "Error while getting current scenario from energy recorder API"
+            )
+            return_value = None
+        return return_value