Merge "Re-Enable Promise testcases"
[functest.git] / functest / utils / openstack_utils.py
old mode 100755 (executable)
new mode 100644 (file)
index 3093cb5..57a2aa2
@@ -8,7 +8,7 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 #
 
 # http://www.apache.org/licenses/LICENSE-2.0
 #
 
-import os
+import logging
 import os.path
 import re
 import sys
 import os.path
 import re
 import sys
@@ -18,16 +18,17 @@ from keystoneauth1 import loading
 from keystoneauth1 import session
 from cinderclient import client as cinderclient
 from glanceclient import client as glanceclient
 from keystoneauth1 import session
 from cinderclient import client as cinderclient
 from glanceclient import client as glanceclient
+from heatclient import client as heatclient
 from novaclient import client as novaclient
 from keystoneclient import client as keystoneclient
 from neutronclient.neutron import client as neutronclient
 
 from novaclient import client as novaclient
 from keystoneclient import client as keystoneclient
 from neutronclient.neutron import client as neutronclient
 
-import functest.utils.functest_logger as ft_logger
 import functest.utils.functest_utils as ft_utils
 
 import functest.utils.functest_utils as ft_utils
 
-logger = ft_logger.Logger("openstack_utils").getLogger()
+logger = logging.getLogger(__name__)
 
 DEFAULT_API_VERSION = '2'
 
 DEFAULT_API_VERSION = '2'
+DEFAULT_HEAT_API_VERSION = '1'
 
 
 # *********************************************
 
 
 # *********************************************
@@ -80,7 +81,8 @@ def get_env_cred_dict():
         'OS_PROJECT_DOMAIN_NAME': 'project_domain_name',
         'OS_PROJECT_NAME': 'project_name',
         'OS_ENDPOINT_TYPE': 'endpoint_type',
         'OS_PROJECT_DOMAIN_NAME': 'project_domain_name',
         'OS_PROJECT_NAME': 'project_name',
         'OS_ENDPOINT_TYPE': 'endpoint_type',
-        'OS_REGION_NAME': 'region_name'
+        'OS_REGION_NAME': 'region_name',
+        'OS_CACERT': 'https_cacert'
     }
     return env_cred_dict
 
     }
     return env_cred_dict
 
@@ -136,20 +138,33 @@ def get_credentials_for_rally():
     endpoint_types = [('internalURL', 'internal'),
                       ('publicURL', 'public'), ('adminURL', 'admin')]
 
     endpoint_types = [('internalURL', 'internal'),
                       ('publicURL', 'public'), ('adminURL', 'admin')]
 
-    endpoint_type = os.getenv('OS_ENDPOINT_TYPE')
+    endpoint_type = get_endpoint_type_from_env()
     if endpoint_type is not None:
         cred_key = env_cred_dict.get('OS_ENDPOINT_TYPE')
         for k, v in endpoint_types:
     if endpoint_type is not None:
         cred_key = env_cred_dict.get('OS_ENDPOINT_TYPE')
         for k, v in endpoint_types:
-            if endpoint_type == k:
+            if endpoint_type == v:
                 rally_conf[cred_key] = v
 
     region_name = os.getenv('OS_REGION_NAME')
     if region_name is not None:
         cred_key = env_cred_dict.get('OS_REGION_NAME')
         rally_conf[cred_key] = region_name
                 rally_conf[cred_key] = v
 
     region_name = os.getenv('OS_REGION_NAME')
     if region_name is not None:
         cred_key = env_cred_dict.get('OS_REGION_NAME')
         rally_conf[cred_key] = region_name
+
+    cacert = os.getenv('OS_CACERT')
+    if cacert is not None:
+        cred_key = env_cred_dict.get('OS_CACERT')
+        rally_conf[cred_key] = cacert
     return rally_conf
 
 
     return rally_conf
 
 
+def get_endpoint_type_from_env():
+    endpoint_type = os.environ.get("OS_ENDPOINT_TYPE",
+                                   os.environ.get("OS_INTERFACE"))
+    if endpoint_type and "URL" in endpoint_type:
+        endpoint_type = endpoint_type.replace("URL", "")
+    return endpoint_type
+
+
 def get_session_auth(other_creds={}):
     loader = loading.get_plugin_loader('password')
     creds = get_credentials(other_creds)
 def get_session_auth(other_creds={}):
     loader = loading.get_plugin_loader('password')
     creds = get_credentials(other_creds)
@@ -166,7 +181,14 @@ def get_endpoint(service_type, endpoint_type='publicURL'):
 
 def get_session(other_creds={}):
     auth = get_session_auth(other_creds)
 
 def get_session(other_creds={}):
     auth = get_session_auth(other_creds)
