From 7040a716bdc4ca36e22988fdc931adb080e2a059 Mon Sep 17 00:00:00 2001 From: boucherv Date: Fri, 2 Oct 2015 09:29:33 +0200 Subject: vIMS deployment and cleanup These scripts allow to : - Prepare platform (tenant, user, image, quota etc) - Deploy cloudify-manager-server - Deploy vIMS Clearwater - Undeploy vIMS - Undeploy cloudify-manager-server - Clean the platform vIMS test coming soon JIRA: FUNCTEST-38 Change-Id: I35be6433c6511d741a27b67fe24c3031f1e29fe5 Signed-off-by: boucherv --- testcases/config_functest.yaml | 53 +++++- testcases/functest_utils.py | 40 ++++- testcases/vIMS/CI/create_venv.sh | 36 ++++ testcases/vIMS/CI/requirements.pip | 1 + testcases/vIMS/CI/vIMS.py | 332 +++++++++++++++++++++++++++++++++++++ 5 files changed, 458 insertions(+), 4 deletions(-) create mode 100755 testcases/vIMS/CI/create_venv.sh create mode 100644 testcases/vIMS/CI/requirements.pip create mode 100644 testcases/vIMS/CI/vIMS.py diff --git a/testcases/config_functest.yaml b/testcases/config_functest.yaml index c38b46066..e8ee6d9c6 100644 --- a/testcases/config_functest.yaml +++ b/testcases/config_functest.yaml @@ -1,4 +1,3 @@ ---- general: directories: # Relative to the path where the repo is cloned: @@ -6,7 +5,9 @@ general: dir_odl: testcases/Controllers/ODL/CI/ dir_rally: testcases/VIM/OpenStack/CI/libraries/ dir_rally_scn: testcases/VIM/OpenStack/CI/suites/ + dir_vIMS: testcases/vIMS/CI/ # Relative to $HOME: + dir_vIMS_data: functest/vIMS_data/ # $HOME/functest/vIMS_data/ dir_rally_res: functest/results/ # $HOME/functest/results dir_rally_repo: functest/Rally_repo/ # $HOME/Rally_repo/ dir_rally_inst: .rally/ # $HOME/.rally/ usually @@ -38,5 +39,53 @@ vping: ip_1: 192.168.120.30 ip_2: 192.168.120.40 +vIMS: + general: + tenant_name: vIMS + tenant_description: vIMS Functionality Testing + base_image_url: http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img + base_image_name: ubuntu_14.04 + cloudify: + blueprint: + url: https://github.com/cloudify-cosmo/cloudify-manager-blueprints.git + branch: "3.2-build" + file_name: "openstack-manager-blueprint.yaml" + inputs: + keystone_username: "" + keystone_password: "" + keystone_tenant_name: "" + keystone_url: "" + manager_public_key_name: 'cloudify-manager' + agent_public_key_name: 'cloudify-agent' + image_id: "" + flavor_id: "2" + external_network_name: "" + use_existing_manager_keypair: false + use_existing_agent_keypair: false + manager_server_name: cloudify-management-server + manager_server_user: ubuntu + manager_security_group_name: cloudify-sg-manager + agents_security_group_name: cloudify-sg-agents + manager_private_key_path: ~/.ssh/cloudify-manager-kp.pem + agent_private_key_path: ~/.ssh/cloudify-agent-kp.pem + agents_user: ubuntu + nova_url: "" + neutron_url: "" + resources_prefix: "" + inputs_path: openstack/inputs.yaml + clearwater: + blueprint: + file_name: 'openstack-blueprint.yaml' + name: "clearwater-opnfv" + destination_folder: "opnfv-cloudify-clearwater" + url: 'https://github.com/Orange-OpenSource/opnfv-cloudify-clearwater.git' + branch: "master" + deployment-name: 'clearwater-opnfv' + inputs: + image_id: '' + flavor_id: '' + agent_user: 'ubuntu' + external_network_name: '' + public_domain: clearwater.opnfv results: - test_db_url: http://213.77.62.197 + test_db_url: http://213.77.62.197 \ No newline at end of file diff --git a/testcases/functest_utils.py b/testcases/functest_utils.py index 101271384..6d60fbce3 100644 --- a/testcases/functest_utils.py +++ b/testcases/functest_utils.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # # jose.lausuch@ericsson.com +# valentin.boucher@orange.com # 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 @@ -217,8 +218,27 @@ def get_network_list(neutron_client): else : return network_list +def get_external_net(neutron_client): + for network in neutron_client.list_networks()['networks']: + if network['router:external']: + return network['name'] + return False + +def update_sg_quota(neutron_client, tenant_id, sg_quota, sg_rule_quota): + json_body = {"quota": { + "security_group": sg_quota, + "security_group_rule": sg_rule_quota + }} + + try: + quota = neutron_client.update_quota(tenant_id=tenant_id, body=json_body) + return True + except: + print "Error:", sys.exc_info()[0] + return False ################# GLANCE ################# + def get_image_id(glance_client, image_name): images = glance_client.images.list() id = '' @@ -228,10 +248,10 @@ def get_image_id(glance_client, image_name): break return id -def create_glance_image(glance_client, image_name, file_path): +def create_glance_image(glance_client, image_name, file_path, is_public=True): try: with open(file_path) as fimage: - image = glance_client.images.create(name=image_name, is_public=True, disk_format="qcow2", + image = glance_client.images.create(name=image_name, is_public=is_public, disk_format="qcow2", container_format="bare", data=fimage) return image.id except: @@ -282,6 +302,22 @@ def delete_tenant(keystone_client, tenant_id): print "Error:", sys.exc_info()[0] return False +def create_user(keystone_client, user_name, user_password, user_email, tenant_id): + try: + user = keystone_client.users.create(user_name, user_password, user_email, tenant_id, enabled=True) + return user.id + except: + print "Error:", sys.exc_info()[0] + return False + +def delete_user(keystone_client, user_id): + try: + tenant = keystone_client.users.delete(user_id) + return True + except: + print "Error:", sys.exc_info()[0] + return False + def add_role_user(keystone_client, user_id, role_id, tenant_id): try: keystone_client.roles.add_user_role(user_id, role_id, tenant_id) diff --git a/testcases/vIMS/CI/create_venv.sh b/testcases/vIMS/CI/create_venv.sh new file mode 100755 index 000000000..15294f77b --- /dev/null +++ b/testcases/vIMS/CI/create_venv.sh @@ -0,0 +1,36 @@ +#!/bin/bash -e + +# Script checks that venv exists. If it doesn't it will be created +# It requires python2.7 and virtualenv packages installed + +BASEDIR=`dirname $0` +VENV_PATH=$1 +VENV_NAME="venv_cloudify" +function venv_install() { + if command -v virtualenv-2.7; then + virtualenv-2.7 $1 + elif command -v virtualenv2; then + virtualenv2 $1 + elif command -v virtualenv; then + virtualenv $1 + else + echo Cannot find virtualenv command. + return 1 + fi +} + +# exit when something goes wrong during venv install +set -e +if [ ! -d "$VENV_PATH/$VENV_NAME" ]; then + venv_install $VENV_PATH/$VENV_NAME + echo "Virtualenv" + $VENV_NAME + "created." +fi + +if [ ! -f "$VENV_PATH/$VENV_NAME/updated" -o $BASEDIR/requirements.pip -nt $VENV_PATH/$VENV_NAME/updated ]; then + source $VENV_PATH/$VENV_NAME/bin/activate + pip install -r $BASEDIR/requirements.pip + touch $VENV_PATH/$VENV_NAME/updated + echo "Requirements installed." + deactivate +fi +set +e diff --git a/testcases/vIMS/CI/requirements.pip b/testcases/vIMS/CI/requirements.pip new file mode 100644 index 000000000..5d13172ec --- /dev/null +++ b/testcases/vIMS/CI/requirements.pip @@ -0,0 +1 @@ +cloudify==3.2 \ No newline at end of file diff --git a/testcases/vIMS/CI/vIMS.py b/testcases/vIMS/CI/vIMS.py new file mode 100644 index 000000000..d2d10f345 --- /dev/null +++ b/testcases/vIMS/CI/vIMS.py @@ -0,0 +1,332 @@ +#!/usr/bin/python +# coding: utf8 +####################################################################### +# +# Copyright (c) 2015 Orange +# valentin.boucher@orange.com +# +# 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 +######################################################################## + +import os, time, subprocess, logging, argparse, yaml, pprint, sys, shutil +from git import Repo +import keystoneclient.v2_0.client as ksclient +import glanceclient.client as glclient +import novaclient.client as nvclient +from neutronclient.v2_0 import client as ntclient + +import urllib +pp = pprint.PrettyPrinter(indent=4) + + +parser = argparse.ArgumentParser() +parser.add_argument("repo_path", help="Path to the repository") +parser.add_argument("-d", "--debug", help="Debug mode", action="store_true") +args = parser.parse_args() + +sys.path.append(args.repo_path + "testcases/") + +import functest_utils + +""" logging configuration """ +logger = logging.getLogger('vIMS') +logger.setLevel(logging.DEBUG) + +ch = logging.StreamHandler() +if args.debug: + ch.setLevel(logging.DEBUG) +else: + ch.setLevel(logging.INFO) +formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') +ch.setFormatter(formatter) +logger.addHandler(ch) + + +HOME = os.environ['HOME']+"/" +# with open(args.repo_path+"config_functest.yaml") as f: +with open(args.repo_path + "testcases/config_functest.yaml") as f: + functest_yaml = yaml.safe_load(f) +f.close() + +# Cloudify parameters +REPO_PATH = args.repo_path +HOME = os.environ['HOME']+"/" +VIMS_DIR = REPO_PATH + functest_yaml.get("general").get("directories").get("dir_vIMS") +VIMS_DATA_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_vIMS_data") + +TENANT_NAME = functest_yaml.get("vIMS").get("general").get("tenant_name") +TENANT_DESCRIPTION = functest_yaml.get("vIMS").get("general").get("tenant_description") +BASE_IMAGE_URL = functest_yaml.get("vIMS").get("general").get("base_image_url") +BASE_IMAGE_NAME = functest_yaml.get("vIMS").get("general").get("base_image_name") +GLANCE_IMAGE_NAME = functest_yaml.get("vIMS").get("cloudify").get("inputs").get("image_id") + +CFY_MANAGER_BLUEPRINT = functest_yaml.get("vIMS").get("cloudify").get("blueprint") +CFY_INPUTS = functest_yaml.get("vIMS").get("cloudify").get("inputs") +CFY_INPUTS_PATH = functest_yaml.get("vIMS").get("cloudify").get("inputs_path") + +CW_BLUEPRINT = functest_yaml.get("vIMS").get("clearwater").get("blueprint") +CW_DEPLOYMENT_NAME = functest_yaml.get("vIMS").get("clearwater").get("deployment-name") +CW_INPUTS = functest_yaml.get("vIMS").get("clearwater").get("inputs") +CW_DOMAIN_NAME = functest_yaml.get("vIMS").get("clearwater").get("inputs").get("public_domain") + + +def pMsg(value): + """pretty printing""" + pp.pprint(value) + +def download_and_add_image_on_glance(glance, image_name, image_url): + dest_path = VIMS_DATA_DIR + "tmp/" + file_name = image_url.rsplit('/')[-1] + if not functest_utils.download_url(image_url, dest_path): + logger.error("Failed to download image %s" %file_name) + return False + + image = functest_utils.create_glance_image(glance, image_name, dest_path + file_name) + if not image: + logger.error("Failed to upload image on glance") + return False + + return image + +def download_blueprints(blueprint_url, branch, dest_path): + if os.path.exists(dest_path): + shutil.rmtree(dest_path) + try: + Repo.clone_from(blueprint_url, dest_path, branch=branch) + return True + except: + return False + +def initialize_deployments(): + if not os.path.exists(VIMS_DATA_DIR): + os.makedirs(VIMS_DATA_DIR) + + ks_creds = functest_utils.get_credentials("keystone") + nv_creds = functest_utils.get_credentials("nova") + nt_creds = functest_utils.get_credentials("neutron") + + logger.info("Prepare OpenStack plateform (create tenant and user)") + keystone = ksclient.Client(**ks_creds) + + user_id = functest_utils.get_user_id(keystone, ks_creds['username']) + if user_id == '': + logger.error("Error : Failed to get id of %s user" %ks_creds['username']) + exit(-1) + + tenant_id = functest_utils.create_tenant(keystone, TENANT_NAME, TENANT_DESCRIPTION) + if tenant_id == '': + logger.error("Error : Failed to create %s tenant" %TENANT_NAME) + exit(-1) + + role_name = "admin" + role_id = functest_utils.get_role_id(keystone, role_name) + if role_id == '': + logger.error("Error : Failed to get id for %s role" %role_name) + + if not functest_utils.add_role_user(keystone, user_id, role_id, tenant_id): + logger.error("Error : Failed to add %s on tenant" %ks_creds['username']) + + user_id = functest_utils.create_user(keystone, TENANT_NAME, TENANT_NAME, None, tenant_id) + if user_id == '': + logger.error("Error : Failed to create %s user" %TENANT_NAME) + + logger.info("Update OpenStack creds informations") + ks_creds.update({ + "username": TENANT_NAME, + "password": TENANT_NAME, + "tenant_name": TENANT_NAME, + }) + + nt_creds.update({ + "tenant_name": TENANT_NAME, + }) + + nv_creds.update({ + "project_id": TENANT_NAME, + }) + + logger.info("Upload ubuntu image if it doesn't exist") + glance_endpoint = keystone.service_catalog.url_for(service_type='image', + endpoint_type='publicURL') + glance = glclient.Client(1, glance_endpoint, token=keystone.auth_token) + + image_id = functest_utils.get_image_id(glance, BASE_IMAGE_NAME) + if image_id == '': + logger.info("""%s image doesn't exist on glance repository. + Try downloading this image and upload on glance !""" %BASE_IMAGE_NAME) + image_id = download_and_add_image_on_glance(glance, BASE_IMAGE_NAME, BASE_IMAGE_URL) + + if image_id == '': + logger.error("Error : Failed to find or upload required OS image for this deployment" %flavor_name) + exit(-1) + + logger.info("Collect flavor id for cloudify and clearwater VMs") + nova = nvclient.Client("2", **nv_creds) + + flavor_name = "m1.small" + flavor_id = functest_utils.get_flavor_id(nova, flavor_name) + if flavor_id == '': + logger.error("Failed to find %s flavor. Try with ram range requirement !" %flavor_name) + flavor_id = get_flavor_id_by_ram_range(nova, 1792, 2048) + + if flavor_id == '': + logger.error("Failed to find required flavor for this deployment" %flavor_name) + exit(-1) + + logger.info("Update security group quota for this tenant") + neutron = ntclient.Client(**nt_creds) + if not functest_utils.update_sg_quota(neutron, tenant_id, 50, 100): + logger.error("Failed to update security group quota for tenant %s" %TENANT_NAME) + exit(-1) + + ext_net = functest_utils.get_external_net(neutron) + if not ext_net: + logger.error("Failed to get external network") + exit(-1) + + logger.info("Update inputs informations") + CFY_INPUTS['image_id'] = image_id + CFY_INPUTS['flavor_id'] = flavor_id + CFY_INPUTS['external_network_name'] = ext_net + + CW_INPUTS['image_id'] = image_id + CW_INPUTS['flavor_id'] = flavor_id + CW_INPUTS['external_network_name'] = ext_net + + CFY_INPUTS['keystone_username'] = ks_creds['username'] + CFY_INPUTS['keystone_password'] = ks_creds['password'] + CFY_INPUTS['keystone_url'] = ks_creds['auth_url'] + CFY_INPUTS['keystone_tenant_name'] = ks_creds['tenant_name'] + + logger.info("Prepare virtualenv for cloudify-cli") + cmd = "chmod +x " + VIMS_DIR + "create_venv.sh" + functest_utils.execute_command(cmd,logger) + cmd = VIMS_DIR + "create_venv.sh " + VIMS_DATA_DIR + functest_utils.execute_command(cmd,logger) + +def cleanup_deployments(): + ks_creds = functest_utils.get_credentials("keystone") + + keystone = ksclient.Client(**ks_creds) + + logger.info("Removing %s tenant .." %CFY_INPUTS['keystone_tenant_name']) + tenant_id = functest_utils.get_tenant_id(keystone, CFY_INPUTS['keystone_tenant_name']) + if tenant_id == '': + logger.error("Error : Failed to get id of %s tenant" %CFY_INPUTS['keystone_tenant_name']) + else: + if not functest_utils.delete_tenant(keystone, tenant_id): + logger.error("Error : Failed to remove %s tenant" %CFY_INPUTS['keystone_tenant_name']) + + logger.info("Removing %s user .." %CFY_INPUTS['keystone_username']) + user_id = functest_utils.get_user_id(keystone, CFY_INPUTS['keystone_username']) + if user_id == '': + logger.error("Error : Failed to get id of %s user" %CFY_INPUTS['keystone_username']) + else: + if not functest_utils.delete_user(keystone, user_id): + logger.error("Error : Failed to remove %s user" %CFY_INPUTS['keystone_username']) + +def deploy_cloudify_manager(): + + logger.info("Downloading the cloudify manager server blueprint") + download_result = download_blueprints(CFY_MANAGER_BLUEPRINT['url'], + CFY_MANAGER_BLUEPRINT['branch'], + VIMS_DATA_DIR + 'cloudify-manager-blueprint/') + + if not download_result: + logger.error("Failed to download manager blueprint") + exit(-1) + + logger.info("Writing the inputs file") + with open( VIMS_DATA_DIR + 'cloudify-manager-blueprint/' + CFY_INPUTS_PATH, "w") as f: + f.write(yaml.dump(CFY_INPUTS, default_style='"') ) + f.close() + + logger.info("Launching the cloudify-manager deployment") + script = "source " + VIMS_DATA_DIR + "venv_cloudify/bin/activate; " + script += "cd " + VIMS_DATA_DIR + "; " + script += "cfy init -r; " + script += "cd cloudify-manager-blueprint/openstack; " + script += "cfy local create-requirements -o requirements.txt -p openstack-manager-blueprint.yaml; " + script += "pip install -r requirements.txt; " + script += "cfy bootstrap --install-plugins -p openstack-manager-blueprint.yaml -i inputs.yaml; " + cmd = "/bin/bash -c '" + script + "'" + functest_utils.execute_command(cmd, logger) + + logger.info("Cloudify-manager server is UP !") + +def undeploy_cloudify_manager(): + + logger.info("Launching the cloudify-manager undeployment") + script = "source " + VIMS_DATA_DIR + "venv_cloudify/bin/activate; " + script += "cd " + VIMS_DATA_DIR + "; " + script += "cfy teardown -f; " + cmd = "/bin/bash -c '" + script + "'" + functest_utils.execute_command(cmd, logger) + + logger.info("Cloudify-manager server has been successfully removed!") + +def deploy_clearwater(): + + logger.info("Downloading the {0} blueprint".format(CW_BLUEPRINT['file_name'])) + download_result = download_blueprints(CW_BLUEPRINT['url'], CW_BLUEPRINT['branch'], + VIMS_DATA_DIR + CW_BLUEPRINT['destination_folder']) + + if not download_result: + logger.error("Failed to download blueprint {0}".format(CW_BLUEPRINT['file_name'])) + exit(-1) + + logger.info("Writing the inputs file") + with open(VIMS_DATA_DIR + CW_BLUEPRINT['destination_folder'] + "/inputs.yaml", "w") as f: + f.write(yaml.dump(CW_INPUTS, default_style='"') ) + f.close() + + logger.info("Launching the {0} deployment".format(CW_BLUEPRINT['name'])) + script = "source " + VIMS_DATA_DIR + "venv_cloudify/bin/activate; " + script += "cd " + VIMS_DATA_DIR + CW_BLUEPRINT['destination_folder'] + "; " + script += "cfy blueprints upload -b " + CW_BLUEPRINT['name'] + " -p openstack-blueprint.yaml; " + script += "cfy deployments create -b " + CW_BLUEPRINT['name'] + " -d " + CW_DEPLOYMENT_NAME + " --inputs inputs.yaml; " + script += "cfy executions start -w install -d " + CW_DEPLOYMENT_NAME + "; " + + cmd = "/bin/bash -c '" + script + "'" + functest_utils.execute_command(cmd, logger) + + logger.info("Clearwater vIMS is UP !") + +def undeploy_clearwater(): + + logger.info("Launching the {0} undeployment".format(CW_BLUEPRINT['name'])) + script = "source " + VIMS_DATA_DIR + "venv_cloudify/bin/activate; " + script += "cd " + VIMS_DATA_DIR + "; " + script += "cfy executions start -w uninstall -d " + CW_DEPLOYMENT_NAME + "; " + script += "cfy deployments delete -d " + CW_DEPLOYMENT_NAME + "; " + + cmd = "/bin/bash -c '" + script + "'" + functest_utils.execute_command(cmd, logger) + +def test_clearwater(): + + script = "source " + VIMS_DATA_DIR + "venv_cloudify/bin/activate; " + script += "cd " + VIMS_DATA_DIR + "; " + script += "cfy deployments outputs -d clearwater-opnfv | grep Value: | sed \"s/ *Value: //g\";" + cmd = "/bin/bash -c '" + script + "'" + dns_ip = os.popen(cmd).read() + dns_ip = dns_ip.splitlines()[0] + + # Coming soon + +def main(): + initialize_deployments() + deploy_cloudify_manager() + deploy_clearwater() + + #test_clearwater() + + undeploy_clearwater() + undeploy_cloudify_manager() + cleanup_deployments() + +if __name__ == '__main__': + main() \ No newline at end of file -- cgit 1.2.3-korg