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
22 from functest.energy import energy
23 from functest.opnfv_tests.openstack.snaps import snaps_utils
24 from functest.opnfv_tests.vnf.ims import cloudify_ims
25 from functest.opnfv_tests.vnf.ims.ixia.utils import IxChassisUtils
26 from functest.opnfv_tests.vnf.ims.ixia.utils import IxLoadUtils
27 from functest.opnfv_tests.vnf.ims.ixia.utils import IxRestUtils
28 from functest.utils import config
30 from snaps.config.flavor import FlavorConfig
31 from snaps.config.image import ImageConfig
32 from snaps.config.network import NetworkConfig, PortConfig, SubnetConfig
33 from snaps.config.router import RouterConfig
34 from snaps.config.security_group import (
35 Direction, Protocol, SecurityGroupConfig, SecurityGroupRuleConfig)
36 from snaps.config.vm_inst import FloatingIpConfig, VmInstanceConfig
37 from snaps.openstack.create_flavor import OpenStackFlavor
38 from snaps.openstack.create_instance import OpenStackVmInstance
39 from snaps.openstack.create_network import OpenStackNetwork
40 from snaps.openstack.create_router import OpenStackRouter
41 from snaps.openstack.create_security_group import OpenStackSecurityGroup
44 __author__ = "Valentin Boucher <valentin.boucher@orange.com>"
47 class CloudifyImsPerf(cloudify_ims.CloudifyIms):
48 """Clearwater vIMS deployed with Cloudify Orchestrator Case."""
50 __logger = logging.getLogger(__name__)
52 def __init__(self, **kwargs):
53 """Initialize CloudifyIms testcase object."""
54 if "case_name" not in kwargs:
55 kwargs["case_name"] = "cloudify_ims_perf"
56 super(CloudifyImsPerf, self).__init__(**kwargs)
58 # Retrieve the configuration
60 self.config = getattr(
61 config.CONF, 'vnf_{}_config'.format(self.case_name))
63 raise Exception("VNF config file not found")
66 self.created_object = []
68 config_file = os.path.join(self.case_dir, self.config)
69 self.orchestrator = dict(
70 requirements=get_config("orchestrator.requirements", config_file),
72 self.details['orchestrator'] = dict(
73 name=get_config("orchestrator.name", config_file),
74 version=get_config("orchestrator.version", config_file),
78 self.__logger.debug("Orchestrator configuration %s", self.orchestrator)
80 descriptor=get_config("vnf.descriptor", config_file),
81 inputs=get_config("vnf.inputs", config_file),
82 requirements=get_config("vnf.requirements", config_file)
84 self.details['vnf'] = dict(
85 descriptor_version=self.vnf['descriptor']['version'],
86 name=get_config("vnf.name", config_file),
87 version=get_config("vnf.version", config_file),
89 self.__logger.debug("VNF configuration: %s", self.vnf)
92 version=get_config("vnf_test_suite.version", config_file),
93 inputs=get_config("vnf_test_suite.inputs", config_file),
94 requirements=get_config("vnf_test_suite.requirements", config_file)
97 self.details['test_vnf'] = dict(
98 name=get_config("vnf_test_suite.name", config_file),
99 version=get_config("vnf_test_suite.version", config_file),
100 requirements=get_config("vnf_test_suite.requirements", config_file)
102 self.images = get_config("tenant_images", config_file)
103 self.__logger.info("Images needed for vIMS: %s", self.images)
106 """Run IXIA Stress test on clearwater ims instance."""
107 start_time = time.time()
109 cfy_client = self.orchestrator['object']
111 outputs = cfy_client.deployments.outputs.get(
112 self.vnf['descriptor'].get('name'))['outputs']
113 dns_ip = outputs['dns_ip']
114 ellis_ip = outputs['ellis_ip']
116 self.__logger.info("Creating full IXIA network ...")
117 subnet_settings = SubnetConfig(name='ixia_management_subnet',
118 cidr='10.10.10.0/24')
119 network_settings = NetworkConfig(name='ixia_management_network',
120 subnet_settings=[subnet_settings])
121 network_creator = OpenStackNetwork(self.snaps_creds, network_settings)
122 network_creator.create()
123 self.created_object.append(network_creator)
124 ext_net_name = snaps_utils.get_ext_net_name(self.snaps_creds)
125 router_creator = OpenStackRouter(
128 name='ixia_management_router',
129 external_gateway=ext_net_name,
130 internal_subnets=[subnet_settings.name]))
131 router_creator.create()
132 self.created_object.append(router_creator)
134 # security group creation
135 self.__logger.info("Creating security groups for IXIA VMs")
138 SecurityGroupRuleConfig(sec_grp_name="ixia_management",
139 direction=Direction.ingress,
140 protocol=Protocol.tcp, port_range_min=1,
141 port_range_max=65535))
143 SecurityGroupRuleConfig(sec_grp_name="ixia_management",
144 direction=Direction.ingress,
145 protocol=Protocol.udp, port_range_min=1,
146 port_range_max=65535))
148 SecurityGroupRuleConfig(sec_grp_name="ixia_management",
149 direction=Direction.ingress,
150 protocol=Protocol.icmp))
152 ixia_managment_sg_settings = SecurityGroupConfig(
153 name="ixia_management", rule_settings=sg_rules)
154 securit_group_creator = OpenStackSecurityGroup(
156 ixia_managment_sg_settings)
158 securit_group_creator.create()
159 self.created_object.append(securit_group_creator)
163 SecurityGroupRuleConfig(sec_grp_name="ixia_ssh_http",
164 direction=Direction.ingress,
165 protocol=Protocol.tcp, port_range_min=1,
166 port_range_max=65535))
168 ixia_ssh_http_sg_settings = SecurityGroupConfig(
169 name="ixia_ssh_http", rule_settings=sg_rules)
170 securit_group_creator = OpenStackSecurityGroup(
172 ixia_ssh_http_sg_settings)
174 securit_group_creator.create()
175 self.created_object.append(securit_group_creator)
177 chassis_flavor_settings = FlavorConfig(
178 name="ixia_vChassis",
182 flavor_creator = OpenStackFlavor(self.snaps_creds,
183 chassis_flavor_settings)
184 flavor_creator.create()
185 self.created_object.append(flavor_creator)
187 card_flavor_settings = FlavorConfig(
192 flavor_creator = OpenStackFlavor(self.snaps_creds,
193 card_flavor_settings)
194 flavor_creator.create()
195 self.created_object.append(flavor_creator)
197 load_flavor_settings = FlavorConfig(
202 flavor_creator = OpenStackFlavor(self.snaps_creds,
203 load_flavor_settings)
204 flavor_creator.create()
205 self.created_object.append(flavor_creator)
207 chassis_image_settings = ImageConfig(
208 name=self.test['requirements']['chassis']['image'],
212 card_image_settings = ImageConfig(
213 name=self.test['requirements']['card']['image'],
217 load_image_settings = ImageConfig(
218 name=self.test['requirements']['load']['image'],
222 chassis_port_settings = PortConfig(
223 name='ixia_chassis_port', network_name=network_settings.name)
225 card1_port1_settings = PortConfig(
226 name='ixia_card1_port1', network_name=network_settings.name)
228 card2_port1_settings = PortConfig(
229 name='ixia_card2_port1', network_name=network_settings.name)
231 card1_port2_settings = PortConfig(
232 name='ixia_card1_port2', network_name="cloudify_ims_network")
234 card2_port2_settings = PortConfig(
235 name='ixia_card2_port2', network_name="cloudify_ims_network")
237 load_port_settings = PortConfig(
238 name='ixia_load_port', network_name=network_settings.name)
240 chassis_settings = VmInstanceConfig(
241 name='ixia_vChassis',
242 flavor=chassis_flavor_settings.name,
243 port_settings=[chassis_port_settings],
244 security_group_names=[ixia_ssh_http_sg_settings.name,
245 ixia_managment_sg_settings.name],
246 floating_ip_settings=[FloatingIpConfig(
247 name='ixia_vChassis_fip',
248 port_name=chassis_port_settings.name,
249 router_name=router_creator.router_settings.name)])
251 vm_creator = OpenStackVmInstance(self.snaps_creds,
253 chassis_image_settings)
255 self.__logger.info("Creating Ixia vChassis VM")
257 fip_chassis = vm_creator.get_floating_ip().ip
258 self.created_object.append(vm_creator)
260 card1_settings = VmInstanceConfig(
262 flavor=card_flavor_settings.name,
263 port_settings=[card1_port1_settings, card1_port2_settings],
264 security_group_names=[ixia_managment_sg_settings.name])
266 vm_creator = OpenStackVmInstance(self.snaps_creds,
270 self.__logger.info("Creating Ixia vCard1 VM")
273 vcard_ips_p2 = list()
274 vcard_ips.append(vm_creator.get_port_ip('ixia_card1_port1'))
275 vcard_ips_p2.append(vm_creator.get_port_ip('ixia_card1_port2'))
276 self.created_object.append(vm_creator)
278 card2_settings = VmInstanceConfig(
280 flavor=card_flavor_settings.name,
281 port_settings=[card2_port1_settings, card2_port2_settings],
282 security_group_names=[ixia_managment_sg_settings.name])
284 vm_creator = OpenStackVmInstance(self.snaps_creds,
288 self.__logger.info("Creating Ixia vCard2 VM")
290 vcard_ips.append(vm_creator.get_port_ip('ixia_card2_port1'))
291 vcard_ips_p2.append(vm_creator.get_port_ip('ixia_card2_port2'))
292 self.created_object.append(vm_creator)
294 load_settings = VmInstanceConfig(
296 flavor=load_flavor_settings.name,
297 port_settings=[load_port_settings],
298 security_group_names=[ixia_ssh_http_sg_settings.name,
299 ixia_managment_sg_settings.name],
300 floating_ip_settings=[FloatingIpConfig(
301 name='ixia_vLoad_fip',
302 port_name=load_port_settings.name,
303 router_name=router_creator.router_settings.name)])
305 vm_creator = OpenStackVmInstance(self.snaps_creds,
309 self.__logger.info("Creating Ixia vLoad VM")
311 fip_load = vm_creator.get_floating_ip().ip
312 self.created_object.append(vm_creator)
314 self.__logger.info("Chassis IP is: %s", fip_chassis)
315 login_url = "https://" + str(fip_chassis) + "/api/v1/auth/session"
316 cards_url = "https://" + str(fip_chassis) + "/api/v2/ixos/cards/"
318 payload = json.dumps({"username": "admin",
320 "rememberMe": "false"})
321 api_key = json.loads((
322 IxChassisUtils.ChassisRestAPI.postWithPayload(
323 login_url, payload)))["apiKey"]
325 self.__logger.info("Adding 2 card back inside the ixia chassis...")
328 payload = {"ipAddress": str(ip)}
329 response = json.loads(IxChassisUtils.ChassisRestAPI.postOperation(
330 cards_url, api_key, payload))
333 IxChassisUtils.ChassisRestAPI.getWithHeaders(
334 response['url'], api_key)['progress']) != 100):
335 self.__logger.debug("Operation did not finish yet. \
336 Waiting for 1 more second..")
339 raise Exception("Adding card take more than 60 seconds")
342 ssh = paramiko.SSHClient()
343 ssh.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy())
344 ssh.connect(fip_chassis, username="admin", password="admin")
345 cmd = "set license-check disable"
346 run_blocking_ssh_command(ssh, cmd)
347 cmd = "restart-service ixServer"
348 run_blocking_ssh_command(ssh, cmd)
350 self.config_ellis(ellis_ip)
353 resolver = dns.resolver.Resolver()
354 resolver.nameservers = [dns_ip]
355 result = resolver.query("bono.clearwater.local")
362 iplistims += str(rdata.address)
366 kResourcesUrl = 'http://%s:%s/api/v0/resources' % (fip_load, 8080)
368 kRxfPath = r"REG_CALL_OPNFV_v13.rxf"
369 test_filname = self.test['inputs']['test_filname']
370 kGatewaySharedFolder = '/mnt/ixload-share/'
371 kRxfRelativeUploadPath = 'uploads/%s' % os.path.split(kRxfPath)[1]
372 kRxfAbsoluteUploadPath = os.path.join(kGatewaySharedFolder,
373 kRxfRelativeUploadPath)
374 kChassisList = [str(fip_chassis)]
375 dataFileNameList = [test_filname,
376 'Registration_only_LPS.tst',
379 kPortListPerCommunityCommunity = {"VoIP1@VM1": [(1, 1, 1)],
380 "VoIP2@VM2": [(1, 2, 1)]}
382 kStatsToDisplayDict = self.test['inputs']['stats']
383 connection = IxRestUtils.getConnection(fip_load, 8080)
385 self.__logger.info("Creating a new session...")
386 sessionUrl = IxLoadUtils.createSession(connection,
387 self.test['version'])
389 license_server = self.test['inputs']['licenseServer']
390 IxLoadUtils.configureLicenseServer(connection,
394 files_dir = os.path.join(self.case_dir, 'ixia/files')
395 target_file = open(os.path.join(files_dir, test_filname), 'w')
396 j2_env = Environment(loader=FileSystemLoader(files_dir),
398 self.test['inputs'].update(dict(
399 ipchassis=fip_chassis, ipcard1=vcard_ips_p2[0],
400 ipcard2=vcard_ips_p2[1], iplistims=iplistims
404 j2_env.get_template(test_filname + '.template').render(
409 self.__logger.info('Uploading files %s...' % kRxfPath)
410 for dataFile in dataFileNameList:
411 localFilePath = os.path.join(files_dir, dataFile)
412 remoteFilePath = os.path.join(kGatewaySharedFolder,
413 'uploads/%s' % dataFile)
414 IxLoadUtils.uploadFile(connection, kResourcesUrl,
415 localFilePath, remoteFilePath)
416 self.__logger.info('Upload file finished.')
418 self.__logger.info("Loading repository %s..." % kRxfAbsoluteUploadPath)
419 IxLoadUtils.loadRepository(connection, sessionUrl,
420 kRxfAbsoluteUploadPath)
422 self.__logger.info("Clearing chassis list...")
423 IxLoadUtils.clearChassisList(connection, sessionUrl)
425 self.__logger.info("Adding chassis %s..." % (kChassisList))
426 IxLoadUtils.addChassisList(connection, sessionUrl, kChassisList)
428 self.__logger.info("Assigning new ports...")
429 IxLoadUtils.assignPorts(connection, sessionUrl,
430 kPortListPerCommunityCommunity)
432 self.__logger.info("Starting the test...")
433 IxLoadUtils.runTest(connection, sessionUrl)
436 "Polling values for stats %s..." % (kStatsToDisplayDict))
437 result = IxLoadUtils.pollStats(connection, sessionUrl,
439 self.__logger.info("Test finished.")
440 self.__logger.info("Checking test status...")
441 testRunError = IxLoadUtils.getTestRunError(connection, sessionUrl)
443 self.__logger.info(result)
444 duration = time.time() - start_time
445 self.details['test_vnf'].update(status='PASS',
450 "The test exited with following error: %s" % (testRunError))
451 self.details['test_vnf'].update(status='FAIL', duration=duration)
454 self.__logger.info("The test completed successfully.")
455 self.details['test_vnf'].update(status='PASS', duration=duration)
456 self.result += 1/3 * 100
460 """Clean created objects/functions."""
461 super(CloudifyImsPerf, self).clean()
463 @energy.enable_recording
464 def run(self, **kwargs):
465 """Execute CloudifyIms test case."""
466 return super(CloudifyImsPerf, self).run(**kwargs)
469 # ----------------------------------------------------------
473 # -----------------------------------------------------------
474 def get_config(parameter, file_path):
476 Get config parameter.
478 Returns the value of a given parameter in file.yaml
479 parameter must be given in string format with dots
480 Example: general.openstack.image_name
482 with open(file_path) as config_file:
483 file_yaml = yaml.safe_load(config_file)
486 for element in parameter.split("."):
487 value = value.get(element)
489 raise ValueError("The parameter %s is not defined in"
490 " reporting.yaml" % parameter)
494 def run_blocking_ssh_command(ssh, cmd, error_msg="Unable to run this command"):
495 """Command to run ssh command with the exit status."""
496 stdin, stdout, stderr = ssh.exec_command(cmd)
497 if stdout.channel.recv_exit_status() != 0:
498 raise Exception(error_msg)