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