SFC Yardstick test 77/14577/28
authorManuel Buil <manuel.buil@ericsson.com>
Tue, 24 May 2016 14:11:53 +0000 (16:11 +0200)
committerManuel Buil <manuel.buil@ericsson.com>
Tue, 5 Jul 2016 07:38:58 +0000 (09:38 +0200)
Modifications of the SFC Yardstick test

The test creates two chains. One chain blocks HTTP the other one blocks SSH.
We doublecheck that HTTP works in one but not in the other and the same for
SSH.

There are some things that must be modified manually as ODL is not yet ready
for ovs 2.5.90. Here are the instructions:

https://wiki.opnfv.org/display/sfc/Yardstick

Change-Id: Ide6588a682f3491ab58c47ee7335205868c109fc
Signed-off-by: Manuel Buil <manuel.buil@ericsson.com>
samples/sfc.yaml [moved from tests/sfc/sfc_TC02.yaml with 57% similarity]
tests/unit/benchmark/scenarios/networking/test_sfc.py
yardstick/benchmark/scenarios/networking/sfc.py
yardstick/benchmark/scenarios/networking/sfc_change_classi.bash [new file with mode: 0755]
yardstick/benchmark/scenarios/networking/sfc_openstack.py [new file with mode: 0644]
yardstick/benchmark/scenarios/networking/sfc_pre_setup.bash
yardstick/benchmark/scenarios/networking/sfc_server.bash
yardstick/benchmark/scenarios/networking/sfc_tacker.bash
yardstick/benchmark/scenarios/networking/sfc_teardown.bash

similarity index 57%
rename from tests/sfc/sfc_TC02.yaml
rename to samples/sfc.yaml
index 85e6eeb..07c59cb 100644 (file)
@@ -6,8 +6,8 @@ scenarios:
 -
   type: sfc
 
-  host: http_client.sfc
-  target: http_server.sfc
+  host: http_client.sfc_test1
+  target: http_server.sfc_test2
 
   runner:
     type: Iteration
@@ -16,21 +16,35 @@ scenarios:
 
 contexts:
 -
-  name: sfc
+  name: sfc_test1
+  user: root
   placement_groups:
     pgrp1:
       policy: "availability"
   servers:
     http_client:
-      flavor: m1.tiny
-      image: cirros-0.3.3
+      flavor: m1.small
+      image: sfc
       floating_ip: true
       placement: "pgrp1"
+  networks:
+     sfc-net_mgmt:
+       cidr: '11.0.0.0/24'
+
+-
+
+  name: sfc_test2
+  user: root
+  placement_groups:
+    pgrp1:
+      policy: "availability"
+  servers:
     http_server:
-      flavor: sfc_custom
+      flavor: m1.small
       image: sfc
       floating_ip: true
       placement: "pgrp1"
   networks:
-     net_mgmt:
+     sfc-net_mgmt:
        cidr: '11.0.0.0/24'
+
index adce082..2d7990e 100644 (file)
@@ -26,26 +26,32 @@ class SfcTestCase(unittest.TestCase):
         # Used in Sfc.setup()
         context_cfg['target'] = dict()
         context_cfg['target']['user'] = 'root'
-        context_cfg['target']['password'] = 'octopus'
-        context_cfg['target']['ip'] = None
+        context_cfg['target']['password'] = 'opnfv'
+        context_cfg['target']['ip'] = '127.0.0.1' 
 
         # Used in Sfc.run()
         context_cfg['host'] = dict()
-        context_cfg['host']['user'] = 'cirros'
-        context_cfg['host']['password'] = 'cubslose:)'
+        context_cfg['host']['user'] = 'root'
+        context_cfg['host']['password'] = 'opnfv'
         context_cfg['host']['ip'] = None
         context_cfg['target'] = dict()
-        context_cfg['target']['ip'] = None
+        context_cfg['target']['ip'] = '127.0.0.1'
 
         self.sfc = sfc.Sfc(scenario_cfg=scenario_cfg, context_cfg=context_cfg)
 
     @mock.patch('yardstick.benchmark.scenarios.networking.sfc.ssh')
