Merge "Move api_check test in smoke category"
[functest.git] / functest / utils / openstack_utils.py
1 #!/usr/bin/env python
2 #
3 # jose.lausuch@ericsson.com
4 # valentin.boucher@orange.com
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10
11 import os
12 import os.path
13 import subprocess
14 import sys
15 import time
16
17 from cinderclient import client as cinderclient
18 import functest.utils.functest_logger as ft_logger
19 import functest.utils.functest_utils as ft_utils
20 from glanceclient import client as glanceclient
21 from keystoneclient.v2_0 import client as keystoneclient
22 from neutronclient.v2_0 import client as neutronclient
23 from novaclient import client as novaclient
24
25 logger = ft_logger.Logger("openstack_utils").getLogger()
26
27
28 # *********************************************
29 #   CREDENTIALS
30 # *********************************************
31 class MissingEnvVar(Exception):
32
33     def __init__(self, var):
34         self.var = var
35
36     def __str__(self):
37         return str.format("Please set the mandatory env var: {}", self.var)
38
39
40 def check_credentials():
41     """
42     Check if the OpenStack credentials (openrc) are sourced
43     """
44     env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD', 'OS_TENANT_NAME']
45     return all(map(lambda v: v in os.environ and os.environ[v], env_vars))
46
47
48 def get_credentials(service):
49     """Returns a creds dictionary filled with the following keys:
50     * username
51     * password/api_key (depending on the service)
52     * tenant_name/project_id (depending on the service)
53     * auth_url
54     :param service: a string indicating the name of the service
55                     requesting the credentials.
56     """
57     creds = {}
58
59     keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
60     if (keystone_api_version is None or
61             keystone_api_version == '2'):
62         keystone_v3 = False
63         tenant_env = 'OS_TENANT_NAME'
64         tenant = 'tenant_name'
65     else:
66         keystone_v3 = True
67         tenant_env = 'OS_PROJECT_NAME'
68         tenant = 'project_name'
69
70     # Check that the env vars exists:
71     envvars = ('OS_USERNAME', 'OS_PASSWORD', 'OS_AUTH_URL', tenant_env)
72     for envvar in envvars:
73         if os.getenv(envvar) is None:
74             raise MissingEnvVar(envvar)
75
76     # Unfortunately, each of the OpenStack client will request slightly
77     # different entries in their credentials dict.
78     if service.lower() in ("nova", "cinder"):
79         password = "api_key"
80         tenant = "project_id"
81     else:
82         password = "password"
83
84     # The most common way to pass these info to the script is to do it through
85     # environment variables.
86     creds.update({
87         "username": os.environ.get("OS_USERNAME"),
88         password: os.environ.get("OS_PASSWORD"),
89         "auth_url": os.environ.get("OS_AUTH_URL"),
90         tenant: os.environ.get(tenant_env)
91     })
92     if keystone_v3:
93         if os.getenv('OS_USER_DOMAIN_NAME') is not None:
94             creds.update({
95                 "user_domain_name": os.getenv('OS_USER_DOMAIN_NAME')
96             })
97         if os.getenv('OS_PROJECT_DOMAIN_NAME') is not None:
98             creds.update({
99                 "project_domain_name": os.getenv('OS_PROJECT_DOMAIN_NAME')
100             })
101
102     if os.getenv('OS_ENDPOINT_TYPE') is not None:
103         creds.update({
104             "endpoint_type": os.environ.get("OS_ENDPOINT_TYPE")
105         })
106     if os.getenv('OS_REGION_NAME') is not None:
107         creds.update({
108             "region_name": os.environ.get("OS_REGION_NAME")
109         })
110     cacert = os.environ.get("OS_CACERT")
111     if cacert is not None:
112         # each openstack client uses differnt kwargs for this
113         creds.update({"cacert": cacert,
114                       "ca_cert": cacert,
115                       "https_ca_cert": cacert,
116                       "https_cacert": cacert,
117                       "ca_file": cacert})
118         creds.update({"insecure": "True", "https_insecure": "True"})
119         if not os.path.isfile(cacert):
120             logger.info("WARNING: The 'OS_CACERT' environment variable is "
121                         "set to %s but the file does not exist." % cacert)
122     return creds
123
124
125 def source_credentials(rc_file):
126     pipe = subprocess.Popen(". %s; env" % rc_file, stdout=subprocess.PIPE,
127                             shell=True)
128     output = pipe.communicate()[0]
129     env = dict((line.split("=", 1) for line in output.splitlines()))
130     os.environ.update(env)
131     return env
132
133
134 def get_credentials_for_rally():
135     creds = get_credentials("keystone")
136     keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION')
137     if (keystone_api_version is None or
138             keystone_api_version == '2'):
139         admin_keys = ['username', 'tenant_name', 'password']
140     else:
141         admin_keys = ['username', 'password', 'user_domain_name',
142                       'project_name', 'project_domain_name']
143
144     endpoint_types = [('internalURL', 'internal'),
145                       ('publicURL', 'public'), ('adminURL', 'admin')]
146     if 'endpoint_type' in creds.keys():
147         for k, v in endpoint_types:
148             if creds['endpoint_type'] == k:
149                 creds['endpoint_type'] = v
150     rally_conf = {"type": "ExistingCloud", "admin": {}}
151     for key in creds:
152         if key in admin_keys:
153             rally_conf['admin'][key] = creds[key]
154         else:
155             rally_conf[key] = creds[key]
156     return rally_conf
157
158
159 # *********************************************
160 #   CLIENTS
161 # *********************************************
162 def get_keystone_client():
163     creds_keystone = get_credentials("keystone")
164     return keystoneclient.Client(**creds_keystone)
165
166
167 def get_nova_client():
168     creds_nova = get_credentials("nova")
169     return novaclient.Client('2', **creds_nova)
170
171
172 def get_cinder_client():
173     creds_cinder = get_credentials("cinder")
174     creds_cinder.update({
175         "service_type": "volume"
176     })
177     return cinderclient.Client('2', **creds_cinder)
178
179
180 def get_neutron_client():
181     creds_neutron = get_credentials("neutron")
182     return neutronclient.Client(**creds_neutron)
183
184
185 def get_glance_client():
186     keystone_client = get_keystone_client()
187     glance_endpoint_type = 'publicURL'
188     os_endpoint_type = os.getenv('OS_ENDPOINT_TYPE')
189     if os_endpoint_type is not None:
190         glance_endpoint_type = os_endpoint_type
191     glance_endpoint = keystone_client.service_catalog.url_for(
192         service_type='image', endpoint_type=glance_endpoint_type)
193     return glanceclient.Client(1, glance_endpoint,
194                                token=keystone_client.auth_token)
195
196
197 # *********************************************
198 #   NOVA
199 # *********************************************
200 def get_instances(nova_client):
201     try:
202         instances = nova_client.servers.list(search_opts={'all_tenants': 1})
203         return instances
204     except Exception, e:
205         logger.error("Error [get_instances(nova_client)]: %s" % e)
206         return None
207
208
209 def get_instance_status(nova_client, instance):
210     try:
211         instance = nova_client.servers.get(instance.id)
212         return instance.status
213     except Exception, e:
214         logger.error("Error [get_instance_status(nova_client)]: %s" % e)
215         return None
216
217
218 def get_instance_by_name(nova_client, instance_name):
219     try:
220         instance = nova_client.servers.find(name=instance_name)
221         return instance
222     except Exception, e:
223         logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
224                      % (instance_name, e))
225         return None
226
227
228 def get_flavor_id(nova_client, flavor_name):
229     flavors = nova_client.flavors.list(detailed=True)
230     id = ''
231     for f in flavors:
232         if f.name == flavor_name:
233             id = f.id
234             break
235     return id
236
237
238 def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram):
239     flavors = nova_client.flavors.list(detailed=True)
240     id = ''
241     for f in flavors:
242         if min_ram <= f.ram and f.ram <= max_ram:
243             id = f.id
244             break
245     return id
246
247
248 def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
249     try:
250         flavor = nova_client.flavors.create(
251             flavor_name, ram, vcpus, disk, is_public=public)
252         try:
253             extra_specs = ft_utils.get_functest_config(
254                 'general.flavor_extra_specs')
255             flavor.set_keys(extra_specs)
256         except ValueError:
257             # flavor extra specs are not configured, therefore skip the update
258             pass
259
260     except Exception, e:
261         logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
262                      "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
263         return None
264     return flavor.id
265
266
267 def get_or_create_flavor(flavor_name, ram, disk, vcpus, public=True):
268     flavor_exists = False
269     nova_client = get_nova_client()
270
271     flavor_id = get_flavor_id(nova_client, flavor_name)
272     if flavor_id != '':
273         logger.info("Using existing flavor '%s'..." % flavor_name)
274         flavor_exists = True
275     else:
276         logger.info("Creating flavor '%s' with '%s' RAM, '%s' disk size, "
277                     "'%s' vcpus..." % (flavor_name, ram, disk, vcpus))
278         flavor_id = create_flavor(
279             nova_client, flavor_name, ram, disk, vcpus, public=public)
280         if not flavor_id:
281             logger.error("Failed to create flavor '%s'..." % (flavor_name))
282         else:
283             logger.debug("Flavor '%s' with ID=%s created successfully."
284                          % (flavor_name, flavor_id))
285
286     return flavor_exists, flavor_id
287
288
289 def get_floating_ips(nova_client):
290     try:
291         floating_ips = nova_client.floating_ips.list()
292         return floating_ips
293     except Exception, e:
294         logger.error("Error [get_floating_ips(nova_client)]: %s" % e)
295         return None
296
297
298 def get_hypervisors(nova_client):
299     try:
300         nodes = []
301         hypervisors = nova_client.hypervisors.list()
302         for hypervisor in hypervisors:
303             if hypervisor.state == "up":
304                 nodes.append(hypervisor.hypervisor_hostname)
305         return nodes
306     except Exception, e:
307         logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
308         return None
309
310
311 def create_instance(flavor_name,
312                     image_id,
313                     network_id,
314                     instance_name="functest-vm",
315                     confdrive=True,
316                     userdata=None,
317                     av_zone='',
318                     fixed_ip=None,
319                     files=None):
320     nova_client = get_nova_client()
321     try:
322         flavor = nova_client.flavors.find(name=flavor_name)
323     except:
324         flavors = nova_client.flavors.list()
325         logger.error("Error: Flavor '%s' not found. Available flavors are: "
326                      "\n%s" % (flavor_name, flavors))
327         return None
328     if fixed_ip is not None:
329         nics = {"net-id": network_id, "v4-fixed-ip": fixed_ip}
330     else:
331         nics = {"net-id": network_id}
332     if userdata is None:
333         instance = nova_client.servers.create(
334             name=instance_name,
335             flavor=flavor,
336             image=image_id,
337             nics=[nics],
338             availability_zone=av_zone,
339             files=files
340         )
341     else:
342         instance = nova_client.servers.create(
343             name=instance_name,
344             flavor=flavor,
345             image=image_id,
346             nics=[nics],
347             config_drive=confdrive,
348             userdata=userdata,
349             availability_zone=av_zone,
350             files=files
351         )
352     return instance
353
354
355 def create_instance_and_wait_for_active(flavor_name,
356                                         image_id,
357                                         network_id,
358                                         instance_name="",
359                                         config_drive=False,
360                                         userdata="",
361                                         av_zone='',
362                                         fixed_ip=None,
363                                         files=None):
364     SLEEP = 3
365     VM_BOOT_TIMEOUT = 180
366     nova_client = get_nova_client()
367     instance = create_instance(flavor_name,
368                                image_id,
369                                network_id,
370                                instance_name,
371                                config_drive,
372                                userdata,
373                                av_zone=av_zone,
374                                fixed_ip=fixed_ip,
375                                files=files)
376     count = VM_BOOT_TIMEOUT / SLEEP
377     for n in range(count, -1, -1):
378         status = get_instance_status(nova_client, instance)
379         if status.lower() == "active":
380             return instance
381         elif status.lower() == "error":
382             logger.error("The instance %s went to ERROR status."
383                          % instance_name)
384             return None
385         time.sleep(SLEEP)
386     logger.error("Timeout booting the instance %s." % instance_name)
387     return None
388
389
390 def create_floating_ip(neutron_client):
391     extnet_id = get_external_net_id(neutron_client)
392     props = {'floating_network_id': extnet_id}
393     try:
394         ip_json = neutron_client.create_floatingip({'floatingip': props})
395         fip_addr = ip_json['floatingip']['floating_ip_address']
396         fip_id = ip_json['floatingip']['id']
397     except Exception, e:
398         logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
399         return None
400     return {'fip_addr': fip_addr, 'fip_id': fip_id}
401
402
403 def add_floating_ip(nova_client, server_id, floatingip_id):
404     try:
405         nova_client.servers.add_floating_ip(server_id, floatingip_id)
406         return True
407     except Exception, e:
408         logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
409                      % (server_id, floatingip_id, e))
410         return False
411
412
413 def delete_instance(nova_client, instance_id):
414     try:
415         nova_client.servers.force_delete(instance_id)
416         return True
417     except Exception, e:
418         logger.error("Error [delete_instance(nova_client, '%s')]: %s"
419                      % (instance_id, e))
420         return False
421
422
423 def delete_floating_ip(nova_client, floatingip_id):
424     try:
425         nova_client.floating_ips.delete(floatingip_id)
426         return True
427     except Exception, e:
428         logger.error("Error [delete_floating_ip(nova_client, '%s')]: %s"
429                      % (floatingip_id, e))
430         return False
431
432
433 # *********************************************
434 #   NEUTRON
435 # *********************************************
436 def get_network_list(neutron_client):
437     network_list = neutron_client.list_networks()['networks']
438     if len(network_list) == 0:
439         return None
440     else:
441         return network_list
442
443
444 def get_router_list(neutron_client):
445     router_list = neutron_client.list_routers()['routers']
446     if len(router_list) == 0:
447         return None
448     else:
449         return router_list
450
451
452 def get_port_list(neutron_client):
453     port_list = neutron_client.list_ports()['ports']
454     if len(port_list) == 0:
455         return None
456     else:
457         return port_list
458
459
460 def get_network_id(neutron_client, network_name):
461     networks = neutron_client.list_networks()['networks']
462     id = ''
463     for n in networks:
464         if n['name'] == network_name:
465             id = n['id']
466             break
467     return id
468
469
470 def get_subnet_id(neutron_client, subnet_name):
471     subnets = neutron_client.list_subnets()['subnets']
472     id = ''
473     for s in subnets:
474         if s['name'] == subnet_name:
475             id = s['id']
476             break
477     return id
478
479
480 def get_router_id(neutron_client, router_name):
481     routers = neutron_client.list_routers()['routers']
482     id = ''
483     for r in routers:
484         if r['name'] == router_name:
485             id = r['id']
486             break
487     return id
488
489
490 def get_private_net(neutron_client):
491     # Checks if there is an existing shared private network
492     networks = neutron_client.list_networks()['networks']
493     if len(networks) == 0:
494         return None
495     for net in networks:
496         if (net['router:external'] is False) and (net['shared'] is True):
497             return net
498     return None
499
500
501 def get_external_net(neutron_client):
502     for network in neutron_client.list_networks()['networks']:
503         if network['router:external']:
504             return network['name']
505     return None
506
507
508 def get_external_net_id(neutron_client):
509     for network in neutron_client.list_networks()['networks']:
510         if network['router:external']:
511             return network['id']
512     return None
513
514
515 def check_neutron_net(neutron_client, net_name):
516     for network in neutron_client.list_networks()['networks']:
517         if network['name'] == net_name:
518             for subnet in network['subnets']:
519                 return True
520     return False
521
522
523 def create_neutron_net(neutron_client, name):
524     json_body = {'network': {'name': name,
525                              'admin_state_up': True}}
526     try:
527         network = neutron_client.create_network(body=json_body)
528         network_dict = network['network']
529         return network_dict['id']
530     except Exception, e:
531         logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
532                      % (name, e))
533         return None
534
535
536 def create_neutron_subnet(neutron_client, name, cidr, net_id):
537     json_body = {'subnets': [{'name': name, 'cidr': cidr,
538                               'ip_version': 4, 'network_id': net_id}]}
539     try:
540         subnet = neutron_client.create_subnet(body=json_body)
541         return subnet['subnets'][0]['id']
542     except Exception, e:
543         logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
544                      "'%s', '%s')]: %s" % (name, cidr, net_id, e))
545         return None
546
547
548 def create_neutron_router(neutron_client, name):
549     json_body = {'router': {'name': name, 'admin_state_up': True}}
550     try:
551         router = neutron_client.create_router(json_body)
552         return router['router']['id']
553     except Exception, e:
554         logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
555                      % (name, e))
556         return None
557
558
559 def create_neutron_port(neutron_client, name, network_id, ip):
560     json_body = {'port': {
561                  'admin_state_up': True,
562                  'name': name,
563                  'network_id': network_id,
564                  'fixed_ips': [{"ip_address": ip}]
565                  }}
566     try:
567         port = neutron_client.create_port(body=json_body)
568         return port['port']['id']
569     except Exception, e:
570         logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
571                      "'%s')]: %s" % (name, network_id, ip, e))
572         return None
573
574
575 def update_neutron_net(neutron_client, network_id, shared=False):
576     json_body = {'network': {'shared': shared}}
577     try:
578         neutron_client.update_network(network_id, body=json_body)
579         return True
580     except Exception, e:
581         logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
582                      "%s" % (network_id, str(shared), e))
583         return False
584
585
586 def update_neutron_port(neutron_client, port_id, device_owner):
587     json_body = {'port': {
588                  'device_owner': device_owner,
589                  }}
590     try:
591         port = neutron_client.update_port(port=port_id,
592                                           body=json_body)
593         return port['port']['id']
594     except Exception, e:
595         logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
596                      " %s" % (port_id, device_owner, e))
597         return None
598
599
600 def add_interface_router(neutron_client, router_id, subnet_id):
601     json_body = {"subnet_id": subnet_id}
602     try:
603         neutron_client.add_interface_router(router=router_id, body=json_body)
604         return True
605     except Exception, e:
606         logger.error("Error [add_interface_router(neutron_client, '%s', "
607                      "'%s')]: %s" % (router_id, subnet_id, e))
608         return False
609
610
611 def add_gateway_router(neutron_client, router_id):
612     ext_net_id = get_external_net_id(neutron_client)
613     router_dict = {'network_id': ext_net_id}
614     try:
615         neutron_client.add_gateway_router(router_id, router_dict)
616         return True
617     except Exception, e:
618         logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
619                      % (router_id, e))
620         return False
621
622
623 def delete_neutron_net(neutron_client, network_id):
624     try:
625         neutron_client.delete_network(network_id)
626         return True
627     except Exception, e:
628         logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
629                      % (network_id, e))
630         return False
631
632
633 def delete_neutron_subnet(neutron_client, subnet_id):
634     try:
635         neutron_client.delete_subnet(subnet_id)
636         return True
637     except Exception, e:
638         logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
639                      % (subnet_id, e))
640         return False
641
642
643 def delete_neutron_router(neutron_client, router_id):
644     try:
645         neutron_client.delete_router(router=router_id)
646         return True
647     except Exception, e:
648         logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
649                      % (router_id, e))
650         return False
651
652
653 def delete_neutron_port(neutron_client, port_id):
654     try:
655         neutron_client.delete_port(port_id)
656         return True
657     except Exception, e:
658         logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
659                      % (port_id, e))
660         return False
661
662
663 def remove_interface_router(neutron_client, router_id, subnet_id):
664     json_body = {"subnet_id": subnet_id}
665     try:
666         neutron_client.remove_interface_router(router=router_id,
667                                                body=json_body)
668         return True
669     except Exception, e:
670         logger.error("Error [remove_interface_router(neutron_client, '%s', "
671                      "'%s')]: %s" % (router_id, subnet_id, e))
672         return False
673
674
675 def remove_gateway_router(neutron_client, router_id):
676     try:
677         neutron_client.remove_gateway_router(router_id)
678         return True
679     except Exception, e:
680         logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
681                      % (router_id, e))
682         return False
683
684
685 def create_network_full(neutron_client,
686                         net_name,
687                         subnet_name,
688                         router_name,
689                         cidr):
690
691     # Check if the network already exists
692     network_id = get_network_id(neutron_client, net_name)
693     subnet_id = get_subnet_id(neutron_client, subnet_name)
694     router_id = get_router_id(neutron_client, router_name)
695
696     if network_id != '' and subnet_id != '' and router_id != '':
697         logger.info("A network with name '%s' already exists..." % net_name)
698     else:
699         neutron_client.format = 'json'
700         logger.info('Creating neutron network %s...' % net_name)
701         network_id = create_neutron_net(neutron_client, net_name)
702
703         if not network_id:
704             return False
705
706         logger.debug("Network '%s' created successfully" % network_id)
707         logger.debug('Creating Subnet....')
708         subnet_id = create_neutron_subnet(neutron_client, subnet_name,
709                                           cidr, network_id)
710         if not subnet_id:
711             return None
712
713         logger.debug("Subnet '%s' created successfully" % subnet_id)
714         logger.debug('Creating Router...')
715         router_id = create_neutron_router(neutron_client, router_name)
716
717         if not router_id:
718             return None
719
720         logger.debug("Router '%s' created successfully" % router_id)
721         logger.debug('Adding router to subnet...')
722
723         if not add_interface_router(neutron_client, router_id, subnet_id):
724             return None
725
726         logger.debug("Interface added successfully.")
727
728         logger.debug('Adding gateway to router...')
729         if not add_gateway_router(neutron_client, router_id):
730             return None
731
732         logger.debug("Gateway added successfully.")
733
734     network_dic = {'net_id': network_id,
735                    'subnet_id': subnet_id,
736                    'router_id': router_id}
737     return network_dic
738
739
740 def create_shared_network_full(net_name, subnt_name, router_name, subnet_cidr):
741     neutron_client = get_neutron_client()
742
743     network_dic = create_network_full(neutron_client,
744                                       net_name,
745                                       subnt_name,
746                                       router_name,
747                                       subnet_cidr)
748     if network_dic:
749         if not update_neutron_net(neutron_client,
750                                   network_dic['net_id'],
751                                   shared=True):
752             logger.error("Failed to update network %s..." % net_name)
753             return None
754         else:
755             logger.debug("Network '%s' is available..." % net_name)
756     else:
757         logger.error("Network %s creation failed" % net_name)
758         return None
759     return network_dic
760
761
762 def create_bgpvpn(neutron_client, **kwargs):
763     # route_distinguishers
764     # route_targets
765     json_body = {"bgpvpn": kwargs}
766     return neutron_client.create_bgpvpn(json_body)
767
768
769 def create_network_association(neutron_client, bgpvpn_id, neutron_network_id):
770     json_body = {"network_association": {"network_id": neutron_network_id}}
771     return neutron_client.create_network_association(bgpvpn_id, json_body)
772
773
774 def create_router_association(neutron_client, bgpvpn_id, router_id):
775     json_body = {"router_association": {"router_id": router_id}}
776     return neutron_client.create_router_association(bgpvpn_id, json_body)
777
778
779 def update_bgpvpn(neutron_client, bgpvpn_id, **kwargs):
780     json_body = {"bgpvpn": kwargs}
781     return neutron_client.update_bgpvpn(bgpvpn_id, json_body)
782
783
784 def delete_bgpvpn(neutron_client, bgpvpn_id):
785     return neutron_client.delete_bgpvpn(bgpvpn_id)
786
787
788 def get_bgpvpn(neutron_client, bgpvpn_id):
789     return neutron_client.show_bgpvpn(bgpvpn_id)
790
791
792 def get_bgpvpn_routers(neutron_client, bgpvpn_id):
793     return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['routers']
794
795
796 def get_bgpvpn_networks(neutron_client, bgpvpn_id):
797     return get_bgpvpn(neutron_client, bgpvpn_id)['bgpvpn']['networks']
798
799 # *********************************************
800 #   SEC GROUPS
801 # *********************************************
802
803
804 def get_security_groups(neutron_client):
805     try:
806         security_groups = neutron_client.list_security_groups()[
807             'security_groups']
808         return security_groups
809     except Exception, e:
810         logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
811         return None
812
813
814 def get_security_group_id(neutron_client, sg_name):
815     security_groups = get_security_groups(neutron_client)
816     id = ''
817     for sg in security_groups:
818         if sg['name'] == sg_name:
819             id = sg['id']
820             break
821     return id
822
823
824 def create_security_group(neutron_client, sg_name, sg_description):
825     json_body = {'security_group': {'name': sg_name,
826                                     'description': sg_description}}
827     try:
828         secgroup = neutron_client.create_security_group(json_body)
829         return secgroup['security_group']
830     except Exception, e:
831         logger.error("Error [create_security_group(neutron_client, '%s', "
832                      "'%s')]: %s" % (sg_name, sg_description, e))
833         return None
834
835
836 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
837                          port_range_min=None, port_range_max=None):
838     if port_range_min is None and port_range_max is None:
839         json_body = {'security_group_rule': {'direction': direction,
840                                              'security_group_id': sg_id,
841                                              'protocol': protocol}}
842     elif port_range_min is not None and port_range_max is not None:
843         json_body = {'security_group_rule': {'direction': direction,
844                                              'security_group_id': sg_id,
845                                              'port_range_min': port_range_min,
846                                              'port_range_max': port_range_max,
847                                              'protocol': protocol}}
848     else:
849         logger.error("Error [create_secgroup_rule(neutron_client, '%s', '%s', "
850                      "'%s', '%s', '%s', '%s')]:" % (neutron_client,
851                                                     sg_id, direction,
852                                                     port_range_min,
853                                                     port_range_max,
854                                                     protocol),
855                      " Invalid values for port_range_min, port_range_max")
856         return False
857     try:
858         neutron_client.create_security_group_rule(json_body)
859         return True
860     except Exception, e:
861         logger.error("Error [create_secgroup_rule(neutron_client, '%s', '%s', "
862                      "'%s', '%s', '%s', '%s')]: %s" % (neutron_client,
863                                                        sg_id,
864                                                        direction,
865                                                        port_range_min,
866                                                        port_range_max,
867                                                        protocol, e))
868         return False
869
870
871 def create_security_group_full(neutron_client,
872                                sg_name, sg_description):
873     sg_id = get_security_group_id(neutron_client, sg_name)
874     if sg_id != '':
875         logger.info("Using existing security group '%s'..." % sg_name)
876     else:
877         logger.info("Creating security group  '%s'..." % sg_name)
878         SECGROUP = create_security_group(neutron_client,
879                                          sg_name,
880                                          sg_description)
881         if not SECGROUP:
882             logger.error("Failed to create the security group...")
883             return None
884
885         sg_id = SECGROUP['id']
886
887         logger.debug("Security group '%s' with ID=%s created successfully."
888                      % (SECGROUP['name'], sg_id))
889
890         logger.debug("Adding ICMP rules in security group '%s'..."
891                      % sg_name)
892         if not create_secgroup_rule(neutron_client, sg_id,
893                                     'ingress', 'icmp'):
894             logger.error("Failed to create the security group rule...")
895             return None
896
897         logger.debug("Adding SSH rules in security group '%s'..."
898                      % sg_name)
899         if not create_secgroup_rule(
900                 neutron_client, sg_id, 'ingress', 'tcp', '22', '22'):
901             logger.error("Failed to create the security group rule...")
902             return None
903
904         if not create_secgroup_rule(
905                 neutron_client, sg_id, 'egress', 'tcp', '22', '22'):
906             logger.error("Failed to create the security group rule...")
907             return None
908     return sg_id
909
910
911 def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
912     try:
913         nova_client.servers.add_security_group(instance_id, secgroup_id)
914         return True
915     except Exception, e:
916         logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
917                      "'%s')]: %s" % (instance_id, secgroup_id, e))
918         return False
919
920
921 def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
922     json_body = {"quota": {
923         "security_group": sg_quota,
924         "security_group_rule": sg_rule_quota
925     }}
926
927     try:
928         neutron_client.update_quota(tenant_id=tenant_id,
929                                     body=json_body)
930         return True
931     except Exception, e:
932         logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
933                      "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
934         return False
935
936
937 def delete_security_group(neutron_client, secgroup_id):
938     try:
939         neutron_client.delete_security_group(secgroup_id)
940         return True
941     except Exception, e:
942         logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
943                      % (secgroup_id, e))
944         return False
945
946
947 # *********************************************
948 #   GLANCE
949 # *********************************************
950 def get_images(nova_client):
951     try:
952         images = nova_client.images.list()
953         return images
954     except Exception, e:
955         logger.error("Error [get_images]: %s" % e)
956         return None
957
958
959 def get_image_id(glance_client, image_name):
960     images = glance_client.images.list()
961     id = ''
962     for i in images:
963         if i.name == image_name:
964             id = i.id
965             break
966     return id
967
968
969 def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
970                         container="bare", public=True):
971     if not os.path.isfile(file_path):
972         logger.error("Error: file %s does not exist." % file_path)
973         return None
974     try:
975         image_id = get_image_id(glance_client, image_name)
976         if image_id != '':
977             if logger:
978                 logger.info("Image %s already exists." % image_name)
979         else:
980             if logger:
981                 logger.info("Creating image '%s' from '%s'..." % (image_name,
982                                                                   file_path))
983             try:
984                 properties = ft_utils.get_functest_config(
985                     'general.image_properties')
986             except ValueError:
987                 # image properties are not configured
988                 # therefore don't add any properties
989                 properties = {}
990             with open(file_path) as fimage:
991                 image = glance_client.images.create(name=image_name,
992                                                     is_public=public,
993                                                     disk_format=disk,
994                                                     container_format=container,
995                                                     properties=properties,
996                                                     data=fimage)
997             image_id = image.id
998         return image_id
999     except Exception, e:
1000         logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
1001                      "'%s')]: %s" % (image_name, file_path, str(public), e))
1002         return None
1003
1004
1005 def get_or_create_image(name, path, format):
1006     image_exists = False
1007     glance_client = get_glance_client()
1008
1009     image_id = get_image_id(glance_client, name)
1010     if image_id != '':
1011         logger.info("Using existing image '%s'..." % name)
1012         image_exists = True
1013     else:
1014         logger.info("Creating image '%s' from '%s'..." % (name, path))
1015         image_id = create_glance_image(glance_client, name, path, format)
1016         if not image_id:
1017             logger.error("Failed to create a Glance image...")
1018         else:
1019             logger.debug("Image '%s' with ID=%s created successfully."
1020                          % (name, image_id))
1021
1022     return image_exists, image_id
1023
1024
1025 def delete_glance_image(nova_client, image_id):
1026     try:
1027         nova_client.images.delete(image_id)
1028         return True
1029     except Exception, e:
1030         logger.error("Error [delete_glance_image(nova_client, '%s')]: %s"
1031                      % (image_id, e))
1032         return False
1033
1034
1035 # *********************************************
1036 #   CINDER
1037 # *********************************************
1038 def get_volumes(cinder_client):
1039     try:
1040         volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
1041         return volumes
1042     except Exception, e:
1043         logger.error("Error [get_volumes(cinder_client)]: %s" % e)
1044         return None
1045
1046
1047 def list_volume_types(cinder_client, public=True, private=True):
1048     try:
1049         volume_types = cinder_client.volume_types.list()
1050         if not public:
1051             volume_types = [vt for vt in volume_types if not vt.is_public]
1052         if not private:
1053             volume_types = [vt for vt in volume_types if vt.is_public]
1054         return volume_types
1055     except Exception, e:
1056         logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
1057         return None
1058
1059
1060 def create_volume_type(cinder_client, name):
1061     try:
1062         volume_type = cinder_client.volume_types.create(name)
1063         return volume_type
1064     except Exception, e:
1065         logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
1066                      % (name, e))
1067         return None
1068
1069
1070 def update_cinder_quota(cinder_client, tenant_id, vols_quota,
1071                         snapshots_quota, gigabytes_quota):
1072     quotas_values = {"volumes": vols_quota,
1073                      "snapshots": snapshots_quota,
1074                      "gigabytes": gigabytes_quota}
1075
1076     try:
1077         cinder_client.quotas.update(tenant_id, **quotas_values)
1078         return True
1079     except Exception, e:
1080         logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
1081                      "'%s' '%s')]: %s" % (tenant_id, vols_quota,
1082                                           snapshots_quota, gigabytes_quota, e))
1083         return False
1084
1085
1086 def delete_volume(cinder_client, volume_id, forced=False):
1087     try:
1088         if forced:
1089             try:
1090                 cinder_client.volumes.detach(volume_id)
1091             except:
1092                 logger.error(sys.exc_info()[0])
1093             cinder_client.volumes.force_delete(volume_id)
1094         else:
1095             cinder_client.volumes.delete(volume_id)
1096         return True
1097     except Exception, e:
1098         logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
1099                      % (volume_id, str(forced), e))
1100         return False
1101
1102
1103 def delete_volume_type(cinder_client, volume_type):
1104     try:
1105         cinder_client.volume_types.delete(volume_type)
1106         return True
1107     except Exception, e:
1108         logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
1109                      % (volume_type, e))
1110         return False
1111
1112
1113 # *********************************************
1114 #   KEYSTONE
1115 # *********************************************
1116 def get_tenants(keystone_client):
1117     try:
1118         tenants = keystone_client.tenants.list()
1119         return tenants
1120     except Exception, e:
1121         logger.error("Error [get_tenants(keystone_client)]: %s" % e)
1122         return None
1123
1124
1125 def get_users(keystone_client):
1126     try:
1127         users = keystone_client.users.list()
1128         return users
1129     except Exception, e:
1130         logger.error("Error [get_users(keystone_client)]: %s" % e)
1131         return None
1132
1133
1134 def get_tenant_id(keystone_client, tenant_name):
1135     tenants = keystone_client.tenants.list()
1136     id = ''
1137     for t in tenants:
1138         if t.name == tenant_name:
1139             id = t.id
1140             break
1141     return id
1142
1143
1144 def get_user_id(keystone_client, user_name):
1145     users = keystone_client.users.list()
1146     id = ''
1147     for u in users:
1148         if u.name == user_name:
1149             id = u.id
1150             break
1151     return id
1152
1153
1154 def get_role_id(keystone_client, role_name):
1155     roles = keystone_client.roles.list()
1156     id = ''
1157     for r in roles:
1158         if r.name == role_name:
1159             id = r.id
1160             break
1161     return id
1162
1163
1164 def create_tenant(keystone_client, tenant_name, tenant_description):
1165     try:
1166         tenant = keystone_client.tenants.create(tenant_name,
1167                                                 tenant_description,
1168                                                 enabled=True)
1169         return tenant.id
1170     except Exception, e:
1171         logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
1172                      % (tenant_name, tenant_description, e))
1173         return None
1174
1175
1176 def create_user(keystone_client, user_name, user_password,
1177                 user_email, tenant_id):
1178     try:
1179         user = keystone_client.users.create(user_name, user_password,
1180                                             user_email, tenant_id,
1181                                             enabled=True)
1182         return user.id
1183     except Exception, e:
1184         logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
1185                      "'%s')]: %s" % (user_name, user_password,
1186                                      user_email, tenant_id, e))
1187         return None
1188
1189
1190 def add_role_user(keystone_client, user_id, role_id, tenant_id):
1191     try:
1192         keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
1193         return True
1194     except Exception, e:
1195         logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
1196                      "'%s')]: %s " % (user_id, role_id, tenant_id, e))
1197         return False
1198
1199
1200 def delete_tenant(keystone_client, tenant_id):
1201     try:
1202         keystone_client.tenants.delete(tenant_id)
1203         return True
1204     except Exception, e:
1205         logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
1206                      % (tenant_id, e))
1207         return False
1208
1209
1210 def delete_user(keystone_client, user_id):
1211     try:
1212         keystone_client.users.delete(user_id)
1213         return True
1214     except Exception, e:
1215         logger.error("Error [delete_user(keystone_client, '%s')]: %s"
1216                      % (user_id, e))
1217         return False