-    return session.Session(auth=auth)
+    cacert = os.getenv('OS_CACERT')
+    if cacert is not None:
+        if not os.path.isfile(cacert):
+            raise Exception("The 'OS_CACERT' environment"
+                            "variable is set to %s but the file"
+                            "does not exist.", cacert)
+
+    return session.Session(auth=auth, verify=cacert)
 
 
 # *********************************************
 
 
 # *********************************************
@@ -183,7 +205,9 @@ def get_keystone_client_version():
 
 def get_keystone_client(other_creds={}):
     sess = get_session(other_creds)
 
 def get_keystone_client(other_creds={}):
     sess = get_session(other_creds)
-    return keystoneclient.Client(get_keystone_client_version(), session=sess)
+    return keystoneclient.Client(get_keystone_client_version(),
+                                 session=sess,
+                                 interface=os.getenv('OS_INTERFACE', 'admin'))
 
 
 def get_nova_client_version():
 
 
 def get_nova_client_version():
@@ -241,6 +265,20 @@ def get_glance_client(other_creds={}):
     return glanceclient.Client(get_glance_client_version(), session=sess)
 
 
     return glanceclient.Client(get_glance_client_version(), session=sess)
 
 
+def get_heat_client_version():
+    api_version = os.getenv('OS_ORCHESTRATION_API_VERSION')
+    if api_version is not None:
+        logger.info("OS_ORCHESTRATION_API_VERSION is set in env as '%s'",
+                    api_version)
+        return api_version
+    return DEFAULT_HEAT_API_VERSION
+
+
+def get_heat_client(other_creds={}):
+    sess = get_session(other_creds)
+    return heatclient.Client(get_heat_client_version(), session=sess)
+
+
 # *********************************************
 #   NOVA
 # *********************************************
 # *********************************************
 #   NOVA
 # *********************************************
@@ -248,7 +286,7 @@ def get_instances(nova_client):
     try:
         instances = nova_client.servers.list(search_opts={'all_tenants': 1})
         return instances
     try:
         instances = nova_client.servers.list(search_opts={'all_tenants': 1})
         return instances
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [get_instances(nova_client)]: %s" % e)
         return None
 
         logger.error("Error [get_instances(nova_client)]: %s" % e)
         return None
 
@@ -257,7 +295,7 @@ def get_instance_status(nova_client, instance):
     try:
         instance = nova_client.servers.get(instance.id)
         return instance.status
     try:
         instance = nova_client.servers.get(instance.id)
         return instance.status
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [get_instance_status(nova_client)]: %s" % e)
         return None
 
         logger.error("Error [get_instance_status(nova_client)]: %s" % e)
         return None
 
@@ -266,7 +304,7 @@ def get_instance_by_name(nova_client, instance_name):
     try:
         instance = nova_client.servers.find(name=instance_name)
         return instance
     try:
         instance = nova_client.servers.find(name=instance_name)
         return instance
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
                      % (instance_name, e))
         return None
         logger.error("Error [get_instance_by_name(nova_client, '%s')]: %s"
                      % (instance_name, e))
         return None
@@ -296,7 +334,7 @@ def get_aggregates(nova_client):
     try:
         aggregates = nova_client.aggregates.list()
         return aggregates
     try:
         aggregates = nova_client.aggregates.list()
         return aggregates
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [get_aggregates(nova_client)]: %s" % e)
         return None
 
         logger.error("Error [get_aggregates(nova_client)]: %s" % e)
         return None
 
@@ -306,7 +344,7 @@ def get_aggregate_id(nova_client, aggregate_name):
         aggregates = get_aggregates(nova_client)
         _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
         return _id
         aggregates = get_aggregates(nova_client)
         _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0]
         return _id
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [get_aggregate_id(nova_client, %s)]:"
                      " %s" % (aggregate_name, e))
         return None
         logger.error("Error [get_aggregate_id(nova_client, %s)]:"
                      " %s" % (aggregate_name, e))
         return None
@@ -316,7 +354,7 @@ def get_availability_zones(nova_client):
     try:
         availability_zones = nova_client.availability_zones.list()
         return availability_zones
     try:
         availability_zones = nova_client.availability_zones.list()
         return availability_zones
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
         return None
 
         logger.error("Error [get_availability_zones(nova_client)]: %s" % e)
         return None
 
@@ -325,7 +363,7 @@ def get_availability_zone_names(nova_client):
     try:
         az_names = [az.zoneName for az in get_availability_zones(nova_client)]
         return az_names
     try:
         az_names = [az.zoneName for az in get_availability_zones(nova_client)]
         return az_names
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [get_availability_zone_names(nova_client)]:"
                      " %s" % e)
         return None
         logger.error("Error [get_availability_zone_names(nova_client)]:"
                      " %s" % e)
         return None
