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
21 import functest.utils.functest_utils as ft_utils
24 def finish_session(current_scenario):
25 """Finish a recording session."""
26 if current_scenario is None:
29 EnergyRecorder.submit_scenario(
30 current_scenario["scenario"],
31 current_scenario["step"]
35 def enable_recording(method):
37 Record energy during method execution.
39 Decorator to record energy during "method" exection.
41 param method: Method to suround with start and stop
42 :type method: function
44 .. note:: "method" should belong to a class having a "case_name"
50 Record energy during method execution (implementation).
52 Wrapper for decorator to handle method arguments.
54 current_scenario = EnergyRecorder.get_current_scenario()
55 EnergyRecorder.start(args[0].case_name)
57 return_value = method(*args)
58 finish_session(current_scenario)
59 except Exception as exc: # pylint: disable=broad-except
60 EnergyRecorder.logger.exception(exc)
61 finish_session(current_scenario)
67 # Class to manage energy recording sessions
68 class EnergyRecorder(object):
69 """Manage Energy recording session."""
71 logger = logging.getLogger(__name__)
72 # Energy recording API connectivity settings
73 # see load_config method
74 energy_recorder_api = None
76 # Default initial step
77 INITIAL_STEP = "running"
79 # Default connection timeout
80 CONNECTION_TIMOUT = urllib3.Timeout(connect=1, read=3)
85 Load connectivity settings from yaml.
87 Load connectivity settings to Energy recording API
88 Use functest global config yaml file
89 (see functest_utils.get_functest_config)
91 # Singleton pattern for energy_recorder_api static member
92 # Load only if not previouly done
93 if EnergyRecorder.energy_recorder_api is None:
94 environment = ft_utils.get_pod_name()
97 energy_recorder_uri = ft_utils.get_functest_config(
98 "energy_recorder.api_url")
99 assert energy_recorder_uri
102 uri_comp = "/recorders/environment/"
103 uri_comp += urllib.quote_plus(environment)
104 EnergyRecorder.logger.debug(
105 "API recorder at: " + energy_recorder_uri + uri_comp)
108 creds_usr = ft_utils.get_functest_config(
109 "energy_recorder.api_user")
110 creds_pass = ft_utils.get_functest_config(
111 "energy_recorder.api_password")
113 if creds_usr != "" and creds_pass != "":
114 energy_recorder_api_auth = (creds_usr, creds_pass)
116 energy_recorder_api_auth = None
119 resp = requests.get(energy_recorder_uri + "/monitoring/ping",
120 auth=energy_recorder_api_auth,
122 'content-type': 'application/json'
124 timeout=EnergyRecorder.CONNECTION_TIMOUT)
125 api_available = json.loads(resp.text)["status"] == "OK"
126 except Exception: # pylint: disable=broad-except
127 EnergyRecorder.logger.error(
128 "Energy recorder API is not available")
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")
159 # Call API to start energy recording
160 response = requests.post(
161 EnergyRecorder.energy_recorder_api["uri"],
162 data=json.dumps(payload),
163 auth=EnergyRecorder.energy_recorder_api["auth"],
165 'content-type': 'application/json'
167 timeout=EnergyRecorder.CONNECTION_TIMOUT
169 if response.status_code != 200:
170 EnergyRecorder.logger.error(
171 "Error while submitting scenario\n%s",
173 return_status = False
174 except requests.exceptions.ConnectionError:
175 EnergyRecorder.logger.warning(
176 "submit_scenario: Unable to connect energy recorder API")
177 return_status = False
178 except Exception: # pylint: disable=broad-except
179 # Default exception handler to ensure that method
181 EnergyRecorder.logger.exception(
182 "Error while submitting scenarion to energy recorder API"
184 return_status = False
190 Start a recording session for scenario.
192 param scenario: Starting scenario
193 :type scenario: string
197 if EnergyRecorder.load_config():
198 EnergyRecorder.logger.debug("Starting recording")
199 return_status = EnergyRecorder.submit_scenario(
201 EnergyRecorder.INITIAL_STEP
204 except Exception: # pylint: disable=broad-except
205 # Default exception handler to ensure that method
207 EnergyRecorder.logger.exception(
208 "Error while starting energy recorder API"
210 return_status = False
215 """Stop current recording session."""
218 # Ensure that connectyvity settings are loaded
219 if EnergyRecorder.load_config():
220 EnergyRecorder.logger.debug("Stopping recording")
222 # Call API to stop energy recording
223 response = requests.delete(
224 EnergyRecorder.energy_recorder_api["uri"],
225 auth=EnergyRecorder.energy_recorder_api["auth"],
227 'content-type': 'application/json'
229 timeout=EnergyRecorder.CONNECTION_TIMOUT
231 if response.status_code != 200:
232 EnergyRecorder.logger.error(
233 "Error while stating energy recording session\n%s",
235 return_status = False
236 except requests.exceptions.ConnectionError:
237 EnergyRecorder.logger.warning(
238 "stop: Unable to connect energy recorder API")
239 return_status = False
240 except Exception: # pylint: disable=broad-except
241 # Default exception handler to ensure that method
243 EnergyRecorder.logger.exception(
244 "Error while stoping energy recorder API"
246 return_status = False
251 """Notify energy recording service of current step of the testcase."""
254 # Ensure that connectyvity settings are loaded
255 if EnergyRecorder.load_config():
256 EnergyRecorder.logger.debug("Setting step")
263 # Call API to define step
264 response = requests.post(
265 EnergyRecorder.energy_recorder_api["uri"] + "/step",
266 data=json.dumps(payload),
267 auth=EnergyRecorder.energy_recorder_api["auth"],
269 'content-type': 'application/json'
271 timeout=EnergyRecorder.CONNECTION_TIMOUT
273 if response.status_code != 200:
274 EnergyRecorder.logger.error(
275 "Error while setting current step of testcase\n%s",
277 return_status = False
278 except requests.exceptions.ConnectionError:
279 EnergyRecorder.logger.warning(
280 "set_step: Unable to connect energy recorder API")
281 return_status = False
282 except Exception: # pylint: disable=broad-except
283 # Default exception handler to ensure that method
285 EnergyRecorder.logger.exception(
286 "Error while setting step on energy recorder API"
288 return_status = False
292 def get_current_scenario():
293 """Get current running scenario (if any, None else)."""
296 # Ensure that connectyvity settings are loaded
297 if EnergyRecorder.load_config():
298 EnergyRecorder.logger.debug("Getting current scenario")
300 # Call API get running scenario
301 response = requests.get(
302 EnergyRecorder.energy_recorder_api["uri"],
303 auth=EnergyRecorder.energy_recorder_api["auth"],
304 timeout=EnergyRecorder.CONNECTION_TIMOUT
306 if response.status_code == 200:
307 return_value = json.loads(response.text)
308 elif response.status_code == 404:
309 EnergyRecorder.logger.info(
310 "No current running scenario at %s",
311 EnergyRecorder.energy_recorder_api["uri"])
314 EnergyRecorder.logger.error(
315 "Error while getting current scenario\n%s",
318 except requests.exceptions.ConnectionError:
319 EnergyRecorder.logger.warning(
320 "get_currernt_sceario: Unable to connect energy recorder API")
322 except Exception: # pylint: disable=broad-except
323 # Default exception handler to ensure that method
325 EnergyRecorder.logger.exception(
326 "Error while getting current scenario from energy recorder API"