aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCédric Ollivier <cedric.ollivier@orange.com>2018-01-31 22:20:42 +0100
committerCédric Ollivier <cedric.ollivier@orange.com>2018-02-03 16:35:31 +0100
commite338c837cfa7476ad83e355b6149c37adc1715a5 (patch)
tree3c935ab4de3dfd9bcbb2cc639bd3b4467005dd2a
parent613d6b44998016ad84d87228cde53109fef0cc5f (diff)
Fix JujuEpc prepare() and deploy_orchestrator()
It bypasses a known unfixed Juju bug [1] by creating a second '_member_' user [1]. An 'admin' user is still required to create flavors and by snaps when listing virtual machines. It highlights a possible bug in user_creator.get_os_creds(). It partially rewrites the testcase by cleaning instance attributes and by taking several os.system() returns into account. It sets the new password automatically generated [2] and starts switching from openstack utils to snaps in vEPC. This patchset must be completed by unit tests and by another patch fully switching to snaps in the last methods. It should be noted that the testcase sets 8.8.8.8 as dns server which could raise side effects. [1] https://bugs.launchpad.net/juju/+bug/1710848 [2] https://gerrit.opnfv.org/gerrit/#/c/50747/ Change-Id: Id18b4b185aa1825196e91f6692338169f51faea8 Signed-off-by: Cédric Ollivier <cedric.ollivier@orange.com>
-rw-r--r--functest/opnfv_tests/vnf/epc/juju_epc.py350
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)