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 from functest.utils.constants import CONST
22 import functest.utils.functest_utils as ft_utils
25 def finish_session(current_scenario):
26 """Finish a recording session."""
27 if current_scenario is None:
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 = urllib3.Timeout(connect=1, read=3)
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 = CONST.__getattribute__('NODE_NAME')
98 energy_recorder_uri = ft_utils.get_functest_config(
99 "energy_recorder.api_url")
100 assert energy_recorder_uri
103 uri_comp = "/recorders/environment/"
104 uri_comp += urllib.quote_plus(environment)
105 EnergyRecorder.logger.debug(
106 "API recorder at: " + energy_recorder_uri + uri_comp)
109 creds_usr = ft_utils.get_functest_config(
110 "energy_recorder.api_user")
111 creds_pass = ft_utils.get_functest_config(
112 "energy_recorder.api_password")
114 if creds_usr != "" and creds_pass != "":
115 energy_recorder_api_auth = (creds_usr, creds_pass)
117 energy_recorder_api_auth = None
120 resp = requests.get(energy_recorder_uri + "/monitoring/ping",
121 auth=energy_recorder_api_auth,
123 'content-type': 'application/json'
125 timeout=EnergyRecorder.CONNECTION_TIMEOUT)
126 api_available = json.loads(resp.text)["status"] == "OK"
127 except Exception as exc: # pylint: disable=broad-except
128 EnergyRecorder.logger.info(
129 "Energy recorder API is not available, cause=%s",
131 api_available = False
133 EnergyRecorder.energy_recorder_api = {
134 "uri": energy_recorder_uri + uri_comp,
135 "auth": energy_recorder_api_auth,
136 "available": api_available
138 return EnergyRecorder.energy_recorder_api["available"]
141 def submit_scenario(scenario, step):
143 Submit a complet scenario definition to Energy recorder API.
145 param scenario: Scenario name
146 :type scenario: string
147 param step: Step name
152 # Ensure that connectyvity settings are loaded
153 if EnergyRecorder.load_config():
154 EnergyRecorder.logger.debug("Submitting scenario")
161 # Call API to start energy recording
162 response = requests.post(
163 EnergyRecorder.energy_recorder_api["uri"],
164 data=json.dumps(payload),
165 auth=EnergyRecorder.energy_recorder_api["auth"],
167 'content-type': 'application/json'
169 timeout=EnergyRecorder.CONNECTION_TIMEOUT
171 if response.status_code != 200:
172 EnergyRecorder.logger.error(
173 "Error while submitting scenario\n%s",
175 return_status = False
176 except requests.exceptions.ConnectionError:
177 EnergyRecorder.logger.warning(
178 "submit_scenario: Unable to connect energy recorder API")
179 return_status = False
180 except Exception: # pylint: disable=broad-except
181 # Default exception handler to ensure that method
183 EnergyRecorder.logger.exception(
184 "Error while submitting scenarion to energy recorder API"
186 return_status = False
192 Start a recording session for scenario.
194 param scenario: Starting scenario
195 :type scenario: string
199 if EnergyRecorder.load_config():
200 EnergyRecorder.logger.debug("Starting recording")
201 return_status = EnergyRecorder.submit_scenario(
203 EnergyRecorder.INITIAL_STEP
206 except Exception: # pylint: disable=broad-except
207 # Default exception handler to ensure that method
209 EnergyRecorder.logger.exception(
210 "Error while starting energy recorder API"
212 return_status = False
217 """Stop current recording session."""
220 # Ensure that connectyvity settings are loaded
221 if EnergyRecorder.load_config():
222 EnergyRecorder.logger.debug("Stopping recording")
224 # Call API to stop energy recording
225 response = requests.delete(
226 EnergyRecorder.energy_recorder_api["uri"],
227 auth=EnergyRecorder.energy_recorder_api["auth"],
229 'content-type': 'application/json'
231 timeout=EnergyRecorder.CONNECTION_TIMEOUT
233 if response.status_code != 200:
234 EnergyRecorder.logger.error(
235 "Error while stating energy recording session\n%s",
237 return_status = False
238 except requests.exceptions.ConnectionError:
239 EnergyRecorder.logger.warning(
240 "stop: Unable to connect energy recorder API")
241 return_status = False
242 except Exception: # pylint: disable=broad-except
243 # Default exception handler to ensure that method
245 EnergyRecorder.logger.exception(
246 "Error while stoping energy recorder API"
248 return_status = False
253 """Notify energy recording service of current step of the testcase."""
256 # Ensure that connectyvity settings are loaded
257 if EnergyRecorder.load_config():
258 EnergyRecorder.logger.debug("Setting step")
265 # Call API to define step
266 response = requests.post(
267 EnergyRecorder.energy_recorder_api["uri"] + "/step",
268 data=json.dumps(payload),
269 auth=EnergyRecorder.energy_recorder_api["auth"],
271 'content-type': 'application/json'
273 timeout=EnergyRecorder.CONNECTION_TIMEOUT
275 if response.status_code != 200:
276 EnergyRecorder.logger.error(
277 "Error while setting current step of testcase\n%s",
279 return_status = False
280 except requests.exceptions.ConnectionError:
281 EnergyRecorder.logger.warning(
282 "set_step: Unable to connect energy recorder API")
283 return_status = False
284 except Exception: # pylint: disable=broad-except
285 # Default exception handler to ensure that method
287 EnergyRecorder.logger.exception(
288 "Error while setting step on energy recorder API"
290 return_status = False
294 def get_current_scenario():
295 """Get current running scenario (if any, None else)."""
298 # Ensure that connectyvity settings are loaded
299 if EnergyRecorder.load_config():
300 EnergyRecorder.logger.debug("Getting current scenario")
302 # Call API get running scenario
303 response = requests.get(
304 EnergyRecorder.energy_recorder_api["uri"],
305 auth=EnergyRecorder.energy_recorder_api["auth"],
306 timeout=EnergyRecorder.CONNECTION_TIMEOUT
308 if response.status_code == 200:
309 return_value = json.loads(response.text)
310 elif response.status_code == 404:
311 EnergyRecorder.logger.info(
312 "No current running scenario at %s",
313 EnergyRecorder.energy_recorder_api["uri"])
316 EnergyRecorder.logger.error(
317 "Error while getting current scenario\n%s",
320 except requests.exceptions.ConnectionError:
321 EnergyRecorder.logger.warning(
322 "get_currernt_sceario: Unable to connect energy recorder API")
324 except Exception: # pylint: disable=broad-except
325 # Default exception handler to ensure that method
327 EnergyRecorder.logger.exception(
328 "Error while getting current scenario from energy recorder API"