From 9a4ed05300b2aed28e8d2ec213049d5475655577 Mon Sep 17 00:00:00 2001 From: Manuel Buil Date: Tue, 24 May 2016 16:11:53 +0200 Subject: SFC Yardstick test 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 --- samples/sfc.yaml | 50 +++++++++ tests/sfc/sfc_TC02.yaml | 36 ------ .../benchmark/scenarios/networking/test_sfc.py | 18 ++- yardstick/benchmark/scenarios/networking/sfc.py | 122 ++++++++++++++++++--- .../scenarios/networking/sfc_change_classi.bash | 7 ++ .../scenarios/networking/sfc_openstack.py | 117 ++++++++++++++++++++ .../scenarios/networking/sfc_pre_setup.bash | 7 +- .../benchmark/scenarios/networking/sfc_server.bash | 6 +- .../benchmark/scenarios/networking/sfc_tacker.bash | 30 +++-- .../scenarios/networking/sfc_teardown.bash | 13 ++- 10 files changed, 330 insertions(+), 76 deletions(-) create mode 100644 samples/sfc.yaml delete mode 100644 tests/sfc/sfc_TC02.yaml create mode 100755 yardstick/benchmark/scenarios/networking/sfc_change_classi.bash create mode 100644 yardstick/benchmark/scenarios/networking/sfc_openstack.py diff --git a/samples/sfc.yaml b/samples/sfc.yaml new file mode 100644 index 000000000..07c59cbc2 --- /dev/null +++ b/samples/sfc.yaml @@ -0,0 +1,50 @@ +#SFC test case using Tacker as Orchestrator and Netvirt as classifier + +schema: "yardstick:task:0.1" + +scenarios: +- + type: sfc + + host: http_client.sfc_test1 + target: http_server.sfc_test2 + + runner: + type: Iteration + iterations: 1 + interval: 1 + +contexts: +- + name: sfc_test1 + user: root + placement_groups: + pgrp1: + policy: "availability" + servers: + http_client: + 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: m1.small + image: sfc + floating_ip: true + placement: "pgrp1" + networks: + sfc-net_mgmt: + cidr: '11.0.0.0/24' + diff --git a/tests/sfc/sfc_TC02.yaml b/tests/sfc/sfc_TC02.yaml deleted file mode 100644 index 85e6eeb52..000000000 --- a/tests/sfc/sfc_TC02.yaml +++ /dev/null @@ -1,36 +0,0 @@ -#SFC test case using Tacker as Orchestrator and Netvirt as classifier - -schema: "yardstick:task:0.1" - -scenarios: -- - type: sfc - - host: http_client.sfc - target: http_server.sfc - - runner: - type: Iteration - iterations: 1 - interval: 1 - -contexts: -- - name: sfc - placement_groups: - pgrp1: - policy: "availability" - servers: - http_client: - flavor: m1.tiny - image: cirros-0.3.3 - floating_ip: true - placement: "pgrp1" - http_server: - flavor: sfc_custom - image: sfc - floating_ip: true - placement: "pgrp1" - networks: - net_mgmt: - cidr: '11.0.0.0/24' diff --git a/tests/unit/benchmark/scenarios/networking/test_sfc.py b/tests/unit/benchmark/scenarios/networking/test_sfc.py index adce0824a..2d7990e59 100644 --- a/tests/unit/benchmark/scenarios/networking/test_sfc.py +++ b/tests/unit/benchmark/scenarios/networking/test_sfc.py @@ -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(): diff --git a/yardstick/benchmark/scenarios/networking/sfc.py b/yardstick/benchmark/scenarios/networking/sfc.py index dc032ee5c..a126bb52a 100644 --- a/yardstick/benchmark/scenarios/networking/sfc.py +++ b/yardstick/benchmark/scenarios/networking/sfc.py @@ -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 index 000000000..70375ab3b --- /dev/null +++ b/yardstick/benchmark/scenarios/networking/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/yardstick/benchmark/scenarios/networking/sfc_openstack.py b/yardstick/benchmark/scenarios/networking/sfc_openstack.py new file mode 100644 index 000000000..2a5fbde1c --- /dev/null +++ b/yardstick/benchmark/scenarios/networking/sfc_openstack.py @@ -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() diff --git a/yardstick/benchmark/scenarios/networking/sfc_pre_setup.bash b/yardstick/benchmark/scenarios/networking/sfc_pre_setup.bash index fcc225504..36ad16d24 100755 --- a/yardstick/benchmark/scenarios/networking/sfc_pre_setup.bash +++ b/yardstick/benchmark/scenarios/networking/sfc_pre_setup.bash @@ -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 diff --git a/yardstick/benchmark/scenarios/networking/sfc_server.bash b/yardstick/benchmark/scenarios/networking/sfc_server.bash index e9b34e032..41ad92188 100755 --- a/yardstick/benchmark/scenarios/networking/sfc_server.bash +++ b/yardstick/benchmark/scenarios/networking/sfc_server.bash @@ -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 diff --git a/yardstick/benchmark/scenarios/networking/sfc_tacker.bash b/yardstick/benchmark/scenarios/networking/sfc_tacker.bash index df1b4af2b..8b53eeb7c 100755 --- a/yardstick/benchmark/scenarios/networking/sfc_tacker.bash +++ b/yardstick/benchmark/scenarios/networking/sfc_tacker.bash @@ -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 diff --git a/yardstick/benchmark/scenarios/networking/sfc_teardown.bash b/yardstick/benchmark/scenarios/networking/sfc_teardown.bash index 4a3924037..d38be09ce 100755 --- a/yardstick/benchmark/scenarios/networking/sfc_teardown.bash +++ b/yardstick/benchmark/scenarios/networking/sfc_teardown.bash @@ -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 -- cgit 1.2.3-korg