diff options
Diffstat (limited to 'sdnvpn/lib')
-rw-r--r-- | sdnvpn/lib/openstack_utils.py | 82 | ||||
-rw-r--r-- | sdnvpn/lib/utils.py | 117 |
2 files changed, 163 insertions, 36 deletions
diff --git a/sdnvpn/lib/openstack_utils.py b/sdnvpn/lib/openstack_utils.py index f0b9ba7..d377c33 100644 --- a/sdnvpn/lib/openstack_utils.py +++ b/sdnvpn/lib/openstack_utils.py @@ -18,19 +18,17 @@ import urllib from keystoneauth1 import loading from keystoneauth1 import session -from cinderclient import client as cinderclient -from heatclient import client as heatclient from keystoneclient import client as keystoneclient from neutronclient.neutron import client as neutronclient from openstack import connection from openstack import cloud as os_cloud +from openstack.exceptions import ResourceNotFound from functest.utils import env logger = logging.getLogger(__name__) DEFAULT_API_VERSION = '2' -DEFAULT_HEAT_API_VERSION = '1' # ********************************************* @@ -165,20 +163,6 @@ def get_keystone_client(other_creds={}): interface=os.getenv('OS_INTERFACE', 'admin')) -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(other_creds={}): - sess = get_session(other_creds) - 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: @@ -193,20 +177,6 @@ def get_neutron_client(other_creds={}): return neutronclient.Client(get_neutron_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) - - def download_url(url, dest_path): """ Download a file to a destination path given a URL @@ -1434,10 +1404,52 @@ def delete_user(keystone_client, user_id): # ********************************************* # HEAT # ********************************************* -def get_resource(heat_client, stack_id, resource): +def get_resource(conn, stack_id, resource): try: - resources = heat_client.resources.get(stack_id, resource) - return resources + resource = conn.orchestration.resources(stack_id, id=resource).next() + return resource except Exception as e: - logger.error("Error [get_resource]: %s" % e) + logger.error("Error [get_resource(orchestration)]: %s" % e) return None + + +def create_stack(conn, **kwargs): + try: + stack = conn.orchestration.create_stack(**kwargs) + stack_id = stack.id + if stack_id is None: + logger.error("Stack create start failed") + raise SystemError("Stack create start failed") + return stack_id + except Exception as e: + logger.error("Error [create_stack(orchestration)]: %s" % e) + return None + + +def delete_stack(conn, stack_id): + try: + conn.orchestration.delete_stack(stack_id) + return True + except Exception as e: + logger.error("Error [delete_stack(orchestration)]: %s" % e) + return False + + +def list_stacks(conn, **kwargs): + try: + result = conn.orchestration.stacks(**kwargs) + return result + except Exception as e: + logger.error("Error [list_stack(orchestration)]: %s" % e) + return None + + +def get_output(conn, stack_id, output_key): + try: + stack = conn.orchestration.get_stack(stack_id) + for output in stack.outputs: + if output['output_key'] == output_key: + return output + except ResourceNotFound as e: + logger.error("Error [get_output(orchestration)]: %s" % e) + return None diff --git a/sdnvpn/lib/utils.py b/sdnvpn/lib/utils.py index 9a5e181..a4bb959 100644 --- a/sdnvpn/lib/utils.py +++ b/sdnvpn/lib/utils.py @@ -15,7 +15,7 @@ import requests import re import subprocess from concurrent.futures import ThreadPoolExecutor -from openstack.exceptions import ResourceNotFound +from openstack.exceptions import ResourceNotFound, NotFoundException from requests.auth import HTTPBasicAuth from opnfv.deployment.factory import Factory as DeploymentFactory @@ -987,3 +987,118 @@ def is_fib_entry_present_on_odl(controllers, ip_prefix, vrf_id): logger.error('Failed to find ip prefix %s with error %s' % (ip_prefix, e)) return False + + +def wait_stack_for_status(conn, stack_id, stack_status, limit=12): + """ Waits to reach specified stack status. To be used with + CREATE_COMPLETE and UPDATE_COMPLETE. + Will try a specific number of attempts at 10sec intervals + (default 2min) + + :param stack_id: the stack id returned by create_stack api call + :param stack_status: the stack status waiting for + :param limit: the maximum number of attempts + """ + logger.debug("Stack '%s' create started" % stack_id) + + stack_create_complete = False + attempts = 0 + while attempts < limit: + try: + stack_st = conn.orchestration.get_stack(stack_id).status + except NotFoundException: + logger.error("Stack create failed") + raise SystemError("Stack create failed") + return False + if stack_st == stack_status: + stack_create_complete = True + break + attempts += 1 + time.sleep(10) + + logger.debug("Stack status check: %s times" % attempts) + if stack_create_complete is False: + logger.error("Stack create failed") + raise SystemError("Stack create failed") + return False + + return True + + +def delete_stack_and_wait(conn, stack_id, limit=12): + """ Starts and waits for completion of delete stack + + Will try a specific number of attempts at 10sec intervals + (default 2min) + + :param stack_id: the id of the stack to be deleted + :param limit: the maximum number of attempts + """ + delete_started = False + if stack_id is not None: + delete_started = os_utils.delete_stack(conn, stack_id) + + if delete_started is True: + logger.debug("Stack delete succesfully started") + else: + logger.error("Stack delete start failed") + + stack_delete_complete = False + attempts = 0 + while attempts < limit: + try: + stack_st = conn.orchestration.get_stack(stack_id).status + if stack_st == 'DELETE_COMPLETE': + stack_delete_complete = True + break + attempts += 1 + time.sleep(10) + except NotFoundException: + stack_delete_complete = True + break + + logger.debug("Stack status check: %s times" % attempts) + if not stack_delete_complete: + logger.error("Stack delete failed") + raise SystemError("Stack delete failed") + return False + + return True + + +def get_heat_environment(testcase, common_config): + """ Reads the heat parameters of a testcase into a yaml object + + Each testcase where Heat Orchestratoin Template (HOT) is introduced + has an associated parameters section. + Reads testcase.heat_parameters section and read COMMON_CONFIG.flavor + and place it under parameters tree. + + :param testcase: the tescase for which the HOT file is fetched + :param common_config: the common config section + :return environment: a yaml object to be used as environment + """ + fl = common_config.default_flavor + param_dict = testcase.heat_parameters + param_dict['flavor'] = fl + env_dict = {'parameters': param_dict} + return env_dict + + +def get_vms_from_stack_outputs(conn, stack_id, vm_stack_output_keys): + """ Converts a vm name from a heat stack output to a nova vm object + + :param stack_id: the id of the stack to fetch the vms from + :param vm_stack_output_keys: a list of stack outputs with the vm names + :return vms: a list of vm objects corresponding to the outputs + """ + vms = [] + for vmk in vm_stack_output_keys: + vm_output = os_utils.get_output(conn, stack_id, vmk) + if vm_output is not None: + vm_name = vm_output['output_value'] + logger.debug("vm '%s' read from heat output" % vm_name) + vm = os_utils.get_instance_by_name(conn, vm_name) + if vm is not None: + vms.append(vm) + return vms |