-    def test_run_for_success(self, mock_ssh):
+    @mock.patch('yardstick.benchmark.scenarios.networking.sfc.sfc_openstack')
+    @mock.patch('yardstick.benchmark.scenarios.networking.sfc.subprocess')
+    def test_run_for_success(self, mock_subprocess, mock_openstack, mock_ssh):
         # Mock a successfull SSH in Sfc.setup() and Sfc.run()
         mock_ssh.SSH().execute.return_value = (0, '100', '')
+        mock_openstack.return_value = "127.0.0.1"
+        mock_subprocess.return_value = 'mocked!'
 
         result = {}
+        self.sfc.setup()
         self.sfc.run(result)
+        self.sfc.teardown()
 
 
 def main():
index dc032ee..a126bb5 100644 (file)
@@ -1,14 +1,14 @@
 import pkg_resources
 import logging
 import subprocess
-
+import sfc_openstack
 import yardstick.ssh as ssh
 from yardstick.benchmark.scenarios import base
 
 LOG = logging.getLogger(__name__)
 
 
-class Sfc(base.Scenario):
+class Sfc(base.Scenario):  # pragma: no cover
     ''' SFC scenario class '''
 
     __scenario_type__ = "sfc"
@@ -17,8 +17,9 @@ class Sfc(base.Scenario):
     TACKER_SCRIPT = 'sfc_tacker.bash'
     SERVER_SCRIPT = 'sfc_server.bash'
     TEARDOWN_SCRIPT = "sfc_teardown.bash"
+    TACKER_CHANGECLASSI = "sfc_change_classi.bash"
 
-    def __init__(self, scenario_cfg, context_cfg):
+    def __init__(self, scenario_cfg, context_cfg):  # pragma: no cover
         self.scenario_cfg = scenario_cfg
         self.context_cfg = context_cfg
         self.setup_done = False
@@ -40,7 +41,7 @@ class Sfc(base.Scenario):
 
         target = self.context_cfg['target']
         target_user = target.get('user', 'root')
-        target_pwd = target.get('password', 'octopus')
+        target_pwd = target.get('password', 'opnfv')
         target_ip = target.get('ip', None)
 
         ''' webserver start automatically during the vm boot '''
@@ -54,40 +55,133 @@ class Sfc(base.Scenario):
         status, stdout, stderr = self.server.execute(cmd_server)
         LOG.debug("Output server command: %s", status)
 
+        ips = sfc_openstack.get_an_IP()
+
+        target = self.context_cfg['target']
+        SF1_user = target.get('user', 'root')
+        SF1_pwd = target.get('password', 'opnfv')
+        SF1_ip = ips[0]
+
+        LOG.info("user:%s, host:%s", SF1_user, SF1_ip)
+        self.server = ssh.SSH(SF1_user, SF1_ip, password=SF1_pwd)
+        self.server.wait(timeout=600)
+        cmd_SF1 = ("nohup python vxlan_tool.py -i eth0 "
+                   "-d forward -v off -b 80 &")
+        LOG.debug("Starting HTTP firewall in SF1")
+        status, stdout, stderr = self.server.execute(cmd_SF1)
+        result = self.server.execute("ps lax | grep python")
+        if "vxlan_tool.py" in result[1]:  # pragma: no cover
+            LOG.debug("HTTP firewall started")
+
+        SF2_user = target.get('user', 'root')
+        SF2_pwd = target.get('password', 'opnfv')
+        SF2_ip = ips[1]
+
+        LOG.info("user:%s, host:%s", SF2_user, SF2_ip)
+        self.server = ssh.SSH(SF2_user, SF2_ip, password=SF2_pwd)
+        self.server.wait(timeout=600)
+        cmd_SF2 = ("nohup python vxlan_tool.py -i eth0 "
+                   "-d forward -v off -b 22 &")
+        LOG.debug("Starting SSH firewall in SF2")
+        status, stdout, stderr = self.server.execute(cmd_SF2)
+
+        result = self.server.execute("ps lax | grep python")
+        if "vxlan_tool.py" in result[1]:  # pragma: no cover
+            LOG.debug("SSH firewall started")
+
         self.setup_done = True
 
     def run(self, result):
         ''' Creating client and server VMs to perform the test'''
         host = self.context_cfg['host']