@@ -343,7 +381,7 @@ def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True):
             # flavor extra specs are not configured, therefore skip the update
             pass
 
             # flavor extra specs are not configured, therefore skip the update
             pass
 
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
                      "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
         return None
         logger.error("Error [create_flavor(nova_client, '%s', '%s', '%s', "
                      "'%s')]: %s" % (flavor_name, ram, disk, vcpus, e))
         return None
@@ -376,7 +414,7 @@ def get_floating_ips(nova_client):
     try:
         floating_ips = nova_client.floating_ips.list()
         return floating_ips
     try:
         floating_ips = nova_client.floating_ips.list()
         return floating_ips
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [get_floating_ips(nova_client)]: %s" % e)
         return None
 
         logger.error("Error [get_floating_ips(nova_client)]: %s" % e)
         return None
 
@@ -389,7 +427,7 @@ def get_hypervisors(nova_client):
             if hypervisor.state == "up":
                 nodes.append(hypervisor.hypervisor_hostname)
         return nodes
             if hypervisor.state == "up":
                 nodes.append(hypervisor.hypervisor_hostname)
         return nodes
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
         return None
 
         logger.error("Error [get_hypervisors(nova_client)]: %s" % e)
         return None
 
@@ -398,7 +436,7 @@ def create_aggregate(nova_client, aggregate_name, av_zone):
     try:
         nova_client.aggregates.create(aggregate_name, av_zone)
         return True
     try:
         nova_client.aggregates.create(aggregate_name, av_zone)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
                      % (aggregate_name, av_zone, e))
         return None
         logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s"
                      % (aggregate_name, av_zone, e))
         return None
@@ -409,7 +447,7 @@ def add_host_to_aggregate(nova_client, aggregate_name, compute_host):
         aggregate_id = get_aggregate_id(nova_client, aggregate_name)
         nova_client.aggregates.add_host(aggregate_id, compute_host)
         return True
         aggregate_id = get_aggregate_id(nova_client, aggregate_name)
         nova_client.aggregates.add_host(aggregate_id, compute_host)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
                      % (aggregate_name, compute_host, e))
         return None
         logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s"
                      % (aggregate_name, compute_host, e))
         return None
@@ -421,7 +459,7 @@ def create_aggregate_with_host(
         create_aggregate(nova_client, aggregate_name, av_zone)
         add_host_to_aggregate(nova_client, aggregate_name, compute_host)
         return True
         create_aggregate(nova_client, aggregate_name, av_zone)
         add_host_to_aggregate(nova_client, aggregate_name, compute_host)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [create_aggregate_with_host("
                      "nova_client, %s, %s, %s)]: %s"
                      % (aggregate_name, av_zone, compute_host, e))
         logger.error("Error [create_aggregate_with_host("
                      "nova_client, %s, %s, %s)]: %s"
                      % (aggregate_name, av_zone, compute_host, e))
@@ -514,7 +552,7 @@ def create_floating_ip(neutron_client):
         ip_json = neutron_client.create_floatingip({'floatingip': props})
         fip_addr = ip_json['floatingip']['floating_ip_address']
         fip_id = ip_json['floatingip']['id']
         ip_json = neutron_client.create_floatingip({'floatingip': props})
         fip_addr = ip_json['floatingip']['floating_ip_address']
         fip_id = ip_json['floatingip']['id']
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
         return None
     return {'fip_addr': fip_addr, 'fip_id': fip_id}
         logger.error("Error [create_floating_ip(neutron_client)]: %s" % e)
         return None
     return {'fip_addr': fip_addr, 'fip_id': fip_id}
@@ -524,7 +562,7 @@ def add_floating_ip(nova_client, server_id, floatingip_addr):
     try:
         nova_client.servers.add_floating_ip(server_id, floatingip_addr)
         return True
     try:
         nova_client.servers.add_floating_ip(server_id, floatingip_addr)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
                      % (server_id, floatingip_addr, e))
         return False
         logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s"
                      % (server_id, floatingip_addr, e))
         return False
@@ -534,7 +572,7 @@ def delete_instance(nova_client, instance_id):
     try:
         nova_client.servers.force_delete(instance_id)
         return True
     try:
         nova_client.servers.force_delete(instance_id)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [delete_instance(nova_client, '%s')]: %s"
                      % (instance_id, e))
         return False
         logger.error("Error [delete_instance(nova_client, '%s')]: %s"
                      % (instance_id, e))
         return False
