From 2f9219dfa44982779990e13c177a703f2239b488 Mon Sep 17 00:00:00 2001 From: boucherv Date: Wed, 23 Aug 2017 16:23:34 +0200 Subject: New testcase creation named "cloudify_ims_perf" * IMS deployment with "cloudify_ims" testcase * IXIA infrastructure creation with SNAPS * Module configuration with REST API * Configure and run the perf tests with REST API Change-Id: I3dfddda87f9e9f4f03df375f6a032ded26a627b3 Signed-off-by: boucherv Co-Authored-By: Arturo Sordo Miralles --- functest/opnfv_tests/vnf/ims/cloudify_ims_perf.py | 509 ++++++++++++++++++++++ 1 file changed, 509 insertions(+) create mode 100644 functest/opnfv_tests/vnf/ims/cloudify_ims_perf.py (limited to 'functest/opnfv_tests/vnf/ims/cloudify_ims_perf.py') diff --git a/functest/opnfv_tests/vnf/ims/cloudify_ims_perf.py b/functest/opnfv_tests/vnf/ims/cloudify_ims_perf.py new file mode 100644 index 00000000..90068525 --- /dev/null +++ b/functest/opnfv_tests/vnf/ims/cloudify_ims_perf.py @@ -0,0 +1,509 @@ +#!/usr/bin/env python + +# Copyright (c) 2017 Orange, IXIA 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 + +"""CloudifyImsPerf testcase implementation.""" + +import logging +import os +import time + +import json +import yaml +import paramiko +import dns.resolver +from jinja2 import Environment, FileSystemLoader + + +from functest.energy import energy +from functest.opnfv_tests.openstack.snaps import snaps_utils +import functest.opnfv_tests.vnf.ims.cloudify_ims as cloudify_ims +from functest.utils.constants import CONST + +from snaps.openstack.create_network import (NetworkSettings, SubnetSettings, + OpenStackNetwork, PortSettings) +from snaps.openstack.create_security_group import (SecurityGroupSettings, + SecurityGroupRuleSettings, + Direction, Protocol, + OpenStackSecurityGroup) +from snaps.openstack.create_router import RouterSettings, OpenStackRouter +from snaps.openstack.create_instance import (VmInstanceSettings, + FloatingIpSettings, + OpenStackVmInstance) +from snaps.openstack.create_flavor import FlavorSettings, OpenStackFlavor +from snaps.openstack.create_image import ImageSettings + +from ixia.utils.IxChassisUtils import ChassisRestAPI +import ixia.utils.IxLoadUtils as IxLoadUtils +import ixia.utils.IxRestUtils as IxRestUtils + +__author__ = "Valentin Boucher " + + +class CloudifyImsPerf(cloudify_ims.CloudifyIms): + """Clearwater vIMS deployed with Cloudify Orchestrator Case.""" + + __logger = logging.getLogger(__name__) + + def __init__(self, **kwargs): + """Initialize CloudifyIms testcase object.""" + if "case_name" not in kwargs: + kwargs["case_name"] = "cloudify_ims_perf" + super(CloudifyImsPerf, self).__init__(**kwargs) + + # Retrieve the configuration + try: + self.config = CONST.__getattribute__( + 'vnf_{}_config'.format(self.case_name)) + except Exception: + raise Exception("VNF config file not found") + + self.snaps_creds = '' + self.created_object = [] + + config_file = os.path.join(self.case_dir, self.config) + self.orchestrator = dict( + requirements=get_config("orchestrator.requirements", config_file), + ) + self.details['orchestrator'] = dict( + name=get_config("orchestrator.name", config_file), + version=get_config("orchestrator.version", config_file), + status='ERROR', + result='' + ) + self.__logger.debug("Orchestrator configuration %s", self.orchestrator) + self.vnf = dict( + descriptor=get_config("vnf.descriptor", config_file), + inputs=get_config("vnf.inputs", 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.test = dict( + version=get_config("vnf_test_suite.version", config_file), + inputs=get_config("vnf_test_suite.inputs", config_file), + requirements=get_config("vnf_test_suite.requirements", config_file) + ) + + self.details['test_vnf'] = dict( + name=get_config("vnf_test_suite.name", config_file), + version=get_config("vnf_test_suite.version", config_file), + requirements=get_config("vnf_test_suite.requirements", config_file) + ) + self.images = get_config("tenant_images", config_file) + self.__logger.info("Images needed for vIMS: %s", self.images) + + def test_vnf(self): + """Run IXIA Stress test on clearwater ims instance.""" + start_time = time.time() + + cfy_client = self.orchestrator['object'] + + outputs = cfy_client.deployments.outputs.get( + self.vnf['descriptor'].get('name'))['outputs'] + dns_ip = outputs['dns_ip'] + ellis_ip = outputs['ellis_ip'] + + self.__logger.info("Creating full IXIA network ...") + subnet_settings = SubnetSettings(name='ixia_management_subnet', + cidr='10.10.10.0/24') + network_settings = NetworkSettings(name='ixia_management_network', + 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) + router_creator = OpenStackRouter( + self.snaps_creds, + RouterSettings( + name='ixia_management_router', + external_gateway=ext_net_name, + internal_subnets=[subnet_settings.name])) + router_creator.create() + self.created_object.append(router_creator) + + # security group creation + self.__logger.info("Creating security groups for IXIA VMs") + sg_rules = list() + sg_rules.append( + SecurityGroupRuleSettings(sec_grp_name="ixia_management", + direction=Direction.ingress, + protocol=Protocol.tcp, port_range_min=1, + port_range_max=65535)) + sg_rules.append( + SecurityGroupRuleSettings(sec_grp_name="ixia_management", + direction=Direction.ingress, + protocol=Protocol.udp, port_range_min=1, + port_range_max=65535)) + sg_rules.append( + SecurityGroupRuleSettings(sec_grp_name="ixia_management", + direction=Direction.ingress, + protocol=Protocol.icmp)) + + ixia_managment_sg_settings = SecurityGroupSettings( + name="ixia_management", + rule_settings=sg_rules) + securit_group_creator = OpenStackSecurityGroup( + self.snaps_creds, + ixia_managment_sg_settings) + + securit_group_creator.create() + self.created_object.append(securit_group_creator) + + sg_rules = list() + sg_rules.append( + SecurityGroupRuleSettings(sec_grp_name="ixia_ssh_http", + direction=Direction.ingress, + protocol=Protocol.tcp, port_range_min=1, + port_range_max=65535)) + + ixia_ssh_http_sg_settings = SecurityGroupSettings( + name="ixia_ssh_http", + rule_settings=sg_rules) + securit_group_creator = OpenStackSecurityGroup( + self.snaps_creds, + ixia_ssh_http_sg_settings) + + securit_group_creator.create() + self.created_object.append(securit_group_creator) + + chassis_flavor_settings = FlavorSettings( + name="ixia_vChassis", + ram=4096, + disk=40, + vcpus=2) + flavor_creator = OpenStackFlavor(self.snaps_creds, + chassis_flavor_settings) + flavor_creator.create() + self.created_object.append(flavor_creator) + + card_flavor_settings = FlavorSettings( + name="ixia_vCard", + ram=4096, + disk=4, + vcpus=2) + flavor_creator = OpenStackFlavor(self.snaps_creds, + card_flavor_settings) + flavor_creator.create() + self.created_object.append(flavor_creator) + + load_flavor_settings = FlavorSettings( + name="ixia_vLoad", + ram=8192, + disk=100, + vcpus=4) + flavor_creator = OpenStackFlavor(self.snaps_creds, + load_flavor_settings) + flavor_creator.create() + self.created_object.append(flavor_creator) + + chassis_image_settings = ImageSettings( + name=self.test['requirements']['chassis']['image'], + image_user='admin', + exists=True) + + card_image_settings = ImageSettings( + name=self.test['requirements']['card']['image'], + image_user='admin', + exists=True) + + load_image_settings = ImageSettings( + name=self.test['requirements']['load']['image'], + image_user='admin', + exists=True) + + chassis_port_settings = PortSettings( + name='ixia_chassis_port', + network_name=network_settings.name) + + card1_port1_settings = PortSettings( + name='ixia_card1_port1', + network_name=network_settings.name) + + card2_port1_settings = PortSettings( + name='ixia_card2_port1', + network_name=network_settings.name) + + card1_port2_settings = PortSettings( + name='ixia_card1_port2', + network_name="cloudify_ims_network") + + card2_port2_settings = PortSettings( + name='ixia_card2_port2', + network_name="cloudify_ims_network") + + load_port_settings = PortSettings( + name='ixia_load_port', + network_name=network_settings.name) + + chassis_settings = VmInstanceSettings( + name='ixia_vChassis', + flavor=chassis_flavor_settings.name, + port_settings=[chassis_port_settings], + security_group_names=[ixia_ssh_http_sg_settings.name, + ixia_managment_sg_settings.name], + floating_ip_settings=[FloatingIpSettings( + name='ixia_vChassis_fip', + port_name=chassis_port_settings.name, + router_name=router_creator.router_settings.name)]) + + vm_creator = OpenStackVmInstance(self.snaps_creds, + chassis_settings, + chassis_image_settings) + + self.__logger.info("Creating Ixia vChassis VM") + vm_creator.create() + fip_chassis = vm_creator.get_floating_ip().ip + self.created_object.append(vm_creator) + + card1_settings = VmInstanceSettings( + name='ixia_vCard1', + flavor=card_flavor_settings.name, + port_settings=[card1_port1_settings, card1_port2_settings], + security_group_names=[ixia_managment_sg_settings.name]) + + vm_creator = OpenStackVmInstance(self.snaps_creds, + card1_settings, + card_image_settings) + + self.__logger.info("Creating Ixia vCard1 VM") + vm_creator.create() + vcard_ips = list() + vcard_ips_p2 = list() + vcard_ips.append(vm_creator.get_port_ip('ixia_card1_port1')) + vcard_ips_p2.append(vm_creator.get_port_ip('ixia_card1_port2')) + self.created_object.append(vm_creator) + + card2_settings = VmInstanceSettings( + name='ixia_vCard2', + flavor=card_flavor_settings.name, + port_settings=[card2_port1_settings, card2_port2_settings], + security_group_names=[ixia_managment_sg_settings.name]) + + vm_creator = OpenStackVmInstance(self.snaps_creds, + card2_settings, + card_image_settings) + + self.__logger.info("Creating Ixia vCard2 VM") + vm_creator.create() + vcard_ips.append(vm_creator.get_port_ip('ixia_card2_port1')) + vcard_ips_p2.append(vm_creator.get_port_ip('ixia_card2_port2')) + self.created_object.append(vm_creator) + + load_settings = VmInstanceSettings( + name='ixia_vLoad', + flavor=load_flavor_settings.name, + port_settings=[load_port_settings], + security_group_names=[ixia_ssh_http_sg_settings.name, + ixia_managment_sg_settings.name], + floating_ip_settings=[FloatingIpSettings( + name='ixia_vLoad_fip', + port_name=load_port_settings.name, + router_name=router_creator.router_settings.name)]) + + vm_creator = OpenStackVmInstance(self.snaps_creds, + load_settings, + load_image_settings) + + self.__logger.info("Creating Ixia vLoad VM") + vm_creator.create() + fip_load = vm_creator.get_floating_ip().ip + self.created_object.append(vm_creator) + + self.__logger.info("Chassis IP is: %s", fip_chassis) + login_url = "https://" + str(fip_chassis) + "/api/v1/auth/session" + cards_url = "https://" + str(fip_chassis) + "/api/v2/ixos/cards/" + + payload = json.dumps({"username": "admin", + "password": "admin", + "rememberMe": "false"}) + api_key = json.loads(( + ChassisRestAPI.postWithPayload(login_url, payload)))["apiKey"] + + self.__logger.info("Adding 2 card back inside the ixia chassis...") + + for ip in vcard_ips: + payload = {"ipAddress": str(ip)} + response = json.loads(ChassisRestAPI.postOperation(cards_url, + api_key, + payload)) + count = 0 + while (int( + ChassisRestAPI.getWithHeaders(response['url'], + api_key)['progress']) != 100): + self.__logger.debug("Operation did not finish yet. \ + Waiting for 1 more second..") + time.sleep(1) + if count > 60: + raise Exception("Adding card take more than 60 seconds") + count += 1 + + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy()) + ssh.connect(fip_chassis, username="admin", password="admin") + cmd = "set license-check disable" + run_blocking_ssh_command(ssh, cmd) + cmd = "restart-service ixServer" + run_blocking_ssh_command(ssh, cmd) + + self.config_ellis(ellis_ip) + + # Get IPs of P-CSCF + resolver = dns.resolver.Resolver() + resolver.nameservers = [dns_ip] + result = resolver.query("bono.clearwater.local") + + iplistims = '' + i = 0 + for rdata in result: + i = i + 1 + print rdata.address + iplistims += str(rdata.address) + if i != len(result): + iplistims += ';' + + kResourcesUrl = 'http://%s:%s/api/v0/resources' % (fip_load, 8080) + + kRxfPath = r"REG_CALL_OPNFV_v13.rxf" + test_filname = self.test['inputs']['test_filname'] + kGatewaySharedFolder = '/mnt/ixload-share/' + kRxfRelativeUploadPath = 'uploads/%s' % os.path.split(kRxfPath)[1] + kRxfAbsoluteUploadPath = os.path.join(kGatewaySharedFolder, + kRxfRelativeUploadPath) + kChassisList = [str(fip_chassis)] + dataFileNameList = [test_filname, + 'Registration_only_LPS.tst', + 'SIPCall.tst'] + + kPortListPerCommunityCommunity = {"VoIP1@VM1": [(1, 1, 1)], + "VoIP2@VM2": [(1, 2, 1)]} + + kStatsToDisplayDict = self.test['inputs']['stats'] + connection = IxRestUtils.getConnection(fip_load, 8080) + + self.__logger.info("Creating a new session...") + sessionUrl = IxLoadUtils.createSession(connection, + self.test['version']) + + license_server = self.test['inputs']['licenseServer'] + IxLoadUtils.configureLicenseServer(connection, + sessionUrl, + license_server) + + files_dir = os.path.join(self.case_dir, 'ixia/files') + target_file = open(os.path.join(files_dir, test_filname), 'w') + j2_env = Environment(loader=FileSystemLoader(files_dir), + trim_blocks=True) + self.test['inputs'].update(dict( + ipchassis=fip_chassis, + ipcard1=vcard_ips_p2[0], + ipcard2=vcard_ips_p2[1], + iplistims=iplistims + )) + + target_file.write( + j2_env.get_template(test_filname + '.template').render( + self.test['inputs'] + )) + target_file.close() + + self.__logger.info('Uploading files %s...' % kRxfPath) + for dataFile in dataFileNameList: + localFilePath = os.path.join(files_dir, dataFile) + remoteFilePath = os.path.join(kGatewaySharedFolder, + 'uploads/%s' % dataFile) + IxLoadUtils.uploadFile(connection, kResourcesUrl, + localFilePath, remoteFilePath) + self.__logger.info('Upload file finished.') + + self.__logger.info("Loading repository %s..." % kRxfAbsoluteUploadPath) + IxLoadUtils.loadRepository(connection, sessionUrl, + kRxfAbsoluteUploadPath) + + self.__logger.info("Clearing chassis list...") + IxLoadUtils.clearChassisList(connection, sessionUrl) + + self.__logger.info("Adding chassis %s..." % (kChassisList)) + IxLoadUtils.addChassisList(connection, sessionUrl, kChassisList) + + self.__logger.info("Assigning new ports...") + IxLoadUtils.assignPorts(connection, sessionUrl, + kPortListPerCommunityCommunity) + + self.__logger.info("Starting the test...") + IxLoadUtils.runTest(connection, sessionUrl) + + self.__logger.info("Polling values for stats %s..." % ( + kStatsToDisplayDict)) + result = IxLoadUtils.pollStats(connection, sessionUrl, + kStatsToDisplayDict) + self.__logger.info("Test finished.") + self.__logger.info("Checking test status...") + testRunError = IxLoadUtils.getTestRunError(connection, sessionUrl) + + self.__logger.info(result) + duration = time.time() - start_time + self.details['test_vnf'].update(status='PASS', + result=result, + duration=duration) + if testRunError: + self.__logger.info("The test exited with following error: %s" % ( + testRunError)) + self.details['test_vnf'].update(status='FAIL', duration=duration) + return False + else: + self.__logger.info("The test completed successfully.") + self.details['test_vnf'].update(status='PASS', duration=duration) + self.result += 1/3 * 100 + return True + + def clean(self): + """Clean created objects/functions.""" + super(CloudifyImsPerf, self).clean() + + @energy.enable_recording + def run(self, **kwargs): + """Execute CloudifyIms test case.""" + return super(CloudifyImsPerf, self).run(**kwargs) + + +# ---------------------------------------------------------- +# +# YAML UTILS +# +# ----------------------------------------------------------- +def get_config(parameter, file_path): + """ + Get config parameter. + + 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 run_blocking_ssh_command(ssh, cmd, error_msg="Unable to run this command"): + """Command to run ssh command with the exit status.""" + stdin, stdout, stderr = ssh.exec_command(cmd) + if stdout.channel.recv_exit_status() != 0: + raise Exception(error_msg) -- cgit 1.2.3-korg