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