@@ -544,7 +582,7 @@ def delete_floating_ip(nova_client, floatingip_id):
     try:
         nova_client.floating_ips.delete(floatingip_id)
         return True
     try:
         nova_client.floating_ips.delete(floatingip_id)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [delete_floating_ip(nova_client, '%s')]: %s"
                      % (floatingip_id, e))
         return False
         logger.error("Error [delete_floating_ip(nova_client, '%s')]: %s"
                      % (floatingip_id, e))
         return False
@@ -555,7 +593,7 @@ def remove_host_from_aggregate(nova_client, aggregate_name, compute_host):
         aggregate_id = get_aggregate_id(nova_client, aggregate_name)
         nova_client.aggregates.remove_host(aggregate_id, compute_host)
         return True
         aggregate_id = get_aggregate_id(nova_client, aggregate_name)
         nova_client.aggregates.remove_host(aggregate_id, compute_host)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
                      " %s" % (aggregate_name, compute_host, e))
         return False
         logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:"
                      " %s" % (aggregate_name, compute_host, e))
         return False
@@ -574,7 +612,7 @@ def delete_aggregate(nova_client, aggregate_name):
         remove_hosts_from_aggregate(nova_client, aggregate_name)
         nova_client.aggregates.delete(aggregate_name)
         return True
         remove_hosts_from_aggregate(nova_client, aggregate_name)
         nova_client.aggregates.delete(aggregate_name)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
                      % (aggregate_name, e))
         return False
         logger.error("Error [delete_aggregate(nova_client, %s)]: %s"
                      % (aggregate_name, e))
         return False
@@ -677,7 +715,7 @@ def create_neutron_net(neutron_client, name):
         network = neutron_client.create_network(body=json_body)
         network_dict = network['network']
         return network_dict['id']
         network = neutron_client.create_network(body=json_body)
         network_dict = network['network']
         return network_dict['id']
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
                      % (name, e))
         return None
         logger.error("Error [create_neutron_net(neutron_client, '%s')]: %s"
                      % (name, e))
         return None
@@ -689,7 +727,7 @@ def create_neutron_subnet(neutron_client, name, cidr, net_id):
     try:
         subnet = neutron_client.create_subnet(body=json_body)
         return subnet['subnets'][0]['id']
     try:
         subnet = neutron_client.create_subnet(body=json_body)
         return subnet['subnets'][0]['id']
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
                      "'%s', '%s')]: %s" % (name, cidr, net_id, e))
         return None
         logger.error("Error [create_neutron_subnet(neutron_client, '%s', "
                      "'%s', '%s')]: %s" % (name, cidr, net_id, e))
         return None
@@ -700,7 +738,7 @@ def create_neutron_router(neutron_client, name):
     try:
         router = neutron_client.create_router(json_body)
         return router['router']['id']
     try:
         router = neutron_client.create_router(json_body)
         return router['router']['id']
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
                      % (name, e))
         return None
         logger.error("Error [create_neutron_router(neutron_client, '%s')]: %s"
                      % (name, e))
         return None
@@ -716,7 +754,7 @@ def create_neutron_port(neutron_client, name, network_id, ip):
     try:
         port = neutron_client.create_port(body=json_body)
         return port['port']['id']
     try:
         port = neutron_client.create_port(body=json_body)
         return port['port']['id']
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
                      "'%s')]: %s" % (name, network_id, ip, e))
         return None
         logger.error("Error [create_neutron_port(neutron_client, '%s', '%s', "
                      "'%s')]: %s" % (name, network_id, ip, e))
         return None
@@ -727,7 +765,7 @@ def update_neutron_net(neutron_client, network_id, shared=False):
     try:
         neutron_client.update_network(network_id, body=json_body)
         return True
     try:
         neutron_client.update_network(network_id, body=json_body)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
                      "%s" % (network_id, str(shared), e))
         return False
         logger.error("Error [update_neutron_net(neutron_client, '%s', '%s')]: "
                      "%s" % (network_id, str(shared), e))
         return False
@@ -741,7 +779,7 @@ def update_neutron_port(neutron_client, port_id, device_owner):
         port = neutron_client.update_port(port=port_id,
                                           body=json_body)
         return port['port']['id']
         port = neutron_client.update_port(port=port_id,
                                           body=json_body)
         return port['port']['id']
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
                      " %s" % (port_id, device_owner, e))
         return None
         logger.error("Error [update_neutron_port(neutron_client, '%s', '%s')]:"
                      " %s" % (port_id, device_owner, e))
         return None
