#!/usr/bin/env python

# Copyright (c) 2016 Orange 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

"""Orchestra Clearwater IMS testcase implementation."""

import json
import logging
import os
import socket
import time
import pkg_resources
import yaml

from snaps.openstack.create_image import OpenStackImage, ImageSettings
from snaps.openstack.create_flavor import OpenStackFlavor, FlavorSettings
from snaps.openstack.create_security_group import (
    OpenStackSecurityGroup,
    SecurityGroupSettings,
    SecurityGroupRuleSettings,
    Direction,
    Protocol)
from snaps.openstack.create_network import (
    OpenStackNetwork,
    NetworkSettings,
    SubnetSettings,
    PortSettings)
from snaps.openstack.create_router import OpenStackRouter, RouterSettings
from snaps.openstack.os_credentials import OSCreds
from snaps.openstack.create_instance import (
    VmInstanceSettings,
    OpenStackVmInstance)
from functest.opnfv_tests.openstack.snaps import snaps_utils

import functest.core.vnf as vnf
import functest.utils.openstack_utils as os_utils
from functest.utils.constants import CONST

from org.openbaton.cli.errors.errors import NfvoException
from org.openbaton.cli.agents.agents import MainAgent


__author__ = "Pauls, Michael <michael.pauls@fokus.fraunhofer.de>"
# ----------------------------------------------------------
#
#               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 servertest(host, port):
    """Method to test that a server is reachable at IP:port"""
    args = socket.getaddrinfo(host, port, socket.AF_INET, socket.SOCK_STREAM)
    for family, socktype, proto, canonname, sockaddr in args:
        sock = socket.socket(family, socktype, proto)
        try:
            sock.connect(sockaddr)
        except socket.error:
            return False
        else:
            sock.close()
            return True


def get_userdata(orchestrator=dict):
    """Build userdata for Open Baton machine"""
    userdata = "#!/bin/bash\n"
    userdata += "echo \"Executing userdata...\"\n"
    userdata += "set -x\n"
    userdata += "set -e\n"
    userdata += "echo \"Set nameserver to '8.8.8.8'...\"\n"
    userdata += "echo \"nameserver   8.8.8.8\" >> /etc/resolv.conf\n"
    userdata += "echo \"Install curl...\"\n"
    userdata += "apt-get install curl\n"
    userdata += "echo \"Inject public key...\"\n"
    userdata += ("echo \"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCuPXrV3"
                 "geeHc6QUdyUr/1Z+yQiqLcOskiEGBiXr4z76MK4abiFmDZ18OMQlc"
                 "fl0p3kS0WynVgyaOHwZkgy/DIoIplONVr2CKBKHtPK+Qcme2PVnCtv"
                 "EqItl/FcD+1h5XSQGoa+A1TSGgCod/DPo+pes0piLVXP8Ph6QS1k7S"
                 "ic7JDeRQ4oT1bXYpJ2eWBDMfxIWKZqcZRiGPgMIbJ1iEkxbpeaAd9O"
                 "4MiM9nGCPESmed+p54uYFjwEDlAJZShcAZziiZYAvMZhvAhe6USljc"
                 "7YAdalAnyD/jwCHuwIrUw/lxo7UdNCmaUxeobEYyyFA1YVXzpNFZya"
                 "XPGAAYIJwEq/ openbaton@opnfv\" >> /home/ubuntu/.ssh/aut"
                 "horized_keys\n")
    userdata += "echo \"Download bootstrap...\"\n"
    userdata += ("curl -s %s "
                 "> ./bootstrap\n" % orchestrator['bootstrap']['url'])
    userdata += ("curl -s %s" "> ./config_file\n" %
                 orchestrator['bootstrap']['config']['url'])
    userdata += ("echo \"Disable usage of mysql...\"\n")
    userdata += "sed -i s/mysql=.*/mysql=no/g /config_file\n"
    userdata += ("echo \"Setting 'rabbitmq_broker_ip' to '%s'\"\n"
                 % orchestrator['details']['fip'].ip)
    userdata += ("sed -i s/rabbitmq_broker_ip=localhost/rabbitmq_broker_ip"
                 "=%s/g /config_file\n" % orchestrator['details']['fip'].ip)
    userdata += "echo \"Set autostart of components to 'false'\"\n"
    userdata += "export OPENBATON_COMPONENT_AUTOSTART=false\n"
    userdata += "echo \"Execute bootstrap...\"\n"
    bootstrap = "sh ./bootstrap release -configFile=./config_file"
    userdata += bootstrap + "\n"
    userdata += "echo \"Setting 'nfvo.plugin.timeout' to '300000'\"\n"
    userdata += ("echo \"nfvo.plugin.timeout=600000\" >> "
                 "/etc/openbaton/openbaton-nfvo.properties\n")
    userdata += (
        "wget %s -O /etc/openbaton/openbaton-vnfm-generic-user-data.sh\n" %
        orchestrator['gvnfm']['userdata']['url'])
    userdata += "sed -i '113i"'\ \ \ \ '"sleep 60' " \
                "/etc/openbaton/openbaton-vnfm-generic-user-data.sh\n"
    userdata += "echo \"Starting NFVO\"\n"
    userdata += "service openbaton-nfvo restart\n"
    userdata += "echo \"Starting Generic VNFM\"\n"
    userdata += "service openbaton-vnfm-generic restart\n"
    userdata += "echo \"...end of userdata...\"\n"
    return userdata


