Add common openstack opertation scenarios: flavor & server
[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(json_body):    # pragma: no cover
268     try:
269         return get_nova_client().servers.create(**json_body)
270     except Exception:
271         log.exception("Error create instance failed")
272         return None
273
274
275 def create_instance_and_wait_for_active(json_body):    # pragma: no cover
276     SLEEP = 3
277     VM_BOOT_TIMEOUT = 180
278     nova_client = get_nova_client()
279     instance = create_instance(json_body)
280     count = VM_BOOT_TIMEOUT / SLEEP
281     for n in range(count, -1, -1):
282         status = get_instance_status(nova_client, instance)
283         if status.lower() == "active":
284             return instance
285         elif status.lower() == "error":
286             log.error("The instance went to ERROR status.")
287             return None
288         time.sleep(SLEEP)
289     log.error("Timeout booting the instance.")
290     return None
291
292
293 def delete_instance(nova_client, instance_id):      # pragma: no cover
294     try:
295         nova_client.servers.force_delete(instance_id)
296     except Exception:
297         log.exception("Error [delete_instance(nova_client, '%s')]",
298                       instance_id)
299         return False
300     else:
301         return True
302
303
304 def remove_host_from_aggregate(nova_client, aggregate_name,
305                                compute_host):  # pragma: no cover
306     try:
307         aggregate_id = get_aggregate_id(nova_client, aggregate_name)
308         nova_client.aggregates.remove_host(aggregate_id, compute_host)
309     except Exception:
310         log.exception("Error remove_host_from_aggregate(nova_client, %s, %s)",
311                       aggregate_name, compute_host)
312         return False
313     else:
314         return True
315
316
317 def remove_hosts_from_aggregate(nova_client,
318                                 aggregate_name):   # pragma: no cover
319     aggregate_id = get_aggregate_id(nova_client, aggregate_name)
320     hosts = nova_client.aggregates.get(aggregate_id).hosts
321     assert(
322         all(remove_host_from_aggregate(nova_client, aggregate_name, host)
323             for host in hosts))
324
325
326 def delete_aggregate(nova_client, aggregate_name):  # pragma: no cover
327     try:
328         remove_hosts_from_aggregate(nova_client, aggregate_name)
329         nova_client.aggregates.delete(aggregate_name)
330     except Exception:
331         log.exception("Error [delete_aggregate(nova_client, %s)]",
332                       aggregate_name)
333         return False
334     else:
335         return True
336
337
338 def get_server_by_name(name):   # pragma: no cover
339     try:
340         return get_nova_client().servers.list(search_opts={'name': name})[0]
341     except IndexError:
342         log.exception('Failed to get nova client')
343         raise
344
345
346 def create_flavor(name, ram, vcpus, disk, **kwargs):   # pragma: no cover
347     try:
348         return get_nova_client().flavors.create(name, ram, vcpus, disk, **kwargs)
349     except Exception:
350         log.exception("Error [create_flavor(nova_client, %s, %s, %s, %s, %s)]",
351                       name, ram, disk, vcpus, kwargs['is_public'])
352         return None
353
354
355 def get_image_by_name(name):    # pragma: no cover
356     images = get_nova_client().images.list()
357     try:
358         return next((a for a in images if a.name == name))
359     except StopIteration:
360         log.exception('No image matched')
361
362
363 def get_flavor_id(nova_client, flavor_name):    # pragma: no cover
364     flavors = nova_client.flavors.list(detailed=True)
365     flavor_id = ''
366     for f in flavors:
367         if f.name == flavor_name:
368             flavor_id = f.id
369             break
370     return flavor_id
371
372
373 def get_flavor_by_name(name):   # pragma: no cover
374     flavors = get_nova_client().flavors.list()
375     try:
376         return next((a for a in flavors if a.name == name))
377     except StopIteration:
378         log.exception('No flavor matched')
379
380
381 def check_status(status, name, iterations, interval):   # pragma: no cover
382     for i in range(iterations):
383         try:
384             server = get_server_by_name(name)
385         except IndexError:
386             log.error('Cannot found %s server', name)
387             raise
388
389         if server.status == status:
390             return True
391
392         time.sleep(interval)
393     return False
394
395
396 def delete_flavor(flavor_id):    # pragma: no cover
397     try:
398         get_nova_client().flavors.delete(flavor_id)
399     except Exception:
400         log.exception("Error [delete_flavor(nova_client, %s)]", flavor_id)
401         return False
402     else:
403         return True
404
405
406 # *********************************************
407 #   NEUTRON
408 # *********************************************
409 def get_network_id(neutron_client, network_name):       # pragma: no cover
410     networks = neutron_client.list_networks()['networks']
411     return next((n['id'] for n in networks if n['name'] == network_name), None)
412
413
414 def get_port_id_by_ip(neutron_client, ip_address):      # pragma: no cover
415     ports = neutron_client.list_ports()['ports']
416     return next((i['id'] for i in ports for j in i.get(
417         'fixed_ips') if j['ip_address'] == ip_address), None)
418
419
420 # *********************************************
421 #   GLANCE
422 # *********************************************
423 def get_image_id(glance_client, image_name):    # pragma: no cover
424     images = glance_client.images.list()
425     return next((i.id for i in images if i.name == image_name), None)
426
427
428 # *********************************************
429 #   CINDER
430 # *********************************************
431 def get_volume_id(volume_name):    # pragma: no cover
432     volumes = get_cinder_client().volumes.list()
433     return next((v.id for v in volumes if v.name == volume_name), None)