@@ -752,7 +790,7 @@ def add_interface_router(neutron_client, router_id, subnet_id):
     try:
         neutron_client.add_interface_router(router=router_id, body=json_body)
         return True
     try:
         neutron_client.add_interface_router(router=router_id, body=json_body)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [add_interface_router(neutron_client, '%s', "
                      "'%s')]: %s" % (router_id, subnet_id, e))
         return False
         logger.error("Error [add_interface_router(neutron_client, '%s', "
                      "'%s')]: %s" % (router_id, subnet_id, e))
         return False
@@ -764,7 +802,7 @@ def add_gateway_router(neutron_client, router_id):
     try:
         neutron_client.add_gateway_router(router_id, router_dict)
         return True
     try:
         neutron_client.add_gateway_router(router_id, router_dict)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
                      % (router_id, e))
         return False
         logger.error("Error [add_gateway_router(neutron_client, '%s')]: %s"
                      % (router_id, e))
         return False
@@ -774,7 +812,7 @@ def delete_neutron_net(neutron_client, network_id):
     try:
         neutron_client.delete_network(network_id)
         return True
     try:
         neutron_client.delete_network(network_id)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
                      % (network_id, e))
         return False
         logger.error("Error [delete_neutron_net(neutron_client, '%s')]: %s"
                      % (network_id, e))
         return False
@@ -784,7 +822,7 @@ def delete_neutron_subnet(neutron_client, subnet_id):
     try:
         neutron_client.delete_subnet(subnet_id)
         return True
     try:
         neutron_client.delete_subnet(subnet_id)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
                      % (subnet_id, e))
         return False
         logger.error("Error [delete_neutron_subnet(neutron_client, '%s')]: %s"
                      % (subnet_id, e))
         return False
@@ -794,7 +832,7 @@ def delete_neutron_router(neutron_client, router_id):
     try:
         neutron_client.delete_router(router=router_id)
         return True
     try:
         neutron_client.delete_router(router=router_id)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
                      % (router_id, e))
         return False
         logger.error("Error [delete_neutron_router(neutron_client, '%s')]: %s"
                      % (router_id, e))
         return False
@@ -804,7 +842,7 @@ def delete_neutron_port(neutron_client, port_id):
     try:
         neutron_client.delete_port(port_id)
         return True
     try:
         neutron_client.delete_port(port_id)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
                      % (port_id, e))
         return False
         logger.error("Error [delete_neutron_port(neutron_client, '%s')]: %s"
                      % (port_id, e))
         return False
@@ -816,7 +854,7 @@ def remove_interface_router(neutron_client, router_id, subnet_id):
         neutron_client.remove_interface_router(router=router_id,
                                                body=json_body)
         return True
         neutron_client.remove_interface_router(router=router_id,
                                                body=json_body)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [remove_interface_router(neutron_client, '%s', "
                      "'%s')]: %s" % (router_id, subnet_id, e))
         return False
         logger.error("Error [remove_interface_router(neutron_client, '%s', "
                      "'%s')]: %s" % (router_id, subnet_id, e))
         return False
@@ -826,7 +864,7 @@ def remove_gateway_router(neutron_client, router_id):
     try:
         neutron_client.remove_gateway_router(router_id)
         return True
     try:
         neutron_client.remove_gateway_router(router_id)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
                      % (router_id, e))
         return False
         logger.error("Error [remove_gateway_router(neutron_client, '%s')]: %s"
                      % (router_id, e))
         return False
@@ -956,7 +994,7 @@ def get_security_groups(neutron_client):
         security_groups = neutron_client.list_security_groups()[
             'security_groups']
         return security_groups
         security_groups = neutron_client.list_security_groups()[
             'security_groups']
         return security_groups
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
         return None
 
         logger.error("Error [get_security_groups(neutron_client)]: %s" % e)
         return None
 
@@ -977,7 +1015,7 @@ def create_security_group(neutron_client, sg_name, sg_description):
     try:
         secgroup = neutron_client.create_security_group(json_body)
         return secgroup['security_group']
     try:
         secgroup = neutron_client.create_security_group(json_body)
         return secgroup['security_group']
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [create_security_group(neutron_client, '%s', "
                      "'%s')]: %s" % (sg_name, sg_description, e))
         return None
         logger.error("Error [create_security_group(neutron_client, '%s', "
                      "'%s')]: %s" % (sg_name, sg_description, e))
         return None
@@ -985,39 +1023,80 @@ def create_security_group(neutron_client, sg_name, sg_description):
 
 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
                          port_range_min=None, port_range_max=None):
 
 def create_secgroup_rule(neutron_client, sg_id, direction, protocol,
                          port_range_min=None, port_range_max=None):
