diff options
-rw-r--r-- | functest/opnfv_tests/vnf/epc/juju_epc.py | 350 |
1 files changed, 177 insertions, 173 deletions
diff --git a/functest/opnfv_tests/vnf/epc/juju_epc.py b/functest/opnfv_tests/vnf/epc/juju_epc.py index 052efd3ff..4ca540f17 100644 --- a/functest/opnfv_tests/vnf/epc/juju_epc.py +++ b/functest/opnfv_tests/vnf/epc/juju_epc.py @@ -8,11 +8,13 @@ # http://www.apache.org/licenses/LICENSE-2.0 """Juju testcase implementation.""" +import errno import logging import os import time import json import sys +import uuid from copy import deepcopy from urlparse import urljoin @@ -26,16 +28,49 @@ from snaps.config.flavor import FlavorConfig from snaps.config.image import ImageConfig from snaps.config.network import NetworkConfig, SubnetConfig from snaps.config.router import RouterConfig +from snaps.config.user import UserConfig from snaps.openstack.create_flavor import OpenStackFlavor from snaps.openstack.create_image import OpenStackImage from snaps.openstack.create_network import OpenStackNetwork from snaps.openstack.create_router import OpenStackRouter +from snaps.openstack.create_user import OpenStackUser from snaps.openstack.utils import keystone_utils +from snaps.openstack.utils import neutron_utils +from snaps.openstack.utils import nova_utils import yaml __author__ = "Amarendra Meher <amarendra@rebaca.com>" __author__ = "Soumaya K Nayek <soumaya.nayek@rebaca.com>" +CLOUD_TEMPLATE = """clouds: + abot-epc: + type: openstack + auth-types: [userpass] + endpoint: {url} + regions: + {region}: + endpoint: {url}""" + +CREDS_TEMPLATE2 = """credentials: + abot-epc: + default-credential: abot-epc + abot-epc: + auth-type: userpass + password: {pass} + project-domain-name: {project_domain_n} + tenant-name: {tenant_n}""" + +CREDS_TEMPLATE3 = """credentials: + abot-epc: + default-credential: abot-epc + abot-epc: + auth-type: userpass + password: {pass} + project-domain-name: {project_domain_n} + tenant-name: {tenant_n} + user-domain-name: {user_domain_n} + username: {user_n}""" + class JujuEpc(vnf.VnfOnBoarding): # pylint:disable=too-many-instance-attributes @@ -54,103 +89,127 @@ class JujuEpc(vnf.VnfOnBoarding): self.case_dir = pkg_resources.resource_filename( 'functest', 'opnfv_tests/vnf/epc') try: - self.config = CONST.__getattribute__( - 'vnf_{}_config'.format(self.case_name)) + self.config = getattr( + CONST, '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.config_file = os.path.join(self.case_dir, self.config) + self.orchestrator = dict(requirements=get_config( + "orchestrator.requirements", self.config_file)) self.created_object = [] - self.snaps_creds = snaps_utils.get_credentials() self.details['orchestrator'] = dict( - name=get_config("orchestrator.name", config_file), - version=get_config("orchestrator.version", config_file), + name=get_config("orchestrator.name", self.config_file), + version=get_config("orchestrator.version", self.config_file), status='ERROR', result='' ) self.vnf = dict( - descriptor=get_config("vnf.descriptor", config_file), - requirements=get_config("vnf.requirements", config_file) + descriptor=get_config("vnf.descriptor", self.config_file), + requirements=get_config("vnf.requirements", self.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), + name=get_config("vnf.name", self.config_file), + version=get_config("vnf.version", self.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) + name=get_config("vnf_test_suite.name", self.config_file), + version=get_config("vnf_test_suite.version", self.config_file), + tag_name=get_config("vnf_test_suite.tag_name", self.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() - self.sec_group_id = None self.public_auth_url = None - self.creds = None - self.filename = None - def prepare(self): - """Prepare testcase (Additional pre-configuration steps).""" - self.__logger.debug("OS Credentials: %s", os_utils.get_credentials()) + self.res_dir = os.path.join( + getattr(CONST, 'dir_results'), self.case_name) - super(JujuEpc, self).prepare() + def _bypass_juju_network_discovery_bug(self, name): + user_creator = OpenStackUser( + self.snaps_creds, + UserConfig( + name=name, password=str(uuid.uuid4()), + roles={'_member_': self.tenant_name})) + user_creator.create() + self.created_object.append(user_creator) + return user_creator + + def _register_cloud(self): + self.__logger.info("Creating Cloud for Abot-epc .....") + clouds_yaml = os.path.join(self.res_dir, "clouds.yaml") + cloud_data = { + 'url': self.public_auth_url, + 'region': os.environ.get( + "OS_REGION_NAME", self.default_region_name)} + with open(clouds_yaml, 'w') as yfile: + yfile.write(CLOUD_TEMPLATE.format(**cloud_data)) + if os.system( + 'juju add-cloud abot-epc -f {} --replace'.format(clouds_yaml)): + raise vnf.VnfPreparationException + + def _register_credentials_v2(self): + self.__logger.info("Creating Credentials for Abot-epc .....") + user_creator = self._bypass_juju_network_discovery_bug( + 'juju_network_discovery_bug') + snaps_creds = user_creator.get_os_creds('juju_network_discovery_bug') + credentials_yaml = os.path.join(self.res_dir, "credentials.yaml") + # 'tenant_n' should habe been equal to snaps_creds.project_name + # user_creator.get_os_creds() must be checked + creds_data = { + 'pass': snaps_creds.password, + 'tenant_n': self.snaps_creds.project_name, + 'user_n': snaps_creds.username} + with open(credentials_yaml, 'w') as yfile: + yfile.write(CREDS_TEMPLATE2.format(**creds_data)) + if os.system( + 'juju add-credential abot-epc -f {} --replace'.format( + credentials_yaml)): + raise vnf.VnfPreparationException + + def _register_credentials_v3(self): + self.__logger.info("Creating Credentials for Abot-epc .....") + user_creator = self._bypass_juju_network_discovery_bug( + 'juju_network_discovery_bug') + snaps_creds = user_creator.get_os_creds('juju_network_discovery_bug') + credentials_yaml = os.path.join(self.res_dir, "credentials.yaml") + # 'tenant_n' should habe been equal to snaps_creds.project_name + # user_creator.get_os_creds() must be checked + creds_data = { + 'pass': snaps_creds.password, + 'tenant_n': self.snaps_creds.project_name, + 'user_n': snaps_creds.username, + 'project_domain_n': snaps_creds.project_domain_name, + 'user_domain_n': snaps_creds.user_domain_name} + with open(credentials_yaml, 'w') as yfile: + yfile.write(CREDS_TEMPLATE3.format(**creds_data)) + if os.system( + 'juju add-credential abot-epc -f {} --replace'.format( + credentials_yaml)): + raise vnf.VnfPreparationException + def prepare(self): + """Prepare testcase (Additional pre-configuration steps).""" self.__logger.info("Additional pre-configuration steps") + super(JujuEpc, self).prepare() + try: + os.makedirs(self.res_dir) + except OSError as ex: + if ex.errno != errno.EEXIST: + self.__logger.exception("Cannot create %s", self.res_dir) + raise vnf.VnfPreparationException self.public_auth_url = keystone_utils.get_endpoint( self.snaps_creds, 'identity') # it enforces a versioned public identity endpoint as juju simply # adds /auth/tokens wich fails vs an unversioned endpoint. if not self.public_auth_url.endswith(('v3', 'v3/', 'v2.0', 'v2.0/')): self.public_auth_url = urljoin(self.public_auth_url, 'v3') - - self.creds = { - "tenant": self.tenant_name, - "username": self.tenant_name, - "password": self.tenant_name, - "auth_url": os_utils.get_credentials()['auth_url'] - } - - cloud_data = { - 'url': self.public_auth_url, - 'pass': self.tenant_name, - 'tenant_n': self.tenant_name, - 'user_n': self.tenant_name, - 'region': os.environ.get( - "OS_REGION_NAME", self.default_region_name) - } - self.__logger.info("Cloud DATA: %s", cloud_data) - self.filename = os.path.join(self.case_dir, 'abot-epc.yaml') - self.__logger.info("Create %s to add cloud info", self.filename) - write_config(self.filename, CLOUD_TEMPLATE, **cloud_data) - + self._register_cloud() 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, - ImageConfig(name=image_name, - image_user='cloud', - img_format='qcow2', - image_file=image_file)) - image_creator.create() - self.created_object.append(image_creator) + self._register_credentials_v3() + else: + self._register_credentials_v2() def deploy_orchestrator(self): # pylint: disable=too-many-locals """ @@ -159,32 +218,31 @@ class JujuEpc(vnf.VnfOnBoarding): Bootstrap juju """ 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)) + private_net_name = getattr( + CONST, 'vnf_{}_private_net_name'.format(self.case_name)) + private_subnet_name = getattr( + CONST, 'vnf_{}_private_subnet_name'.format(self.case_name)) + private_subnet_cidr = getattr( + CONST, 'vnf_{}_private_subnet_cidr'.format(self.case_name)) + abot_router = getattr( + CONST, 'vnf_{}_external_router'.format(self.case_name)) + dns_nameserver = getattr( + CONST, 'vnf_{}_dns_nameserver'.format(self.case_name)) self.__logger.info("Creating full network ...") - subnet_settings = SubnetConfig(name=private_subnet_name, - cidr=private_subnet_cidr, - dns_nameservers=dns_nameserver) - network_settings = NetworkConfig(name=private_net_name, - subnet_settings=[subnet_settings]) + subnet_settings = SubnetConfig( + name=private_subnet_name, cidr=private_subnet_cidr, + dns_nameservers=dns_nameserver) + network_settings = NetworkConfig( + name=private_net_name, subnet_settings=[subnet_settings]) network_creator = OpenStackNetwork(self.snaps_creds, network_settings) - network_creator.create() + net_id = network_creator.create().id 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, - RouterConfig( + self.snaps_creds, RouterConfig( name=abot_router, external_gateway=ext_net_name, internal_subnets=[subnet_settings.name])) @@ -194,33 +252,35 @@ class JujuEpc(vnf.VnfOnBoarding): flavor_settings = FlavorConfig( name=self.orchestrator['requirements']['flavor']['name'], ram=self.orchestrator['requirements']['flavor']['ram_min'], - disk=10, - vcpus=1) + 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("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 ' - '{} -u {}'.format( - image_id, image_name, - os.environ.get("OS_REGION_NAME", self.default_region_name), - self.public_auth_url)) - net_id = os_utils.get_network_id(self.neutron_client, private_net_name) + self.__logger.info("Upload some OS images if it doesn't exist") + images = get_config("tenant_images", self.config_file) + self.__logger.info("Images needed for vEPC: %s", images) + for image_name, image_file in 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, ImageConfig( + name=image_name, image_user='cloud', img_format='qcow2', + image_file=image_file)) + image_id = image_creator.create().id + os.system( + 'juju metadata generate-image -d ~ -i {} -s {} -r ' + '{} -u {}'.format( + image_id, image_name, + os.environ.get( + "OS_REGION_NAME", self.default_region_name), + self.public_auth_url)) + self.created_object.append(image_creator) self.__logger.info("Credential information : %s", net_id) - juju_bootstrap_command = ('juju bootstrap abot-epc abot-controller ' - '--config network={} --metadata-source ~ ' - '--config ssl-hostname-verification=false ' - '--constraints mem=2G --bootstrap-series ' - 'xenial ' - '--config use-floating-ip=true --debug'. - format(net_id)) + juju_bootstrap_command = ( + 'juju bootstrap abot-epc abot-controller --config network={} ' + '--metadata-source ~ --config ssl-hostname-verification=false ' + '--constraints mem=2G --bootstrap-series xenial ' + '--config use-floating-ip=true --debug ' + '--config use-default-secgroup=true'.format(net_id)) os.system(juju_bootstrap_command) return True @@ -243,19 +303,21 @@ class JujuEpc(vnf.VnfOnBoarding): status = os.system('juju-wait') self.__logger.info("juju wait completed: %s", status) self.__logger.info("Deployed Abot-epc on Openstack") + nova_client = nova_utils.nova_client(self.snaps_creds) + neutron_client = neutron_utils.neutron_client(self.snaps_creds) if status == 0: - instances = os_utils.get_instances(self.nova_client) + instances = os_utils.get_instances(nova_client) for items in instances: - metadata = get_instance_metadata(self.nova_client, items) + metadata = get_instance_metadata(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) + 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) + os_utils.create_secgroup_rule( + 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)) @@ -312,9 +374,6 @@ class JujuEpc(vnf.VnfOnBoarding): 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') @@ -324,27 +383,8 @@ class JujuEpc(vnf.VnfOnBoarding): 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: # pylint: disable=broad-except - self.__logger.error('Unexpected error cleaning - %s', exc) - - self.__logger.info("Releasing all the floating IPs") - 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) + super(JujuEpc, self).clean() + return True @@ -456,39 +496,3 @@ def get_instance_metadata(nova_client, instance): except Exception as exc: # pylint: disable=broad-except logging.error("Error [get_instance_status(nova_client)]: %s", exc) return None - - -CLOUD_TEMPLATE = """clouds: - abot-epc: - type: openstack - auth-types: [userpass] - endpoint: {url} - regions: - {region}: - 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) |