-        host_user = host.get('user', 'cirros')
-        host_pwd = host.get('password', 'cubswin:)')
+        host_user = host.get('user', 'root')
+        host_pwd = host.get('password', 'opnfv')
         host_ip = host.get('ip', None)
 
         LOG.info("user:%s, host:%s", host_user, host_ip)
         self.client = ssh.SSH(host_user, host_ip, password=host_pwd)
         self.client.wait(timeout=600)
 
-        if not self.setup_done:
+        if not self.setup_done:  # pragma: no cover
             self.setup()
 
         target = self.context_cfg['target']
         target_ip = target.get('ip', None)
 
-        cmd_client = "curl %s", target_ip
-        LOG.debug("Executing command: %s", cmd_client)
+        cmd_client = "nc -w 5 -zv " + target_ip + " 22"
+        result = self.client.execute(cmd_client)
+
+        i = 0
+        if "timed out" in result[2]:  # pragma: no cover
+            LOG.info('\033[92m' + "TEST 1 [PASSED] "
+                     "==> SSH BLOCKED" + '\033[0m')
+            i = i + 1
+        else:  # pragma: no cover
+            LOG.debug('\033[91m' + "TEST 1 [FAILED] "
+                      "==> SSH NOT BLOCKED" + '\033[0m')
+            return
+
+        cmd_client = "nc -w 5 -zv " + target_ip + " 80"
+        LOG.info("Executing command: %s", cmd_client)
+        result = self.client.execute(cmd_client)
+        if "succeeded" in result[2]:  # pragma: no cover
+            LOG.info('\033[92m' + "TEST 2 [PASSED] "
+                     "==> HTTP WORKS" + '\033[0m')
+            i = i + 1
+        else:  # pragma: no cover
+            LOG.debug('\033[91m' + "TEST 2 [FAILED] "
+                      "==> HTTP BLOCKED" + '\033[0m')
+            return
+
+        self.tacker_classi = pkg_resources.resource_filename(
+            'yardstick.benchmark.scenarios.networking',
+            Sfc.TACKER_CHANGECLASSI)
+
+        ''' calling Tacker to change the classifier '''
+        cmd_tacker = "%s" % (self.tacker_classi)
+        subprocess.call(cmd_tacker, shell=True)
+
+        cmd_client = "nc -w 5 -zv " + target_ip + " 80"
+        LOG.info("Executing command: %s", cmd_client)
         result = self.client.execute(cmd_client)
-        LOG.debug("Output client command: %s", result)
+        LOG.info("Output client command: %s", result)
+        if "timed out" in result[2]:  # pragma: no cover
+            LOG.info('\033[92m' + "TEST 3 [WORKS] "
+                     "==> HTTP BLOCKED" + '\033[0m')
+            i = i + 1
+        else:  # pragma: no cover
+            LOG.debug('\033[91m' + "TEST 3 [FAILED] "
+                      "==> HTTP NOT BLOCKED" + '\033[0m')
+            return
+
+        cmd_client = "nc -zv " + target_ip + " 22"
+        result = self.client.execute(cmd_client + " \r")
+        LOG.debug(result)
+
+        if "succeeded" in result[2]:  # pragma: no cover
+            LOG.info('\033[92m' + "TEST 4 [WORKS] "
+                     "==> SSH WORKS" + '\033[0m')
+            i = i + 1
+        else:  # pragma: no cover
+            LOG.debug('\033[91m' + "TEST 4 [FAILED] "
+                      "==> SSH BLOCKED" + '\033[0m')
+            return
+
+        if i == 4:  # pragma: no cover
+            for x in range(0, 5):
+                LOG.info('\033[92m' + "SFC TEST WORKED"
+                         " :) \n" + '\033[0m')
 
     def teardown(self):
         ''' for scenario teardown remove tacker VNFs, chains and classifiers'''
         self.teardown_script = pkg_resources.resource_filename(
-            "yardstick.benchmark.scenarios.sfc",
+            "yardstick.benchmark.scenarios.networking",
             Sfc.TEARDOWN_SCRIPT)
         subprocess.call(self.teardown_script, shell=True)
         self.teardown_done = True
 
 