-    if port_range_min is None and port_range_max is None:
-        json_body = {'security_group_rule': {'direction': direction,
-                                             'security_group_id': sg_id,
-                                             'protocol': protocol}}
-    elif port_range_min is not None and port_range_max is not None:
-        json_body = {'security_group_rule': {'direction': direction,
-                                             'security_group_id': sg_id,
-                                             'port_range_min': port_range_min,
-                                             'port_range_max': port_range_max,
-                                             'protocol': protocol}}
+    # We create a security group in 2 steps
+    # 1 - we check the format and set the json body accordingly
+    # 2 - we call neturon client to create the security group
+
+    # Format check
+    json_body = {'security_group_rule': {'direction': direction,
+                                         'security_group_id': sg_id,
+                                         'protocol': protocol}}
+    # parameters may be
+    # - both None => we do nothing
+    # - both Not None => we add them to the json description
+    # but one cannot be None is the other is not None
+    if (port_range_min is not None and port_range_max is not None):
+        # add port_range in json description
+        json_body['security_group_rule']['port_range_min'] = port_range_min
+        json_body['security_group_rule']['port_range_max'] = port_range_max
+        logger.debug("Security_group format set (port range included)")
     else:
     else:
-        logger.error("Error [create_secgroup_rule(neutron_client, '%s', '%s', "
-                     "'%s', '%s', '%s', '%s')]:" % (neutron_client,
-                                                    sg_id, direction,
-                                                    port_range_min,
-                                                    port_range_max,
-                                                    protocol),
-                     " Invalid values for port_range_min, port_range_max")
-        return False
+        # either both port range are set to None => do nothing
+        # or one is set but not the other => log it and return False
+        if port_range_min is None and port_range_max is None:
+            logger.debug("Security_group format set (no port range mentioned)")
+        else:
+            logger.error("Bad security group format."
+                         "One of the port range is not properly set:"
+                         "range min: {},"
+                         "range max: {}".format(port_range_min,
+                                                port_range_max))
+            return False
+
+    # Create security group using neutron client
     try:
         neutron_client.create_security_group_rule(json_body)
         return True
     try:
         neutron_client.create_security_group_rule(json_body)
         return True
-    except Exception, e:
-        logger.error("Error [create_secgroup_rule(neutron_client, '%s', '%s', "
-                     "'%s', '%s', '%s', '%s')]: %s" % (neutron_client,
-                                                       sg_id,
-                                                       direction,
-                                                       port_range_min,
-                                                       port_range_max,
-                                                       protocol, e))
+    except:
+        logger.exception("Impossible to create_security_group_rule,"
+                         "security group rule probably already exists")
         return False
 
 
         return False
 
 
+def get_security_group_rules(neutron_client, sg_id):
+    try:
+        security_rules = neutron_client.list_security_group_rules()[
+            'security_group_rules']
+        security_rules = [rule for rule in security_rules
+                          if rule["security_group_id"] == sg_id]
+        return security_rules
+    except Exception as e:
+        logger.error("Error [get_security_group_rules(neutron_client, sg_id)]:"
+                     " %s" % e)
+        return None
+
+
+def check_security_group_rules(neutron_client, sg_id, direction, protocol,
+                               port_min=None, port_max=None):
+    try:
+        security_rules = get_security_group_rules(neutron_client, sg_id)
+        security_rules = [rule for rule in security_rules
+                          if (rule["direction"].lower() == direction and
+                              rule["protocol"].lower() == protocol and
+                              rule["port_range_min"] == port_min and
+                              rule["port_range_max"] == port_max)]
+        if len(security_rules) == 0:
+            return True
+        else:
+            return False
+    except Exception as e:
+        logger.error("Error [check_security_group_rules("
+                     " neutron_client, sg_id, direction,"
+                     " protocol, port_min=None, port_max=None)]: "
+                     "%s" % e)
+        return None
+
+
 def create_security_group_full(neutron_client,
                                sg_name, sg_description):
     sg_id = get_security_group_id(neutron_client, sg_name)
 def create_security_group_full(neutron_client,
                                sg_name, sg_description):
     sg_id = get_security_group_id(neutron_client, sg_name)
@@ -1062,7 +1141,7 @@ def add_secgroup_to_instance(nova_client, instance_id, secgroup_id):
     try:
         nova_client.servers.add_security_group(instance_id, secgroup_id)
         return True
     try:
         nova_client.servers.add_security_group(instance_id, secgroup_id)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
                      "'%s')]: %s" % (instance_id, secgroup_id, e))
         return False
         logger.error("Error [add_secgroup_to_instance(nova_client, '%s', "
                      "'%s')]: %s" % (instance_id, secgroup_id, e))
         return False
