Removal of deprecated SNAPS-OO classes.
[functest.git] / functest / opnfv_tests / vnf / ims / cloudify_ims_perf.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2017 Orange, IXIA and others.
4 #
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
9
10 """CloudifyImsPerf testcase implementation."""
11
12 import logging
13 import os
14 import time
15
16 import json
17 import yaml
18 import paramiko
19 import dns.resolver
20 from jinja2 import Environment, FileSystemLoader
21
22
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
27
28 from snaps.config.flavor import FlavorConfig
29 from snaps.config.image import ImageConfig
30 from snaps.config.network import NetworkConfig, PortConfig, SubnetConfig
31 from snaps.config.router import RouterConfig
32 from snaps.config.security_group import (
33     Direction, Protocol, SecurityGroupConfig, SecurityGroupRuleConfig)
34 from snaps.config.vm_inst import FloatingIpConfig, VmInstanceConfig
35
36 from snaps.openstack.create_flavor import OpenStackFlavor
37 from snaps.openstack.create_instance import OpenStackVmInstance
38 from snaps.openstack.create_network import OpenStackNetwork
39 from snaps.openstack.create_router import OpenStackRouter
40 from snaps.openstack.create_security_group import OpenStackSecurityGroup
41
42 from ixia.utils.IxChassisUtils import ChassisRestAPI
43 import ixia.utils.IxLoadUtils as IxLoadUtils
44 import ixia.utils.IxRestUtils as IxRestUtils
45
46 __author__ = "Valentin Boucher <valentin.boucher@orange.com>"
47
48
49 class CloudifyImsPerf(cloudify_ims.CloudifyIms):
50     """Clearwater vIMS deployed with Cloudify Orchestrator Case."""
51
52     __logger = logging.getLogger(__name__)
53
54     def __init__(self, **kwargs):
55         """Initialize CloudifyIms testcase object."""
56         if "case_name" not in kwargs:
57             kwargs["case_name"] = "cloudify_ims_perf"
58         super(CloudifyImsPerf, self).__init__(**kwargs)
59
60         # Retrieve the configuration
61         try:
62             self.config = CONST.__getattribute__(
63                 'vnf_{}_config'.format(self.case_name))
64         except Exception:
65             raise Exception("VNF config file not found")
66
67         self.snaps_creds = ''
68         self.created_object = []
69
70         config_file = os.path.join(self.case_dir, self.config)
71         self.orchestrator = dict(
72             requirements=get_config("orchestrator.requirements", config_file),
73         )
74         self.details['orchestrator'] = dict(
75             name=get_config("orchestrator.name", config_file),
76             version=get_config("orchestrator.version", config_file),
77             status='ERROR',
78             result=''
79         )
80         self.__logger.debug("Orchestrator configuration %s", self.orchestrator)
81         self.vnf = dict(
82             descriptor=get_config("vnf.descriptor", config_file),
83             inputs=get_config("vnf.inputs", config_file),
84             requirements=get_config("vnf.requirements", config_file)
85         )
86         self.details['vnf'] = dict(
87             descriptor_version=self.vnf['descriptor']['version'],
88             name=get_config("vnf.name", config_file),
89             version=get_config("vnf.version", config_file),
90         )
91         self.__logger.debug("VNF configuration: %s", self.vnf)
92
93         self.test = dict(
94             version=get_config("vnf_test_suite.version", config_file),
95             inputs=get_config("vnf_test_suite.inputs", config_file),
96             requirements=get_config("vnf_test_suite.requirements", config_file)
97         )
98
99         self.details['test_vnf'] = dict(
100             name=get_config("vnf_test_suite.name", config_file),
101             version=get_config("vnf_test_suite.version", config_file),
102             requirements=get_config("vnf_test_suite.requirements", config_file)
103         )
104         self.images = get_config("tenant_images", config_file)
105         self.__logger.info("Images needed for vIMS: %s", self.images)
106
107     def test_vnf(self):
108         """Run IXIA Stress test on clearwater ims instance."""
109         start_time = time.time()
110
111         cfy_client = self.orchestrator['object']
112
113         outputs = cfy_client.deployments.outputs.get(
114             self.vnf['descriptor'].get('name'))['outputs']
115         dns_ip = outputs['dns_ip']
116         ellis_ip = outputs['ellis_ip']
117
118         self.__logger.info("Creating full IXIA network ...")
119         subnet_settings = SubnetConfig(name='ixia_management_subnet',
120                                        cidr='10.10.10.0/24')
121         network_settings = NetworkConfig(name='ixia_management_network',
122                                          subnet_settings=[subnet_settings])
123         network_creator = OpenStackNetwork(self.snaps_creds, network_settings)
124         network_creator.create()
125         self.created_object.append(network_creator)
126         ext_net_name = snaps_utils.get_ext_net_name(self.snaps_creds)
127         router_creator = OpenStackRouter(
128             self.snaps_creds,
129             RouterConfig(
130                 name='ixia_management_router',
131                 external_gateway=ext_net_name,
132                 internal_subnets=[subnet_settings.name]))
133         router_creator.create()
134         self.created_object.append(router_creator)
135
136         # security group creation
137         self.__logger.info("Creating security groups for IXIA VMs")
138         sg_rules = list()
139         sg_rules.append(
140             SecurityGroupRuleConfig(sec_grp_name="ixia_management",
141                                     direction=Direction.ingress,
142                                     protocol=Protocol.tcp, port_range_min=1,
143                                     port_range_max=65535))
144         sg_rules.append(
145             SecurityGroupRuleConfig(sec_grp_name="ixia_management",
146                                     direction=Direction.ingress,
147                                     protocol=Protocol.udp, port_range_min=1,
148                                     port_range_max=65535))
149         sg_rules.append(
150             SecurityGroupRuleConfig(sec_grp_name="ixia_management",
151                                     direction=Direction.ingress,
152                                     protocol=Protocol.icmp))
153
154         ixia_managment_sg_settings = SecurityGroupConfig(
155                                         name="ixia_management",
156                                         rule_settings=sg_rules)
157         securit_group_creator = OpenStackSecurityGroup(
158             self.snaps_creds,
159             ixia_managment_sg_settings)
160
161         securit_group_creator.create()
162         self.created_object.append(securit_group_creator)
163
164         sg_rules = list()
165         sg_rules.append(
166             SecurityGroupRuleConfig(sec_grp_name="ixia_ssh_http",
167                                     direction=Direction.ingress,
168                                     protocol=Protocol.tcp, port_range_min=1,
169                                     port_range_max=65535))
170
171         ixia_ssh_http_sg_settings = SecurityGroupConfig(
172                                         name="ixia_ssh_http",
173                                         rule_settings=sg_rules)
174         securit_group_creator = OpenStackSecurityGroup(
175             self.snaps_creds,
176             ixia_ssh_http_sg_settings)
177
178         securit_group_creator.create()
179         self.created_object.append(securit_group_creator)
180
181         chassis_flavor_settings = FlavorConfig(
182             name="ixia_vChassis",
183             ram=4096,
184             disk=40,
185             vcpus=2)
186         flavor_creator = OpenStackFlavor(self.snaps_creds,
187                                          chassis_flavor_settings)
188         flavor_creator.create()
189         self.created_object.append(flavor_creator)
190
191         card_flavor_settings = FlavorConfig(
192             name="ixia_vCard",
193             ram=4096,
194             disk=4,
195             vcpus=2)
196         flavor_creator = OpenStackFlavor(self.snaps_creds,
197                                          card_flavor_settings)
198         flavor_creator.create()
199         self.created_object.append(flavor_creator)
200
201         load_flavor_settings = FlavorConfig(
202             name="ixia_vLoad",
203             ram=8192,
204             disk=100,
205             vcpus=4)
206         flavor_creator = OpenStackFlavor(self.snaps_creds,
207                                          load_flavor_settings)
208         flavor_creator.create()
209         self.created_object.append(flavor_creator)
210
211         chassis_image_settings = ImageConfig(
212             name=self.test['requirements']['chassis']['image'],
213             image_user='admin',
214             exists=True)
215
216         card_image_settings = ImageConfig(
217             name=self.test['requirements']['card']['image'],
218             image_user='admin',
219             exists=True)
220
221         load_image_settings = ImageConfig(
222             name=self.test['requirements']['load']['image'],
223             image_user='admin',
224             exists=True)
225
226         chassis_port_settings = PortConfig(
227                                      name='ixia_chassis_port',
228                                      network_name=network_settings.name)
229
230         card1_port1_settings = PortConfig(
231                                      name='ixia_card1_port1',
232                                      network_name=network_settings.name)
233
234         card2_port1_settings = PortConfig(
235                                      name='ixia_card2_port1',
236                                      network_name=network_settings.name)
237
238         card1_port2_settings = PortConfig(
239                                      name='ixia_card1_port2',
240                                      network_name="cloudify_ims_network")
241
242         card2_port2_settings = PortConfig(
243                                      name='ixia_card2_port2',
244                                      network_name="cloudify_ims_network")
245
246         load_port_settings = PortConfig(
247                                      name='ixia_load_port',
248                                      network_name=network_settings.name)
249
250         chassis_settings = VmInstanceConfig(
251             name='ixia_vChassis',
252             flavor=chassis_flavor_settings.name,
253             port_settings=[chassis_port_settings],
254             security_group_names=[ixia_ssh_http_sg_settings.name,
255                                   ixia_managment_sg_settings.name],
256             floating_ip_settings=[FloatingIpConfig(
257                 name='ixia_vChassis_fip',
258                 port_name=chassis_port_settings.name,
259                 router_name=router_creator.router_settings.name)])
260
261         vm_creator = OpenStackVmInstance(self.snaps_creds,
262                                          chassis_settings,
263                                          chassis_image_settings)
264
265         self.__logger.info("Creating Ixia vChassis VM")
266         vm_creator.create()
267         fip_chassis = vm_creator.get_floating_ip().ip
268         self.created_object.append(vm_creator)
269
270         card1_settings = VmInstanceConfig(
271             name='ixia_vCard1',
272             flavor=card_flavor_settings.name,
273             port_settings=[card1_port1_settings, card1_port2_settings],
274             security_group_names=[ixia_managment_sg_settings.name])
275
276         vm_creator = OpenStackVmInstance(self.snaps_creds,
277                                          card1_settings,
278                                          card_image_settings)
279
280         self.__logger.info("Creating Ixia vCard1 VM")
281         vm_creator.create()
282         vcard_ips = list()
283         vcard_ips_p2 = list()
284         vcard_ips.append(vm_creator.get_port_ip('ixia_card1_port1'))
285         vcard_ips_p2.append(vm_creator.get_port_ip('ixia_card1_port2'))
286         self.created_object.append(vm_creator)
287
288         card2_settings = VmInstanceConfig(
289             name='ixia_vCard2',
290             flavor=card_flavor_settings.name,
291             port_settings=[card2_port1_settings, card2_port2_settings],
292             security_group_names=[ixia_managment_sg_settings.name])
293
294         vm_creator = OpenStackVmInstance(self.snaps_creds,
295                                          card2_settings,
296                                          card_image_settings)
297
298         self.__logger.info("Creating Ixia vCard2 VM")
299         vm_creator.create()
300         vcard_ips.append(vm_creator.get_port_ip('ixia_card2_port1'))
301         vcard_ips_p2.append(vm_creator.get_port_ip('ixia_card2_port2'))
302         self.created_object.append(vm_creator)
303
304         load_settings = VmInstanceConfig(
305             name='ixia_vLoad',
306             flavor=load_flavor_settings.name,
307             port_settings=[load_port_settings],
308             security_group_names=[ixia_ssh_http_sg_settings.name,
309                                   ixia_managment_sg_settings.name],
310             floating_ip_settings=[FloatingIpConfig(
311                 name='ixia_vLoad_fip',
312                 port_name=load_port_settings.name,
313                 router_name=router_creator.router_settings.name)])
314
315         vm_creator = OpenStackVmInstance(self.snaps_creds,
316                                          load_settings,
317                                          load_image_settings)
318
319         self.__logger.info("Creating Ixia vLoad VM")
320         vm_creator.create()
321         fip_load = vm_creator.get_floating_ip().ip
322         self.created_object.append(vm_creator)
323
324         self.__logger.info("Chassis IP is: %s", fip_chassis)
325         login_url = "https://" + str(fip_chassis) + "/api/v1/auth/session"
326         cards_url = "https://" + str(fip_chassis) + "/api/v2/ixos/cards/"
327
328         payload = json.dumps({"username": "admin",
329                               "password": "admin",
330                               "rememberMe": "false"})
331         api_key = json.loads((
332             ChassisRestAPI.postWithPayload(login_url, payload)))["apiKey"]
333
334         self.__logger.info("Adding 2 card back inside the ixia chassis...")
335
336         for ip in vcard_ips:
337             payload = {"ipAddress": str(ip)}
338             response = json.loads(ChassisRestAPI.postOperation(cards_url,
339                                                                api_key,
340                                                                payload))
341             count = 0
342             while (int(
343                  ChassisRestAPI.getWithHeaders(response['url'],
344                                                api_key)['progress']) != 100):
345                 self.__logger.debug("Operation did not finish yet. \
346                                     Waiting for 1 more second..")
347                 time.sleep(1)
348                 if count > 60:
349                     raise Exception("Adding card take more than 60 seconds")
350                 count += 1
351
352         ssh = paramiko.SSHClient()
353         ssh.set_missing_host_key_policy(paramiko.MissingHostKeyPolicy())
354         ssh.connect(fip_chassis, username="admin", password="admin")
355         cmd = "set license-check disable"
356         run_blocking_ssh_command(ssh, cmd)
357         cmd = "restart-service ixServer"
358         run_blocking_ssh_command(ssh, cmd)
359
360         self.config_ellis(ellis_ip)
361
362         # Get IPs of P-CSCF
363         resolver = dns.resolver.Resolver()
364         resolver.nameservers = [dns_ip]
365         result = resolver.query("bono.clearwater.local")
366
367         iplistims = ''
368         i = 0
369         for rdata in result:
370             i = i + 1
371             print rdata.address
372             iplistims += str(rdata.address)
373             if i != len(result):
374                 iplistims += ';'
375
376         kResourcesUrl = 'http://%s:%s/api/v0/resources' % (fip_load, 8080)
377
378         kRxfPath = r"REG_CALL_OPNFV_v13.rxf"
379         test_filname = self.test['inputs']['test_filname']
380         kGatewaySharedFolder = '/mnt/ixload-share/'
381         kRxfRelativeUploadPath = 'uploads/%s' % os.path.split(kRxfPath)[1]
382         kRxfAbsoluteUploadPath = os.path.join(kGatewaySharedFolder,
383                                               kRxfRelativeUploadPath)
384         kChassisList = [str(fip_chassis)]
385         dataFileNameList = [test_filname,
386                             'Registration_only_LPS.tst',
387                             'SIPCall.tst']
388
389         kPortListPerCommunityCommunity = {"VoIP1@VM1": [(1, 1, 1)],
390                                           "VoIP2@VM2": [(1, 2, 1)]}
391
392         kStatsToDisplayDict = self.test['inputs']['stats']
393         connection = IxRestUtils.getConnection(fip_load, 8080)
394
395         self.__logger.info("Creating a new session...")
396         sessionUrl = IxLoadUtils.createSession(connection,
397                                                self.test['version'])
398
399         license_server = self.test['inputs']['licenseServer']
400         IxLoadUtils.configureLicenseServer(connection,
401                                            sessionUrl,
402                                            license_server)
403
404         files_dir = os.path.join(self.case_dir, 'ixia/files')
405         target_file = open(os.path.join(files_dir, test_filname), 'w')
406         j2_env = Environment(loader=FileSystemLoader(files_dir),
407                              trim_blocks=True)
408         self.test['inputs'].update(dict(
409                                     ipchassis=fip_chassis,
410                                     ipcard1=vcard_ips_p2[0],
411                                     ipcard2=vcard_ips_p2[1],
412                                     iplistims=iplistims
413         ))
414
415         target_file.write(
416             j2_env.get_template(test_filname + '.template').render(
417                 self.test['inputs']
418             ))
419         target_file.close()
420
421         self.__logger.info('Uploading files %s...' % kRxfPath)
422         for dataFile in dataFileNameList:
423             localFilePath = os.path.join(files_dir, dataFile)
424             remoteFilePath = os.path.join(kGatewaySharedFolder,
425                                           'uploads/%s' % dataFile)
426             IxLoadUtils.uploadFile(connection, kResourcesUrl,
427                                    localFilePath, remoteFilePath)
428         self.__logger.info('Upload file finished.')
429
430         self.__logger.info("Loading repository %s..." % kRxfAbsoluteUploadPath)
431         IxLoadUtils.loadRepository(connection, sessionUrl,
432                                    kRxfAbsoluteUploadPath)
433
434         self.__logger.info("Clearing chassis list...")
435         IxLoadUtils.clearChassisList(connection, sessionUrl)
436
437         self.__logger.info("Adding chassis %s..." % (kChassisList))
438         IxLoadUtils.addChassisList(connection, sessionUrl, kChassisList)
439
440         self.__logger.info("Assigning new ports...")
441         IxLoadUtils.assignPorts(connection, sessionUrl,
442                                 kPortListPerCommunityCommunity)
443
444         self.__logger.info("Starting the test...")
445         IxLoadUtils.runTest(connection, sessionUrl)
446
447         self.__logger.info("Polling values for stats %s..." % (
448                                                         kStatsToDisplayDict))
449         result = IxLoadUtils.pollStats(connection, sessionUrl,
450                                        kStatsToDisplayDict)
451         self.__logger.info("Test finished.")
452         self.__logger.info("Checking test status...")
453         testRunError = IxLoadUtils.getTestRunError(connection, sessionUrl)
454
455         self.__logger.info(result)
456         duration = time.time() - start_time
457         self.details['test_vnf'].update(status='PASS',
458                                         result=result,
459                                         duration=duration)
460         if testRunError:
461             self.__logger.info("The test exited with following error: %s" % (
462                                                             testRunError))
463             self.details['test_vnf'].update(status='FAIL', duration=duration)
464             return False
465         else:
466             self.__logger.info("The test completed successfully.")
467             self.details['test_vnf'].update(status='PASS', duration=duration)
468             self.result += 1/3 * 100
469             return True
470
471     def clean(self):
472         """Clean created objects/functions."""
473         super(CloudifyImsPerf, self).clean()
474
475     @energy.enable_recording
476     def run(self, **kwargs):
477         """Execute CloudifyIms test case."""
478         return super(CloudifyImsPerf, self).run(**kwargs)
479
480
481 # ----------------------------------------------------------
482 #
483 #               YAML UTILS
484 #
485 # -----------------------------------------------------------
486 def get_config(parameter, file_path):
487     """
488     Get config parameter.
489
490     Returns the value of a given parameter in file.yaml
491     parameter must be given in string format with dots
492     Example: general.openstack.image_name
493     """
494     with open(file_path) as config_file:
495         file_yaml = yaml.safe_load(config_file)
496     config_file.close()
497     value = file_yaml
498     for element in parameter.split("."):
499         value = value.get(element)
500         if value is None:
501             raise ValueError("The parameter %s is not defined in"
502                              " reporting.yaml" % parameter)
503     return value
504
505
506 def run_blocking_ssh_command(ssh, cmd, error_msg="Unable to run this command"):
507     """Command to run ssh command with the exit status."""
508     stdin, stdout, stderr = ssh.exec_command(cmd)
509     if stdout.channel.recv_exit_status() != 0:
510         raise Exception(error_msg)