Chmod 755 functest/ci/download_images.sh
[functest.git] / functest / energy / energy.py
1 #!/usr/bin/env python
2 # -*- coding: UTF-8 -*-
3
4 # Copyright (c) 2017 Orange and others.
5 #
6 # All rights reserved. This program and the accompanying materials
7 # are made available under the terms of the Apache License, Version 2.0
8 # which accompanies this distribution, and is available at
9 # http://www.apache.org/licenses/LICENSE-2.0
10
11 """This module manages calls to Energy recording API."""
12
13 import json
14 import logging
15 import urllib
16 import requests
17
18 import functest.utils.functest_utils as ft_utils
19
20
21 def enable_recording(method):
22     """
23     Decorator to record energy during "method" exection.
24
25         param method: Method to suround with start and stop
26         :type method: function
27
28         .. note:: "method" should belong to a class having a "case_name"
29                   attribute
30     """
31     def wrapper(*args):
32         """Wrapper for decorator to handle method arguments."""
33         EnergyRecorder.start(args[0].case_name)
34         return_value = method(*args)
35         EnergyRecorder.stop()
36         return return_value
37     return wrapper
38
39
40 # Class to manage energy recording sessions
41 class EnergyRecorder(object):
42     """Manage Energy recording session."""
43
44     logger = logging.getLogger(__name__)
45     # Energy recording API connectivity settings
46     # see load_config method
47     energy_recorder_api = None
48
49     # Default initial step
50     INITIAL_STEP = "starting"
51
52     @staticmethod
53     def load_config():
54         """
55         Load connectivity settings from yaml.
56
57         Load connectivity settings to Energy recording API
58         Use functest global config yaml file
59         (see functest_utils.get_functest_config)
60         """
61         # Singleton pattern for energy_recorder_api static member
62         # Load only if not previouly done
63         if EnergyRecorder.energy_recorder_api is None:
64             environment = ft_utils.get_pod_name()
65
66             # API URL
67             energy_recorder_uri = ft_utils.get_functest_config(
68                 "energy_recorder.api_url")
69             assert energy_recorder_uri
70             assert environment
71
72             energy_recorder_uri += "/recorders/environment/"
73             energy_recorder_uri += urllib.quote_plus(environment)
74             EnergyRecorder.logger.debug(
75                 "API recorder at: " + energy_recorder_uri)
76
77             # Creds
78             user = ft_utils.get_functest_config(
79                 "energy_recorder.api_user")
80             password = ft_utils.get_functest_config(
81                 "energy_recorder.api_password")
82
83             if user != "" and password != "":
84                 energy_recorder_api_auth = (user, password)
85             else:
86                 energy_recorder_api_auth = None
87
88             # Final config
89             EnergyRecorder.energy_recorder_api = {
90                 "uri": energy_recorder_uri,
91                 "auth": energy_recorder_api_auth
92             }
93
94     @staticmethod
95     def start(scenario):
96         """
97         Start a recording session for scenario.
98
99             param scenario: Starting scenario
100             :type scenario: string
101         """
102         return_status = True
103         try:
104             EnergyRecorder.logger.debug("Starting recording")
105             # Ensure that connectyvity settings are loaded
106             EnergyRecorder.load_config()
107
108             # Create API payload
109             payload = {
110                 "step": EnergyRecorder.INITIAL_STEP,
111                 "scenario": scenario
112             }
113             # Call API to start energy recording
114             response = requests.post(
115                 EnergyRecorder.energy_recorder_api["uri"],
116                 data=json.dumps(payload),
117                 auth=EnergyRecorder.energy_recorder_api["auth"],
118                 headers={
119                     'content-type': 'application/json'
120                 }
121             )
122             if response.status_code != 200:
123                 log_msg = "Error while starting energy recording session\n{}"
124                 log_msg = log_msg.format(response.text)
125                 EnergyRecorder.logger.info(log_msg)
126                 return_status = False
127
128         except Exception:  # pylint: disable=broad-except
129             # Default exception handler to ensure that method
130             # is safe for caller
131             EnergyRecorder.logger.exception(
132                 "Error while starting energy recorder API"
133             )
134             return_status = False
135         return return_status
136
137     @staticmethod
138     def stop():
139         """Stop current recording session."""
140         EnergyRecorder.logger.debug("Stopping recording")
141         return_status = True
142         try:
143             # Ensure that connectyvity settings are loaded
144             EnergyRecorder.load_config()
145
146             # Call API to stop energy recording
147             response = requests.delete(
148                 EnergyRecorder.energy_recorder_api["uri"],
149                 auth=EnergyRecorder.energy_recorder_api["auth"],
150                 headers={
151                     'content-type': 'application/json'
152                 }
153             )
154             if response.status_code != 200:
155                 log_msg = "Error while stating energy recording session\n{}"
156                 log_msg = log_msg.format(response.text)
157                 EnergyRecorder.logger.error(log_msg)
158                 return_status = False
159         except Exception:  # pylint: disable=broad-except
160             # Default exception handler to ensure that method
161             # is safe for caller
162             EnergyRecorder.logger.exception(
163                 "Error while stoping energy recorder API"
164             )
165             return_status = False
166         return return_status
167
168     @staticmethod
169     def set_step(step):
170         """Notify energy recording service of current step of the testcase."""
171         EnergyRecorder.logger.debug("Setting step")
172         return_status = True
173         try:
174             # Ensure that connectyvity settings are loaded
175             EnergyRecorder.load_config()
176
177             # Create API payload
178             payload = {
179                 "step": step,
180             }
181
182             # Call API to define step
183             response = requests.post(
184                 EnergyRecorder.energy_recorder_api["uri"] + "/step",
185                 data=json.dumps(payload),
186                 auth=EnergyRecorder.energy_recorder_api["auth"],
187                 headers={
188                     'content-type': 'application/json'
189                 }
190             )
191             if response.status_code != 200:
192                 log_msg = "Error while setting current step of testcase\n{}"
193                 log_msg = log_msg.format(response.text)
194                 EnergyRecorder.logger.error(log_msg)
195                 return_status = False
196         except Exception:  # pylint: disable=broad-except
197             # Default exception handler to ensure that method
198             # is safe for caller
199             EnergyRecorder.logger.exception(
200                 "Error while setting step on energy recorder API"
201             )
202             return_status = False
203         return return_status