3 # Copyright (c) 2017 Orange, IXIA and others.
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
10 """CloudifyImsPerf testcase implementation."""
20 from jinja2 import Environment, FileSystemLoader
23 from functest.energy import energy
24 from functest.opnfv_tests.openstack.snaps import snaps_utils
25 import functest.opnfv_tests.vnf.ims.cloudify_ims as cloudify_ims
26 from functest.utils.constants import CONST
28 from snaps.openstack.create_network import (NetworkSettings, SubnetSettings,
29 OpenStackNetwork, PortSettings)
30 from snaps.openstack.create_security_group import (SecurityGroupSettings,
31 SecurityGroupRuleSettings,
33 OpenStackSecurityGroup)
34 from snaps.openstack.create_router import RouterSettings, OpenStackRouter
35 from snaps.openstack.create_instance import (VmInstanceSettings,
38 from snaps.openstack.create_flavor import FlavorSettings, OpenStackFlavor
39 from snaps.openstack.create_image import ImageSettings
41 from ixia.utils.IxChassisUtils import ChassisRestAPI
42 import ixia.utils.IxLoadUtils as IxLoadUtils
43 import ixia.utils.IxRestUtils as IxRestUtils
45 __author__ = "Valentin Boucher <valentin.boucher@orange.com>"
48 class CloudifyImsPerf(cloudify_ims.CloudifyIms):
49 """Clearwater vIMS deployed with Cloudify Orchestrator Case."""
51 __logger = logging.getLogger(__name__)
53 def __init__(self, **kwargs):
54 """Initialize CloudifyIms testcase object."""
55 if "case_name" not in kwargs:
56 kwargs["case_name"] = "cloudify_ims_perf"
57 super(CloudifyImsPerf, self).__init__(**kwargs)
59 # Retrieve the configuration
61 self.config = CONST.__getattribute__(
62 'vnf_{}_config'.format(self.case_name))
64 raise Exception("VNF config file not found")
67 self.created_object = []
69 config_file = os.path.join(self.case_dir, self.config)
70 self.orchestrator = dict(
71 requirements=get_config("orchestrator.requirements", config_file),
73 self.details['orchestrator'] = dict(
74 name=get_config("orchestrator.name", config_file),
75 version=get_config("orchestrator.version", config_file),
79 self.__logger.debug("Orchestrator configuration %s", self.orchestrator)
81 descriptor=get_config("vnf.descriptor", config_file),
82 inputs=get_config("vnf.inputs", config_file),
83 requirements=get_config("vnf.requirements", config_file)
85 self.details['vnf'] = dict(
86 descriptor_version=self.vnf['descriptor']['version'],
87 name=get_config("vnf.name", config_file),
88 version=get_config("vnf.version", config_file),
90 self.__logger.debug("VNF configuration: %s", self.vnf)
93 version=get_config("vnf_test_suite.version", config_file),
94 inputs=get_config("vnf_test_suite.inputs", config_file),
95 requirements=get_config("vnf_test_suite.requirements", config_file)
98 self.details['test_vnf'] = dict(
99 name=get_config("vnf_test_suite.name", config_file),
100 version=get_config("vnf_test_suite.version", config_file),
101 requirements=get_config("vnf_test_suite.requirements", config_file)
103 self.images = get_config("tenant_images", config_file)
104 self.__logger.info("Images needed for vIMS: %s", self.images)
107 """Run IXIA Stress test on clearwater ims instance."""
108 start_time = time.time()
110 cfy_client = self.orchestrator['object']
112 outputs = cfy_client.deployments.outputs.get(
113 self.vnf['descriptor'].get('name'))['outputs']
114 dns_ip = outputs['dns_ip']
115 ellis_ip = outputs['ellis_ip']
117 self.__logger.info("Creating full IXIA network ...")
118 subnet_settings = SubnetSettings(name='ixia_management_subnet',
119 cidr='10.10.10.0/24')
120 network_settings = NetworkSettings(name='ixia_management_network',
121 subnet_settings=[subnet_settings])
122 network_creator = OpenStackNetwork(self.snaps_creds, network_settings)
123 network_creator.create()
124 self.created_object.append(network_creator)
125 ext_net_name = snaps_utils.get_ext_net_name(self.snaps_creds)
126 router_creator = OpenStackRouter(
129 name='ixia_management_router',
130 external_gateway=ext_net_name,
131 internal_subnets=[subnet_settings.name]))
132 router_creator.create()
133 self.created_object.append(router_creator)
135 # security group creation
136 self.__logger.info("Creating security groups for IXIA VMs")
139 SecurityGroupRuleSettings(sec_grp_name="ixia_management",
140 direction=Direction.ingress,
141 protocol=Protocol.tcp, port_range_min=1,
142 port_range_max=65535))
144 SecurityGroupRuleSettings(sec_grp_name="ixia_management",
145 direction=Direction.ingress,
146 protocol=Protocol.udp, port_range_min=1,
147 port_range_max=65535))
149 SecurityGroupRuleSettings(sec_grp_name="ixia_management",
150 direction=Direction.ingress,
151 protocol=Protocol.icmp))
153 ixia_managment_sg_settings = SecurityGroupSettings(
154 name="ixia_management",
155 rule_settings=sg_rules)
156 securit_group_creator = OpenStackSecurityGroup(
158 ixia_managment_sg_settings)
160 securit_group_creator.create()
161 self.created_object.append(securit_group_creator)
165 SecurityGroupRuleSettings(sec_grp_name="ixia_ssh_http",
166 direction=Direction.ingress,
167 protocol=Protocol.tcp, port_range_min=1,
168 port_range_max=65535))
170 ixia_ssh_http_sg_settings = SecurityGroupSettings(
171 name="ixia_ssh_http",
172 rule_settings=sg_rules)
173 securit_group_creator = OpenStackSecurityGroup(
175 ixia_ssh_http_sg_settings)
177 securit_group_creator.create()
178 self.created_object.append(securit_group_creator)
180 chassis_flavor_settings = FlavorSettings(
181 name="ixia_vChassis",
185 flavor_creator = OpenStackFlavor(self.snaps_creds,
186 chassis_flavor_settings)
187 flavor_creator.create()
188 self.created_object.append(flavor_creator)
190 card_flavor_settings = FlavorSettings(
195 flavor_creator = OpenStackFlavor(self.snaps_creds,
196 card_flavor_settings)
197 flavor_creator.create()
198 self.created_object.append(flavor_creator)
200 load_flavor_settings = FlavorSettings(
205 flavor_creator = OpenStackFlavor(self.snaps_creds,
206 load_flavor_settings)
207 flavor_creator.create()
208 self.created_object.append(flavor_creator)
210 chassis_image_settings = ImageSettings(
211 name=self.test['requirements']['chassis']['image'],
215 card_image_settings = ImageSettings(
216 name=self.test['requirements']['card']['image'],
220 load_image_settings = ImageSettings(
221 name=self.test['requirements']['load']['image'],
225 chassis_port_settings = PortSettings(
226 name='ixia_chassis_port',
227 network_name=network_settings.name)
229 card1_port1_settings = PortSettings(
230 name='ixia_card1_port1',
231 network_name=network_settings.name)
233 card2_port1_settings = PortSettings(
234 name='ixia_card2_port1',
235 network_name=network_settings.name)
237 card1_port2_settings = PortSettings(
238 name='ixia_card1_port2',
239 network_name="cloudify_ims_network")
241 card2_port2_settings = PortSettings(
242 name='ixia_card2_port2',
243 network_name="cloudify_ims_network")
245 load_port_settings = PortSettings(
246 name='ixia_load_port',
247 network_name=network_settings.name)
249 chassis_settings = VmInstanceSettings(
250 name='ixia_vChassis',
251 flavor=chassis_flavor_settings.name,
252 port_settings=[chassis_port_settings],
253 security_group_names=[ixia_ssh_http_sg_settings.name,
254 ixia_managment_sg_settings.name],
255 floating_ip_settings=[FloatingIpSettings(
256 name='ixia_vChassis_fip',
257 port_name=chassis_port_settings.name,
258 router_name=router_creator.router_settings.name)])
260 vm_creator = OpenStackVmInstance(self.snaps_creds,
262 chassis_image_settings)
264 self.__logger.info("Creating Ixia vChassis VM")
266 fip_chassis = vm_creator.get_floating_ip().ip
267 self.created_object.append(vm_creator)
269 card1_settings = VmInstanceSettings(
271 flavor=card_flavor_settings.name,
272 port_settings=[card1_port1_settings, card1_port2_settings],
273 security_group_names=[ixia_managment_sg_settings.name])
275 vm_creator = OpenStackVmInstance(self.snaps_creds,
279 self.__logger.info("Creating Ixia vCard1 VM")
282 vcard_ips_p2 = list()
283 vcard_ips.append(vm_creator.get_port_ip('ixia_card1_port1'))
284 vcard_ips_p2.append(vm_creator.get_port_ip('ixia_card1_port2'))
285 self.created_object.append(vm_creator)
287 card2_settings = VmInstanceSettings(
289 flavor=card_flavor_settings.name,
290 port_settings=[card2_port1_settings, card2_port2_settings],
291 security_group_names=[ixia_managment_sg_settings.name])
293 vm_creator = OpenStackVmInstance(self.snaps_creds,
297 self.__logger.info("Creating Ixia vCard2 VM")
299 vcard_ips.append(vm_creator.get_port_ip('ixia_card2_port1'))
300 vcard_ips_p2.append(vm_creator.get_port_ip('ixia_card2_port2'))
301 self.created_object.append(vm_creator)
303 load_settings = VmInstanceSettings(
305 flavor=load_flavor_settings.name,
306 port_settings=[load_port_settings],
307 security_group_names=[ixia_ssh_http_sg_settings.name,
308 ixia_managment_sg_settings.name],
309 floating_ip_settings=[FloatingIpSettings(
310 name='ixia_vLoad_fip',
311 port_name=load_port_settings.name,
312 router_name=router_creator.router_settings.name)])
314 vm_creator = OpenStackVmInstance(self.snaps_creds,
318 self.__logger.info("Creating Ixia vLoad VM")
320 fip_load = vm_creator.get_floating_ip().ip
321 self.created_object.append(vm_creator)
323 self.__logger.info("Chassis IP is: %s", fip_chassis)
324 login_url = "https://" + str(fip_chassis) + "/api/v1/auth/session"
325 cards_url = "https://" + str(fip_chassis) + "/api/v2/ixos/cards/"
327 payload = json.dumps({"username": "admin",
329 "rememberMe": "false"})
330 api_key = json.loads((
331 ChassisRestAPI.postWithPayload(login_url, payload)))["apiKey"]
333 self.__logger.info("Adding 2 card back inside the ixia chassis...")
336 payload = {"ipAddress": str(ip)}
337 response = json.loads(ChassisRestAPI.postOperation(cards_url,
342 ChassisRestAPI.getWithHeaders(response['url'],
343 api_key)['progress']) != 100):
344 self.__logger.debug("Operation did not finish yet. \
345 Waiting for 1 more second..")
348 raise Exception("Adding card take more than 60 seconds")
351 ssh = paramiko.SSHClient()
352 ssh.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy())
353 ssh.connect(fip_chassis, username="admin", password="admin")
354 cmd = "set license-check disable"
355 run_blocking_ssh_command(ssh, cmd)
356 cmd = "restart-service ixServer"
357 run_blocking_ssh_command(ssh, cmd)
359 self.config_ellis(ellis_ip)
362 resolver = dns.resolver.Resolver()
363 resolver.nameservers = [dns_ip]
364 result = resolver.query("bono.clearwater.local")
371 iplistims += str(rdata.address)
375 kResourcesUrl = 'http://%s:%s/api/v0/resources' % (fip_load, 8080)
377 kRxfPath = r"REG_CALL_OPNFV_v13.rxf"
378 test_filname = self.test['inputs']['test_filname']
379 kGatewaySharedFolder = '/mnt/ixload-share/'
380 kRxfRelativeUploadPath = 'uploads/%s' % os.path.split(kRxfPath)[1]
381 kRxfAbsoluteUploadPath = os.path.join(kGatewaySharedFolder,
382 kRxfRelativeUploadPath)
383 kChassisList = [str(fip_chassis)]
384 dataFileNameList = [test_filname,
385 'Registration_only_LPS.tst',
388 kPortListPerCommunityCommunity = {"VoIP1@VM1": [(1, 1, 1)],
389 "VoIP2@VM2": [(1, 2, 1)]}
391 kStatsToDisplayDict = self.test['inputs']['stats']
392 connection = IxRestUtils.getConnection(fip_load, 8080)
394 self.__logger.info("Creating a new session...")
395 sessionUrl = IxLoadUtils.createSession(connection,
396 self.test['version'])
398 license_server = self.test['inputs']['licenseServer']
399 IxLoadUtils.configureLicenseServer(connection,
403 files_dir = os.path.join(self.case_dir, 'ixia/files')
404 target_file = open(os.path.join(files_dir, test_filname), 'w')
405 j2_env = Environment(loader=FileSystemLoader(files_dir),
407 self.test['inputs'].update(dict(
408 ipchassis=fip_chassis,
409 ipcard1=vcard_ips_p2[0],
410 ipcard2=vcard_ips_p2[1],
415 j2_env.get_template(test_filname + '.template').render(
420 self.__logger.info('Uploading files %s...' % kRxfPath)
421 for dataFile in dataFileNameList:
422 localFilePath = os.path.join(files_dir, dataFile)
423 remoteFilePath = os.path.join(kGatewaySharedFolder,
424 'uploads/%s' % dataFile)
425 IxLoadUtils.uploadFile(connection, kResourcesUrl,
426 localFilePath, remoteFilePath)
427 self.__logger.info('Upload file finished.')
429 self.__logger.info("Loading repository %s..." % kRxfAbsoluteUploadPath)
430 IxLoadUtils.loadRepository(connection, sessionUrl,
431 kRxfAbsoluteUploadPath)
433 self.__logger.info("Clearing chassis list...")
434 IxLoadUtils.clearChassisList(connection, sessionUrl)
436 self.__logger.info("Adding chassis %s..." % (kChassisList))
437 IxLoadUtils.addChassisList(connection, sessionUrl, kChassisList)
439 self.__logger.info("Assigning new ports...")
440 IxLoadUtils.assignPorts(connection, sessionUrl,
441 kPortListPerCommunityCommunity)
443 self.__logger.info("Starting the test...")
444 IxLoadUtils.runTest(connection, sessionUrl)
446 self.__logger.info("Polling values for stats %s..." % (
447 kStatsToDisplayDict))
448 result = IxLoadUtils.pollStats(connection, sessionUrl,
450 self.__logger.info("Test finished.")
451 self.__logger.info("Checking test status...")
452 testRunError = IxLoadUtils.getTestRunError(connection, sessionUrl)
454 self.__logger.info(result)
455 duration = time.time() - start_time
456 self.details['test_vnf'].update(status='PASS',
460 self.__logger.info("The test exited with following error: %s" % (
462 self.details['test_vnf'].update(status='FAIL', duration=duration)
465 self.__logger.info("The test completed successfully.")
466 self.details['test_vnf'].update(status='PASS', duration=duration)
467 self.result += 1/3 * 100
471 """Clean created objects/functions."""
472 super(CloudifyImsPerf, self).clean()
474 @energy.enable_recording
475 def run(self, **kwargs):
476 """Execute CloudifyIms test case."""
477 return super(CloudifyImsPerf, self).run(**kwargs)
480 # ----------------------------------------------------------
484 # -----------------------------------------------------------
485 def get_config(parameter, file_path):
487 Get config parameter.
489 Returns the value of a given parameter in file.yaml
490 parameter must be given in string format with dots
491 Example: general.openstack.image_name
493 with open(file_path) as config_file:
494 file_yaml = yaml.safe_load(config_file)
497 for element in parameter.split("."):
498 value = value.get(element)
500 raise ValueError("The parameter %s is not defined in"
501 " reporting.yaml" % parameter)
505 def run_blocking_ssh_command(ssh, cmd, error_msg="Unable to run this command"):
506 """Command to run ssh command with the exit status."""
507 stdin, stdout, stderr = ssh.exec_command(cmd)
508 if stdout.channel.recv_exit_status() != 0:
509 raise Exception(error_msg)