-'''def _test():
+'''def _test():  # pragma: no cover
 
     internal test function
     logger = logging.getLogger("Sfc Yardstick")
@@ -95,11 +189,11 @@ class Sfc(base.Scenario):
 
     result = {}
 
-    sfc = Sfc()
+    sfc = Sfc(scenario_cfg, context_cfg)
     sfc.setup()
     sfc.run(result)
     print result
     sfc.teardown()
 
-if __name__ == '__main__':
+if __name__ == '__main__':  # pragma: no cover
     _test()'''
diff --git a/yardstick/benchmark/scenarios/networking/sfc_change_classi.bash b/yardstick/benchmark/scenarios/networking/sfc_change_classi.bash
new file mode 100755 (executable)
index 0000000..70375ab
--- /dev/null
@@ -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/yardstick/benchmark/scenarios/networking/sfc_openstack.py b/yardstick/benchmark/scenarios/networking/sfc_openstack.py
new file mode 100644 (file)
index 0000000..2a5fbde
--- /dev/null
@@ -0,0 +1,117 @@
+import os
+from novaclient.v2 import client as novaclient
+from neutronclient.v2_0 import client as neutronclient
+
+
+def get_credentials(service):  # pragma: no cover
+    """Returns a creds dictionary filled with the following keys:
+    * username
+    * password/api_key (depending on the service)
+    * tenant_name/project_id (depending on the service)
+    * auth_url
+    :param service: a string indicating the name of the service
+                    requesting the credentials.
+    """
+    creds = {}
+    # Unfortunately, each of the OpenStack client will request slightly
+    # different entries in their credentials dict.
+    if service.lower() in ("nova", "cinder"):
+        password = "api_key"
+        tenant = "project_id"
+    else:
+        password = "password"
+        tenant = "tenant_name"
+
+    # The most common way to pass these info to the script is to do it through
+    # environment variables.
+    creds.update({
+        "username": os.environ.get('OS_USERNAME', "admin"),
+        password: os.environ.get("OS_PASSWORD", 'admin'),
+        "auth_url": os.environ.get("OS_AUTH_URL"),
+        tenant: os.environ.get("OS_TENANT_NAME", "admin"),
+    })
+    cacert = os.environ.get("OS_CACERT")
+    if cacert is not None:
+        # each openstack client uses differnt kwargs for this
+        creds.update({"cacert": cacert,
+                      "ca_cert": cacert,
+                      "https_ca_cert": cacert,
+                      "https_cacert": cacert,
+                      "ca_file": cacert})
+        creds.update({"insecure": "True", "https_insecure": "True"})
+        if not os.path.isfile(cacert):
+            print ("WARNING: The 'OS_CACERT' environment variable is " +
+                   "set to %s but the file does not exist." % cacert)
+    return creds
+
+
+def get_instances(nova_client):  # pragma: no cover
+    try:
+        instances = nova_client.servers.list(search_opts={'all_tenants': 1})
+        return instances
+    except Exception, e:
+        print "Error [get_instances(nova_client)]:", e
+        return None
+
+
+def get_SFs(nova_client):  # pragma: no cover
+    try:
+        instances = get_instances(nova_client)
+        SFs = []
+        for instance in instances:
+            if "sfc_test" not in instance.name:
+                SFs.append(instance)
+        return SFs
+    except Exception, e:
+        print "Error [get_SFs(nova_client)]:", e
+        return None
+
+
+def get_external_net_id(neutron_client):  # pragma: no cover
+    for network in neutron_client.list_networks()['networks']:
+        if network['router:external']:
+            return network['id']
+    return False
+
+
+def create_floating_ips(neutron_client):  # pragma: no cover
+    extnet_id = get_external_net_id(neutron_client)
+    ips = []
+    props = {'floating_network_id': extnet_id}
+    try:
+        while (len(ips) < 2):
+            ip_json = neutron_client.create_floatingip({'floatingip': props})
+            fip_addr = ip_json['floatingip']['floating_ip_address']
+            ips.append(fip_addr)
+    except Exception, e:
+        print "Error [create_floating_ip(neutron_client)]:", e
+        return None
+    return ips
+
+
+def floatIPtoSFs(SFs, floatips):  # pragma: no cover
+    try:
+        i = 0
+        for SF in SFs:
+            SF.add_floating_ip(floatips[i])
+            i = i + 1
+        return True
+    except Exception, e:
+        print ("Error [add_floating_ip(nova_client, '%s', '%s')]:" %
+               (SF, floatips[i]), e)
+        return False
+
+
+def get_an_IP():  # pragma: no cover
+
+    creds_nova = get_credentials("nova")
+    nova_client = novaclient.Client(version='2', **creds_nova)
+    creds_neutron = get_credentials("neutron")
+    neutron_client = neutronclient.Client(**creds_neutron)
+    SFs = get_SFs(nova_client)
+    floatips = create_floating_ips(neutron_client)
+    floatIPtoSFs(SFs, floatips)
+    return floatips
+
+if __name__ == '__main__':  # pragma: no cover
+    get_an_IP()
index fcc2255..36ad16d 100755 (executable)
@@ -2,8 +2,9 @@
 set -e
 
 # download and create image
-wget https://www.dropbox.com/s/focu44sh52li7fz/sfc_cloud.qcow2
-glance image-create --name sfc --disk-format qcow2 --container-format bare --file sfc_cloud.qcow2
+#wget https://www.dropbox.com/s/focu44sh52li7fz/sfc_cloud.qcow2
+glance image-create --name sfc --disk-format qcow2 --container-format bare --file SF.qcow2
+
 
 #create flavor
-nova flavor-create --is-public true sfc_custom 666 1000 5 2
+openstack flavor create custom --ram 1500 --disk 10 --public
index e9b34e0..41ad921 100755 (executable)
@@ -1,5 +1,7 @@
 #!/bin/bash
 set -e
 
-service iptables stop
-python -m SimpleHTTPServer 80
+#service iptables stop
+python -m SimpleHTTPServer 80 > /dev/null 2>&1 &
+touch index.html
+echo "WORKED" >> index.html
index df1b4af..8b53eeb 100755 (executable)
@@ -1,19 +1,31 @@
 #!/bin/bash
-set -e
-BASEDIR= `pwd`
+BASEDIR=`pwd`
 
 #import VNF descriptor
-tacker vnfd-create --vnfd-file ${BASEDIR}/test-vnfd.yaml
+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-vnfd
-tacker vnf-create --name testVNF2 --vnfd-name test-vnfd
+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 chainA --chain testVNF1
-tacker sfc-create --name chainB --chain testVNF2
+tacker sfc-create --name red --chain testVNF1
+tacker sfc-create --name blue --chain testVNF2
 
 #create classifier
-tacker sfc-classifier-create --name myclassA --chain chainA --match dest_port=80,protocol=6
-tacker sfc-classifier-create --name myclassB --chain chainB --match dest_port=22,protocol=6
+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
index 4a39240..d38be09 100755 (executable)
@@ -1,17 +1,18 @@
 #!/bin/bash
-set -e
+#set -e
 
 #delete classifier
-tacker sfc-classifier-create myclassA
-tacker sfc-classifier-create myclassB
+tacker sfc-classifier-delete red_http
+tacker sfc-classifier-delete red_ssh
 
 #delete service chain
-tacker sfc-delete chainA
-tacker sfc-delete chainB
+tacker sfc-delete red
+tacker sfc-delete blue
 
 #delete VNFs
 tacker vnf-delete testVNF1
 tacker vnf-delete testVNF2
 
 #delete VNF descriptor
-tacker vnfd-delete test-vnfd
+tacker vnfd-delete test-vnfd1
+tacker vnfd-delete test-vnfd2