Merge "Bugfix: yardstick https support"
[yardstick.git] / yardstick / common / openstack_utils.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
10 from __future__ import absolute_import
11
12 import os
13 import time
14 import logging
15
16 from keystoneauth1 import loading
17 from keystoneauth1 import session
18 from novaclient import client as novaclient
19 from glanceclient import client as glanceclient
20 from neutronclient.neutron import client as neutronclient
21
22 log = logging.getLogger(__name__)
23
24 DEFAULT_HEAT_API_VERSION = '1'
25 DEFAULT_API_VERSION = '2'
26
27
28 # *********************************************
29 #   CREDENTIALS
30 # *********************************************
31 def get_credentials():
32     """Returns a creds dictionary filled with parsed from env"""
33     creds = {}
34
35     keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
36
37     if keystone_api_version is None or keystone_api_version == '2':
38         keystone_v3 = False
39         tenant_env = 'OS_TENANT_NAME'
40         tenant = 'tenant_name'
41     else:
42         keystone_v3 = True
43         tenant_env = 'OS_PROJECT_NAME'
44         tenant = 'project_name'
45
46     # The most common way to pass these info to the script is to do it
47     # through environment variables.
48     creds.update({
49         "username": os.environ.get("OS_USERNAME"),
50         "password": os.environ.get("OS_PASSWORD"),
51         "auth_url": os.environ.get("OS_AUTH_URL"),
52         tenant: os.environ.get(tenant_env)
53     })
54
55     if keystone_v3:
56         if os.getenv('OS_USER_DOMAIN_NAME') is not None:
57             creds.update({
58                 "user_domain_name": os.getenv('OS_USER_DOMAIN_NAME')
59             })
60         if os.getenv('OS_PROJECT_DOMAIN_NAME') is not None:
61             creds.update({
62                 "project_domain_name": os.getenv('OS_PROJECT_DOMAIN_NAME')
63             })
64
65     return creds
66
67
68 def get_session_auth():
69     loader = loading.get_plugin_loader('password')
70     creds = get_credentials()
71     auth = loader.load_from_options(**creds)
72     return auth
73
74
75 def get_session():
76     auth = get_session_auth()
77     try:
78         cacert = os.environ['OS_CACERT']
79     except KeyError:
80         return session.Session(auth=auth)
81     else:
82         return session.Session(auth=auth, verify=cacert)
83
84
85 def get_endpoint(service_type, endpoint_type='publicURL'):
86     auth = get_session_auth()
87     return get_session().get_endpoint(auth=auth,
88                                       service_type=service_type,
89                                       endpoint_type=endpoint_type)
90
91
92 # *********************************************
93 #   CLIENTS
94 # *********************************************
95 def get_heat_api_version():     # pragma: no cover
96     try:
97         api_version = os.environ['HEAT_API_VERSION']
98     except KeyError:
99         return DEFAULT_HEAT_API_VERSION
100     else:
101         log.info("HEAT_API_VERSION is set in env as '%s'", api_version)
102         return api_version
103
104
105 def get_nova_client_version():      # pragma: no cover
106     try:
107         api_version = os.environ['OS_COMPUTE_API_VERSION']
108     except KeyError:
109         return DEFAULT_API_VERSION
110     else:
111         log.info("OS_COMPUTE_API_VERSION is set in env as '%s'", api_version)
112         return api_version
113
114
115 def get_nova_client():      # pragma: no cover
116     sess = get_session()
117     return novaclient.Client(get_nova_client_version(), session=sess)
118
119
120 def get_neutron_client_version():   # pragma: no cover
121     try:
122         api_version = os.environ['OS_NETWORK_API_VERSION']
123     except KeyError:
124         return DEFAULT_API_VERSION
125     else:
126         log.info("OS_NETWORK_API_VERSION is set in env as '%s'", api_version)
127         return api_version
128
129
130 def get_neutron_client():   # pragma: no cover
131     sess = get_session()
132     return neutronclient.Client(get_neutron_client_version(), session=sess)
133
134
135 def get_glance_client_version():    # pragma: no cover
136     try:
137         api_version = os.environ['OS_IMAGE_API_VERSION']
138     except KeyError:
139         return DEFAULT_API_VERSION
140     else:
141         log.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version)
142         return api_version
143
144
145 def get_glance_client():    # pragma: no cover
146     sess = get_session()
147     return glanceclient.Client(get_glance_client_version(), session=sess)
148
149
150 # *********************************************
151 #   NOVA
152 # *********************************************
153 def get_instances(nova_client):     # pragma: no cover
154     try:
155         return nova_client.servers.list(search_opts={'all_tenants': 1})
156     except Exception:
157         log.exception("Error [get_instances(nova_client)]")
158
159
160 def get_instance_status(nova_client, instance):     # pragma: no cover
161     try:
162         return nova_client.servers.get(instance.id).status
163     except Exception:
164         log.exception("Error [get_instance_status(nova_client)]")
165
166
167 def get_instance_by_name(nova_client, instance_name):   # pragma: no cover
168     try:
169         return nova_client.servers.find(name=instance_name)
170     except Exception:
171         log.exception("Error [get_instance_by_name(nova_client, '%s')]",
172                       instance_name)
173
174
175 def get_aggregates(nova_client):    # pragma: no cover
176     try:
177         return nova_client.aggregates.list()
178     except Exception:
179         log.exception("Error [get_aggregates(nova_client)]")
180
181
182 def get_availability_zones(nova_client):    # pragma: no cover
183     try:
184         return nova_client.availability_zones.list()
185     except Exception:
186         log.exception("Error [get_availability_zones(nova_client)]")
187
188
189 def get_availability_zone_names(nova_client):   # pragma: no cover
190     try:
191         return [az.zoneName for az in get_availability_zones(nova_client)]
192     except Exception:
193         log.exception("Error [get_availability_zone_names(nova_client)]")
194
195
196 def create_aggregate(nova_client, aggregate_name, av_zone):  # pragma: no cover
197     try:
198         nova_client.aggregates.create(aggregate_name, av_zone)
199     except Exception:
200         log.exception("Error [create_aggregate(nova_client, %s, %s)]",
201                       aggregate_name, av_zone)
202         return False
203     else:
204         return True
205
206
207 def get_aggregate_id(nova_client, aggregate_name):      # pragma: no cover
208     try:
209         aggregates = get_aggregates(nova_client)
210         _id = next((ag.id for ag in aggregates if ag.name == aggregate_name))
211     except Exception:
212         log.exception("Error [get_aggregate_id(nova_client, %s)]",
213                       aggregate_name)
214     else:
215         return _id
216
217
218 def add_host_to_aggregate(nova_client, aggregate_name,
219                           compute_host):    # pragma: no cover
220     try:
221         aggregate_id = get_aggregate_id(nova_client, aggregate_name)
222         nova_client.aggregates.add_host(aggregate_id, compute_host)
223     except Exception:
224         log.exception("Error [add_host_to_aggregate(nova_client, %s, %s)]",
225                       aggregate_name, compute_host)
226         return False
227     else:
228         return True
229
230
231 def create_aggregate_with_host(nova_client, aggregate_name, av_zone,
232                                compute_host):    # pragma: no cover
233     try:
234         create_aggregate(nova_client, aggregate_name, av_zone)
235         add_host_to_aggregate(nova_client, aggregate_name, compute_host)
236     except Exception:
237         log.exception("Error [create_aggregate_with_host("
238                       "nova_client, %s, %s, %s)]",
239                       aggregate_name, av_zone, compute_host)
240         return False
241     else:
242         return True
243
244
245 def create_instance(flavor_name,
246                     image_id,
247                     network_id,
248                     instance_name="instance-vm",
249                     confdrive=True,
250                     userdata=None,
251                     av_zone='',
252                     fixed_ip=None,
253                     files=None):    # pragma: no cover
254     nova_client = get_nova_client()
255     try:
256         flavor = nova_client.flavors.find(name=flavor_name)
257     except:
258         flavors = nova_client.flavors.list()
259         log.exception("Error: Flavor '%s' not found. Available flavors are: "
260                       "\n%s", flavor_name, flavors)
261         return None
262     if fixed_ip is not None:
263         nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
264     else:
265         nics = {"net-id": network_id}
266     if userdata is None:
267         instance = nova_client.servers.create(
268             name=instance_name,
269             flavor=flavor,
270             image=image_id,
271             nics=[nics],
272             availability_zone=av_zone,
273             files=files
274         )
275     else:
276         instance = nova_client.servers.create(
277             name=instance_name,
278             flavor=flavor,
279             image=image_id,
280             nics=[nics],
281             config_drive=confdrive,
282             userdata=userdata,
283             availability_zone=av_zone,
284             files=files
285         )
286     return instance
287
288
289 def create_instance_and_wait_for_active(flavor_name,
290                                         image_id,
291                                         network_id,
292                                         instance_name="instance-vm",
293                                         config_drive=False,
294                                         userdata="",
295                                         av_zone='',
296                                         fixed_ip=None,
297                                         files=None):    # pragma: no cover
298     SLEEP = 3
299     VM_BOOT_TIMEOUT = 180
300     nova_client = get_nova_client()
301     instance = create_instance(flavor_name,
302                                image_id,
303                                network_id,
304                                instance_name,
305                                config_drive,
306                                userdata,
307                                av_zone=av_zone,
308                                fixed_ip=fixed_ip,
309                                files=files)
310     count = VM_BOOT_TIMEOUT / SLEEP
311     for n in range(count, -1, -1):
312         status = get_instance_status(nova_client, instance)
313         if status.lower() == "active":
314             return instance
315         elif status.lower() == "error":
316             log.error("The instance %s went to ERROR status.", instance_name)
317             return None
318         time.sleep(SLEEP)
319     log.error("Timeout booting the instance %s.", instance_name)
320     return None
321
322
323 def delete_instance(nova_client, instance_id):      # pragma: no cover
324     try:
325         nova_client.servers.force_delete(instance_id)
326     except Exception:
327         log.exception("Error [delete_instance(nova_client, '%s')]",
328                       instance_id)
329         return False
330     else:
331         return True
332
333
334 def remove_host_from_aggregate(nova_client, aggregate_name,
335                                compute_host):  # pragma: no cover
336     try:
337         aggregate_id = get_aggregate_id(nova_client, aggregate_name)
338         nova_client.aggregates.remove_host(aggregate_id, compute_host)
339     except Exception:
340         log.exception("Error remove_host_from_aggregate(nova_client, %s, %s)",
341                       aggregate_name, compute_host)
342         return False
343     else:
344         return True
345
346
347 def remove_hosts_from_aggregate(nova_client,
348                                 aggregate_name):   # pragma: no cover
349     aggregate_id = get_aggregate_id(nova_client, aggregate_name)
350     hosts = nova_client.aggregates.get(aggregate_id).hosts
351     assert(
352         all(remove_host_from_aggregate(nova_client, aggregate_name, host)
353             for host in hosts))
354
355
356 def delete_aggregate(nova_client, aggregate_name):  # pragma: no cover
357     try:
358         remove_hosts_from_aggregate(nova_client, aggregate_name)
359         nova_client.aggregates.delete(aggregate_name)
360     except Exception:
361         log.exception("Error [delete_aggregate(nova_client, %s)]",
362                       aggregate_name)
363         return False
364     else:
365         return True
366
367
368 def get_server_by_name(name):   # pragma: no cover
369     try:
370         return get_nova_client().servers.list(search_opts={'name': name})[0]
371     except IndexError:
372         log.exception('Failed to get nova client')
373         raise
374
375
376 def get_image_by_name(name):    # pragma: no cover
377     images = get_nova_client().images.list()
378     try:
379         return next((a for a in images if a.name == name))
380     except StopIteration:
381         log.exception('No image matched')
382
383
384 def get_flavor_by_name(name):   # pragma: no cover
385     flavors = get_nova_client().flavors.list()
386     try:
387         return next((a for a in flavors if a.name == name))
388     except StopIteration:
389         log.exception('No flavor matched')
390
391
392 def check_status(status, name, iterations, interval):   # pragma: no cover
393     for i in range(iterations):
394         try:
395             server = get_server_by_name(name)
396         except IndexError:
397             log.error('Cannot found %s server', name)
398             raise
399
400         if server.status == status:
401             return True
402
403         time.sleep(interval)
404     return False
405
406
407 # *********************************************
408 #   NEUTRON
409 # *********************************************
410 def get_network_id(neutron_client, network_name):       # pragma: no cover
411     networks = neutron_client.list_networks()['networks']
412     return next((n['id'] for n in networks if n['name'] == network_name), None)
413
414
415 def get_port_id_by_ip(neutron_client, ip_address):      # pragma: no cover
416     ports = neutron_client.list_ports()['ports']
417     return next((i['id'] for i in ports for j in i.get(
418         'fixed_ips') if j['ip_address'] == ip_address), None)
419
420
421 # *********************************************
422 #   GLANCE
423 # *********************************************
424 def get_image_id(glance_client, image_name):    # pragma: no cover
425     images = glance_client.images.list()
426     return next((i.id for i in images if i.name == image_name), None)