8955f3cb6ce83851e42dae1033ba8afe17cb4daf
[yardstick.git] / api / resources / env_action.py
1 ##############################################################################
2 # Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9 from __future__ import absolute_import
10
11 import errno
12 import json
13 import logging
14 import os
15 import subprocess
16 import threading
17 import time
18 import uuid
19
20 from six.moves import configparser
21
22 from api import conf as api_conf
23 from api.database.handler import AsyncTaskHandler
24 from api.utils import influx
25 from api.utils.common import result_handler
26 from docker import Client
27 from yardstick.common import constants as config
28 from yardstick.common import utils as yardstick_utils
29 from yardstick.common.httpClient import HttpClient
30
31 logger = logging.getLogger(__name__)
32 logger.setLevel(logging.DEBUG)
33
34
35 def createGrafanaContainer(args):
36     task_id = str(uuid.uuid4())
37
38     thread = threading.Thread(target=_create_grafana, args=(task_id,))
39     thread.start()
40
41     return result_handler('success', {'task_id': task_id})
42
43
44 def _create_grafana(task_id):
45     _create_task(task_id)
46
47     client = Client(base_url=config.DOCKER_URL)
48
49     try:
50         if not _check_image_exist(client, '%s:%s' % (config.GRAFANA_IMAGE,
51                                                      config.GRAFANA_TAGS)):
52             client.pull(config.GRAFANA_IMAGE, config.GRAFANA_TAGS)
53
54         _create_grafana_container(client)
55
56         time.sleep(5)
57
58         _create_data_source()
59
60         _create_dashboard()
61
62         _update_task_status(task_id)
63     except Exception as e:
64         _update_task_error(task_id, str(e))
65         logger.debug('Error: %s', e)
66
67
68 def _create_dashboard():
69     url = 'http://admin:admin@%s:3000/api/dashboards/db' % api_conf.GATEWAY_IP
70     with open('../dashboard/ping_dashboard.json') as dashboard_json:
71         data = json.load(dashboard_json)
72     HttpClient().post(url, data)
73
74
75 def _create_data_source():
76     url = 'http://admin:admin@%s:3000/api/datasources' % api_conf.GATEWAY_IP
77     data = {
78         "name": "yardstick",
79         "type": "influxdb",
80         "access": "proxy",
81         "url": "http://%s:8086" % api_conf.GATEWAY_IP,
82         "password": "root",
83         "user": "root",
84         "database": "yardstick",
85         "basicAuth": True,
86         "basicAuthUser": "admin",
87         "basicAuthPassword": "admin",
88         "isDefault": False,
89     }
90     HttpClient().post(url, data)
91
92
93 def _create_grafana_container(client):
94     ports = [3000]
95     port_bindings = {k: k for k in ports}
96     host_config = client.create_host_config(port_bindings=port_bindings)
97
98     container = client.create_container(image='%s:%s' % (config.GRAFANA_IMAGE,
99                                                          config.GRAFANA_TAGS),
100                                         ports=ports,
101                                         detach=True,
102                                         tty=True,
103                                         host_config=host_config)
104     client.start(container)
105
106
107 def _check_image_exist(client, t):
108     return any(t in a['RepoTags'][0] for a in client.images() if a['RepoTags'])
109
110
111 def createInfluxDBContainer(args):
112     task_id = str(uuid.uuid4())
113
114     thread = threading.Thread(target=_create_influxdb, args=(task_id,))
115     thread.start()
116
117     return result_handler('success', {'task_id': task_id})
118
119
120 def _create_influxdb(task_id):
121     _create_task(task_id)
122
123     client = Client(base_url=config.DOCKER_URL)
124
125     try:
126         _change_output_to_influxdb()
127
128         if not _check_image_exist(client, '%s:%s' % (config.INFLUXDB_IMAGE,
129                                                      config.INFLUXDB_TAG)):
130             client.pull(config.INFLUXDB_IMAGE, tag=config.INFLUXDB_TAG)
131
132         _create_influxdb_container(client)
133
134         time.sleep(5)
135
136         _config_influxdb()
137
138         _update_task_status(task_id)
139     except Exception as e:
140         _update_task_error(task_id, str(e))
141         logger.debug('Error: %s', e)
142
143
144 def _create_influxdb_container(client):
145
146     ports = [8083, 8086]
147     port_bindings = {k: k for k in ports}
148     host_config = client.create_host_config(port_bindings=port_bindings)
149
150     container = client.create_container(image='%s:%s' % (config.INFLUXDB_IMAGE,
151                                                          config.INFLUXDB_TAG),
152                                         ports=ports,
153                                         detach=True,
154                                         tty=True,
155                                         host_config=host_config)
156     client.start(container)
157
158
159 def _config_influxdb():
160     try:
161         client = influx.get_data_db_client()
162         client.create_user(config.USER, config.PASSWORD, config.DATABASE)
163         client.create_database(config.DATABASE)
164         logger.info('Success to config influxDB')
165     except Exception as e:
166         logger.debug('Failed to config influxDB: %s', e)
167
168
169 def _change_output_to_influxdb():
170     yardstick_utils.makedirs(config.YARDSTICK_CONFIG_DIR)
171
172     parser = configparser.ConfigParser()
173     parser.read(config.YARDSTICK_CONFIG_SAMPLE_FILE)
174
175     parser.set('DEFAULT', 'dispatcher', 'influxdb')
176     parser.set('dispatcher_influxdb', 'target',
177                'http://%s:8086' % api_conf.GATEWAY_IP)
178
179     with open(config.YARDSTICK_CONFIG_FILE, 'w') as f:
180         parser.write(f)
181
182
183 def prepareYardstickEnv(args):
184     task_id = str(uuid.uuid4())
185
186     thread = threading.Thread(target=_prepare_env_daemon, args=(task_id,))
187     thread.start()
188
189     return result_handler('success', {'task_id': task_id})
190
191
192 def _prepare_env_daemon(task_id):
193     _create_task(task_id)
194
195     installer_ip = os.environ.get('INSTALLER_IP', 'undefined')
196     installer_type = os.environ.get('INSTALLER_TYPE', 'undefined')
197
198     try:
199         _check_variables(installer_ip, installer_type)
200
201         _create_directories()
202
203         rc_file = config.OPENSTACK_RC_FILE
204
205         _get_remote_rc_file(rc_file, installer_ip, installer_type)
206
207         _source_file(rc_file)
208
209         _append_external_network(rc_file)
210
211         # update the external_network
212         _source_file(rc_file)
213
214         _clean_images()
215
216         _load_images()
217
218         _update_task_status(task_id)
219     except Exception as e:
220         _update_task_error(task_id, str(e))
221         logger.debug('Error: %s', e)
222
223
224 def _check_variables(installer_ip, installer_type):
225
226     if installer_ip == 'undefined':
227         raise SystemExit('Missing INSTALLER_IP')
228
229     if installer_type == 'undefined':
230         raise SystemExit('Missing INSTALLER_TYPE')
231     elif installer_type not in config.INSTALLERS:
232         raise SystemExit('INSTALLER_TYPE is not correct')
233
234
235 def _create_directories():
236     yardstick_utils.makedirs(config.YARDSTICK_CONFIG_DIR)
237
238
239 def _source_file(rc_file):
240     yardstick_utils.source_env(rc_file)
241
242
243 def _get_remote_rc_file(rc_file, installer_ip, installer_type):
244
245     os_fetch_script = os.path.join(config.RELENG_DIR, config.OS_FETCH_SCRIPT)
246
247     try:
248         cmd = [os_fetch_script, '-d', rc_file, '-i', installer_type,
249                '-a', installer_ip]
250         p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
251         p.communicate()[0]
252
253         if p.returncode != 0:
254             logger.debug('Failed to fetch credentials from installer')
255     except OSError as e:
256         if e.errno != errno.EEXIST:
257             raise
258
259
260 def _append_external_network(rc_file):
261     neutron_client = yardstick_utils.get_neutron_client()
262     networks = neutron_client.list_networks()['networks']
263     try:
264         ext_network = next(n['name'] for n in networks if n['router:external'])
265     except StopIteration:
266         logger.warning("Can't find external network")
267     else:
268         cmd = 'export EXTERNAL_NETWORK=%s' % ext_network
269         try:
270             with open(rc_file, 'a') as f:
271                 f.write(cmd + '\n')
272         except OSError as e:
273             if e.errno != errno.EEXIST:
274                 raise
275
276
277 def _clean_images():
278     cmd = [config.CLEAN_IMAGES_SCRIPT]
279     p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
280                          cwd=config.YARDSTICK_REPOS_DIR)
281     output = p.communicate()[0]
282     logger.debug('The result is: %s', output)
283
284
285 def _load_images():
286     cmd = [config.LOAD_IMAGES_SCRIPT]
287     p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
288                          cwd=config.YARDSTICK_REPOS_DIR)
289     output = p.communicate()[0]
290     logger.debug('The result is: %s', output)
291
292
293 def _create_task(task_id):
294     async_handler = AsyncTaskHandler()
295     task_dict = {
296         'task_id': task_id,
297         'status': 0
298     }
299     async_handler.insert(task_dict)
300
301
302 def _update_task_status(task_id):
303     async_handler = AsyncTaskHandler()
304
305     task = async_handler.get_task_by_taskid(task_id)
306     async_handler.update_status(task, 1)
307
308
309 def _update_task_error(task_id, error):
310     async_handler = AsyncTaskHandler()
311
312     task = async_handler.get_task_by_taskid(task_id)
313     async_handler.update_status(task, 2)
314     async_handler.update_error(task, error)