X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=functest%2Futils%2Fopenstack_utils.py;h=3093cb558062872b379946ebd4611d6b4358a019;hb=5807f2c7d8eb73b11331147de9a240f53b329693;hp=15dc87c38c621d8e151211983d9f004f7b25a16c;hpb=1ac822083026d42ebe5f1a96e4eb0d34eed613c8;p=functest.git diff --git a/functest/utils/openstack_utils.py b/functest/utils/openstack_utils.py index 15dc87c38..3093cb558 100755 --- a/functest/utils/openstack_utils.py +++ b/functest/utils/openstack_utils.py @@ -10,20 +10,25 @@ import os import os.path -import subprocess +import re import sys import time +from keystoneauth1 import loading +from keystoneauth1 import session from cinderclient import client as cinderclient -import functest.utils.functest_logger as ft_logger -import functest.utils.functest_utils as ft_utils from glanceclient import client as glanceclient -from keystoneclient.v2_0 import client as keystoneclient -from neutronclient.v2_0 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 logger = ft_logger.Logger("openstack_utils").getLogger() +DEFAULT_API_VERSION = '2' + # ********************************************* # CREDENTIALS @@ -37,161 +42,203 @@ class MissingEnvVar(Exception): return str.format("Please set the mandatory env var: {}", self.var) +def is_keystone_v3(): + keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION') + if (keystone_api_version is None or + keystone_api_version == '2'): + return False + else: + return True + + +def get_rc_env_vars(): + env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD'] + if is_keystone_v3(): + env_vars.extend(['OS_PROJECT_NAME', + 'OS_USER_DOMAIN_NAME', + 'OS_PROJECT_DOMAIN_NAME']) + else: + env_vars.extend(['OS_TENANT_NAME']) + return env_vars + + def check_credentials(): """ Check if the OpenStack credentials (openrc) are sourced """ - env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD', 'OS_TENANT_NAME'] + env_vars = get_rc_env_vars() return all(map(lambda v: v in os.environ and os.environ[v], env_vars)) -def get_credentials(service): - """Returns a creds dictionary filled with the following keys: - * username - * password/api_key (depending on the service) - * tenant_name/project_id (depending on the service) - * auth_url - :param service: a string indicating the name of the service - requesting the credentials. +def get_env_cred_dict(): + env_cred_dict = { + 'OS_USERNAME': 'username', + 'OS_PASSWORD': 'password', + 'OS_AUTH_URL': 'auth_url', + 'OS_TENANT_NAME': 'tenant_name', + 'OS_USER_DOMAIN_NAME': 'user_domain_name', + 'OS_PROJECT_DOMAIN_NAME': 'project_domain_name', + 'OS_PROJECT_NAME': 'project_name', + 'OS_ENDPOINT_TYPE': 'endpoint_type', + 'OS_REGION_NAME': 'region_name' + } + return env_cred_dict + + +def get_credentials(other_creds={}): + """Returns a creds dictionary filled with parsed from env """ creds = {} + env_vars = get_rc_env_vars() + env_cred_dict = get_env_cred_dict() - keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION') - if (keystone_api_version is None or - keystone_api_version == '2'): - keystone_v3 = False - tenant_env = 'OS_TENANT_NAME' - tenant = 'tenant_name' - else: - keystone_v3 = True - tenant_env = 'OS_PROJECT_NAME' - tenant = 'project_name' - - # Check that the env vars exists: - envvars = ('OS_USERNAME', 'OS_PASSWORD', 'OS_AUTH_URL', tenant_env) - for envvar in envvars: + for envvar in env_vars: if os.getenv(envvar) is None: raise MissingEnvVar(envvar) + else: + creds_key = env_cred_dict.get(envvar) + creds.update({creds_key: os.getenv(envvar)}) + + if 'tenant' in other_creds.keys(): + if is_keystone_v3(): + tenant = 'project_name' + else: + tenant = 'tenant_name' + other_creds[tenant] = other_creds.pop('tenant') + + creds.update(other_creds) - # Unfortunately, each of the OpenStack client will request slightly - # different entries in their credentials dict. - if service.lower() in ("nova", "cinder"): - password = "api_key" - tenant = "project_id" - else: - password = "password" - - # The most common way to pass these info to the script is to do it through - # environment variables. - creds.update({ - "username": os.environ.get("OS_USERNAME"), - password: os.environ.get("OS_PASSWORD"), - "auth_url": os.environ.get("OS_AUTH_URL"), - tenant: os.environ.get(tenant_env) - }) - if keystone_v3: - if os.getenv('OS_USER_DOMAIN_NAME') is not None: - creds.update({ - "user_domain_name": os.getenv('OS_USER_DOMAIN_NAME') - }) - if os.getenv('OS_PROJECT_DOMAIN_NAME') is not None: - creds.update({ - "project_domain_name": os.getenv('OS_PROJECT_DOMAIN_NAME') - }) - - if os.getenv('OS_ENDPOINT_TYPE') is not None: - creds.update({ - "endpoint_type": os.environ.get("OS_ENDPOINT_TYPE") - }) - if os.getenv('OS_REGION_NAME') is not None: - creds.update({ - "region_name": os.environ.get("OS_REGION_NAME") - }) - cacert = os.environ.get("OS_CACERT") - if cacert is not None: - # each openstack client uses differnt kwargs for this - creds.update({"cacert": cacert, - "ca_cert": cacert, - "https_ca_cert": cacert, - "https_cacert": cacert, - "ca_file": cacert}) - creds.update({"insecure": "True", "https_insecure": "True"}) - if not os.path.isfile(cacert): - logger.info("WARNING: The 'OS_CACERT' environment variable is " - "set to %s but the file does not exist." % cacert) return creds def source_credentials(rc_file): - pipe = subprocess.Popen(". %s; env" % rc_file, stdout=subprocess.PIPE, - shell=True) - output = pipe.communicate()[0] - env = dict((line.split("=", 1) for line in output.splitlines())) - os.environ.update(env) - return env + with open(rc_file, "r") as f: + for line in f: + var = line.rstrip('"\n').replace('export ', '').split("=") + # The two next lines should be modified as soon as rc_file + # conforms with common rules. Be aware that it could induce + # issues if value starts with ' + key = re.sub(r'^["\' ]*|[ \'"]*$', '', var[0]) + value = re.sub(r'^["\' ]*|[ \'"]*$', '', "".join(var[1:])) + os.environ[key] = value def get_credentials_for_rally(): - creds = get_credentials("keystone") - keystone_api_version = os.getenv('OS_IDENTITY_API_VERSION') - if (keystone_api_version is None or - keystone_api_version == '2'): - admin_keys = ['username', 'tenant_name', 'password'] - else: - admin_keys = ['username', 'password', 'user_domain_name', - 'project_name', 'project_domain_name'] + creds = get_credentials() + env_cred_dict = get_env_cred_dict() + rally_conf = {"type": "ExistingCloud", "admin": {}} + for key in creds: + if key == 'auth_url': + rally_conf[key] = creds[key] + else: + rally_conf['admin'][key] = creds[key] endpoint_types = [('internalURL', 'internal'), ('publicURL', 'public'), ('adminURL', 'admin')] - if 'endpoint_type' in creds.keys(): + + endpoint_type = os.getenv('OS_ENDPOINT_TYPE') + if endpoint_type is not None: + cred_key = env_cred_dict.get('OS_ENDPOINT_TYPE') for k, v in endpoint_types: - if creds['endpoint_type'] == k: - creds['endpoint_type'] = v - rally_conf = {"type": "ExistingCloud", "admin": {}} - for key in creds: - if key in admin_keys: - rally_conf['admin'][key] = creds[key] - else: - rally_conf[key] = creds[key] + if endpoint_type == k: + 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 return rally_conf +def get_session_auth(other_creds={}): + loader = loading.get_plugin_loader('password') + creds = get_credentials(other_creds) + auth = loader.load_from_options(**creds) + return auth + + +def get_endpoint(service_type, endpoint_type='publicURL'): + auth = get_session_auth() + return get_session().get_endpoint(auth=auth, + service_type=service_type, + endpoint_type=endpoint_type) + + +def get_session(other_creds={}): + auth = get_session_auth(other_creds) + return session.Session(auth=auth) + + # ********************************************* # CLIENTS # ********************************************* -def get_keystone_client(): - creds_keystone = get_credentials("keystone") - return keystoneclient.Client(**creds_keystone) +def get_keystone_client_version(): + api_version = os.getenv('OS_IDENTITY_API_VERSION') + if api_version is not None: + logger.info("OS_IDENTITY_API_VERSION is set in env as '%s'", + api_version) + return api_version + return DEFAULT_API_VERSION + + +def get_keystone_client(other_creds={}): + sess = get_session(other_creds) + return keystoneclient.Client(get_keystone_client_version(), session=sess) + +def get_nova_client_version(): + api_version = os.getenv('OS_COMPUTE_API_VERSION') + if api_version is not None: + logger.info("OS_COMPUTE_API_VERSION is set in env as '%s'", + api_version) + return api_version + return DEFAULT_API_VERSION -def get_nova_client(): - creds_nova = get_credentials("nova") - return novaclient.Client('2', **creds_nova) +def get_nova_client(other_creds={}): + sess = get_session(other_creds) + return novaclient.Client(get_nova_client_version(), session=sess) -def get_cinder_client(): - creds_cinder = get_credentials("cinder") - creds_cinder.update({ - "service_type": "volume" - }) - return cinderclient.Client('2', **creds_cinder) +def get_cinder_client_version(): + api_version = os.getenv('OS_VOLUME_API_VERSION') + if api_version is not None: + logger.info("OS_VOLUME_API_VERSION is set in env as '%s'", + api_version) + return api_version + return DEFAULT_API_VERSION -def get_neutron_client(): - creds_neutron = get_credentials("neutron") - return neutronclient.Client(**creds_neutron) +def get_cinder_client(other_creds={}): + sess = get_session(other_creds) + return cinderclient.Client(get_cinder_client_version(), session=sess) -def get_glance_client(): - keystone_client = get_keystone_client() - glance_endpoint_type = 'publicURL' - os_endpoint_type = os.getenv('OS_ENDPOINT_TYPE') - if os_endpoint_type is not None: - glance_endpoint_type = os_endpoint_type - glance_endpoint = keystone_client.service_catalog.url_for( - service_type='image', endpoint_type=glance_endpoint_type) - return glanceclient.Client(1, glance_endpoint, - token=keystone_client.auth_token) + +def get_neutron_client_version(): + api_version = os.getenv('OS_NETWORK_API_VERSION') + if api_version is not None: + logger.info("OS_NETWORK_API_VERSION is set in env as '%s'", + api_version) + return api_version + return DEFAULT_API_VERSION + + +def get_neutron_client(other_creds={}): + sess = get_session(other_creds) + return neutronclient.Client(get_neutron_client_version(), session=sess) + + +def get_glance_client_version(): + api_version = os.getenv('OS_IMAGE_API_VERSION') + if api_version is not None: + logger.info("OS_IMAGE_API_VERSION is set in env as '%s'", api_version) + return api_version + return DEFAULT_API_VERSION + + +def get_glance_client(other_creds={}): + sess = get_session(other_creds) + return glanceclient.Client(get_glance_client_version(), session=sess) # ********************************************* @@ -473,13 +520,13 @@ def create_floating_ip(neutron_client): return {'fip_addr': fip_addr, 'fip_id': fip_id} -def add_floating_ip(nova_client, server_id, floatingip_id): +def add_floating_ip(nova_client, server_id, floatingip_addr): try: - nova_client.servers.add_floating_ip(server_id, floatingip_id) + nova_client.servers.add_floating_ip(server_id, floatingip_addr) return True except Exception, e: logger.error("Error [add_floating_ip(nova_client, '%s', '%s')]: %s" - % (server_id, floatingip_id, e)) + % (server_id, floatingip_addr, e)) return False @@ -1070,38 +1117,29 @@ def get_image_id(glance_client, image_name): def create_glance_image(glance_client, image_name, file_path, disk="qcow2", - container="bare", public=True): + container="bare", public="public"): if not os.path.isfile(file_path): logger.error("Error: file %s does not exist." % file_path) return None try: image_id = get_image_id(glance_client, image_name) if image_id != '': - if logger: - logger.info("Image %s already exists." % image_name) + logger.info("Image %s already exists." % image_name) else: - if logger: - logger.info("Creating image '%s' from '%s'..." % (image_name, - file_path)) - try: - properties = ft_utils.get_functest_config( - 'general.image_properties') - except ValueError: - # image properties are not configured - # therefore don't add any properties - properties = {} - with open(file_path) as fimage: - image = glance_client.images.create(name=image_name, - is_public=public, - disk_format=disk, - container_format=container, - properties=properties, - data=fimage) + logger.info("Creating image '%s' from '%s'..." % (image_name, + file_path)) + + image = glance_client.images.create(name=image_name, + visibility=public, + disk_format=disk, + container_format=container) image_id = image.id + with open(file_path) as image_data: + glance_client.images.upload(image_id, image_data) return image_id except Exception, e: logger.error("Error [create_glance_image(glance_client, '%s', '%s', " - "'%s')]: %s" % (image_name, file_path, str(public), e)) + "'%s')]: %s" % (image_name, file_path, public, e)) return None @@ -1218,7 +1256,10 @@ def delete_volume_type(cinder_client, volume_type): # ********************************************* def get_tenants(keystone_client): try: - tenants = keystone_client.tenants.list() + if is_keystone_v3(): + tenants = keystone_client.projects.list() + else: + tenants = keystone_client.tenants.list() return tenants except Exception, e: logger.error("Error [get_tenants(keystone_client)]: %s" % e) @@ -1235,7 +1276,7 @@ def get_users(keystone_client): def get_tenant_id(keystone_client, tenant_name): - tenants = keystone_client.tenants.list() + tenants = get_tenants(keystone_client) id = '' for t in tenants: if t.name == tenant_name: @@ -1245,7 +1286,7 @@ def get_tenant_id(keystone_client, tenant_name): def get_user_id(keystone_client, user_name): - users = keystone_client.users.list() + users = get_users(keystone_client) id = '' for u in users: if u.name == user_name: @@ -1266,9 +1307,16 @@ def get_role_id(keystone_client, role_name): def create_tenant(keystone_client, tenant_name, tenant_description): try: - tenant = keystone_client.tenants.create(tenant_name, - tenant_description, - enabled=True) + if is_keystone_v3(): + tenant = keystone_client.projects.create( + name=tenant_name, + description=tenant_description, + domain="default", + enabled=True) + else: + tenant = keystone_client.tenants.create(tenant_name, + tenant_description, + enabled=True) return tenant.id except Exception, e: logger.error("Error [create_tenant(keystone_client, '%s', '%s')]: %s" @@ -1279,9 +1327,18 @@ def create_tenant(keystone_client, tenant_name, tenant_description): def create_user(keystone_client, user_name, user_password, user_email, tenant_id): try: - user = keystone_client.users.create(user_name, user_password, - user_email, tenant_id, - enabled=True) + if is_keystone_v3(): + user = keystone_client.users.create(name=user_name, + password=user_password, + email=user_email, + project_id=tenant_id, + enabled=True) + else: + user = keystone_client.users.create(user_name, + user_password, + user_email, + tenant_id, + enabled=True) return user.id except Exception, e: logger.error("Error [create_user(keystone_client, '%s', '%s', '%s'" @@ -1292,7 +1349,12 @@ def create_user(keystone_client, user_name, user_password, def add_role_user(keystone_client, user_id, role_id, tenant_id): try: - keystone_client.roles.add_user_role(user_id, role_id, tenant_id) + if is_keystone_v3(): + keystone_client.roles.grant(role=role_id, + user=user_id, + project=tenant_id) + else: + keystone_client.roles.add_user_role(user_id, role_id, tenant_id) return True except Exception, e: logger.error("Error [add_role_user(keystone_client, '%s', '%s'" @@ -1302,7 +1364,10 @@ def add_role_user(keystone_client, user_id, role_id, tenant_id): def delete_tenant(keystone_client, tenant_id): try: - keystone_client.tenants.delete(tenant_id) + if is_keystone_v3(): + keystone_client.projects.delete(tenant_id) + else: + keystone_client.tenants.delete(tenant_id) return True except Exception, e: logger.error("Error [delete_tenant(keystone_client, '%s')]: %s"