class ClearwaterImsVnf(vnf.VnfOnBoarding):
    """Clearwater IMS VNF deployed with openBaton orchestrator"""

    logger = logging.getLogger(__name__)

    def __init__(self, **kwargs):
        if "case_name" not in kwargs:
            kwargs["case_name"] = "orchestra_clearwaterims"
        super(ClearwaterImsVnf, self).__init__(**kwargs)
        # self.logger = logging.getLogger("functest.ci.run_tests.orchestra")
        self.logger.info("kwargs %s", (kwargs))

        self.case_dir = pkg_resources.resource_filename(
            'functest', 'opnfv_tests/vnf/ims/')
        self.data_dir = CONST.__getattribute__('dir_ims_data')
        self.test_dir = CONST.__getattribute__('dir_repo_vims_test')
        self.created_resources = []
        self.logger.info("%s VNF onboarding test starting", self.case_name)

        try:
            self.config = CONST.__getattribute__(
                'vnf_{}_config'.format(self.case_name))
        except BaseException:
            raise Exception("Orchestra VNF config file not found")
        config_file = self.case_dir + self.config

        self.mano = dict(
            get_config("mano", config_file),
            details={}
        )
        self.logger.debug("Orchestrator configuration %s", self.mano)

        self.details['orchestrator'] = dict(
            name=self.mano['name'],
            version=self.mano['version'],
            status='ERROR',
            result=''
        )

        self.vnf = dict(
            get_config(self.case_name, config_file),
        )
        self.logger.debug("VNF configuration: %s", self.vnf)

        self.details['vnf'] = dict(
            name=self.vnf['name'],
        )

        self.details['test_vnf'] = dict(
            name=self.case_name,
        )

        # Orchestra base Data directory creation
        if not os.path.exists(self.data_dir):
            os.makedirs(self.data_dir)

        self.images = get_config("tenant_images.orchestrator", config_file)
        self.images.update(
            get_config(
                "tenant_images.%s" %
                self.case_name,
                config_file))
        self.snaps_creds = None

    def prepare(self):
        """Prepare testscase (Additional pre-configuration steps)."""
        super(ClearwaterImsVnf, self).prepare()

        self.logger.info("Additional pre-configuration steps")
        self.logger.info("creds %s", (self.creds))

        self.snaps_creds = OSCreds(
            username=self.creds['username'],
            password=self.creds['password'],
            auth_url=self.creds['auth_url'],
            project_name=self.creds['tenant'],
            identity_api_version=int(os_utils.get_keystone_client_version()))

        self.prepare_images()
        self.prepare_flavor()
        self.prepare_security_groups()
        self.prepare_network()
        self.prepare_floating_ip()

    def prepare_images(self):
        """Upload images if they doen't exist yet"""
        self.logger.info("Upload images if they doen't exist yet")
        for image_name, image_file in self.images.iteritems():
            self.logger.info("image: %s, file: %s", image_name, image_file)
            if image_file and image_name:
                image = OpenStackImage(
                    self.snaps_creds,
                    ImageSettings(name=image_name,
                                  image_user='cloud',
                                  img_format='qcow2',
                                  image_file=image_file))
                image.create()
                # self.created_resources.append(image);

    def prepare_security_groups(self):
        """Create Open Baton security group if it doesn't exist yet"""
        self.logger.info(
            "Creating security group for Open Baton if not yet existing...")
        sg_rules = list()
        sg_rules.append(
            SecurityGroupRuleSettings(
                sec_grp_name="orchestra-sec-group-allowall",
                direction=Direction.ingress,
                protocol=Protocol.tcp,
                port_range_min=1,
                port_range_max=65535))
        sg_rules.append(
            SecurityGroupRuleSettings(
                sec_grp_name="orchestra-sec-group-allowall",
                direction=Direction.egress,
                protocol=Protocol.tcp,
                port_range_min=1,
                port_range_max=65535))
        sg_rules.append(
            SecurityGroupRuleSettings(
                sec_grp_name="orchestra-sec-group-allowall",
                direction=Direction.ingress,
                protocol=Protocol.udp,
                port_range_min=1,
                port_range_max=65535))
        sg_rules.append(
            SecurityGroupRuleSettings(
                sec_grp_name="orchestra-sec-group-allowall",
                direction=Direction.egress,
                protocol=Protocol.udp,
                port_range_min=1,
                port_range_max=65535))
        sg_rules.append(
            SecurityGroupRuleSettings(
                sec_grp_name="orchestra-sec-group-allowall",
                direction=Direction.ingress,
                protocol=Protocol.icmp))
        sg_rules.append(
            SecurityGroupRuleSettings(
                sec_grp_name="orchestra-sec-group-allowall",
                direction=Direction.egress,
                protocol=Protocol.icmp))
        # sg_rules.append(
        #     SecurityGroupRuleSettings(
        #         sec_grp_name="orchestra-sec-group-allowall",
        #         direction=Direction.ingress,
        #         protocol=Protocol.icmp,
        #         port_range_min=-1,
        #         port_range_max=-1))
        # sg_rules.append(
        #     SecurityGroupRuleSettings(
        #         sec_grp_name="orchestra-sec-group-allowall",
        #         direction=Direction.egress,
        #         protocol=Protocol.icmp,
        #         port_range_min=-1,
        #         port_range_max=-1))

        security_group = OpenStackSecurityGroup(
            self.snaps_creds,
            SecurityGroupSettings(
                name="orchestra-sec-group-allowall",
                rule_settings=sg_rules))

        security_group_info = security_group.create()
        self.created_resources.append(security_group)
        self.mano['details']['sec_group'] = security_group_info.name
        self.logger.info(
            "Security group orchestra-sec-group-allowall prepared")

    def prepare_flavor(self):
        """Create Open Baton flavor if it doesn't exist yet"""
        self.logger.info(
            "Create Flavor for Open Baton NFVO if not yet existing")

        flavor_settings = FlavorSettings(
            name=self.mano['requirements']['flavor']['name'],
            ram=self.mano['requirements']['flavor']['ram_min'],
            disk=self.mano['requirements']['flavor']['disk'],
            vcpus=self.mano['requirements']['flavor']['vcpus'])
        flavor = OpenStackFlavor(self.snaps_creds, flavor_settings)
        flavor_info = flavor.create()
        self.created_resources.append(flavor)
        self.mano['details']['flavor'] = {}
        self.mano['details']['flavor']['name'] = flavor_settings.name
        self.mano['details']['flavor']['id'] = flavor_info.id

    def prepare_network(self):
        """Create network/subnet/router if they doen't exist yet"""
        self.logger.info(
            "Creating network/subnet/router if they doen't exist yet...")
        subnet_settings = SubnetSettings(
            name='%s_subnet' %
            self.case_name,
            cidr="192.168.100.0/24")
        network_settings = NetworkSettings(
            name='%s_net' %
            self.case_name,
            subnet_settings=[subnet_settings])
        orchestra_network = OpenStackNetwork(
            self.snaps_creds, network_settings)
        orchestra_network_info = orchestra_network.create()
        self.mano['details']['network'] = {}
        self.mano['details']['network']['id'] = orchestra_network_info.id
        self.mano['details']['network']['name'] = orchestra_network_info.name
        self.mano['details']['external_net_name'] = snaps_utils.\
            get_ext_net_name(self.snaps_creds)
        self.created_resources.append(orchestra_network)
        orchestra_router = OpenStackRouter(
            self.snaps_creds,
            RouterSettings(
                name='%s_router' %
                self.case_name,
                external_gateway=self.mano['details']['external_net_name'],
                internal_subnets=[
                    subnet_settings.name]))
        orchestra_router.create()
        self.created_resources.append(orchestra_router)
        self.logger.info("Created network and router for Open Baton NFVO...")

    def prepare_floating_ip(self):
        """Select/Create Floating IP if it doesn't exist yet"""
        self.logger.info("Retrieving floating IP for Open Baton NFVO")
        neutron_client = snaps_utils.neutron_utils.neutron_client(
            self.snaps_creds)
        # Finding Tenant ID to check to which tenant the Floating IP belongs
        tenant_id = os_utils.get_tenant_id(
            os_utils.get_keystone_client(self.creds),
            self.tenant_name)
        # Use os_utils to retrieve complete information of Floating IPs
        floating_ips = os_utils.get_floating_ips(neutron_client)
        my_floating_ips = []
        # Filter Floating IPs with tenant id
        for floating_ip in floating_ips:
            # self.logger.info("Floating IP: %s", floating_ip)
            if floating_ip.get('tenant_id') == tenant_id:
                my_floating_ips.append(floating_ip.get('floating_ip_address'))
        # Select if Floating IP exist else create new one
        if len(my_floating_ips) >= 1:
            # Get Floating IP object from snaps for clean up
            snaps_floating_ips = snaps_utils.neutron_utils.get_floating_ips(
                neutron_client)
            for my_floating_ip in my_floating_ips:
                for snaps_floating_ip in snaps_floating_ips:
                    if snaps_floating_ip.ip == my_floating_ip:
                        self.mano['details']['fip'] = snaps_floating_ip
                        self.logger.info(
                            "Selected floating IP for Open Baton NFVO %s",
                            (self.mano['details']['fip'].ip))
                        break
                if self.mano['details']['fip'] is not None:
                    break
        else:
            self.logger.info("Creating floating IP for Open Baton NFVO")
            self.mano['details']['fip'] = snaps_utils.neutron_utils.\
                create_floating_ip(
                    neutron_client,
                    self.mano['details']['external_net_name'])
            self.logger.info(
                "Created floating IP for Open Baton NFVO %s",
                (self.mano['details']['fip'].ip))

    def get_vim_descriptor(self):
        """"Create VIM descriptor to be used for onboarding"""
        self.logger.info(
            "Building VIM descriptor with PoP creds: %s",
            self.creds)
        # Depending on API version either tenant ID or project name must be
        # used
        if os_utils.is_keystone_v3():
            self.logger.info(
                "Using v3 API of OpenStack... -> Using OS_PROJECT_ID")
            project_id = os_utils.get_tenant_id(
                os_utils.get_keystone_client(),
                self.creds.get("project_name"))
        else:
            self.logger.info(
                "Using v2 API of OpenStack... -> Using OS_TENANT_NAME")
            project_id = self.creds.get("tenant_name")
        self.logger.debug("VIM project/tenant id: %s", project_id)
        vim_json = {
            "name": "vim-instance",
            "authUrl": self.creds.get("auth_url"),
            "tenant": project_id,
            "username": self.creds.get("username"),
            "password": self.creds.get("password"),
            "securityGroups": [
                self.mano['details']['sec_group']
            ],
            "type": "openstack",
            "location": {
                "name": "opnfv",
                "latitude": "52.525876",
                "longitude": "13.314400"
            }
        }
        self.logger.info("Built VIM descriptor: %s", vim_json)
        return vim_json

    def deploy_orchestrator(self):
        self.logger.info("Deploying Open Baton...")
        self.logger.info("Details: %s", self.mano['details'])
        start_time = time.time()

        self.logger.info("Creating orchestra instance...")
        userdata = get_userdata(self.mano)
        self.logger.info("flavor: %s\n"
                         "image: %s\n"
                         "network_id: %s\n",
                         self.mano['details']['flavor']['name'],
                         self.mano['requirements']['image'],
                         self.mano['details']['network']['id'])
        self.logger.debug("userdata: %s\n", userdata)
        # setting up image
        image_settings = ImageSettings(
            name=self.mano['requirements']['image'],
            image_user='ubuntu',
            exists=True)
        # setting up port
        port_settings = PortSettings(
            name='%s_port' % self.case_name,
            network_name=self.mano['details']['network']['name'])
        # build configuration of vm
        orchestra_settings = VmInstanceSettings(
            name=self.case_name,
            flavor=self.mano['details']['flavor']['name'],
            port_settings=[port_settings],
            security_group_names=[self.mano['details']['sec_group']],
            userdata=userdata)
        orchestra_vm = OpenStackVmInstance(self.snaps_creds,
                                           orchestra_settings,
                                           image_settings)

        orchestra_vm.create()
        self.created_resources.append(orchestra_vm)
        self.mano['details']['id'] = orchestra_vm.get_vm_info()['id']
        self.logger.info(
            "Created orchestra instance: %s",
            self.mano['details']['id'])

        self.logger.info("Associating floating ip: '%s' to VM '%s' ",
                         self.mano['details']['fip'].ip,
                         self.case_name)
        nova_client = os_utils.get_nova_client()
        if not os_utils.add_floating_ip(
                nova_client,
                self.mano['details']['id'],
                self.mano['details']['fip'].ip):
            duration = time.time() - start_time
            self.details["orchestrator"].update(
                status='FAIL', duration=duration)
            self.logger.error("Cannot associate floating IP to VM.")
            return False

        self.logger.info("Waiting for Open Baton NFVO to be up and running...")
        timeout = 0
        while timeout < 200:
            if servertest(
                    self.mano['details']['fip'].ip,
                    "8080"):
                break
            else:
                self.logger.info(
                    "Open Baton NFVO is not started yet (%ss)",
                    (timeout * 5))
                time.sleep(5)
                timeout += 1

        if timeout >= 200:
            duration = time.time() - start_time
            self.details["orchestrator"].update(
                status='FAIL', duration=duration)
            self.logger.error("Open Baton is not started correctly")
            return False

        self.logger.info("Waiting for all components to be up and running...")
        time.sleep(60)
        duration = time.time() - start_time
        self.details["orchestrator"].update(status='PASS', duration=duration)
        self.logger.info("Deploy Open Baton NFVO: OK")
        return True

    def deploy_vnf(self):
        start_time = time.time()
        self.logger.info("Deploying %s...", self.vnf['name'])

        main_agent = MainAgent(
            nfvo_ip=self.mano['details']['fip'].ip,
            nfvo_port=8080,
            https=False,
            version=1,
            username=self.mano['credentials']['username'],
            password=self.mano['credentials']['password'])

        self.logger.info(
            "Create %s Flavor if not existing", self.vnf['name'])
        flavor_settings = FlavorSettings(
            name=self.vnf['requirements']['flavor']['name'],
            ram=self.vnf['requirements']['flavor']['ram_min'],
            disk=self.vnf['requirements']['flavor']['disk'],
            vcpus=self.vnf['requirements']['flavor']['vcpus'])
        flavor = OpenStackFlavor(self.snaps_creds, flavor_settings)
        flavor_info = flavor.create()
        self.logger.debug("Flavor id: %s", flavor_info.id)

        self.logger.info("Getting project 'default'...")
        project_agent = main_agent.get_agent("project", "")
        for project in json.loads(project_agent.find()):
            if project.get("name") == "default":
                self.mano['details']['project_id'] = project.get("id")
                self.logger.info("Found project 'default': %s", project)
                break

        vim_json = self.get_vim_descriptor()
        self.logger.info("Registering VIM: %s", vim_json)

        main_agent.get_agent(
            "vim", project_id=self.mano['details']['project_id']).create(
                entity=json.dumps(vim_json))

        market_agent = main_agent.get_agent(
            "market", project_id=self.mano['details']['project_id'])

        try:
            self.logger.info("sending: %s", self.vnf['descriptor']['url'])
            nsd = market_agent.create(entity=self.vnf['descriptor']['url'])
            if nsd.get('id') is None:
                self.logger.error("NSD not onboarded correctly")
                duration = time.time() - start_time
                self.details["vnf"].update(status='FAIL', duration=duration)
                return False
            self.mano['details']['nsd_id'] = nsd.get('id')
            self.logger.info("Onboarded NSD: " + nsd.get("name"))

            nsr_agent = main_agent.get_agent(
                "nsr", project_id=self.mano['details']['project_id'])

            self.mano['details']['nsr'] = nsr_agent.create(
                self.mano['details']['nsd_id'])
        except NfvoException as exc:
            self.logger.error(exc.message)
            duration = time.time() - start_time
            self.details["vnf"].update(status='FAIL', duration=duration)
            return False

        if self.mano['details']['nsr'].get('code') is not None:
            self.logger.error(
                "%s cannot be deployed: %s -> %s",
                self.vnf['name'],
                self.mano['details']['nsr'].get('code'),
                self.mano['details']['nsr'].get('message'))
            self.logger.error("%s cannot be deployed", self.vnf['name'])
            duration = time.time() - start_time
            self.details["vnf"].update(status='FAIL', duration=duration)
            return False

        timeout = 0
        self.logger.info("Waiting for NSR to go to ACTIVE...")
        while self.mano['details']['nsr'].get("status") != 'ACTIVE' \
                and self.mano['details']['nsr'].get("status") != 'ERROR':
            timeout += 1
            self.logger.info("NSR is not yet ACTIVE... (%ss)", 5 * timeout)
            if timeout == 300:
                self.logger.error("INACTIVE NSR after %s sec..", 5 * timeout)
                duration = time.time() - start_time
                self.details["vnf"].update(status='FAIL', duration=duration)
                return False
            time.sleep(5)
            self.mano['details']['nsr'] = json.loads(
                nsr_agent.find(self.mano['details']['nsr'].get('id')))

        duration = time.time() - start_time
        if self.mano['details']['nsr'].get("status") == 'ACTIVE':
            self.details["vnf"].update(status='PASS', duration=duration)
            self.logger.info("Sleep for 60s to ensure that all "
                             "services are up and running...")
            time.sleep(60)
            result = True
        else:
            self.details["vnf"].update(status='FAIL', duration=duration)
            self.logger.error("NSR: %s", self.mano['details'].get('nsr'))
            result = False
        return result

    def test_vnf(self):
        self.logger.info(
            "Testing VNF Clearwater IMS is not yet implemented...")
        start_time = time.time()

        duration = time.time() - start_time
        self.details["test_vnf"].update(status='PASS', duration=duration)
        self.logger.info("Test VNF: OK")
        return True

    def clean(self):
        self.logger.info("Cleaning %s...", self.case_name)
        try:
            main_agent = MainAgent(
                nfvo_ip=self.mano['details']['fip'].ip,
                nfvo_port=8080,
                https=False,
                version=1,
                username=self.mano['credentials']['username'],
                password=self.mano['credentials']['password'])
            self.logger.info("Terminating %s...", self.vnf['name'])
            if (self.mano['details'].get('nsr')):
                main_agent.get_agent(
                    "nsr",
                    project_id=self.mano['details']['project_id']).delete(
                        self.mano['details']['nsr'].get('id'))
                self.logger.info("Sleeping 60 seconds...")
                time.sleep(60)
            else:
                self.logger.info("No need to terminate the VNF...")
            # os_utils.delete_instance(nova_client=os_utils.get_nova_client(),
            #                          instance_id=self.mano_instance_id)
        except (NfvoException, KeyError) as exc:
            self.logger.error('Unexpected error cleaning - %s', exc)

        try:
            neutron_client = os_utils.get_neutron_client(self.creds)
            self.logger.info("Deleting Open Baton Port...")
            port = snaps_utils.neutron_utils.get_port_by_name(
                neutron_client, '%s_port' % self.case_name)
            snaps_utils.neutron_utils.delete_port(neutron_client, port)
            time.sleep(10)
        except Exception as exc:
            self.logger.error('Unexpected error cleaning - %s', exc)
        try:
            self.logger.info("Deleting Open Baton Floating IP...")
            snaps_utils.neutron_utils.delete_floating_ip(
                neutron_client, self.mano['details']['fip'])
        except Exception as exc:
            self.logger.error('Unexpected error cleaning - %s', exc)

        for resource in reversed(self.created_resources):
            try:
                self.logger.info("Cleaning %s", str(resource))
                resource.clean()
            except Exception as exc:
                self.logger.error('Unexpected error cleaning - %s', exc)
        super(ClearwaterImsVnf, self).clean()