summaryrefslogtreecommitdiffstats
path: root/mcp/config/labs/local/pod1.yaml
blob: 219b2a6835f6e74ff6947be72fa1140b20863a41 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
##############################################################################
# Copyright (c) 2018 Linux Foundation, Enea AB 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
##############################################################################
---
### LF POD 2 descriptor file ###

version: 1.0
details:
  pod_owner: Trevor Bramwell
  contact: tbramwell@linuxfoundation.org
  lab: LF Pharos Lab
  location: Portland
  type: production
  link: https://wiki.opnfv.org/display/pharos/LF+POD+2
##############################################################################
jumphost:
  name: pod2-jump
  node:
    type: baremetal
    vendor: Cisco Systems Inc
    model: UCSB-B200-M4
    arch: x86_64
    cpus: 2
    cpu_cflags: haswell
    cores: 8
    memory: 128G
  disks: &disks
    - name: 'disk1'
      disk_capacity: 2400G
      disk_type: hdd
      disk_interface: sas
      disk_rotation: 0
  os: centos-7
  remote_params: &remote_params
    type: ipmi
    versions:
      - 2.0
    user: admin
    pass: octopus
  remote_management:
    <<: *remote_params
    address: 172.30.8.83
    mac_address: "a8:9d:21:c9:c4:9e"
  interfaces:
    - mac_address: "00:25:b5:a0:00:1a"
      speed: 40gb
      features: 'dpdk|sriov'
      address: 192.168.11.1
      name: 'nic1'
    - mac_address: "00:25:b5:a0:00:1b"
      speed: 40gb
      features: 'dpdk|sriov'
      name: 'nic2'
    - mac_address: "00:25:b5:a0:00:1c"
      speed: 40gb
      features: 'dpdk|sriov'
      name: 'nic3'
    - mac_address: "00:25:b5:a0:00:1d"
      speed: 40gb
      features: 'dpdk|sriov'
      name: 'nic4'
##############################################################################
nodes:
  - name: pod2-node1
    node: &nodeparams
      type: baremetal
      vendor: Cisco Systems Inc
      model: UCSB-B200-M4
      arch: x86_64
      cpus: 2
      cpu_cflags: haswell
      cores: 8
      memory: 32G
    disks: *disks
    remote_management:
      <<: *remote_params
      address: 172.30.8.75
      mac_address: "a8:9d:21:c9:8b:56"
    interfaces:
      - mac_address: "00:25:b5:a0:00:2a"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic1'
      - mac_address: "00:25:b5:a0:00:2b"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic2'
      - mac_address: "00:25:b5:a0:00:2c"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic3'
      - mac_address: "00:25:b5:a0:00:2d"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic4'
  ############################################################################
  - name: pod2-node2
    node: *nodeparams
    disks: *disks
    remote_management:
      <<: *remote_params
      address: 172.30.8.65
      mac_address: "a8:9d:21:c9:4d:26"
    interfaces:
      - mac_address: "00:25:b5:a0:00:3a"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic1'
      - mac_address: "00:25:b5:a0:00:3b"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic2'
      - mac_address: "00:25:b5:a0:00:3c"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic3'
      - mac_address: "00:25:b5:a0:00:3d"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic4'
  ############################################################################
  - name: pod2-node3
    node: *nodeparams
    disks: *disks
    remote_management:
      <<: *remote_params
      address: 172.30.8.74
      mac_address: "a8:9d:21:c9:3a:92"
    interfaces:
      - mac_address: "00:25:b5:a0:00:4a"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic1'
      - mac_address: "00:25:b5:a0:00:4b"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic2'
      - mac_address: "00:25:b5:a0:00:4c"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic3'
      - mac_address: "00:25:b5:a0:00:4d"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic4'
  ############################################################################
  - name: pod2-node4
    node: *nodeparams
    disks: *disks
    remote_management:
      <<: *remote_params
      address: 172.30.8.73
      mac_address: "74:a2:e6:a4:14:9c"
    interfaces:
      - mac_address: "00:25:b5:a0:00:5a"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic1'
      - mac_address: "00:25:b5:a0:00:5b"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic2'
      - mac_address: "00:25:b5:a0:00:5c"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic3'
      - mac_address: "00:25:b5:a0:00:5d"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic4'
  ############################################################################
  - name: pod2-node5
    node: *nodeparams
    disks: *disks
    remote_management:
      <<: *remote_params
      address: 172.30.8.72
      mac_address: "a8:9d:21:a0:15:9c"
    interfaces:
      - mac_address: "00:25:b5:a0:00:6a"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic1'
      - mac_address: "00:25:b5:a0:00:6b"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic2'
      - mac_address: "00:25:b5:a0:00:6c"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic3'
      - mac_address: "00:25:b5:a0:00:6d"
        speed: 40gb
        features: 'dpdk|sriov'
        name: 'nic4'