@@ -1078,7 +1157,7 @@ def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota):
         neutron_client.update_quota(tenant_id=tenant_id,
                                     body=json_body)
         return True
         neutron_client.update_quota(tenant_id=tenant_id,
                                     body=json_body)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
                      "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
         return False
         logger.error("Error [update_sg_quota(neutron_client, '%s', '%s', "
                      "'%s')]: %s" % (tenant_id, sg_quota, sg_rule_quota, e))
         return False
@@ -1088,7 +1167,7 @@ def delete_security_group(neutron_client, secgroup_id):
     try:
         neutron_client.delete_security_group(secgroup_id)
         return True
     try:
         neutron_client.delete_security_group(secgroup_id)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
                      % (secgroup_id, e))
         return False
         logger.error("Error [delete_security_group(neutron_client, '%s')]: %s"
                      % (secgroup_id, e))
         return False
@@ -1101,7 +1180,7 @@ def get_images(nova_client):
     try:
         images = nova_client.images.list()
         return images
     try:
         images = nova_client.images.list()
         return images
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [get_images]: %s" % e)
         return None
 
         logger.error("Error [get_images]: %s" % e)
         return None
 
@@ -1137,7 +1216,7 @@ def create_glance_image(glance_client, image_name, file_path, disk="qcow2",
             with open(file_path) as image_data:
                 glance_client.images.upload(image_id, image_data)
         return image_id
             with open(file_path) as image_data:
                 glance_client.images.upload(image_id, image_data)
         return image_id
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
                      "'%s')]: %s" % (image_name, file_path, public, e))
         return None
         logger.error("Error [create_glance_image(glance_client, '%s', '%s', "
                      "'%s')]: %s" % (image_name, file_path, public, e))
         return None
@@ -1167,7 +1246,7 @@ def delete_glance_image(nova_client, image_id):
     try:
         nova_client.images.delete(image_id)
         return True
     try:
         nova_client.images.delete(image_id)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [delete_glance_image(nova_client, '%s')]: %s"
                      % (image_id, e))
         return False
         logger.error("Error [delete_glance_image(nova_client, '%s')]: %s"
                      % (image_id, e))
         return False
@@ -1180,7 +1259,7 @@ def get_volumes(cinder_client):
     try:
         volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
         return volumes
     try:
         volumes = cinder_client.volumes.list(search_opts={'all_tenants': 1})
         return volumes
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [get_volumes(cinder_client)]: %s" % e)
         return None
 
         logger.error("Error [get_volumes(cinder_client)]: %s" % e)
         return None
 
@@ -1193,7 +1272,7 @@ def list_volume_types(cinder_client, public=True, private=True):
         if not private:
             volume_types = [vt for vt in volume_types if vt.is_public]
         return volume_types
         if not private:
             volume_types = [vt for vt in volume_types if vt.is_public]
         return volume_types
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
         return None
 
         logger.error("Error [list_volume_types(cinder_client)]: %s" % e)
         return None
 
@@ -1202,7 +1281,7 @@ def create_volume_type(cinder_client, name):
     try:
         volume_type = cinder_client.volume_types.create(name)
         return volume_type
     try:
         volume_type = cinder_client.volume_types.create(name)
         return volume_type
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
                      % (name, e))
         return None
         logger.error("Error [create_volume_type(cinder_client, '%s')]: %s"
                      % (name, e))
         return None
@@ -1217,7 +1296,7 @@ def update_cinder_quota(cinder_client, tenant_id, vols_quota,
     try:
         cinder_client.quotas.update(tenant_id, **quotas_values)
         return True
     try:
         cinder_client.quotas.update(tenant_id, **quotas_values)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
                      "'%s' '%s')]: %s" % (tenant_id, vols_quota,
                                           snapshots_quota, gigabytes_quota, e))
         logger.error("Error [update_cinder_quota(cinder_client, '%s', '%s', "
                      "'%s' '%s')]: %s" % (tenant_id, vols_quota,
                                           snapshots_quota, gigabytes_quota, e))
@@ -1235,7 +1314,7 @@ def delete_volume(cinder_client, volume_id, forced=False):
         else:
             cinder_client.volumes.delete(volume_id)
         return True
         else:
             cinder_client.volumes.delete(volume_id)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
                      % (volume_id, str(forced), e))
         return False
         logger.error("Error [delete_volume(cinder_client, '%s', '%s')]: %s"
                      % (volume_id, str(forced), e))
         return False
