aboutsummaryrefslogtreecommitdiffstats
path: root/functest/opnfv_tests/vnf/epc/juju_epc.py
diff options
context:
space:
mode:
authorsoumaya <soumaya.nayek@rebaca.com>2017-09-12 22:49:21 +0530
committerCédric Ollivier <cedric.ollivier@orange.com>2017-12-11 13:51:52 +0100
commit00315cbac45bdffe0cfd3174a4b0871ccb610b97 (patch)
tree382caa3f197947fe3a39690527bc467ae6bc4481 /functest/opnfv_tests/vnf/epc/juju_epc.py
parent41a81e7f5ca5d3733e6e5655f5ece7859ce9f49b (diff)
vEPC tests with juju as an VNF manager
juju_epc testcase validate EPC setup with the help of ABoT which acting as test executor. Functest-abot-epc-bundle deploys OAI charms alongwith mysql and ABoT. JUJU is acting as a VNF manager. Change-Id: I45d7b37f21f6b8c7049ab2bf42a4678e30b67a72 Signed-off-by: soumaya <soumaya.nayek@rebaca.com>
Diffstat (limited to 'functest/opnfv_tests/vnf/epc/juju_epc.py')
-rw-r--r--functest/opnfv_tests/vnf/epc/juju_epc.py502
1 files changed, 502 insertions, 0 deletions
diff --git a/functest/opnfv_tests/vnf/epc/juju_epc.py b/functest/opnfv_tests/vnf/epc/juju_epc.py
new file mode 100644
index 000000000..8e2bca22e
--- /dev/null
+++ b/functest/opnfv_tests/vnf/epc/juju_epc.py
@@ -0,0 +1,502 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2016 Rebaca and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+"""Juju testcase implementation."""
+
+import logging
+import shutil
+import os
+import time
+import json
+import sys
+from copy import deepcopy
+import yaml
+import functest.utils.openstack_utils as os_utils
+import functest.core.vnf as vnf
+import pkg_resources
+
+from functest.opnfv_tests.openstack.snaps import snaps_utils
+from functest.utils.constants import CONST
+
+from snaps.openstack.os_credentials import OSCreds
+from snaps.openstack.create_network import (NetworkSettings,
+ SubnetSettings, OpenStackNetwork)
+from snaps.openstack.create_router import (RouterSettings, OpenStackRouter)
+from snaps.openstack.create_flavor import (FlavorSettings, OpenStackFlavor)
+from snaps.openstack.create_image import (ImageSettings, OpenStackImage)
+from snaps.openstack.tests import openstack_tests
+from snaps.openstack.utils import keystone_utils
+
+__author__ = "Amarendra Meher <amarendra@rebaca.com>"
+__author__ = "Soumaya K Nayek <soumaya.nayek@rebaca.com>"
+
+
+class JujuEpc(vnf.VnfOnBoarding):
+ """Abot EPC deployed with JUJU Orchestrator Case"""
+
+ __logger = logging.getLogger(__name__)
+
+ def __init__(self, **kwargs):
+ if "case_name" not in kwargs:
+ kwargs["case_name"] = "juju_epc"
+ super(JujuEpc, self).__init__(**kwargs)
+
+ # Retrieve the configuration
+ self.case_dir = pkg_resources.resource_filename(
+ 'functest', 'opnfv_tests/vnf/epc')
+ try:
+ self.config = CONST.__getattribute__(
+ 'vnf_{}_config'.format(self.case_name))
+ except Exception:
+ raise Exception("VNF config file not found")
+ config_file = os.path.join(self.case_dir, self.config)
+ self.orchestrator = dict(
+ requirements=get_config("orchestrator.requirements", config_file),
+ )
+
+ self.created_object = []
+ self.snaps_creds = ''
+
+ self.os_creds = openstack_tests.get_credentials(
+ os_env_file=CONST.__getattribute__('openstack_creds'))
+
+ self.details['orchestrator'] = dict(
+ name=get_config("orchestrator.name", config_file),
+ version=get_config("orchestrator.version", config_file),
+ status='ERROR',
+ result=''
+ )
+
+ self.vnf = dict(
+ descriptor=get_config("vnf.descriptor", config_file),
+ requirements=get_config("vnf.requirements", config_file)
+ )
+ self.details['vnf'] = dict(
+ descriptor_version=self.vnf['descriptor']['version'],
+ name=get_config("vnf.name", config_file),
+ version=get_config("vnf.version", config_file),
+ )
+ self.__logger.debug("VNF configuration: %s", self.vnf)
+
+ self.details['test_vnf'] = dict(
+ name=get_config("vnf_test_suite.name", config_file),
+ version=get_config("vnf_test_suite.version", config_file),
+ tag_name=get_config("vnf_test_suite.tag_name", config_file)
+ )
+ self.images = get_config("tenant_images", config_file)
+ self.__logger.info("Images needed for vEPC: %s", self.images)
+ self.keystone_client = os_utils.get_keystone_client()
+ self.glance_client = os_utils.get_glance_client()
+ self.neutron_client = os_utils.get_neutron_client()
+ self.nova_client = os_utils.get_nova_client()
+
+ def prepare(self):
+ """Prepare testcase (Additional pre-configuration steps)."""
+ self.__logger.debug("OS Credentials: %s", os_utils.get_credentials())
+
+ super(JujuEpc, self).prepare()
+
+ self.__logger.info("Additional pre-configuration steps")
+ self.public_auth_url = keystone_utils.get_endpoint(
+ self.snaps_creds, 'identity')
+
+ self.creds = {
+ "tenant": self.tenant_name,
+ "username": self.tenant_name,
+ "password": self.tenant_name,
+ "auth_url": os_utils.get_credentials()['auth_url']
+ }
+
+ self.snaps_creds = OSCreds(
+ username=self.creds['username'],
+ password=self.creds['password'],
+ auth_url=self.creds['auth_url'],
+ project_name=self.creds['tenant'],
+ identity_api_version=int(os_utils.get_keystone_client_version()))
+
+ cloud_data = {
+ 'url': self.public_auth_url,
+ 'pass': self.tenant_name,
+ 'tenant_n': self.tenant_name,
+ 'user_n': self.tenant_name
+ }
+ self.__logger.info("Cloud DATA: %s", cloud_data)
+ self.filename = os.path.join(self.case_dir, 'abot-epc.yaml')
+ self.__logger.info("Cretae %s to add cloud info", self.filename)
+ write_config(self.filename, CLOUD_TEMPLATE, **cloud_data)
+
+ if self.snaps_creds.identity_api_version == 3:
+ append_config(self.filename, '{}'.format(
+ os_utils.get_credentials()['project_domain_name']),
+ '{}'.format(os_utils.get_credentials()
+ ['user_domain_name']))
+
+ self.__logger.info("Upload some OS images if it doesn't exist")
+ for image_name, image_file in self.images.iteritems():
+ self.__logger.info("image: %s, file: %s", image_name, image_file)
+ if image_file and image_name:
+ image_creator = OpenStackImage(
+ self.snaps_creds,
+ ImageSettings(name=image_name,
+ image_user='cloud',
+ img_format='qcow2',
+ image_file=image_file))
+ image_creator.create()
+ self.created_object.append(image_creator)
+
+ def deploy_orchestrator(self):
+ self.__logger.info("Deployed Orchestrator")
+ private_net_name = CONST.__getattribute__(
+ 'vnf_{}_private_net_name'.format(self.case_name))
+ private_subnet_name = CONST.__getattribute__(
+ 'vnf_{}_private_subnet_name'.format(self.case_name))
+ private_subnet_cidr = CONST.__getattribute__(
+ 'vnf_{}_private_subnet_cidr'.format(self.case_name))
+ abot_router = CONST.__getattribute__(
+ 'vnf_{}_external_router'.format(self.case_name))
+ dns_nameserver = CONST.__getattribute__(
+ 'vnf_{}_dns_nameserver'.format(self.case_name))
+ ext_net_name = CONST.__getattribute__(
+ 'vnf_{}_external_network_name'.format(self.case_name))
+
+ self.__logger.info("Creating full network ...")
+ subnet_settings = SubnetSettings(name=private_subnet_name,
+ cidr=private_subnet_cidr,
+ dns_nameservers=dns_nameserver)
+ network_settings = NetworkSettings(name=private_net_name,
+ subnet_settings=[subnet_settings])
+ network_creator = OpenStackNetwork(self.snaps_creds, network_settings)
+ network_creator.create()
+ self.created_object.append(network_creator)
+
+ ext_net_name = snaps_utils.get_ext_net_name(self.snaps_creds)
+ self.__logger.info("Creating network Router ....")
+ router_creator = OpenStackRouter(
+ self.snaps_creds,
+ RouterSettings(
+ name=abot_router,
+ external_gateway=ext_net_name,
+ internal_subnets=[subnet_settings.name]))
+ router_creator.create()
+ self.created_object.append(router_creator)
+ self.__logger.info("Creating Flavor ....")
+ flavor_settings = FlavorSettings(
+ name=self.orchestrator['requirements']['flavor']['name'],
+ ram=self.orchestrator['requirements']['flavor']['ram_min'],
+ disk=10,
+ vcpus=1)
+ flavor_creator = OpenStackFlavor(self.snaps_creds, flavor_settings)
+ self.__logger.info("Juju Bootstrap: Skip creation of flavors")
+ flavor_creator.create()
+ self.created_object.append(flavor_creator)
+ self.__logger.info("Installing Dependency Packages .......")
+ source_dir = "/src/epc-requirements/juju_bin_build"
+ if os.path.exists(source_dir):
+ shutil.rmtree(source_dir)
+ os.makedirs(source_dir)
+ os.environ['GOPATH'] = str(source_dir)
+ os.environ['GOBIN'] = str(source_dir) + "/bin"
+ os.environ['PATH'] = ((os.path.expandvars('$GOPATH')) + ":" +
+ (os.path.expandvars('$GOBIN')) + ":" +
+ (os.path.expandvars('$PATH')))
+ os.system('go get -d -v github.com/juju/juju/...')
+ os.chdir(source_dir + "/src" + "/github.com" + "/juju" + "/juju")
+ os.system('git checkout tags/juju-2.2.5')
+ os.system('go get github.com/rogpeppe/godeps')
+ os.system('godeps -u dependencies.tsv')
+ os.system('go install -v github.com/juju/juju/...')
+ self.__logger.info("Creating Cloud for Abot-epc .....")
+ os.system('juju add-cloud abot-epc -f {}'.format(self.filename))
+ os.system('juju add-credential abot-epc -f {}'.format(self.filename))
+ for image_name in self.images.keys():
+ self.__logger.info("Generating Metadata for %s", image_name)
+ image_id = os_utils.get_image_id(self.glance_client, image_name)
+ os.system('juju metadata generate-image -d ~ -i {} -s {} -r '
+ 'RegionOne -u {}'.format(image_id,
+ image_name,
+ self.public_auth_url))
+ net_id = os_utils.get_network_id(self.neutron_client, private_net_name)
+ self.__logger.info("Credential information : %s", net_id)
+ juju_bootstrap_command = ('juju bootstrap abot-epc abot-controller '
+ '--config network={} --metadata-source ~ '
+ '--constraints mem=2G --bootstrap-series '
+ 'trusty '
+ '--config use-floating-ip=true --debug'.
+ format(net_id))
+ os.system(juju_bootstrap_command)
+ return True
+
+ def deploy_vnf(self):
+ """Deploy ABOT-OAI-EPC."""
+ self.__logger.info("Upload VNFD")
+ descriptor = self.vnf['descriptor']
+ self.__logger.info("Get or create flavor for all Abot-EPC")
+ flavor_settings = FlavorSettings(
+ name=self.vnf['requirements']['flavor']['name'],
+ ram=self.vnf['requirements']['flavor']['ram_min'],
+ disk=10,
+ vcpus=1)
+ flavor_creator = OpenStackFlavor(self.snaps_creds, flavor_settings)
+ flavor_creator.create()
+ self.created_object.append(flavor_creator)
+ self.__logger.info("Deploying Abot-epc bundle file ...")
+ os.system('juju deploy {}'.format('/' + descriptor.get('file_name')))
+ self.__logger.info("Waiting for instances .....")
+ status = os.system('juju-wait')
+ self.__logger.info("juju wait completed: %s", status)
+ self.__logger.info("Deployed Abot-epc on Openstack")
+ if status == 0:
+ instances = os_utils.get_instances(self.nova_client)
+ for items in instances:
+ metadata = get_instance_metadata(self.nova_client, items)
+ if 'juju-units-deployed' in metadata:
+ sec_group = ('juju-' + metadata['juju-controller-uuid'] +
+ '-' + metadata['juju-model-uuid'])
+ self.sec_group_id = os_utils.get_security_group_id(
+ self.neutron_client, sec_group)
+ break
+ self.__logger.info("Adding Security group rule....")
+ os_utils.create_secgroup_rule(self.neutron_client,
+ self.sec_group_id, 'ingress', 132)
+ self.__logger.info("Copying the feature files to Abot_node ")
+ os.system('juju scp -- -r {}/featureFiles abot-'
+ 'epc-basic/0:~/'.format(self.case_dir))
+ self.__logger.info("Copying the feature files in Abot_node ")
+ os.system("juju ssh abot-epc-basic/0 'sudo rsync -azvv "
+ "~/featureFiles /etc/rebaca-test-suite"
+ "/featureFiles'")
+ count = 0
+ while count < 10:
+ epcstatus = os.system('juju status oai-epc | '
+ 'grep {} | grep {} | grep {}'
+ .format('EPC', 'is', 'running'))
+ if epcstatus == 0:
+ break
+ else:
+ time.sleep(60)
+ count = count + 1
+ os.system('juju-wait')
+ return True
+ else:
+ return False
+
+ def test_vnf(self):
+ start_time = time.time()
+ self.__logger.info("Running VNF Test cases....")
+ os.system('juju run-action abot-epc-basic/0 run '
+ 'tagnames={}'.format(self.details['test_vnf']['tag_name']))
+ os.system('juju-wait')
+ duration = time.time() - start_time
+ self.__logger.info("Getting results from Abot node....")
+ os.system('juju scp abot-epc-basic/0:/var/lib/abot-'
+ 'epc-basic/artifacts/TestResults.json {}/.'
+ .format(self.case_dir))
+ self.__logger.info("Parsing the Test results...")
+ res = (process_abot_test_result('{}/TestResults.'
+ 'json'.format(self.case_dir)))
+ short_result = sig_test_format(res)
+ self.__logger.info(short_result)
+ self.details['test_vnf'].update(status='PASS',
+ result=short_result,
+ full_result=res,
+ duration=duration)
+
+ self.__logger.info("Test VNF result: Passed: %d, Failed:"
+ "%d, Skipped: %d", short_result['passed'],
+ short_result['failures'], short_result['skipped'])
+ return True
+
+ def clean(self):
+ try:
+ if not self.orchestrator['requirements']['preserve_setup']:
+ self.__logger.info("Removing deployment files...")
+ testresult = os.path.join(self.case_dir, 'TestResults.json')
+ if os.path.exists(testresult):
+ os.remove(testresult)
+ self.__logger.info("Removing %s file ", self.filename)
+ if os.path.exists(self.filename):
+ os.remove(self.filename)
+ self.__logger.info("Destroying Orchestrator...")
+ os.system('juju destroy-controller -y abot-controller '
+ '--destroy-all-models')
+ except:
+ self.__logger.warn("Some issue during the undeployment ..")
+ self.__logger.warn("Tenant clean continue ..")
+
+ if not self.orchestrator['requirements']['preserve_setup']:
+ self.__logger.info('Remove the Abot_epc OS object ..')
+ for creator in reversed(self.created_object):
+ try:
+ creator.clean()
+ except Exception as exc:
+ self.__logger.error('Unexpected error cleaning - %s', exc)
+
+ self.__logger.info("Releasing all the floating IPs")
+ # user_id = os_utils.get_user_id(self.keystone_client,
+ # self.tenant_name)
+ floating_ips = os_utils.get_floating_ips(self.neutron_client)
+ tenant_id = os_utils.get_tenant_id(self.keystone_client,
+ self.tenant_name)
+ self.__logger.info("TENANT ID : %s", tenant_id)
+ for item in floating_ips:
+ if item['tenant_id'] == tenant_id:
+ os_utils.delete_floating_ip(self.neutron_client,
+ item['id'])
+ self.__logger.info("Cleaning Projects and Users")
+ for creator in reversed(self.created_object):
+ try:
+ creator.clean()
+ except Exception as exc: # pylint: disable=broad-except
+ self.__logger.error('Unexpected error cleaning - %s', exc)
+ return True
+
+
+# ----------------------------------------------------------
+#
+# YAML UTILS
+#
+# -----------------------------------------------------------
+def get_config(parameter, file_path):
+ """
+ Returns the value of a given parameter in file.yaml
+ parameter must be given in string format with dots
+ Example: general.openstack.image_name
+ """
+ with open(file_path) as config_file:
+ file_yaml = yaml.safe_load(config_file)
+ config_file.close()
+ value = file_yaml
+ for element in parameter.split("."):
+ value = value.get(element)
+ if value is None:
+ raise ValueError("The parameter %s is not defined in"
+ " reporting.yaml" % parameter)
+ return value
+
+
+def sig_test_format(sig_test):
+ """
+ Process the signaling result to have a short result
+ """
+ nb_passed = 0
+ nb_failures = 0
+ nb_skipped = 0
+ for data_test in sig_test:
+ if data_test['result'] == "passed":
+ nb_passed += 1
+ elif data_test['result'] == "failed":
+ nb_failures += 1
+ elif data_test['result'] == "skipped":
+ nb_skipped += 1
+ total_sig_test_result = {}
+ total_sig_test_result['passed'] = nb_passed
+ total_sig_test_result['failures'] = nb_failures
+ total_sig_test_result['skipped'] = nb_skipped
+ return total_sig_test_result
+
+
+def process_abot_test_result(file_path):
+ """ Process ABoT Result """
+ with open(file_path) as test_result:
+ data = json.load(test_result)
+ res = []
+ for tests in data:
+ tests = update_data(tests)
+ try:
+ flatten_steps = tests['elements'][0].pop('flatten_steps')
+ for steps in flatten_steps:
+ steps['result'] = steps['step_status']
+ res.append(steps)
+ except:
+ logging.error("Could not post data to ElasticSearch host")
+ raise
+ return res
+
+
+def update_data(obj):
+ """ Update Result data"""
+ try:
+ obj['feature_file'] = os.path.splitext(os.path.basename(obj['uri']))[0]
+
+ for element in obj['elements']:
+ element['final_result'] = "passed"
+ element['flatten_steps'] = []
+
+ for step in element['steps']:
+ temp_dict = {}
+ step['result'][step['result']['status']] = 1
+ if step['result']['status'].lower() in ['fail', 'failed']:
+ element['final_result'] = "failed"
+
+ temp_dict['feature_file'] = obj['feature_file']
+ temp_dict['step_name'] = step['name']
+ temp_dict['step_status'] = step['result']['status']
+ temp_dict['step_duration'] = step['result'].get('duration', 0)
+ temp_dict['step_' + step['result']['status']] = 1
+ element['flatten_steps'].append(deepcopy(temp_dict))
+
+ # Need to put the tag in OBJ and not ELEMENT
+ if 'tags' in obj:
+ element['tags'] = deepcopy(obj['tags'])
+ for tag in obj['tags']:
+ element[tag['name']] = 1
+ else:
+ for tag in element['tags']:
+ element[tag['name']] = 1
+
+ except:
+ logging.error("Error in updating data, %s" % (sys.exc_info()[0]))
+ raise
+
+ return obj
+
+
+def get_instance_metadata(nova_client, instance):
+ """ Get instance Metadata - Instance ID """
+ try:
+ instance = nova_client.servers.get(instance.id)
+ return instance.metadata
+ except Exception as e:
+ logging.error("Error [get_instance_status(nova_client)]: %s" % e)
+ return None
+
+
+CLOUD_TEMPLATE = """clouds:
+ abot-epc:
+ type: openstack
+ auth-types: [userpass]
+ endpoint: {url}
+ regions:
+ RegionOne:
+ endpoint: {url}
+credentials:
+ abot-epc:
+ abot-epc:
+ auth-type: userpass
+ password: {pass}
+ tenant-name: {tenant_n}
+ username: {user_n}"""
+
+
+def write_config(fname, template, **kwargs):
+ """ Generate yaml from template for addinh cloud in juju """
+ with open(fname, 'w') as yfile:
+ yfile.write(template.format(**kwargs))
+
+
+def append_config(file_name, p_domain, u_domain):
+ """ Append values into a yaml file """
+ with open(file_name) as yfile:
+ doc = yaml.load(yfile)
+ doc['credentials']['abot-epc']['abot-epc']['project-domain-name'] = (
+ p_domain)
+ doc['credentials']['abot-epc']['abot-epc']['user-domain-name'] = (
+ u_domain)
+
+ with open(file_name, 'w') as yfile:
+ yaml.safe_dump(doc, yfile, default_flow_style=False)