2 # -*- coding: UTF-8 -*-
4 # Copyright (c) 2017 Orange and others.
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
11 """This module manages calls to Energy recording API."""
17 from functools import wraps
19 from six.moves import urllib
22 def finish_session(current_scenario):
23 """Finish a recording session."""
24 if current_scenario is None:
27 EnergyRecorder.logger.debug("Restoring previous scenario (%s/%s)",
28 current_scenario["scenario"],
29 current_scenario["step"])
30 EnergyRecorder.submit_scenario(
31 current_scenario["scenario"],
32 current_scenario["step"]
36 def enable_recording(method):
38 Record energy during method execution.
40 Decorator to record energy during "method" exection.
42 param method: Method to suround with start and stop
43 :type method: function
45 .. note:: "method" should belong to a class having a "case_name"
51 Record energy during method execution (implementation).
53 Wrapper for decorator to handle method arguments.
55 current_scenario = EnergyRecorder.get_current_scenario()
56 EnergyRecorder.start(args[0].case_name)
58 return_value = method(*args)
59 finish_session(current_scenario)
60 except Exception as exc: # pylint: disable=broad-except
61 EnergyRecorder.logger.exception(exc)
62 finish_session(current_scenario)
68 # Class to manage energy recording sessions
69 class EnergyRecorder(object):
70 """Manage Energy recording session."""
72 logger = logging.getLogger(__name__)
73 # Energy recording API connectivity settings
74 # see load_config method
75 energy_recorder_api = None
77 # Default initial step
78 INITIAL_STEP = "running"
80 # Default connection timeout
81 CONNECTION_TIMEOUT = 4
86 Load connectivity settings from yaml.
88 Load connectivity settings to Energy recording API
89 Use functest global config yaml file
90 (see functest_utils.get_functest_config)
92 # Singleton pattern for energy_recorder_api static member
93 # Load only if not previouly done
94 if EnergyRecorder.energy_recorder_api is None:
95 environment = os.environ['NODE_NAME']
99 energy_recorder_uri = os.environ["ENERGY_RECORDER_API_URL"]
100 assert energy_recorder_uri
103 creds_usr = os.environ.get("ENERGY_RECORDER_API_USER", "")
104 creds_pass = os.environ.get("ENERGY_RECORDER_API_PASSWORD", "")
106 uri_comp = "/recorders/environment/"
107 uri_comp += urllib.parse.quote_plus(environment)
109 if creds_usr != "" and creds_pass != "":
110 energy_recorder_api_auth = (creds_usr, creds_pass)
112 energy_recorder_api_auth = None
115 resp = requests.get(energy_recorder_uri + "/monitoring/ping",
116 auth=energy_recorder_api_auth,
118 'content-type': 'application/json'
120 timeout=EnergyRecorder.CONNECTION_TIMEOUT)
121 api_available = json.loads(resp.text)["status"] == "OK"
122 EnergyRecorder.logger.info(
123 "API recorder available at : %s",
124 energy_recorder_uri + uri_comp)
125 except Exception as exc: # pylint: disable=broad-except
126 EnergyRecorder.logger.info(
127 "Energy recorder API is not available, cause=%s",
129 api_available = False
131 EnergyRecorder.energy_recorder_api = {
132 "uri": energy_recorder_uri + uri_comp,
133 "auth": energy_recorder_api_auth,
134 "available": api_available
136 return EnergyRecorder.energy_recorder_api["available"]
139 def submit_scenario(scenario, step):
141 Submit a complet scenario definition to Energy recorder API.
143 param scenario: Scenario name
144 :type scenario: string
145 param step: Step name
150 # Ensure that connectyvity settings are loaded
151 if EnergyRecorder.load_config():
152 EnergyRecorder.logger.debug("Submitting scenario (%s/%s)",
160 # Call API to start energy recording
161 response = requests.post(
162 EnergyRecorder.energy_recorder_api["uri"],
163 data=json.dumps(payload),
164 auth=EnergyRecorder.energy_recorder_api["auth"],
166 'content-type': 'application/json'
168 timeout=EnergyRecorder.CONNECTION_TIMEOUT
170 if response.status_code != 200:
171 EnergyRecorder.logger.error(
172 "Error while submitting scenario\n%s",
174 return_status = False
175 except requests.exceptions.ConnectionError:
176 EnergyRecorder.logger.warning(
177 "submit_scenario: Unable to connect energy recorder API")
178 return_status = False
179 except Exception: # pylint: disable=broad-except
180 # Default exception handler to ensure that method
182 EnergyRecorder.logger.exception(
183 "Error while submitting scenarion to energy recorder API"
185 return_status = False
191 Start a recording session for scenario.
193 param scenario: Starting scenario
194 :type scenario: string
198 if EnergyRecorder.load_config():
199 EnergyRecorder.logger.debug("Starting recording")
200 return_status = EnergyRecorder.submit_scenario(
202 EnergyRecorder.INITIAL_STEP
205 except Exception: # pylint: disable=broad-except
206 # Default exception handler to ensure that method
208 EnergyRecorder.logger.exception(
209 "Error while starting energy recorder API"
211 return_status = False
216 """Stop current recording session."""
219 # Ensure that connectyvity settings are loaded
220 if EnergyRecorder.load_config():
221 EnergyRecorder.logger.debug("Stopping recording")
223 # Call API to stop energy recording
224 response = requests.delete(
225 EnergyRecorder.energy_recorder_api["uri"],
226 auth=EnergyRecorder.energy_recorder_api["auth"],
228 'content-type': 'application/json'
230 timeout=EnergyRecorder.CONNECTION_TIMEOUT
232 if response.status_code != 200:
233 EnergyRecorder.logger.error(
234 "Error while stating energy recording session\n%s",
236 return_status = False
237 except requests.exceptions.ConnectionError:
238 EnergyRecorder.logger.warning(
239 "stop: Unable to connect energy recorder API")
240 return_status = False
241 except Exception: # pylint: disable=broad-except
242 # Default exception handler to ensure that method
244 EnergyRecorder.logger.exception(
245 "Error while stoping energy recorder API"
247 return_status = False
252 """Notify energy recording service of current step of the testcase."""
255 # Ensure that connectyvity settings are loaded
256 if EnergyRecorder.load_config():
257 EnergyRecorder.logger.debug("Setting step")
264 # Call API to define step
265 response = requests.post(
266 EnergyRecorder.energy_recorder_api["uri"] + "/step",
267 data=json.dumps(payload),
268 auth=EnergyRecorder.energy_recorder_api["auth"],
270 'content-type': 'application/json'
272 timeout=EnergyRecorder.CONNECTION_TIMEOUT
274 if response.status_code != 200:
275 EnergyRecorder.logger.error(
276 "Error while setting current step of testcase\n%s",
278 return_status = False
279 except requests.exceptions.ConnectionError:
280 EnergyRecorder.logger.warning(
281 "set_step: Unable to connect energy recorder API")
282 return_status = False
283 except Exception: # pylint: disable=broad-except
284 # Default exception handler to ensure that method
286 EnergyRecorder.logger.exception(
287 "Error while setting step on energy recorder API"
289 return_status = False
293 def get_current_scenario():
294 """Get current running scenario (if any, None else)."""
297 # Ensure that connectyvity settings are loaded
298 if EnergyRecorder.load_config():
299 EnergyRecorder.logger.debug("Getting current scenario")
301 # Call API get running scenario
302 response = requests.get(
303 EnergyRecorder.energy_recorder_api["uri"],
304 auth=EnergyRecorder.energy_recorder_api["auth"],
305 timeout=EnergyRecorder.CONNECTION_TIMEOUT
307 if response.status_code == 200:
308 return_value = json.loads(response.text)
309 elif response.status_code == 404:
310 EnergyRecorder.logger.info(
311 "No current running scenario at %s",
312 EnergyRecorder.energy_recorder_api["uri"])
315 EnergyRecorder.logger.error(
316 "Error while getting current scenario\n%s",
319 except requests.exceptions.ConnectionError:
320 EnergyRecorder.logger.warning(
321 "get_currernt_sceario: Unable to connect energy recorder API")
323 except Exception: # pylint: disable=broad-except
324 # Default exception handler to ensure that method
326 EnergyRecorder.logger.exception(
327 "Error while getting current scenario from energy recorder API"