@@ -1245,7 +1324,7 @@ def delete_volume_type(cinder_client, volume_type):
     try:
         cinder_client.volume_types.delete(volume_type)
         return True
     try:
         cinder_client.volume_types.delete(volume_type)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
                      % (volume_type, e))
         return False
         logger.error("Error [delete_volume_type(cinder_client, '%s')]: %s"
                      % (volume_type, e))
         return False
@@ -1261,7 +1340,7 @@ def get_tenants(keystone_client):
         else:
             tenants = keystone_client.tenants.list()
         return tenants
         else:
             tenants = keystone_client.tenants.list()
         return tenants
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [get_tenants(keystone_client)]: %s" % e)
         return None
 
         logger.error("Error [get_tenants(keystone_client)]: %s" % e)
         return None
 
@@ -1270,7 +1349,7 @@ def get_users(keystone_client):
     try:
         users = keystone_client.users.list()
         return users
     try:
         users = keystone_client.users.list()
         return users
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [get_users(keystone_client)]: %s" % e)
         return None
 
         logger.error("Error [get_users(keystone_client)]: %s" % e)
         return None
 
@@ -1318,12 +1397,21 @@ def create_tenant(keystone_client, tenant_name, tenant_description):
                                                     tenant_description,
                                                     enabled=True)
         return tenant.id
                                                     tenant_description,
                                                     enabled=True)
         return tenant.id
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
                      % (tenant_name, tenant_description, e))
         return None
 
 
         logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s"
                      % (tenant_name, tenant_description, e))
         return None
 
 
+def get_or_create_tenant(keystone_client, tenant_name, tenant_description):
+    tenant_id = get_tenant_id(keystone_client, tenant_name)
+    if not tenant_id:
+        tenant_id = create_tenant(keystone_client, tenant_name,
+                                  tenant_description)
+
+    return tenant_id
+
+
 def create_user(keystone_client, user_name, user_password,
                 user_email, tenant_id):
     try:
 def create_user(keystone_client, user_name, user_password,
                 user_email, tenant_id):
     try:
@@ -1340,13 +1428,22 @@ def create_user(keystone_client, user_name, user_password,
                                                 tenant_id,
                                                 enabled=True)
         return user.id
                                                 tenant_id,
                                                 enabled=True)
         return user.id
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
                      "'%s')]: %s" % (user_name, user_password,
                                      user_email, tenant_id, e))
         return None
 
 
         logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'"
                      "'%s')]: %s" % (user_name, user_password,
                                      user_email, tenant_id, e))
         return None
 
 
+def get_or_create_user(keystone_client, user_name, user_password,
+                       tenant_id, user_email=None):
+    user_id = get_user_id(keystone_client, user_name)
+    if not user_id:
+        user_id = create_user(keystone_client, user_name, user_password,
+                              user_email, tenant_id)
+    return user_id
+
+
 def add_role_user(keystone_client, user_id, role_id, tenant_id):
     try:
         if is_keystone_v3():
 def add_role_user(keystone_client, user_id, role_id, tenant_id):
     try:
         if is_keystone_v3():
@@ -1356,7 +1453,7 @@ def add_role_user(keystone_client, user_id, role_id, tenant_id):
         else:
             keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
         return True
         else:
             keystone_client.roles.add_user_role(user_id, role_id, tenant_id)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
                      "'%s')]: %s " % (user_id, role_id, tenant_id, e))
         return False
         logger.error("Error [add_role_user(keystone_client, '%s', '%s'"
                      "'%s')]: %s " % (user_id, role_id, tenant_id, e))
         return False
@@ -1369,7 +1466,7 @@ def delete_tenant(keystone_client, tenant_id):
         else:
             keystone_client.tenants.delete(tenant_id)
         return True
         else:
             keystone_client.tenants.delete(tenant_id)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
                      % (tenant_id, e))
         return False
         logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"
                      % (tenant_id, e))
         return False
@@ -1379,7 +1476,19 @@ def delete_user(keystone_client, user_id):
     try:
         keystone_client.users.delete(user_id)
         return True
     try:
         keystone_client.users.delete(user_id)
         return True
-    except Exception, e:
+    except Exception as e:
         logger.error("Error [delete_user(keystone_client, '%s')]: %s"
                      % (user_id, e))
         return False
         logger.error("Error [delete_user(keystone_client, '%s')]: %s"
                      % (user_id, e))
         return False
+
+
+# *********************************************
+#   HEAT
+# *********************************************
+def get_resource(heat_client, stack_id, resource):
+    try:
+        resources = heat_client.resources.get(stack_id, resource)
+        return resources
+    except Exception as e:
+        logger.error("Error [get_resource]: %s" % e)
+        return None