e is for debugging purposes
+# for line in iter(output.stdout.readline, ''):
+# print(line)
+# sys.stdout.flush()
+
+ output.stdout.close()
+
+ if not (output.poll()):
+ output.wait()
+
+ # Get return value
+ if output.returncode:
+ print("The compute config did not work on compute %s" % ip)
+ sys.exit(output.returncode)
+
+sys.exit(0)
diff --git a/functest/opnfv_tests/features/sfc/server_presetup_CI.bash b/functest/opnfv_tests/features/sfc/server_presetup_CI.bash
new file mode 100755
index 00000000..240353f5
--- /dev/null
+++ b/functest/opnfv_tests/features/sfc/server_presetup_CI.bash
@@ -0,0 +1,13 @@
+#!/bin/bash
+set -e
+ssh_options='-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
+BASEDIR=`dirname $0`
+INSTALLER_IP=${INSTALLER_IP:-10.20.0.2}
+
+pushd $BASEDIR
+ip=$(sshpass -p r00tme ssh $ssh_options root@${INSTALLER_IP} 'fuel node'|grep controller|awk '{print $10}' | head -1)
+echo $ip
+
+sshpass -p r00tme scp $ssh_options delete.sh ${INSTALLER_IP}:/root
+sshpass -p r00tme ssh $ssh_options root@${INSTALLER_IP} 'scp '"$ip"':/root/tackerc .'
+sshpass -p r00tme scp $ssh_options ${INSTALLER_IP}:/root/tackerc $BASEDIR
diff --git a/functest/opnfv_tests/features/sfc/sfc.py b/functest/opnfv_tests/features/sfc/sfc.py
new file mode 100755
index 00000000..17ffef22
--- /dev/null
+++ b/functest/opnfv_tests/features/sfc/sfc.py
@@ -0,0 +1,545 @@
+import argparse
+import os
+import subprocess
+import sys
+import time
+import functest.utils.functest_logger as ft_logger
+import functest.utils.functest_utils as ft_utils
+import functest.utils.openstack_utils as os_utils
+import re
+import json
+import SSHUtils as ssh_utils
+import ovs_utils
+
+parser = argparse.ArgumentParser()
+
+parser.add_argument("-r", "--report",
+ help="Create json result file",
+ action="store_true")
+
+args = parser.parse_args()
+
+""" logging configuration """
+logger = ft_logger.Logger("ODL_SFC").getLogger()
+
+FUNCTEST_RESULTS_DIR = '/home/opnfv/functest/results/odl-sfc'
+FUNCTEST_REPO = ft_utils.FUNCTEST_REPO
+REPO_PATH = os.environ['repos_dir'] + '/functest/'
+HOME = os.environ['HOME'] + "/"
+CLIENT = "client"
+SERVER = "server"
+FLAVOR = "custom"
+IMAGE_NAME = "sf_nsh_colorado"
+IMAGE_FILENAME = "sf_nsh_colorado.qcow2"
+IMAGE_FORMAT = "qcow2"
+IMAGE_DIR = "/home/opnfv/functest/data"
+IMAGE_PATH = IMAGE_DIR + "/" + IMAGE_FILENAME
+IMAGE_URL = "http://artifacts.opnfv.org/sfc/demo/" + IMAGE_FILENAME
+
+# NEUTRON Private Network parameters
+NET_NAME = "example-net"
+SUBNET_NAME = "example-subnet"
+SUBNET_CIDR = "11.0.0.0/24"
+ROUTER_NAME = "example-router"
+SECGROUP_NAME = "example-sg"
+SECGROUP_DESCR = "Example Security group"
+SFC_TEST_DIR = REPO_PATH + "/opnfv_tests/features/sfc/"
+TACKER_SCRIPT = SFC_TEST_DIR + "sfc_tacker.bash"
+TACKER_CHANGECLASSI = SFC_TEST_DIR + "sfc_change_classi.bash"
+ssh_options = '-q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
+json_results = {"tests": 4, "failures": 0}
+
+PROXY = {
+ 'ip': '10.20.0.2',
+ 'username': 'root',
+ 'password': 'r00tme'
+}
+
+# run given command locally and return commands output if success
+
+
+def run_cmd(cmd, wdir=None, ignore_stderr=False, ignore_no_output=True):
+ pipe = subprocess.Popen(cmd, shell=True,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE, cwd=wdir)
+
+ (output, errors) = pipe.communicate()
+ if output:
+ output = output.strip()
+ if pipe.returncode < 0:
+ logger.error(errors)
+ return False
+ if errors:
+ logger.error(errors)
+ if ignore_stderr:
+ return True
+ else:
+ return False
+
+ if ignore_no_output:
+ if not output:
+ return True
+
+ return output
+
+# run given command on OpenStack controller
+
+
+def run_cmd_on_cntlr(cmd):
+ ip_cntlrs = get_openstack_node_ips("controller")
+ if not ip_cntlrs:
+ return None
+
+ ssh_cmd = "ssh %s %s %s" % (ssh_options, ip_cntlrs[0], cmd)
+ return run_cmd_on_fm(ssh_cmd)
+
+# run given command on OpenStack Compute node
+
+
+def run_cmd_on_compute(cmd):
+ ip_computes = get_openstack_node_ips("compute")
+ if not ip_computes:
+ return None
+
+ ssh_cmd = "ssh %s %s %s" % (ssh_options, ip_computes[0], cmd)
+ return run_cmd_on_fm(ssh_cmd)
+
+# run given command on Fuel Master
+
+
+def run_cmd_on_fm(cmd, username="root", passwd="r00tme"):
+ ip = os.environ.get("INSTALLER_IP")
+ ssh_cmd = "sshpass -p %s ssh %s %s@%s %s" % (
+ passwd, ssh_options, username, ip, cmd)
+ return run_cmd(ssh_cmd)
+
+# run given command on Remote Machine, Can be VM
+
+
+def run_cmd_remote(ip, cmd, username="root", passwd="opnfv"):
+ ssh_opt_append = "%s -o ConnectTimeout=50 " % ssh_options
+ ssh_cmd = "sshpass -p %s ssh %s %s@%s %s" % (
+ passwd, ssh_opt_append, username, ip, cmd)
+ return run_cmd(ssh_cmd)
+
+# Get OpenStack Nodes IP Address
+
+
+def get_openstack_node_ips(role):
+ fuel_env = os.environ.get("FUEL_ENV")
+ if fuel_env is not None:
+ cmd = "fuel2 node list -f json -e %s" % fuel_env
+ else:
+ cmd = "fuel2 node list -f json"
+
+ nodes = run_cmd_on_fm(cmd)
+ ips = []
+ nodes = json.loads(nodes)
+ for node in nodes:
+ if role in node["roles"]:
+ ips.append(node["ip"])
+
+ return ips
+
+# Configures IPTABLES on OpenStack Controller
+
+
+def configure_iptables():
+ iptable_cmds = ["iptables -P INPUT ACCEPT",
+ "iptables -t nat -P INPUT ACCEPT",
+ "iptables -A INPUT -m state \
+ --state NEW,ESTABLISHED,RELATED -j ACCEPT"]
+
+ for cmd in iptable_cmds:
+ logger.info("Configuring %s on contoller" % cmd)
+ run_cmd_on_cntlr(cmd)
+
+ return
+
+
+def download_image():
+ if not os.path.isfile(IMAGE_PATH):
+ logger.info("Downloading image")
+ ft_utils.download_url(IMAGE_URL, IMAGE_DIR)
+
+ logger.info("Using old image")
+ return
+
+
+def setup_glance(glance_client):
+ image_id = os_utils.create_glance_image(glance_client,
+ IMAGE_NAME,
+ IMAGE_PATH,
+ disk=IMAGE_FORMAT,
+ container="bare",
+ public=True)
+
+ return image_id
+
+
+def setup_neutron(neutron_client):
+ n_dict = os_utils.create_network_full(neutron_client,
+ NET_NAME,
+ SUBNET_NAME,
+ ROUTER_NAME,
+ SUBNET_CIDR)
+ if not n_dict:
+ logger.error("failed to create neutron network")
+ sys.exit(-1)
+
+ network_id = n_dict["net_id"]
+ return network_id
+
+
+def setup_ingress_egress_secgroup(neutron_client, protocol,
+ min_port=None, max_port=None):
+ secgroups = os_utils.get_security_groups(neutron_client)
+ for sg in secgroups:
+ os_utils.create_secgroup_rule(neutron_client, sg['id'],
+ 'ingress', protocol,
+ port_range_min=min_port,
+ port_range_max=max_port)
+ os_utils.create_secgroup_rule(neutron_client, sg['id'],
+ 'egress', protocol,
+ port_range_min=min_port,
+ port_range_max=max_port)
+ return
+
+
+def setup_security_groups(neutron_client):
+ sg_id = os_utils.create_security_group_full(neutron_client,
+ SECGROUP_NAME, SECGROUP_DESCR)
+ setup_ingress_egress_secgroup(neutron_client, "icmp")
+ setup_ingress_egress_secgroup(neutron_client, "udp", 67, 68)
+ setup_ingress_egress_secgroup(neutron_client, "tcp", 22, 22)
+ setup_ingress_egress_secgroup(neutron_client, "tcp", 80, 80)
+ return sg_id
+
+
+def boot_instance(nova_client, name, flavor, image_id, network_id, sg_id):
+ logger.info("Creating instance '%s'..." % name)
+ logger.debug(
+ "Configuration:\n name=%s \n flavor=%s \n image=%s \n "
+ "network=%s \n" % (name, flavor, image_id, network_id))
+
+ instance = os_utils.create_instance_and_wait_for_active(flavor,
+ image_id,
+ network_id,
+ name)
+
+ if instance is None:
+ logger.error("Error while booting instance.")
+ sys.exit(-1)
+
+ instance_ip = instance.networks.get(NET_NAME)[0]
+ logger.debug("Instance '%s' got private ip '%s'." %
+ (name, instance_ip))
+
+ logger.info("Adding '%s' to security group %s" % (name, SECGROUP_NAME))
+ os_utils.add_secgroup_to_instance(nova_client, instance.id, sg_id)
+
+ return instance_ip
+
+
+def ping(remote, pkt_cnt=1, iface=None, retries=100, timeout=None):
+ ping_cmd = 'ping'
+
+ if timeout:
+ ping_cmd = ping_cmd + ' -w %s' % timeout
+
+ grep_cmd = "grep -e 'packet loss' -e rtt"
+
+ if iface is not None:
+ ping_cmd = ping_cmd + ' -I %s' % iface
+
+ ping_cmd = ping_cmd + ' -i 0 -c %d %s' % (pkt_cnt, remote)
+ cmd = ping_cmd + '|' + grep_cmd
+
+ while retries > 0:
+ output = run_cmd(cmd)
+ if not output:
+ return False
+
+ match = re.search('(\d*)% packet loss', output)
+ if not match:
+ return False
+
+ packet_loss = int(match.group(1))
+ if packet_loss == 0:
+ return True
+
+ retries = retries - 1
+
+ return False
+
+
+def get_floating_ips(nova_client, neutron_client):
+ ips = []
+ instances = nova_client.servers.list(search_opts={'all_tenants': 1})
+ for instance in instances:
+ floatip_dic = os_utils.create_floating_ip(neutron_client)
+ floatip = floatip_dic['fip_addr']
+ instance.add_floating_ip(floatip)
+ logger.info("Instance name and ip %s:%s " % (instance.name, floatip))
+ logger.info("Waiting for instance %s:%s to come up" %
+ (instance.name, floatip))
+ if not ping(floatip):
+ logger.info("Instance %s:%s didn't come up" %
+ (instance.name, floatip))
+ sys.exit(1)
+
+ if instance.name == "server":
+ logger.info("Server:%s is reachable" % floatip)
+ server_ip = floatip
+ elif instance.name == "client":
+ logger.info("Client:%s is reachable" % floatip)
+ client_ip = floatip
+ else:
+ logger.info("SF:%s is reachable" % floatip)
+ ips.append(floatip)
+
+ return server_ip, client_ip, ips[1], ips[0]
+
+# Start http server on a give machine, Can be VM
+
+
+def start_http_server(ip):
+ cmd = "\'python -m SimpleHTTPServer 80"
+ cmd = cmd + " > /dev/null 2>&1 &\'"
+ return run_cmd_remote(ip, cmd)
+
+# Set firewall using vxlan_tool.py on a give machine, Can be VM
+
+
+def vxlan_firewall(sf, iface="eth0", port="22", block=True):
+ cmd = "python vxlan_tool.py"
+ cmd = cmd + " -i " + iface + " -d forward -v off"
+ if block:
+ cmd = "python vxlan_tool.py -i eth0 -d forward -v off -b " + port
+
+ cmd = "sh -c 'cd /root;nohup " + cmd + " > /dev/null 2>&1 &'"
+ run_cmd_remote(sf, cmd)
+
+# Run netcat on a give machine, Can be VM
+
+
+def netcat(s_ip, c_ip, port="80", timeout=5):
+ cmd = "nc -zv "
+ cmd = cmd + " -w %s %s %s" % (timeout, s_ip, port)
+ cmd = cmd + " 2>&1"
+ output = run_cmd_remote(c_ip, cmd)
+ logger.info("%s" % output)
+ return output
+
+
+def is_ssh_blocked(srv_prv_ip, client_ip):
+ res = netcat(srv_prv_ip, client_ip, port="22")
+ match = re.search("nc:.*timed out:.*", res, re.M)
+ if match:
+ return True
+
+ return False
+
+
+def is_http_blocked(srv_prv_ip, client_ip):
+ res = netcat(srv_prv_ip, client_ip, port="80")
+ match = re.search(".* 80 port.* succeeded!", res, re.M)
+ if match:
+ return False
+
+ return True
+
+
+def capture_err_logs(controller_clients, compute_clients, error):
+ ovs_logger = ovs_utils.OVSLogger(
+ os.path.join(os.getcwd(), 'ovs-logs'),
+ FUNCTEST_RESULTS_DIR)
+
+ timestamp = time.strftime("%Y%m%d-%H%M%S")
+ ovs_logger.dump_ovs_logs(controller_clients,
+ compute_clients,
+ related_error=error,
+ timestamp=timestamp)
+ return
+
+
+def update_json_results(name, result):
+ json_results.update({name: result})
+ if result is not "Passed":
+ json_results["failures"] += 1
+
+ return
+
+
+def get_ssh_clients(role):
+ clients = []
+ for ip in get_openstack_node_ips(role):
+ s_client = ssh_utils.get_ssh_client(ip,
+ 'root',
+ proxy=PROXY)
+ clients.append(s_client)
+
+ return clients
+
+# Check SSH connectivity to VNFs
+
+
+def check_ssh(ips, retries=100):
+ check = [False, False]
+ logger.info("Checking SSH connectivity to the SFs with ips %s" % str(ips))
+ while retries and not all(check):
+ for index, ip in enumerate(ips):
+ check[index] = run_cmd_remote(ip, "exit")
+
+ if all(check):
+ logger.info("SSH connectivity to the SFs established")
+ return True
+
+ time.sleep(3)
+ retries -= 1
+
+ return False
+
+
+def main():
+ installer_type = os.environ.get("INSTALLER_TYPE")
+ if installer_type != "fuel":
+ logger.error(
+ '\033[91mCurrently supported only Fuel Installer type\033[0m')
+ sys.exit(1)
+
+ installer_ip = os.environ.get("INSTALLER_IP")
+ if not installer_ip:
+ logger.error(
+ '\033[91minstaller ip is not set\033[0m')
+ logger.error(
+ '\033[91mexport INSTALLER_IP=<ip>\033[0m')
+ sys.exit(1)
+
+ env_list = run_cmd_on_fm("fuel2 env list -f json")
+ fuel_env = os.environ.get("FUEL_ENV")
+ if len(eval(env_list)) > 1 and fuel_env is None:
+ out = run_cmd_on_fm("fuel env")
+ logger.error(
+ '\033[91mMore than one fuel env found\033[0m\n %s' % out)
+ logger.error(
+ '\033[91mexport FUEL_ENV=<env-id> to set ENV\033[0m')
+ sys.exit(1)
+
+ start_time = time.time()
+ status = "PASS"
+ configure_iptables()
+ download_image()
+ _, custom_flv_id = os_utils.get_or_create_flavor(
+ FLAVOR, 1500, 10, 1, public=True)
+ if not custom_flv_id:
+ logger.error("Failed to create custom flavor")
+ sys.exit(1)
+
+ glance_client = os_utils.get_glance_client()
+ neutron_client = os_utils.get_neutron_client()
+ nova_client = os_utils.get_nova_client()
+
+ controller_clients = get_ssh_clients("controller")
+ compute_clients = get_ssh_clients("compute")
+
+ image_id = setup_glance(glance_client)
+ network_id = setup_neutron(neutron_client)
+ sg_id = setup_security_groups(neutron_client)
+
+ boot_instance(
+ nova_client, CLIENT, FLAVOR, image_id, network_id, sg_id)
+ srv_prv_ip = boot_instance(
+ nova_client, SERVER, FLAVOR, image_id, network_id, sg_id)
+
+ subprocess.call(TACKER_SCRIPT, shell=True)
+ server_ip, client_ip, sf1, sf2 = get_floating_ips(
+ nova_client, neutron_client)
+
+ if not check_ssh([sf1, sf2]):
+ logger.error("Cannot establish SSH connection to the SFs")
+ sys.exit(1)
+
+ logger.info("Starting HTTP server on %s" % server_ip)
+ if not start_http_server(server_ip):
+ logger.error(
+ '\033[91mFailed to start HTTP server on %s\033[0m' % server_ip)
+ sys.exit(1)
+
+ logger.info("Starting HTTP firewall on %s" % sf2)
+ vxlan_firewall(sf2, port="80")
+ logger.info("Starting SSH firewall on %s" % sf1)
+ vxlan_firewall(sf1, port="22")
+
+ logger.info("Wait for ODL to update the classification rules in OVS")
+ time.sleep(120)
+
+ logger.info("Test SSH")
+ if is_ssh_blocked(srv_prv_ip, client_ip):
+ logger.info('\033[92mTEST 1 [PASSED] ==> SSH BLOCKED\033[0m')
+ update_json_results("Test 1: SSH Blocked", "Passed")
+ else:
+ error = ('\033[91mTEST 1 [FAILED] ==> SSH NOT BLOCKED\033[0m')
+ logger.error(error)
+ capture_err_logs(controller_clients, compute_clients, error)
+ update_json_results("Test 1: SSH Blocked", "Failed")
+
+ logger.info("Test HTTP")
+ if not is_http_blocked(srv_prv_ip, client_ip):
+ logger.info('\033[92mTEST 2 [PASSED] ==> HTTP WORKS\033[0m')
+ update_json_results("Test 2: HTTP works", "Passed")
+ else:
+ error = ('\033[91mTEST 2 [FAILED] ==> HTTP BLOCKED\033[0m')
+ logger.error(error)
+ capture_err_logs(controller_clients, compute_clients, error)
+ update_json_results("Test 2: HTTP works", "Failed")
+
+ logger.info("Changing the classification")
+ subprocess.call(TACKER_CHANGECLASSI, shell=True)
+ logger.info("Wait for ODL to update the classification rules in OVS")
+ time.sleep(100)
+
+ logger.info("Test HTTP")
+ if is_http_blocked(srv_prv_ip, client_ip):
+ logger.info('\033[92mTEST 3 [PASSED] ==> HTTP Blocked\033[0m')
+ update_json_results("Test 3: HTTP Blocked", "Passed")
+ else:
+ error = ('\033[91mTEST 3 [FAILED] ==> HTTP WORKS\033[0m')
+ logger.error(error)
+ capture_err_logs(controller_clients, compute_clients, error)
+ update_json_results("Test 3: HTTP Blocked", "Failed")
+
+ logger.info("Test SSH")
+ if not is_ssh_blocked(srv_prv_ip, client_ip):
+ logger.info('\033[92mTEST 4 [PASSED] ==> SSH Works\033[0m')
+ update_json_results("Test 4: SSH Works", "Passed")
+ else:
+ error = ('\033[91mTEST 4 [FAILED] ==> SSH BLOCKED\033[0m')
+ logger.error(error)
+ capture_err_logs(controller_clients, compute_clients, error)
+ update_json_results("Test 4: SSH Works", "Failed")
+
+ if json_results["failures"]:
+ status = "FAIL"
+ logger.error('\033[91mSFC TESTS: %s :( FOUND %s FAIL \033[0m' % (
+ status, json_results["failures"]))
+
+ if args.report:
+ stop_time = time.time()
+ logger.debug("Promise Results json: " + str(json_results))
+ ft_utils.push_results_to_db("sfc",
+ "functest-odl-sfc",
+ start_time,
+ stop_time,
+ status,
+ json_results)
+
+ if status == "PASS":
+ logger.info('\033[92mSFC ALL TESTS: %s :)\033[0m' % status)
+ sys.exit(0)
+
+ sys.exit(1)
+
+if __name__ == '__main__':
+ main()
diff --git a/functest/opnfv_tests/features/sfc/sfc_change_classi.bash b/functest/opnfv_tests/features/sfc/sfc_change_classi.bash
new file mode 100755
index 00000000..70375ab3
--- /dev/null
+++ b/functest/opnfv_tests/features/sfc/sfc_change_classi.bash
@@ -0,0 +1,7 @@
+tacker sfc-classifier-delete red_http
+tacker sfc-classifier-delete red_ssh
+
+tacker sfc-classifier-create --name blue_http --chain blue --match source_port=0,dest_port=80,protocol=6
+tacker sfc-classifier-create --name blue_ssh --chain blue --match source_port=0,dest_port=22,protocol=6
+
+tacker sfc-classifier-list
diff --git a/functest/opnfv_tests/features/sfc/sfc_colorado1.py b/functest/opnfv_tests/features/sfc/sfc_colorado1.py
new file mode 100755
index 00000000..6965f283
--- /dev/null
+++ b/functest/opnfv_tests/features/sfc/sfc_colorado1.py
@@ -0,0 +1,596 @@
+import os
+import subprocess
+import sys
+import time
+import argparse
+import paramiko
+
+import functest.utils.functest_logger as ft_logger
+import functest.utils.functest_utils as ft_utils
+import functest.utils.openstack_utils as os_utils
+import SSHUtils as ssh_utils
+import ovs_utils
+
+parser = argparse.ArgumentParser()
+
+parser.add_argument("-r", "--report",
+ help="Create json result file",
+ action="store_true")
+
+args = parser.parse_args()
+
+""" logging configuration """
+logger = ft_logger.Logger("ODL_SFC").getLogger()
+
+FUNCTEST_RESULTS_DIR = '/home/opnfv/functest/results/odl-sfc'
+FUNCTEST_REPO = ft_utils.FUNCTEST_REPO
+
+HOME = os.environ['HOME'] + "/"
+
+VM_BOOT_TIMEOUT = 180
+INSTANCE_NAME = "client"
+FLAVOR = "custom"
+IMAGE_NAME = "sf_nsh_colorado"
+IMAGE_FILENAME = "sf_nsh_colorado.qcow2"
+IMAGE_FORMAT = "qcow2"
+IMAGE_PATH = "/home/opnfv/functest/data" + "/" + IMAGE_FILENAME
+
+# NEUTRON Private Network parameters
+
+NET_NAME = "example-net"
+SUBNET_NAME = "example-subnet"
+SUBNET_CIDR = "11.0.0.0/24"
+ROUTER_NAME = "example-router"
+
+SECGROUP_NAME = "example-sg"
+SECGROUP_DESCR = "Example Security group"
+
+INSTANCE_NAME_2 = "server"
+
+# TEST_DB = ft_utils.get_parameter_from_yaml("results.test_db_url")
+
+PRE_SETUP_SCRIPT = 'sfc_pre_setup.bash'
+TACKER_SCRIPT = 'sfc_tacker.bash'
+TEARDOWN_SCRIPT = "sfc_teardown.bash"
+TACKER_CHANGECLASSI = "sfc_change_classi.bash"
+
+ssh_options = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
+
+PROXY = {
+ 'ip': '10.20.0.2',
+ 'username': 'root',
+ 'password': 'r00tme'
+}
+
+
+def check_ssh(ip):
+ cmd = "sshpass -p opnfv ssh " + ssh_options + " -q " + ip + " exit"
+ success = subprocess.call(cmd, shell=True) == 0
+ if not success:
+ logger.debug("Wating for SSH connectivity in SF with IP: %s" % ip)
+ return success
+
+
+def main():
+
+ # Allow any port so that tacker commands reaches the server.
+ # This will be deleted when tacker is included in OPNFV installation
+
+ status = "PASS"
+ failures = 0
+ start_time = time.time()
+ json_results = {}
+
+ contr_cmd = ("sshpass -p r00tme ssh " + ssh_options + " root@10.20.0.2"
+ " 'fuel node'|grep controller|awk '{print $10}'")
+ logger.info("Executing script to get ip_server: '%s'" % contr_cmd)
+ process = subprocess.Popen(contr_cmd,
+ shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ ip_server = process.stdout.readline().rstrip()
+
+ comp_cmd = ("sshpass -p r00tme ssh " + ssh_options + " root@10.20.0.2"
+ " 'fuel node'|grep compute|awk '{print $10}'")
+ logger.info("Executing script to get compute IPs: '%s'" % comp_cmd)
+ process = subprocess.Popen(comp_cmd,
+ shell=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ ip_computes = [ip.strip() for ip in process.stdout.readlines()]
+
+ iptable_cmd1 = ("sshpass -p r00tme ssh " + ssh_options + " root@10.20.0.2"
+ " ssh " + ip_server + " iptables -P INPUT ACCEPT ")
+ iptable_cmd2 = ("sshpass -p r00tme ssh " + ssh_options + " root@10.20.0.2"
+ " ssh " + ip_server + " iptables -t nat -P INPUT ACCEPT ")
+ iptable_cmd3 = ("sshpass -p r00tme ssh " + ssh_options + " root@10.20.0.2"
+ " ssh " + ssh_options + " " + ip_server +
+ " iptables -A INPUT -m state"
+ " --state NEW,ESTABLISHED,RELATED -j ACCEPT")
+
+ logger.info("Changing firewall policy in controller: '%s'" % iptable_cmd1)
+ subprocess.call(iptable_cmd1, shell=True, stderr=subprocess.PIPE)
+
+ logger.info("Changing firewall policy in controller: '%s'" % iptable_cmd2)
+ subprocess.call(iptable_cmd2, shell=True, stderr=subprocess.PIPE)
+
+ logger.info("Changing firewall policy in controller: '%s'" % iptable_cmd3)
+ subprocess.call(iptable_cmd2, shell=True, stderr=subprocess.PIPE)
+
+# Getting the different clients
+
+ nova_client = os_utils.get_nova_client()
+ neutron_client = os_utils.get_neutron_client()
+ glance_client = os_utils.get_glance_client()
+
+ ovs_logger = ovs_utils.OVSLogger(
+ os.path.join(os.getcwd(), 'ovs-logs'),
+ FUNCTEST_RESULTS_DIR)
+
+ controller_clients = [ssh_utils.get_ssh_client(ip_server,
+ 'root',
+ proxy=PROXY)]
+ compute_clients = []
+ for c_ip in ip_computes:
+ c_client = ssh_utils.get_ssh_client(c_ip,
+ 'root',
+ proxy=PROXY)
+ compute_clients.append(c_client)
+
+# Download the image
+
+ if not os.path.isfile(IMAGE_PATH):
+ logger.info("Downloading image")
+ ft_utils.download_url(
+ "http://artifacts.opnfv.org/sfc/demo/sf_nsh_colorado.qcow2",
+ "/home/opnfv/functest/data/")
+ else:
+ logger.info("Using old image")
+
+# Create glance image and the neutron network
+
+ image_id = os_utils.create_glance_image(glance_client,
+ IMAGE_NAME,
+ IMAGE_PATH,
+ disk=IMAGE_FORMAT,
+ container="bare",
+ public=True)
+
+ network_dic = os_utils.create_network_full(neutron_client,
+ NET_NAME,
+ SUBNET_NAME,
+ ROUTER_NAME,
+ SUBNET_CIDR)
+ if not network_dic:
+ logger.error(
+ "There has been a problem when creating the neutron network")
+ sys.exit(-1)
+
+ network_id = network_dic["net_id"]
+
+ sg_id = os_utils.create_security_group_full(neutron_client,
+ SECGROUP_NAME, SECGROUP_DESCR)
+
+ secgroups = os_utils.get_security_groups(neutron_client)
+
+ for sg in secgroups:
+ os_utils.create_secgroup_rule(neutron_client, sg['id'],
+ 'ingress', 'udp',
+ port_range_min=67,
+ port_range_max=68)
+ os_utils.create_secgroup_rule(neutron_client, sg['id'],
+ 'egress', 'udp',
+ port_range_min=67,
+ port_range_max=68)
+ os_utils.create_secgroup_rule(neutron_client, sg['id'],
+ 'ingress', 'tcp',
+ port_range_min=22,
+ port_range_max=22)
+ os_utils.create_secgroup_rule(neutron_client, sg['id'],
+ 'egress', 'tcp',
+ port_range_min=22,
+ port_range_max=22)
+ os_utils.create_secgroup_rule(neutron_client, sg['id'],
+ 'ingress', 'tcp',
+ port_range_min=80,
+ port_range_max=80)
+ os_utils.create_secgroup_rule(neutron_client, sg['id'],
+ 'egress', 'tcp',
+ port_range_min=80,
+ port_range_max=80)
+
+ _, custom_flv_id = os_utils.get_or_create_flavor(
+ 'custom', 1500, 10, 1, public=True)
+ if not custom_flv_id:
+ logger.error("Failed to create custom flavor")
+ sys.exit(1)
+
+ iterator = 0
+ while(iterator < 6):
+ # boot INSTANCE
+ logger.info("Creating instance '%s'..." % INSTANCE_NAME)
+ logger.debug(
+ "Configuration:\n name=%s \n flavor=%s \n image=%s \n "
+ "network=%s \n" % (INSTANCE_NAME, FLAVOR, image_id, network_id))
+ instance = os_utils.create_instance_and_wait_for_active(
+ FLAVOR,
+ image_id,
+ network_id,
+ INSTANCE_NAME,
+ av_zone='nova')
+
+ if instance is None:
+ logger.error("Error while booting instance.")
+ iterator += 1
+ continue
+ # Retrieve IP of INSTANCE
+ instance_ip = instance.networks.get(NET_NAME)[0]
+ logger.debug("Instance '%s' got private ip '%s'." %
+ (INSTANCE_NAME, instance_ip))
+
+ logger.info("Adding '%s' to security group '%s'..."
+ % (INSTANCE_NAME, SECGROUP_NAME))
+ os_utils.add_secgroup_to_instance(nova_client, instance.id, sg_id)
+
+ logger.info("Creating floating IP for VM '%s'..." % INSTANCE_NAME)
+ floatip_dic = os_utils.create_floating_ip(neutron_client)
+ floatip_client = floatip_dic['fip_addr']
+ # floatip_id = floatip_dic['fip_id']
+
+ if floatip_client is None:
+ logger.error("Cannot create floating IP.")
+ iterator += 1
+ continue
+ logger.info("Floating IP created: '%s'" % floatip_client)
+
+ logger.info("Associating floating ip: '%s' to VM '%s' "
+ % (floatip_client, INSTANCE_NAME))
+ if not os_utils.add_floating_ip(nova_client,
+ instance.id,
+ floatip_client):
+ logger.error("Cannot associate floating IP to VM.")
+ iterator += 1
+ continue
+
+ # STARTING SECOND VM (server) ###
+
+ # boot INTANCE
+ logger.info("Creating instance '%s'..." % INSTANCE_NAME_2)
+ logger.debug(
+ "Configuration:\n name=%s \n flavor=%s \n image=%s \n "
+ "network=%s \n" % (INSTANCE_NAME_2, FLAVOR, image_id, network_id))
+ instance_2 = os_utils.create_instance_and_wait_for_active(
+ FLAVOR,
+ image_id,
+ network_id,
+ INSTANCE_NAME_2,
+ av_zone='nova')
+
+ if instance_2 is None:
+ logger.error("Error while booting instance.")
+ iterator += 1
+ continue
+ # Retrieve IP of INSTANCE
+ instance_ip_2 = instance_2.networks.get(NET_NAME)[0]
+ logger.debug("Instance '%s' got private ip '%s'." %
+ (INSTANCE_NAME_2, instance_ip_2))
+
+ logger.info("Adding '%s' to security group '%s'..."
+ % (INSTANCE_NAME_2, SECGROUP_NAME))
+ os_utils.add_secgroup_to_instance(nova_client, instance_2.id, sg_id)
+
+ logger.info("Creating floating IP for VM '%s'..." % INSTANCE_NAME_2)
+ floatip_dic = os_utils.create_floating_ip(neutron_client)
+ floatip_server = floatip_dic['fip_addr']
+ # floatip_id = floatip_dic['fip_id']
+
+ if floatip_server is None:
+ logger.error("Cannot create floating IP.")
+ iterator += 1
+ continue
+ logger.info("Floating IP created: '%s'" % floatip_server)
+
+ logger.info("Associating floating ip: '%s' to VM '%s' "
+ % (floatip_server, INSTANCE_NAME_2))
+
+ if not os_utils.add_floating_ip(nova_client,
+ instance_2.id,
+ floatip_server):
+ logger.error("Cannot associate floating IP to VM.")
+ iterator += 1
+ continue
+
+ # CREATION OF THE 2 SF ####
+
+ tacker_script = "%s/opnfv_tests/features/sfc/%s" % \
+ (FUNCTEST_REPO, TACKER_SCRIPT)
+ logger.info("Executing tacker script: '%s'" % tacker_script)
+ subprocess.call(tacker_script, shell=True)
+
+ # SSH CALL TO START HTTP SERVER
+ ssh = paramiko.SSHClient()
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+
+ try:
+ ssh.connect(floatip_server, username="root",
+ password="opnfv", timeout=2)
+ command = "python -m SimpleHTTPServer 80 > /dev/null 2>&1 &"
+ logger.info("Starting HTTP server")
+ (stdin, stdout, stderr) = ssh.exec_command(command)
+ except:
+ logger.debug("Waiting for %s..." % floatip_server)
+ time.sleep(6)
+ # timeout -= 1
+
+ instances = nova_client.servers.list(search_opts={'all_tenants': 1})
+ ips = []
+ try:
+ for instance in instances:
+ if "server" not in instance.name:
+ if "client" not in instance.name:
+ logger.debug(
+ "This is the instance name: %s " % instance.name)
+ floatip_dic = os_utils.create_floating_ip(
+ neutron_client)
+ floatip = floatip_dic['fip_addr']
+ ips.append(floatip)
+ instance.add_floating_ip(floatip)
+ except:
+ logger.debug("Problems assigning floating IP to SFs")
+
+ # If no IPs were obtained, then we cant continue
+ if not ips:
+ logger.error('Failed to obtain IPs, cant continue, exiting')
+ return
+
+ logger.debug("Floating IPs for SFs: %s..." % ips)
+
+ # Check SSH connectivity to VNFs
+ r = 0
+ retries = 100
+ check = [False, False]
+
+ logger.info("Checking SSH connectivity to the SFs with ips {0}"
+ .format(str(ips)))
+ while r < retries and not all(check):
+ try:
+ check = [check_ssh(ips[0]), check_ssh(ips[1])]
+ except Exception:
+ logger.exception("SSH check failed")
+ check = [False, False]
+ time.sleep(3)
+ r += 1
+
+ if not all(check):
+ logger.error("Cannot establish SSH connection to the SFs")
+ iterator += 1
+ continue
+
+ logger.info("SSH connectivity to the SFs established")
+
+ # SSH TO START THE VXLAN_TOOL ON SF1
+ logger.info("Configuring the SFs")
+ try:
+ ssh.connect(ips[0], username="root",
+ password="opnfv", timeout=2)
+ command = ("nohup python vxlan_tool.py -i eth0 "
+ "-d forward -v off -b 80 > /dev/null 2>&1 &")
+ (stdin, stdout, stderr) = ssh.exec_command(command)
+ except:
+ logger.debug("Waiting for %s..." % ips[0])
+ time.sleep(6)
+ # timeout -= 1
+
+ try:
+ n = 0
+ while 1:
+ (stdin, stdout, stderr) = ssh.exec_command(
+ "ps aux | grep \"vxlan_tool.py\" | grep -v grep")
+ if len(stdout.readlines()) > 0:
+ logger.debug("HTTP firewall started")
+ break
+ else:
+ n += 1
+ if (n > 7):
+ break
+ logger.debug("HTTP firewall not started")
+ time.sleep(3)
+ except Exception:
+ logger.exception("vxlan_tool not started in SF1")
+
+ # SSH TO START THE VXLAN_TOOL ON SF2
+ try:
+ ssh.connect(ips[1], username="root",
+ password="opnfv", timeout=2)
+ command = ("nohup python vxlan_tool.py -i eth0 "
+ "-d forward -v off -b 22 > /dev/null 2>&1 &")
+ (stdin, stdout, stderr) = ssh.exec_command(command)
+ except:
+ logger.debug("Waiting for %s..." % ips[1])
+ time.sleep(6)
+ # timeout -= 1
+
+ try:
+ n = 0
+ while 1:
+ (stdin, stdout, stderr) = ssh.exec_command(
+ "ps aux | grep \"vxlan_tool.py\" | grep -v grep")
+ if len(stdout.readlines()) > 0:
+ logger.debug("SSH firewall started")
+ break
+ else:
+ n += 1
+ if (n > 7):
+ break
+ logger.debug("SSH firewall not started")
+ time.sleep(3)
+ except Exception:
+ logger.exception("vxlan_tool not started in SF2")
+
+ i = 0
+
+ # SSH TO EXECUTE cmd_client
+ logger.info("TEST STARTED")
+ time.sleep(70)
+ try:
+ ssh.connect(floatip_client, username="root",
+ password="opnfv", timeout=2)
+ command = "nc -w 5 -zv " + instance_ip_2 + " 22 2>&1"
+ (stdin, stdout, stderr) = ssh.exec_command(command)
+
+ # WRITE THE CORRECT WAY TO DO LOGGING
+ if "timed out" in stdout.readlines()[0]:
+ logger.info('\033[92m' + "TEST 1 [PASSED] "
+ "==> SSH BLOCKED" + '\033[0m')
+ i = i + 1
+ json_results.update({"Test 1: SSH Blocked": "Passed"})
+ else:
+ timestamp = time.strftime("%Y%m%d-%H%M%S")
+ error = ('\033[91m' + "TEST 1 [FAILED] "
+ "==> SSH NOT BLOCKED" + '\033[0m')
+ logger.error(error)
+ ovs_logger.dump_ovs_logs(controller_clients,
+ compute_clients,
+ related_error=error,
+ timestamp=timestamp)
+ status = "FAIL"
+ json_results.update({"Test 1: SSH Blocked": "Failed"})
+ failures += 1
+ except:
+ logger.debug("Waiting for %s..." % floatip_client)
+ time.sleep(6)
+ # timeout -= 1
+
+ # SSH TO EXECUTE cmd_client
+ try:
+ ssh.connect(floatip_client, username="root",
+ password="opnfv", timeout=2)
+ command = "nc -w 5 -zv " + instance_ip_2 + " 80 2>&1"
+ (stdin, stdout, stderr) = ssh.exec_command(command)
+
+ if "succeeded" in stdout.readlines()[0]:
+ logger.info('\033[92m' + "TEST 2 [PASSED] "
+ "==> HTTP WORKS" + '\033[0m')
+ i = i + 1
+ json_results.update({"Test 2: HTTP works": "Passed"})
+ else:
+ timestamp = time.strftime("%Y%m%d-%H%M%S")
+ error = ('\033[91m' + "TEST 2 [FAILED] "
+ "==> HTTP BLOCKED" + '\033[0m')
+ logger.error(error)
+ ovs_logger.dump_ovs_logs(controller_clients,
+ compute_clients,
+ related_error=error,
+ timestamp=timestamp)
+ status = "FAIL"
+ json_results.update({"Test 2: HTTP works": "Failed"})
+ failures += 1
+ except:
+ logger.debug("Waiting for %s..." % floatip_client)
+ time.sleep(6)
+ # timeout -= 1
+
+ # CHANGE OF CLASSIFICATION #
+ logger.info("Changing the classification")
+ tacker_classi = "%s/opnfv_tests/features/sfc/%s" % \
+ (FUNCTEST_REPO, TACKER_CHANGECLASSI)
+ subprocess.call(tacker_classi, shell=True)
+
+ logger.info("Wait for ODL to update the classification rules in OVS")
+ time.sleep(100)
+
+ # SSH TO EXECUTE cmd_client
+
+ try:
+ ssh.connect(floatip_client, username="root",
+ password="opnfv", timeout=2)
+ command = "nc -w 5 -zv " + instance_ip_2 + " 80 2>&1"
+ (stdin, stdout, stderr) = ssh.exec_command(command)
+
+ if "timed out" in stdout.readlines()[0]:
+ logger.info('\033[92m' + "TEST 3 [PASSED] "
+ "==> HTTP BLOCKED" + '\033[0m')
+ i = i + 1
+ json_results.update({"Test 3: HTTP Blocked": "Passed"})
+ else:
+ timestamp = time.strftime("%Y%m%d-%H%M%S")
+ error = ('\033[91m' + "TEST 3 [FAILED] "
+ "==> HTTP NOT BLOCKED" + '\033[0m')
+ logger.error(error)
+ ovs_logger.dump_ovs_logs(controller_clients,
+ compute_clients,
+ related_error=error,
+ timestamp=timestamp)
+ status = "FAIL"
+ json_results.update({"Test 3: HTTP Blocked": "Failed"})
+ failures += 1
+ except:
+ logger.debug("Waiting for %s..." % floatip_client)
+ time.sleep(6)
+ # timeout -= 1
+
+ # SSH TO EXECUTE cmd_client
+ try:
+ ssh.connect(floatip_client, username="root",
+ password="opnfv", timeout=2)
+ command = "nc -w 5 -zv " + instance_ip_2 + " 22 2>&1"
+ (stdin, stdout, stderr) = ssh.exec_command(command)
+
+ if "succeeded" in stdout.readlines()[0]:
+ logger.info('\033[92m' + "TEST 4 [PASSED] "
+ "==> SSH WORKS" + '\033[0m')
+ i = i + 1
+ json_results.update({"Test 4: SSH works": "Passed"})
+ else:
+ timestamp = time.strftime("%Y%m%d-%H%M%S")
+ error = ('\033[91m' + "TEST 4 [FAILED] "
+ "==> SSH BLOCKED" + '\033[0m')
+ logger.error(error)
+ ovs_logger.dump_ovs_logs(controller_clients,
+ compute_clients,
+ related_error=error,
+ timestamp=timestamp)
+ status = "FAIL"
+ json_results.update({"Test 4: SSH works": "Failed"})
+ failures += 1
+ except:
+ logger.debug("Waiting for %s..." % floatip_client)
+ time.sleep(6)
+ # timeout -= 1
+
+ ovs_logger.create_artifact_archive()
+
+ iterator += 1
+ if i == 4:
+ for x in range(0, 5):
+ logger.info('\033[92m' + "SFC TEST WORKED"
+ " :) \n" + '\033[0m')
+ break
+ else:
+ logger.info("Iterating again!")
+ delete = "bash %s/opnfv_tests/features/sfc/delete.sh" % \
+ (FUNCTEST_REPO)
+ try:
+ subprocess.call(delete, shell=True, stderr=subprocess.PIPE)
+ time.sleep(10)
+ except Exception, e:
+ logger.error("Problem when executing the delete.sh")
+ logger.error("Problem %s" % e)
+
+ if args.report:
+ stop_time = time.time()
+ json_results.update({"tests": "4", "failures": int(failures)})
+ logger.debug("Promise Results json: " + str(json_results))
+ ft_utils.push_results_to_db("sfc",
+ "functest-odl-sfc",
+ start_time,
+ stop_time,
+ status,
+ json_results)
+ if status == "PASS":
+ sys.exit(0)
+ else:
+ sys.exit(1)
+
+if __name__ == '__main__':
+ main()
diff --git a/functest/opnfv_tests/features/sfc/sfc_tacker.bash b/functest/opnfv_tests/features/sfc/sfc_tacker.bash
new file mode 100755
index 00000000..690d5f52
--- /dev/null
+++ b/functest/opnfv_tests/features/sfc/sfc_tacker.bash
@@ -0,0 +1,31 @@
+#!/bin/bash
+BASEDIR=`dirname $0`
+
+#import VNF descriptor
+tacker vnfd-create --vnfd-file ${BASEDIR}/test-vnfd1.yaml
+tacker vnfd-create --vnfd-file ${BASEDIR}/test-vnfd2.yaml
+
+#create instances of the imported VNF
+tacker vnf-create --name testVNF1 --vnfd-name test-vnfd1
+tacker vnf-create --name testVNF2 --vnfd-name test-vnfd2
+
+key=true
+while $key;do
+ sleep 3
+ active=`tacker vnf-list | grep -E 'PENDING|ERROR'`
+ echo -e "checking if SFs are up: $active"
+ if [ -z "$active" ]; then
+ key=false
+ fi
+done
+
+#create service chain
+tacker sfc-create --name red --chain testVNF1
+tacker sfc-create --name blue --chain testVNF2
+
+#create classifier
+tacker sfc-classifier-create --name red_http --chain red --match source_port=0,dest_port=80,protocol=6
+tacker sfc-classifier-create --name red_ssh --chain red --match source_port=0,dest_port=22,protocol=6
+
+tacker sfc-list
+tacker sfc-classifier-list
diff --git a/functest/opnfv_tests/features/sfc/tacker_client_install.sh b/functest/opnfv_tests/features/sfc/tacker_client_install.sh
new file mode 100755
index 00000000..adb9a44b
--- /dev/null
+++ b/functest/opnfv_tests/features/sfc/tacker_client_install.sh
@@ -0,0 +1,43 @@
+MYDIR=$(dirname $(readlink -f "$0"))
+CLIENT=$(echo python-python-tackerclient_*_all.deb)
+CLIREPO="tacker-client"
+
+# Function checks whether a python egg is available, if not, installs
+function chkPPkg() {
+ PKG="$1"
+ IPPACK=$(python - <<'____EOF'
+import pip
+from os.path import join
+for package in pip.get_installed_distributions():
+ print(package.location)
+ print(join(package.location, *package._get_metadata("top_level.txt")))
+____EOF
+)
+ echo "$IPPACK" | grep -q "$PKG"
+ if [ $? -ne 0 ];then
+ pip install "$PKG"
+ fi
+}
+
+function envSetup() {
+ apt-get install -y python-all debhelper fakeroot
+ #pip install --upgrade python-keystoneclient==1.7.4
+ chkPPkg stdeb
+}
+
+# Function installs python-tackerclient from github
+function deployTackerClient() {
+ cd $MYDIR
+ git clone -b 'SFC_refactor' https://github.com/trozet/python-tackerclient.git $CLIREPO
+ cd $CLIREPO
+ python setup.py --command-packages=stdeb.command bdist_deb
+ cd "deb_dist"
+ CLIENT=$(echo python-python-tackerclient_*_all.deb)
+ cp $CLIENT $MYDIR
+ dpkg -i "${MYDIR}/${CLIENT}"
+ apt-get -f -y install
+ dpkg -i "${MYDIR}/${CLIENT}"
+}
+
+envSetup
+deployTackerClient
diff --git a/functest/opnfv_tests/features/sfc/test-vnfd1.yaml b/functest/opnfv_tests/features/sfc/test-vnfd1.yaml
new file mode 100644
index 00000000..5c672e38
--- /dev/null
+++ b/functest/opnfv_tests/features/sfc/test-vnfd1.yaml
@@ -0,0 +1,31 @@
+template_name: test-vnfd1
+description: firewall1-example
+
+service_properties:
+ Id: firewall1-vnfd
+ vendor: tacker
+ version: 1
+ type:
+ - firewall1
+vdus:
+ vdu1:
+ id: vdu1
+ vm_image: sf_nsh_colorado
+ instance_type: custom
+ service_type: firewall1
+
+ network_interfaces:
+ management:
+ network: example-net
+ management: true
+
+ placement_policy:
+ availability_zone: nova
+
+ auto-scaling: noop
+ monitoring_policy: noop
+ failure_policy: respawn
+
+ config:
+ param0: key0
+ param1: key1
diff --git a/functest/opnfv_tests/features/sfc/test-vnfd2.yaml b/functest/opnfv_tests/features/sfc/test-vnfd2.yaml
new file mode 100644
index 00000000..8a570ab9
--- /dev/null
+++ b/functest/opnfv_tests/features/sfc/test-vnfd2.yaml
@@ -0,0 +1,31 @@
+template_name: test-vnfd2
+description: firewall2-example
+
+service_properties:
+ Id: firewall2-vnfd
+ vendor: tacker
+ version: 1
+ type:
+ - firewall2
+vdus:
+ vdu1:
+ id: vdu1
+ vm_image: sf_nsh_colorado
+ instance_type: custom
+ service_type: firewall2
+
+ network_interfaces:
+ management:
+ network: example-net
+ management: true
+
+ placement_policy:
+ availability_zone: nova
+
+ auto-scaling: noop
+ monitoring_policy: noop
+ failure_policy: respawn
+
+ config:
+ param0: key0
+ param1: key1