diff options
Diffstat (limited to 'functest/utils')
-rw-r--r-- | functest/utils/functest_utils.py | 36 | ||||
-rwxr-xr-x | functest/utils/openstack_clean.py | 12 | ||||
-rwxr-xr-x | functest/utils/openstack_snapshot.py | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | functest/utils/openstack_tacker.py | 2 | ||||
-rwxr-xr-x | functest/utils/openstack_utils.py | 374 |
5 files changed, 294 insertions, 134 deletions
diff --git a/functest/utils/functest_utils.py b/functest/utils/functest_utils.py index a25967b6..b1e4d3cd 100644 --- a/functest/utils/functest_utils.py +++ b/functest/utils/functest_utils.py @@ -21,6 +21,9 @@ import requests import yaml from git import Repo +import time +import functools + import functest.utils.functest_logger as ft_logger logger = ft_logger.Logger("functest_utils").getLogger() @@ -418,25 +421,8 @@ def merge_dicts(dict1, dict2): yield (k, dict2[k]) -def check_test_result(test_name, ret, start_time, stop_time): - def get_criteria_value(): - return get_criteria_by_test(test_name).split('==')[1].strip() - - status = 'FAIL' - if str(ret) == get_criteria_value(): - status = 'PASS' - - details = { - 'timestart': start_time, - 'duration': round(stop_time - start_time, 1), - 'status': status, - } - - return status, details - - def get_testcases_file_dir(): - return "/home/opnfv/repos/functest/functest/ci/testcases.yaml" + return get_functest_config('general.functest.testcases_yaml') def get_functest_yaml(): @@ -448,3 +434,17 @@ def get_functest_yaml(): def print_separator(): logger.info("==============================================") + + +def timethis(func): + """Measure the time it takes for a function to complete""" + @functools.wraps(func) + def timed(*args, **kwargs): + ts = time.time() + result = func(*args, **kwargs) + te = time.time() + elapsed = '{0}'.format(te - ts) + logger.info('{f}(*{a}, **{kw}) took: {t} sec'.format( + f=func.__name__, a=args, kw=kwargs, t=elapsed)) + return result, elapsed + return timed diff --git a/functest/utils/openstack_clean.py b/functest/utils/openstack_clean.py index 949eee90..c08568bd 100755 --- a/functest/utils/openstack_clean.py +++ b/functest/utils/openstack_clean.py @@ -9,6 +9,8 @@ # - Neutron networks, subnets and ports # - Routers # - Users and tenants +# - Tacker VNFDs and VNFs +# - Tacker SFCs and SFC classifiers # # Author: # jose.lausuch@ericsson.com @@ -105,7 +107,7 @@ def remove_volumes(cinder_client, default_volumes): for volume in volumes: volume_id = getattr(volume, 'id') - volume_name = getattr(volume, 'display_name') + volume_name = getattr(volume, 'name') logger.debug("'%s', ID=%s " % (volume_name, volume_id)) if (volume_id not in default_volumes and volume_name not in default_volumes.values()): @@ -393,7 +395,7 @@ def main(): default_security_groups = snapshot_yaml.get('secgroups') default_floatingips = snapshot_yaml.get('floatingips') default_users = snapshot_yaml.get('users') - default_tenants = snapshot_yaml.get('tenants') + # default_tenants = snapshot_yaml.get('tenants') if not os_utils.check_credentials(): logger.error("Please source the openrc credentials and run " @@ -414,8 +416,10 @@ def main(): separator() remove_users(keystone_client, default_users) separator() - remove_tenants(keystone_client, default_tenants) - separator() + # TODO (Helen) tenant does not exist in V3 + # need to figure our anohter general verification point + # remove_tenants(keystone_client, default_tenants) + # separator() if __name__ == '__main__': diff --git a/functest/utils/openstack_snapshot.py b/functest/utils/openstack_snapshot.py index 4be1af44..5b50ffa5 100755 --- a/functest/utils/openstack_snapshot.py +++ b/functest/utils/openstack_snapshot.py @@ -62,7 +62,7 @@ def get_volumes(cinder_client): volumes = os_utils.get_volumes(cinder_client) if volumes is not None: for volume in volumes: - dic_volumes.update({volume.id: volume.display_name}) + dic_volumes.update({volume.id: volume.name}) return {'volumes': dic_volumes} @@ -149,7 +149,7 @@ def main(): snapshot.update(get_security_groups(neutron_client)) snapshot.update(get_floatinips(nova_client)) snapshot.update(get_users(keystone_client)) - snapshot.update(get_tenants(keystone_client)) + # snapshot.update(get_tenants(keystone_client)) with open(OS_SNAPSHOT_FILE, 'w+') as yaml_file: yaml_file.write(yaml.safe_dump(snapshot, default_flow_style=False)) diff --git a/functest/utils/openstack_tacker.py b/functest/utils/openstack_tacker.py index 6ab05668..f17b421e 100644..100755 --- a/functest/utils/openstack_tacker.py +++ b/functest/utils/openstack_tacker.py @@ -21,7 +21,7 @@ logger = ft_logger.Logger("tacker_utils").getLogger() def get_tacker_client(): - creds_tacker = os_utils.get_credentials('tacker') + creds_tacker = os_utils.get_credentials() return tackerclient.Client(**creds_tacker) diff --git a/functest/utils/openstack_utils.py b/functest/utils/openstack_utils.py index df6fb5d1..ec784121 100755 --- a/functest/utils/openstack_utils.py +++ b/functest/utils/openstack_utils.py @@ -14,16 +14,21 @@ import subprocess 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,68 +42,63 @@ 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(): + keystone_v3 = is_keystone_v3() + env_vars = ['OS_AUTH_URL', 'OS_USERNAME', 'OS_PASSWORD'] + if keystone_v3 is False: + env_vars.extend(['OS_TENANT_NAME']) + else: + env_vars.extend(['OS_PROJECT_NAME', + 'OS_USER_DOMAIN_NAME', + 'OS_PROJECT_DOMAIN_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(): + """Returns a creds dictionary filled with parsed from env """ creds = {} + env_vars = get_rc_env_vars() + env_cred_dict = get_env_cred_dict() - # Check that the env vars exists: - envvars = ('OS_USERNAME', 'OS_PASSWORD', 'OS_AUTH_URL', 'OS_TENANT_NAME') - for envvar in envvars: + for envvar in env_vars: if os.getenv(envvar) is None: raise MissingEnvVar(envvar) - - # 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" - tenant = "tenant_name" - - # 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("OS_TENANT_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) + else: + creds_key = env_cred_dict.get(envvar) + creds.update({creds_key: os.getenv(envvar)}) return creds @@ -112,59 +112,121 @@ def source_credentials(rc_file): def get_credentials_for_rally(): - creds = get_credentials("keystone") - admin_keys = ['username', 'tenant_name', 'password'] - endpoint_types = [('internalURL', 'internal'), - ('publicURL', 'public'), ('adminURL', 'admin')] - if 'endpoint_type' in creds.keys(): - for k, v in endpoint_types: - if creds['endpoint_type'] == k: - creds['endpoint_type'] = v + creds = get_credentials() + env_cred_dict = get_env_cred_dict() rally_conf = {"type": "ExistingCloud", "admin": {}} for key in creds: - if key in admin_keys: - rally_conf['admin'][key] = creds[key] - else: + if key == 'auth_url': rally_conf[key] = creds[key] + else: + rally_conf['admin'][key] = creds[key] + + endpoint_types = [('internalURL', 'internal'), + ('publicURL', 'public'), ('adminURL', 'admin')] + + 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 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(): + loader = loading.get_plugin_loader('password') + creds = get_credentials() + 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(): + auth = get_session_auth() + return session.Session(auth=auth) + + # ********************************************* # CLIENTS # ********************************************* +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(): - creds_keystone = get_credentials("keystone") - return keystoneclient.Client(**creds_keystone) + sess = get_session() + 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) + sess = get_session() + return novaclient.Client(get_nova_client_version(), session=sess) + + +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_cinder_client(): - creds_cinder = get_credentials("cinder") - creds_cinder.update({ - "service_type": "volume" - }) - return cinderclient.Client('2', **creds_cinder) + sess = get_session() + return cinderclient.Client(get_cinder_client_version(), session=sess) + + +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(): - creds_neutron = get_credentials("neutron") - return neutronclient.Client(**creds_neutron) + sess = get_session() + 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(): - 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) + sess = get_session() + return glanceclient.Client(get_glance_client_version(), session=sess) # ********************************************* @@ -218,6 +280,45 @@ def get_flavor_id_by_ram_range(nova_client, min_ram, max_ram): return id +def get_aggregates(nova_client): + try: + aggregates = nova_client.aggregates.list() + return aggregates + except Exception, e: + logger.error("Error [get_aggregates(nova_client)]: %s" % e) + return None + + +def get_aggregate_id(nova_client, aggregate_name): + try: + aggregates = get_aggregates(nova_client) + _id = [ag.id for ag in aggregates if ag.name == aggregate_name][0] + return _id + except Exception, e: + logger.error("Error [get_aggregate_id(nova_client, %s)]:" + " %s" % (aggregate_name, e)) + return None + + +def get_availability_zones(nova_client): + try: + availability_zones = nova_client.availability_zones.list() + return availability_zones + except Exception, e: + logger.error("Error [get_availability_zones(nova_client)]: %s" % e) + return None + + +def get_availability_zone_names(nova_client): + try: + az_names = [az.zoneName for az in get_availability_zones(nova_client)] + return az_names + except Exception, e: + logger.error("Error [get_availability_zone_names(nova_client)]:" + " %s" % e) + return None + + def create_flavor(nova_client, flavor_name, ram, disk, vcpus, public=True): try: flavor = nova_client.flavors.create( @@ -281,6 +382,40 @@ def get_hypervisors(nova_client): return None +def create_aggregate(nova_client, aggregate_name, av_zone): + try: + nova_client.aggregates.create(aggregate_name, av_zone) + return True + except Exception, e: + logger.error("Error [create_aggregate(nova_client, %s, %s)]: %s" + % (aggregate_name, av_zone, e)) + return None + + +def add_host_to_aggregate(nova_client, aggregate_name, compute_host): + try: + aggregate_id = get_aggregate_id(nova_client, aggregate_name) + nova_client.aggregates.add_host(aggregate_id, compute_host) + return True + except Exception, e: + logger.error("Error [add_host_to_aggregate(nova_client, %s, %s)]: %s" + % (aggregate_name, compute_host, e)) + return None + + +def create_aggregate_with_host( + nova_client, aggregate_name, av_zone, compute_host): + try: + create_aggregate(nova_client, aggregate_name, av_zone) + add_host_to_aggregate(nova_client, aggregate_name, compute_host) + return True + except Exception, e: + logger.error("Error [create_aggregate_with_host(" + "nova_client, %s, %s, %s)]: %s" + % (aggregate_name, av_zone, compute_host, e)) + return None + + def create_instance(flavor_name, image_id, network_id, @@ -373,13 +508,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 @@ -403,6 +538,36 @@ def delete_floating_ip(nova_client, floatingip_id): return False +def remove_host_from_aggregate(nova_client, aggregate_name, compute_host): + try: + aggregate_id = get_aggregate_id(nova_client, aggregate_name) + nova_client.aggregates.remove_host(aggregate_id, compute_host) + return True + except Exception, e: + logger.error("Error [remove_host_from_aggregate(nova_client, %s, %s)]:" + " %s" % (aggregate_name, compute_host, e)) + return False + + +def remove_hosts_from_aggregate(nova_client, aggregate_name): + aggregate_id = get_aggregate_id(nova_client, aggregate_name) + hosts = nova_client.aggregates.get(aggregate_id).hosts + assert( + all(remove_host_from_aggregate(nova_client, aggregate_name, host) + for host in hosts)) + + +def delete_aggregate(nova_client, aggregate_name): + try: + remove_hosts_from_aggregate(nova_client, aggregate_name) + nova_client.aggregates.delete(aggregate_name) + return True + except Exception, e: + logger.error("Error [delete_aggregate(nova_client, %s)]: %s" + % (aggregate_name, e)) + return False + + # ********************************************* # NEUTRON # ********************************************* @@ -940,38 +1105,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 |