Switch from CONST to CONF
[functest.git] / functest / opnfv_tests / vnf / ims / orchestra_openims.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2016 Orange 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 """Orchestra OpenIMS testcase implementation."""
11
12 import json
13 import logging
14 import os
15 import socket
16 import time
17 import pkg_resources
18 import yaml
19
20 import functest.core.vnf as vnf
21 import functest.utils.openstack_utils as os_utils
22 from functest.utils import config
23
24 from org.openbaton.cli.errors.errors import NfvoException
25 from org.openbaton.cli.agents.agents import MainAgent
26 from snaps.config.flavor import FlavorConfig
27 from snaps.config.image import ImageConfig
28 from snaps.config.network import NetworkConfig, PortConfig, SubnetConfig
29 from snaps.config.router import RouterConfig
30 from snaps.config.security_group import (
31     Direction, Protocol, SecurityGroupConfig, SecurityGroupRuleConfig)
32 from snaps.config.vm_inst import VmInstanceConfig
33 from snaps.openstack.utils import keystone_utils
34 from snaps.openstack.create_image import OpenStackImage
35 from snaps.openstack.create_flavor import OpenStackFlavor
36 from snaps.openstack.create_security_group import OpenStackSecurityGroup
37 from snaps.openstack.create_network import OpenStackNetwork
38 from snaps.openstack.create_router import OpenStackRouter
39 from snaps.openstack.create_instance import OpenStackVmInstance
40
41 from functest.opnfv_tests.openstack.snaps import snaps_utils
42
43
44 __author__ = "Pauls, Michael <michael.pauls@fokus.fraunhofer.de>"
45 # ----------------------------------------------------------
46 #
47 #               UTILS
48 #
49 # -----------------------------------------------------------
50
51
52 def get_config(parameter, file_path):
53     """
54     Get config parameter.
55
56     Returns the value of a given parameter in file.yaml
57     parameter must be given in string format with dots
58     Example: general.openstack.image_name
59     """
60     with open(file_path) as config_file:
61         file_yaml = yaml.safe_load(config_file)
62     config_file.close()
63     value = file_yaml
64     for element in parameter.split("."):
65         value = value.get(element)
66         if value is None:
67             raise ValueError("The parameter %s is not defined in"
68                              " reporting.yaml", parameter)
69     return value
70
71
72 def servertest(host, port):
73     """Method to test that a server is reachable at IP:port"""
74     args = socket.getaddrinfo(host, port, socket.AF_INET, socket.SOCK_STREAM)
75     for family, socktype, proto, canonname, sockaddr in args:
76         sock = socket.socket(family, socktype, proto)
77         try:
78             sock.connect(sockaddr)
79         except socket.error:
80             return False
81         else:
82             sock.close()
83             return True
84
85
86 def get_userdata(orchestrator=dict):
87     """Build userdata for Open Baton machine"""
88     userdata = "#!/bin/bash\n"
89     userdata += "echo \"Executing userdata...\"\n"
90     userdata += "set -x\n"
91     userdata += "set -e\n"
92     userdata += "echo \"Set nameserver to '8.8.8.8'...\"\n"
93     userdata += "echo \"nameserver   8.8.8.8\" >> /etc/resolv.conf\n"
94     userdata += "echo \"Install curl...\"\n"
95     userdata += "apt-get install curl\n"
96     userdata += "echo \"Inject public key...\"\n"
97     userdata += ("echo \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuPXrV3"
98                  "geeHc6QUdyUr/1Z+yQiqLcOskiEGBiXr4z76MK4abiFmDZ18OMQlc"
99                  "fl0p3kS0WynVgyaOHwZkgy/DIoIplONVr2CKBKHtPK+Qcme2PVnCtv"
100                  "EqItl/FcD+1h5XSQGoa+A1TSGgCod/DPo+pes0piLVXP8Ph6QS1k7S"
101                  "ic7JDeRQ4oT1bXYpJ2eWBDMfxIWKZqcZRiGPgMIbJ1iEkxbpeaAd9O"
102                  "4MiM9nGCPESmed+p54uYFjwEDlAJZShcAZziiZYAvMZhvAhe6USljc"
103                  "7YAdalAnyD/jwCHuwIrUw/lxo7UdNCmaUxeobEYyyFA1YVXzpNFZya"
104                  "XPGAAYIJwEq/ openbaton@opnfv\" >> /home/ubuntu/.ssh/aut"
105                  "horized_keys\n")
106     userdata += "echo \"Download bootstrap...\"\n"
107     userdata += ("curl -s %s "
108                  "> ./bootstrap\n" % orchestrator['bootstrap']['url'])
109     userdata += ("curl -s %s" "> ./config_file\n" %
110                  orchestrator['bootstrap']['config']['url'])
111     userdata += ("echo \"Disable usage of mysql...\"\n")
112     userdata += "sed -i s/mysql=.*/mysql=no/g /config_file\n"
113     userdata += ("echo \"Setting 'rabbitmq_broker_ip' to '%s'\"\n"
114                  % orchestrator['details']['fip'].ip)
115     userdata += ("sed -i s/rabbitmq_broker_ip=localhost/rabbitmq_broker_ip"
116                  "=%s/g /config_file\n" % orchestrator['details']['fip'].ip)
117     userdata += "echo \"Set autostart of components to 'false'\"\n"
118     userdata += "export OPENBATON_COMPONENT_AUTOSTART=false\n"
119     userdata += "echo \"Execute bootstrap...\"\n"
120     bootstrap = "sh ./bootstrap release -configFile=./config_file"
121     userdata += bootstrap + "\n"
122     userdata += "echo \"Setting 'nfvo.plugin.timeout' to '300000'\"\n"
123     userdata += ("echo \"nfvo.plugin.timeout=600000\" >> "
124                  "/etc/openbaton/openbaton-nfvo.properties\n")
125     userdata += (
126         "wget %s -O /etc/openbaton/openbaton-vnfm-generic-user-data.sh\n" %
127         orchestrator['gvnfm']['userdata']['url'])
128     userdata += "sed -i '113i"'\ \ \ \ '"sleep 60' " \
129                 "/etc/openbaton/openbaton-vnfm-generic-user-data.sh\n"
130     userdata += ("sed -i s/nfvo.marketplace.port=8082/nfvo.marketplace."
131                  "port=8080/g /etc/openbaton/openbaton-nfvo.properties\n")
132     userdata += "echo \"Starting NFVO\"\n"
133     userdata += "service openbaton-nfvo restart\n"
134     userdata += "echo \"Starting Generic VNFM\"\n"
135     userdata += "service openbaton-vnfm-generic restart\n"
136     userdata += "echo \"...end of userdata...\"\n"
137     return userdata
138
139
140 class OpenImsVnf(vnf.VnfOnBoarding):
141     """OpenIMS VNF deployed with openBaton orchestrator"""
142
143     # logger = logging.getLogger(__name__)
144
145     def __init__(self, **kwargs):
146         if "case_name" not in kwargs:
147             kwargs["case_name"] = "orchestra_openims"
148         super(OpenImsVnf, self).__init__(**kwargs)
149         self.logger = logging.getLogger("functest.ci.run_tests.orchestra")
150         self.logger.info("kwargs %s", (kwargs))
151
152         self.case_dir = pkg_resources.resource_filename(
153             'functest', 'opnfv_tests/vnf/ims/')
154         self.data_dir = getattr(config.CONF, 'dir_ims_data')
155         self.test_dir = getattr(config.CONF, 'dir_repo_vims_test')
156         self.created_resources = []
157         self.logger.info("%s VNF onboarding test starting", self.case_name)
158
159         try:
160             self.config = getattr(
161                 config.CONF, 'vnf_{}_config'.format(self.case_name))
162         except BaseException:
163             raise Exception("Orchestra VNF config file not found")
164         config_file = self.case_dir + self.config
165
166         self.mano = dict(
167             get_config("mano", config_file),
168             details={}
169         )
170         self.logger.debug("Orchestrator configuration %s", self.mano)
171
172         self.details['orchestrator'] = dict(
173             name=self.mano['name'],
174             version=self.mano['version'],
175             status='ERROR',
176             result=''
177         )
178
179         self.vnf = dict(
180             get_config(self.case_name, config_file),
181         )
182         self.logger.debug("VNF configuration: %s", self.vnf)
183
184         self.details['vnf'] = dict(
185             name=self.vnf['name'],
186         )
187
188         self.details['test_vnf'] = dict(
189             name=self.case_name,
190         )
191
192         # Orchestra base Data directory creation
193         if not os.path.exists(self.data_dir):
194             os.makedirs(self.data_dir)
195
196         self.images = get_config("tenant_images.orchestrator", config_file)
197         self.images.update(get_config("tenant_images.%s" %
198                                       self.case_name, config_file))
199
200     def prepare(self):
201         """Prepare testscase (Additional pre-configuration steps)."""
202         super(OpenImsVnf, self).prepare()
203
204         public_auth_url = keystone_utils.get_endpoint(
205             self.snaps_creds, 'identity')
206
207         self.logger.info("Additional pre-configuration steps")
208         self.creds = {
209             "tenant": self.snaps_creds.project_name,
210             "username": self.snaps_creds.username,
211             "password": self.snaps_creds.password,
212             "auth_url": public_auth_url}
213         self.prepare_images()
214         self.prepare_flavor()
215         self.prepare_security_groups()
216         self.prepare_network()
217         self.prepare_floating_ip()
218
219     def prepare_images(self):
220         """Upload images if they doen't exist yet"""
221         self.logger.info("Upload images if they doen't exist yet")
222         for image_name, image_file in self.images.iteritems():
223             self.logger.info("image: %s, file: %s", image_name, image_file)
224             if image_file and image_name:
225                 image = OpenStackImage(
226                     self.snaps_creds,
227                     ImageConfig(name=image_name,
228                                 image_user='cloud',
229                                 img_format='qcow2',
230                                 image_file=image_file,
231                                 public=True))
232                 image.create()
233                 # self.created_resources.append(image);
234
235     def prepare_security_groups(self):
236         """Create Open Baton security group if it doesn't exist yet"""
237         self.logger.info(
238             "Creating security group for Open Baton if not yet existing...")
239         sg_rules = list()
240         sg_rules.append(
241             SecurityGroupRuleConfig(
242                 sec_grp_name="orchestra-sec-group-allowall",
243                 direction=Direction.ingress,
244                 protocol=Protocol.tcp,
245                 port_range_min=1,
246                 port_range_max=65535))
247         sg_rules.append(
248             SecurityGroupRuleConfig(
249                 sec_grp_name="orchestra-sec-group-allowall",
250                 direction=Direction.egress,
251                 protocol=Protocol.tcp,
252                 port_range_min=1,
253                 port_range_max=65535))
254         sg_rules.append(
255             SecurityGroupRuleConfig(
256                 sec_grp_name="orchestra-sec-group-allowall",
257                 direction=Direction.ingress,
258                 protocol=Protocol.udp,
259                 port_range_min=1,
260                 port_range_max=65535))
261         sg_rules.append(
262             SecurityGroupRuleConfig(
263                 sec_grp_name="orchestra-sec-group-allowall",
264                 direction=Direction.egress,
265                 protocol=Protocol.udp,
266                 port_range_min=1,
267                 port_range_max=65535))
268         security_group = OpenStackSecurityGroup(
269             self.snaps_creds,
270             SecurityGroupConfig(
271                 name="orchestra-sec-group-allowall",
272                 rule_settings=sg_rules))
273
274         security_group_info = security_group.create()
275         self.created_resources.append(security_group)
276         self.mano['details']['sec_group'] = security_group_info.name
277         self.logger.info(
278             "Security group orchestra-sec-group-allowall prepared")
279
280     def prepare_flavor(self):
281         """Create Open Baton flavor if it doesn't exist yet"""
282         self.logger.info(
283             "Create Flavor for Open Baton NFVO if not yet existing")
284
285         flavor_settings = FlavorConfig(
286             name=self.mano['requirements']['flavor']['name'],
287             ram=self.mano['requirements']['flavor']['ram_min'],
288             disk=self.mano['requirements']['flavor']['disk'],
289             vcpus=self.mano['requirements']['flavor']['vcpus'])
290         flavor = OpenStackFlavor(self.snaps_creds, flavor_settings)
291         flavor_info = flavor.create()
292         self.created_resources.append(flavor)
293         self.mano['details']['flavor'] = {}
294         self.mano['details']['flavor']['name'] = flavor_settings.name
295         self.mano['details']['flavor']['id'] = flavor_info.id
296
297     def prepare_network(self):
298         """Create network/subnet/router if they doen't exist yet"""
299         self.logger.info(
300             "Creating network/subnet/router if they doen't exist yet...")
301         subnet_settings = SubnetConfig(
302             name='%s_subnet' %
303             self.case_name,
304             cidr="192.168.100.0/24")
305         network_settings = NetworkConfig(
306             name='%s_net' %
307             self.case_name,
308             subnet_settings=[subnet_settings])
309         orchestra_network = OpenStackNetwork(
310             self.snaps_creds, network_settings)
311         orchestra_network_info = orchestra_network.create()
312         self.mano['details']['network'] = {}
313         self.mano['details']['network']['id'] = orchestra_network_info.id
314         self.mano['details']['network']['name'] = orchestra_network_info.name
315         self.mano['details']['external_net_name'] = \
316             snaps_utils.get_ext_net_name(self.snaps_creds)
317         self.created_resources.append(orchestra_network)
318         orchestra_router = OpenStackRouter(
319             self.snaps_creds,
320             RouterConfig(
321                 name='%s_router' %
322                 self.case_name,
323                 external_gateway=self.mano['details']['external_net_name'],
324                 internal_subnets=[
325                     subnet_settings.name]))
326         orchestra_router.create()
327         self.created_resources.append(orchestra_router)
328         self.logger.info("Created network and router for Open Baton NFVO...")
329
330     def prepare_floating_ip(self):
331         """Select/Create Floating IP if it doesn't exist yet"""
332         self.logger.info("Retrieving floating IP for Open Baton NFVO")
333         neutron_client = snaps_utils.neutron_utils.neutron_client(
334             self.snaps_creds)
335         # Finding Tenant ID to check to which tenant the Floating IP belongs
336         tenant_id = os_utils.get_tenant_id(
337             os_utils.get_keystone_client(self.creds),
338             self.tenant_name)
339         # Use os_utils to retrieve complete information of Floating IPs
340         floating_ips = os_utils.get_floating_ips(neutron_client)
341         my_floating_ips = []
342         # Filter Floating IPs with tenant id
343         for floating_ip in floating_ips:
344             # self.logger.info("Floating IP: %s", floating_ip)
345             if floating_ip.get('tenant_id') == tenant_id:
346                 my_floating_ips.append(floating_ip.get('floating_ip_address'))
347         # Select if Floating IP exist else create new one
348         if len(my_floating_ips) >= 1:
349             # Get Floating IP object from snaps for clean up
350             snaps_floating_ips = snaps_utils.neutron_utils.get_floating_ips(
351                 neutron_client)
352             for my_floating_ip in my_floating_ips:
353                 for snaps_floating_ip in snaps_floating_ips:
354                     if snaps_floating_ip.ip == my_floating_ip:
355                         self.mano['details']['fip'] = snaps_floating_ip
356                         self.logger.info(
357                             "Selected floating IP for Open Baton NFVO %s",
358                             (self.mano['details']['fip'].ip))
359                         break
360                 if self.mano['details']['fip'] is not None:
361                     break
362         else:
363             self.logger.info("Creating floating IP for Open Baton NFVO")
364             self.mano['details']['fip'] = (
365                 snaps_utils.neutron_utils. create_floating_ip(
366                     neutron_client, self.mano['details']['external_net_name']))
367             self.logger.info(
368                 "Created floating IP for Open Baton NFVO %s",
369                 (self.mano['details']['fip'].ip))
370
371     def get_vim_descriptor(self):
372         """"Create VIM descriptor to be used for onboarding"""
373         self.logger.info(
374             "Building VIM descriptor with PoP creds: %s",
375             self.creds)
376         # Depending on API version either tenant ID or project name must be
377         # used
378         if os_utils.is_keystone_v3():
379             self.logger.info(
380                 "Using v3 API of OpenStack... -> Using OS_PROJECT_ID")
381             project_id = os_utils.get_tenant_id(
382                 os_utils.get_keystone_client(),
383                 self.creds.get("project_name"))
384         else:
385             self.logger.info(
386                 "Using v2 API of OpenStack... -> Using OS_TENANT_NAME")
387             project_id = self.creds.get("tenant_name")
388         self.logger.debug("VIM project/tenant id: %s", project_id)
389         vim_json = {
390             "name": "vim-instance",
391             "authUrl": self.creds.get("auth_url"),
392             "tenant": project_id,
393             "username": self.creds.get("username"),
394             "password": self.creds.get("password"),
395             "securityGroups": [
396                 self.mano['details']['sec_group']
397             ],
398             "type": "openstack",
399             "location": {
400                 "name": "opnfv",
401                 "latitude": "52.525876",
402                 "longitude": "13.314400"
403             }
404         }
405         self.logger.info("Built VIM descriptor: %s", vim_json)
406         return vim_json
407
408     def deploy_orchestrator(self):
409         self.logger.info("Deploying Open Baton...")
410         self.logger.info("Details: %s", self.mano['details'])
411         start_time = time.time()
412
413         self.logger.info("Creating orchestra instance...")
414         userdata = get_userdata(self.mano)
415         self.logger.info("flavor: %s\n"
416                          "image: %s\n"
417                          "network_id: %s\n",
418                          self.mano['details']['flavor']['name'],
419                          self.mano['requirements']['image'],
420                          self.mano['details']['network']['id'])
421         self.logger.debug("userdata: %s\n", userdata)
422         # setting up image
423         image_settings = ImageConfig(
424             name=self.mano['requirements']['image'],
425             image_user='ubuntu',
426             exists=True)
427         # setting up port
428         port_settings = PortConfig(
429             name='%s_port' % self.case_name,
430             network_name=self.mano['details']['network']['name'])
431         # build configuration of vm
432         orchestra_settings = VmInstanceConfig(
433             name=self.case_name,
434             flavor=self.mano['details']['flavor']['name'],
435             port_settings=[port_settings],
436             security_group_names=[self.mano['details']['sec_group']],
437             userdata=str(userdata))
438         orchestra_vm = OpenStackVmInstance(self.snaps_creds,
439                                            orchestra_settings,
440                                            image_settings)
441
442         orchestra_vm.create()
443         self.created_resources.append(orchestra_vm)
444         self.mano['details']['id'] = orchestra_vm.get_vm_info()['id']
445         self.logger.info(
446             "Created orchestra instance: %s",
447             self.mano['details']['id'])
448
449         self.logger.info("Associating floating ip: '%s' to VM '%s' ",
450                          self.mano['details']['fip'].ip,
451                          self.case_name)
452         nova_client = os_utils.get_nova_client()
453         if not os_utils.add_floating_ip(
454                 nova_client,
455                 self.mano['details']['id'],
456                 self.mano['details']['fip'].ip):
457             duration = time.time() - start_time
458             self.details["orchestrator"].update(
459                 status='FAIL', duration=duration)
460             self.logger.error("Cannot associate floating IP to VM.")
461             return False
462
463         self.logger.info("Waiting for Open Baton NFVO to be up and running...")
464         timeout = 0
465         while timeout < 20:
466             if servertest(
467                     self.mano['details']['fip'].ip,
468                     "8080"):
469                 break
470             else:
471                 self.logger.info("Open Baton NFVO is not started yet (%ss)",
472                                  (timeout * 60))
473                 time.sleep(60)
474                 timeout += 1
475
476         if timeout >= 20:
477             duration = time.time() - start_time
478             self.details["orchestrator"].update(
479                 status='FAIL', duration=duration)
480             self.logger.error("Open Baton is not started correctly")
481             return False
482
483         self.logger.info("Waiting for all components to be up and running...")
484         time.sleep(60)
485         duration = time.time() - start_time
486         self.details["orchestrator"].update(status='PASS', duration=duration)
487         self.logger.info("Deploy Open Baton NFVO: OK")
488         return True
489
490     def deploy_vnf(self):
491         start_time = time.time()
492         self.logger.info("Deploying %s...", self.vnf['name'])
493
494         main_agent = MainAgent(
495             nfvo_ip=self.mano['details']['fip'].ip,
496             nfvo_port=8080,
497             https=False,
498             version=1,
499             username=self.mano['credentials']['username'],
500             password=self.mano['credentials']['password'])
501
502         self.logger.info(
503             "Create %s Flavor if not existing", self.vnf['name'])
504         flavor_settings = FlavorConfig(
505             name=self.vnf['requirements']['flavor']['name'],
506             ram=self.vnf['requirements']['flavor']['ram_min'],
507             disk=self.vnf['requirements']['flavor']['disk'],
508             vcpus=self.vnf['requirements']['flavor']['vcpus'])
509         flavor = OpenStackFlavor(self.snaps_creds, flavor_settings)
510         flavor_info = flavor.create()
511         self.logger.debug("Flavor id: %s", flavor_info.id)
512
513         self.logger.info("Getting project 'default'...")
514         project_agent = main_agent.get_agent("project", "")
515         for project in json.loads(project_agent.find()):
516             if project.get("name") == "default":
517                 self.mano['details']['project_id'] = project.get("id")
518                 self.logger.info("Found project 'default': %s", project)
519                 break
520
521         vim_json = self.get_vim_descriptor()
522         self.logger.info("Registering VIM: %s", vim_json)
523
524         main_agent.get_agent(
525             "vim", project_id=self.mano['details']['project_id']).create(
526                 entity=json.dumps(vim_json))
527
528         market_agent = main_agent.get_agent(
529             "market", project_id=self.mano['details']['project_id'])
530
531         try:
532             self.logger.info("sending: %s", self.vnf['descriptor']['url'])
533             nsd = market_agent.create(entity=self.vnf['descriptor']['url'])
534             if nsd.get('id') is None:
535                 self.logger.error("NSD not onboarded correctly")
536                 duration = time.time() - start_time
537                 self.details["vnf"].update(status='FAIL', duration=duration)
538                 return False
539             self.mano['details']['nsd_id'] = nsd.get('id')
540             self.logger.info("Onboarded NSD: " + nsd.get("name"))
541
542             nsr_agent = main_agent.get_agent(
543                 "nsr", project_id=self.mano['details']['project_id'])
544
545             self.mano['details']['nsr'] = nsr_agent.create(
546                 self.mano['details']['nsd_id'])
547         except NfvoException as exc:
548             self.logger.error(exc.message)
549             duration = time.time() - start_time
550             self.details["vnf"].update(status='FAIL', duration=duration)
551             return False
552
553         if self.mano['details']['nsr'].get('code') is not None:
554             self.logger.error(
555                 "%s cannot be deployed: %s -> %s",
556                 self.vnf['name'],
557                 self.mano['details']['nsr'].get('code'),
558                 self.mano['details']['nsr'].get('message'))
559             self.logger.error("%s cannot be deployed", self.vnf['name'])
560             duration = time.time() - start_time
561             self.details["vnf"].update(status='FAIL', duration=duration)
562             return False
563
564         timeout = 0
565         self.logger.info("Waiting for NSR to go to ACTIVE...")
566         while self.mano['details']['nsr'].get("status") != 'ACTIVE' \
567                 and self.mano['details']['nsr'].get("status") != 'ERROR':
568             timeout += 1
569             self.logger.info("NSR is not yet ACTIVE... (%ss)", 60 * timeout)
570             if timeout == 30:
571                 self.logger.error("INACTIVE NSR after %s sec..", 60 * timeout)
572                 duration = time.time() - start_time
573                 self.details["vnf"].update(status='FAIL', duration=duration)
574                 return False
575             time.sleep(60)
576             self.mano['details']['nsr'] = json.loads(
577                 nsr_agent.find(self.mano['details']['nsr'].get('id')))
578
579         duration = time.time() - start_time
580         if self.mano['details']['nsr'].get("status") == 'ACTIVE':
581             self.details["vnf"].update(status='PASS', duration=duration)
582             self.logger.info("Sleep for 60s to ensure that all "
583                              "services are up and running...")
584             time.sleep(60)
585             result = True
586         else:
587             self.details["vnf"].update(status='FAIL', duration=duration)
588             self.logger.error("NSR: %s", self.mano['details'].get('nsr'))
589             result = False
590         return result
591
592     def test_vnf(self):
593         self.logger.info("Testing VNF OpenIMS...")
594         start_time = time.time()
595         self.logger.info(
596             "Testing if %s works properly...",
597             self.mano['details']['nsr'].get('name'))
598         for vnfr in self.mano['details']['nsr'].get('vnfr'):
599             self.logger.info(
600                 "Checking ports %s of VNF %s",
601                 self.vnf['test'][vnfr.get('name')]['ports'],
602                 vnfr.get('name'))
603             for vdu in vnfr.get('vdu'):
604                 for vnfci in vdu.get('vnfc_instance'):
605                     self.logger.debug(
606                         "Checking ports of VNFC instance %s",
607                         vnfci.get('hostname'))
608                     for floating_ip in vnfci.get('floatingIps'):
609                         self.logger.debug(
610                             "Testing %s:%s",
611                             vnfci.get('hostname'),
612                             floating_ip.get('ip'))
613                         for port in self.vnf['test'][vnfr.get(
614                                 'name')]['ports']:
615                             if servertest(floating_ip.get('ip'), port):
616                                 self.logger.info(
617                                     "VNFC instance %s is reachable at %s:%s",
618                                     vnfci.get('hostname'),
619                                     floating_ip.get('ip'),
620                                     port)
621                             else:
622                                 self.logger.error(
623                                     "VNFC instance %s is not reachable "
624                                     "at %s:%s",
625                                     vnfci.get('hostname'),
626                                     floating_ip.get('ip'),
627                                     port)
628                                 duration = time.time() - start_time
629                                 self.details["test_vnf"].update(
630                                     status='FAIL', duration=duration, esult=(
631                                         "Port %s of server %s -> %s is "
632                                         "not reachable",
633                                         port,
634                                         vnfci.get('hostname'),
635                                         floating_ip.get('ip')))
636                                 self.logger.error("Test VNF: ERROR")
637                                 return False
638         duration = time.time() - start_time
639         self.details["test_vnf"].update(status='PASS', duration=duration)
640         self.logger.info("Test VNF: OK")
641         return True
642
643     def clean(self):
644         self.logger.info("Cleaning %s...", self.case_name)
645         try:
646             main_agent = MainAgent(
647                 nfvo_ip=self.mano['details']['fip'].ip,
648                 nfvo_port=8080,
649                 https=False,
650                 version=1,
651                 username=self.mano['credentials']['username'],
652                 password=self.mano['credentials']['password'])
653             self.logger.info("Terminating %s...", self.vnf['name'])
654             if (self.mano['details'].get('nsr')):
655                 main_agent.get_agent(
656                     "nsr",
657                     project_id=self.mano['details']['project_id']).\
658                         delete(self.mano['details']['nsr'].get('id'))
659                 self.logger.info("Sleeping 60 seconds...")
660                 time.sleep(60)
661             else:
662                 self.logger.info("No need to terminate the VNF...")
663         except (NfvoException, KeyError) as exc:
664             self.logger.error('Unexpected error cleaning - %s', exc)
665
666         try:
667             neutron_client = os_utils.get_neutron_client(self.creds)
668             self.logger.info("Deleting Open Baton Port...")
669             port = snaps_utils.neutron_utils.get_port(
670                 neutron_client,
671                 port_name='%s_port' % self.case_name)
672             snaps_utils.neutron_utils.delete_port(neutron_client, port)
673             time.sleep(10)
674         except Exception as exc:  # pylint: disable=broad-except
675             self.logger.error('Unexpected error cleaning - %s', exc)
676         try:
677             self.logger.info("Deleting Open Baton Floating IP...")
678             snaps_utils.neutron_utils.delete_floating_ip(
679                 neutron_client, self.mano['details']['fip'])
680         except Exception as exc:  # pylint: disable=broad-except
681             self.logger.error('Unexpected error cleaning - %s', exc)
682
683         for resource in reversed(self.created_resources):
684             try:
685                 self.logger.info("Cleaning %s", str(resource))
686                 resource.clean()
687             except Exception as exc:
688                 self.logger.error('Unexpected error cleaning - %s', exc)
689         super(OpenImsVnf, self).clean()