aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--conf/12_k8s.conf41
-rw-r--r--conf/kubernetes/01_testcases.conf12
-rw-r--r--core/component_factory.py15
-rwxr-xr-xcore/loader/loader.py37
-rw-r--r--core/pod_controller.py93
-rw-r--r--core/vswitch_controller_p2p.py5
-rw-r--r--pods/__init__.py19
-rw-r--r--pods/papi/__init__.py19
-rw-r--r--pods/papi/papi.py143
-rw-r--r--pods/pod/__init__.py18
-rw-r--r--pods/pod/pod.py63
-rw-r--r--requirements.txt1
-rw-r--r--testcases/__init__.py1
-rw-r--r--testcases/k8s_performance.py39
-rw-r--r--testcases/testcase.py57
-rwxr-xr-xvsperf21
-rw-r--r--vswitches/vpp_dpdk_vhost.py2
17 files changed, 580 insertions, 6 deletions
diff --git a/conf/12_k8s.conf b/conf/12_k8s.conf
new file mode 100644
index 00000000..5cfac966
--- /dev/null
+++ b/conf/12_k8s.conf
@@ -0,0 +1,41 @@
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Information about the Master Node.
+
+POD_DIR=os.path.join(ROOT_DIR, 'pods/')
+POD='Papi'
+
+MASTER_IP = '10.10.120.22'
+MASTER_LOGIN = 'opnfv'
+MASTER_PASSWD = 'opnfv'
+
+K8S_CONFIG_FILEPATH = '/home/opnfv/sridhar/k8sconfig'
+
+# Information about the Worker Node. Default is Localhost.
+WORKER_IP = '10.10.120.21'
+WORKER_LOGIN = 'opnfv'
+WORKER_PASSWD = 'opnfv'
+
+
+# Plugin to use.
+PLUGIN = 'ovsdpdk'
+
+# Paths. Default location: Master Node.
+NETWORK_ATTACHMENT_FILEPATH = ['/home/opnfv/sridhar/cnb/userspace/ovsdpdk/userspace-ovs-netAttach.yaml']
+POD_MANIFEST_FILEPATH = '/home/opnfv/sridhar/cnb/userspace/ovsdpdk/userspace-ovs-netapp-pod.yaml'
+
+
+# Application pod
+APP_NAME = 'l2fwd'
+
diff --git a/conf/kubernetes/01_testcases.conf b/conf/kubernetes/01_testcases.conf
new file mode 100644
index 00000000..c5b3135c
--- /dev/null
+++ b/conf/kubernetes/01_testcases.conf
@@ -0,0 +1,12 @@
+K8SPERFORMANCE_TESTS = [
+ {
+ "Name": "pcp_tput",
+ "Deployment": "p2p",
+ "Description": "LTD.Throughput.RFC2544.Throughput",
+ "Parameters" : {
+ "TRAFFIC" : {
+ "traffic_type" : "rfc2544_throughput",
+ },
+ },
+ },
+]
diff --git a/core/component_factory.py b/core/component_factory.py
index 2c51a060..f13bfb5b 100644
--- a/core/component_factory.py
+++ b/core/component_factory.py
@@ -24,7 +24,7 @@ from core.vswitch_controller_op2p import VswitchControllerOP2P
from core.vswitch_controller_ptunp import VswitchControllerPtunP
from core.vnf_controller import VnfController
from core.pktfwd_controller import PktFwdController
-
+from core.pod_controller import PodController
def __init__():
"""Finds and loads all the modules required.
@@ -102,6 +102,19 @@ def create_vnf(deployment_scenario, vnf_class, extra_vnfs):
"""
return VnfController(deployment_scenario, vnf_class, extra_vnfs)
+def create_pod(deployment_scenario, pod_class):
+ """Return a new PodController for the deployment_scenario.
+
+ The returned controller is configured with the given POD class.
+
+ Deployment scenarios: 'pvp', 'pvvp'
+
+ :param deployment_scenario: The deployment scenario name
+ :param pod_class: Reference to pod class to be used.
+ :return: PodController for the deployment_scenario
+ """
+ return PodController(deployment_scenario, pod_class)
+
def create_collector(collector_class, result_dir, test_name):
"""Return a new Collector of the given class
diff --git a/core/loader/loader.py b/core/loader/loader.py
index dcd77ced..45e0d5ba 100755
--- a/core/loader/loader.py
+++ b/core/loader/loader.py
@@ -23,6 +23,7 @@ from tools.pkt_fwd.pkt_fwd import IPktFwd
from tools.pkt_gen.trafficgen import ITrafficGenerator
from vswitches.vswitch import IVSwitch
from vnfs.vnf.vnf import IVnf
+from pods.pod.pod import IPod
# pylint: disable=too-many-public-methods
class Loader(object):
@@ -71,6 +72,11 @@ class Loader(object):
settings.getValue('PKTFWD'),
IPktFwd)
+ self._pod_loader = LoaderServant(
+ settings.getValue('POD_DIR'),
+ settings.getValue('POD'),
+ IPod)
+
def get_trafficgen(self):
"""Returns a new instance configured traffic generator.
@@ -220,6 +226,37 @@ class Loader(object):
"""
return self._vnf_loader.get_classes_printable()
+ def get_pod(self):
+ """Returns instance of currently configured pod implementation.
+
+ :return: IPod implementation if available, None otherwise.
+ """
+ return self._pod_loader.get_class()()
+
+ def get_pod_class(self):
+ """Returns type of currently configured pod implementation.
+
+ :return: Type of IPod implementation if available.
+ None otherwise.
+ """
+ return self._pod_loader.get_class()
+
+ def get_pods(self):
+ """Returns dictionary of all available pods.
+
+ :return: Dictionary of pods.
+ - key: name of the class which implements IPod,
+ - value: Type of vnf which implements IPod.
+ """
+ return self._pod_loader.get_classes()
+
+ def get_pods_printable(self):
+ """Returns all available pods in printable format.
+
+ :return: String containing printable list of pods.
+ """
+ return self._pod_loader.get_classes_printable()
+
def get_pktfwd(self):
"""Returns instance of currently configured packet forwarder implementation.
diff --git a/core/pod_controller.py b/core/pod_controller.py
new file mode 100644
index 00000000..8bc91ec4
--- /dev/null
+++ b/core/pod_controller.py
@@ -0,0 +1,93 @@
+# Copyright 2020 Spirent Communications
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+""" pod Controller interface
+"""
+
+import logging
+import pexpect
+#from conf import settings
+from pods.pod.pod import IPod
+
+class PodController():
+ """POD controller class
+
+ Used to set-up and control PODs for specified scenario
+
+ Attributes:
+ _pod_class: A class object representing the POD.
+ _deployment: A string describing the scenario to set-up in the
+ constructor.
+ _pods: A list of pods controlled by the controller.
+ """
+
+ def __init__(self, deployment, pod_class):
+ """Sets up the POD infrastructure based on deployment scenario
+
+ :param pod_class: The POD class to be used.
+ """
+ # reset POD ID counter for each testcase
+ IPod.reset_pod_counter()
+ pod_number = 0
+ # setup controller with requested number of pods
+ self._logger = logging.getLogger(__name__)
+ self._pod_class = pod_class
+ self._deployment = deployment.lower()
+ self._pods = []
+ if self._deployment == 'p2p':
+ pod_number = 1
+
+ if pod_number:
+ self._pods = [pod_class() for _ in range(pod_number)]
+
+ self._logger.debug('Initializing the pod')
+
+ def get_pods(self):
+ """Returns a list of pods controlled by this controller.
+ """
+ self._logger.debug('get the pods')
+ return self._pods
+
+ def get_pods_number(self):
+ """Returns a number of pods controlled by this controller.
+ """
+ self._logger.debug('get_pods_number %s pod[s]', str(len(self._pods)))
+ return len(self._pods)
+
+ def start(self):
+ """Boots all pods set-up by __init__.
+
+ This is a blocking function.
+ """
+ self._logger.debug('start the pod')
+ try:
+ for pod in self._pods:
+ pod.create()
+ except pexpect.TIMEOUT:
+ self.stop()
+ raise
+
+ def stop(self):
+ """Stops all pods set-up by __init__.
+
+ This is a blocking function.
+ """
+ self._logger.debug('stopping the pod')
+ for pod in self._pods:
+ pod.terminate()
+
+ def __enter__(self):
+ self.start()
+
+ def __exit__(self, type_, value, traceback):
+ self.stop()
diff --git a/core/vswitch_controller_p2p.py b/core/vswitch_controller_p2p.py
index d8f22e4c..0037d484 100644
--- a/core/vswitch_controller_p2p.py
+++ b/core/vswitch_controller_p2p.py
@@ -45,8 +45,9 @@ class VswitchControllerP2P(IVswitchController):
(port1, _) = self._vswitch.add_phy_port(self._bridge)
(port2, _) = self._vswitch.add_phy_port(self._bridge)
- self._vswitch.add_connection(self._bridge, port1, port2, self._traffic)
- self._vswitch.add_connection(self._bridge, port2, port1, self._traffic)
+ if not settings.getValue('K8S'):
+ self._vswitch.add_connection(self._bridge, port1, port2, self._traffic)
+ self._vswitch.add_connection(self._bridge, port2, port1, self._traffic)
except:
self._vswitch.stop()
diff --git a/pods/__init__.py b/pods/__init__.py
new file mode 100644
index 00000000..e3ce18d9
--- /dev/null
+++ b/pods/__init__.py
@@ -0,0 +1,19 @@
+# Copyright 2020 Spirent Communications
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Package for POD wrappers for use with VSPERF.
+
+This package contains an interface the VSPERF core uses for controlling
+PODs and POD-specific implementation modules of this interface.
+"""
diff --git a/pods/papi/__init__.py b/pods/papi/__init__.py
new file mode 100644
index 00000000..16760b86
--- /dev/null
+++ b/pods/papi/__init__.py
@@ -0,0 +1,19 @@
+# Copyright 2020 Spirent Communications
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Package for POD wrappers for use with VSPERF.
+
+This package contains an implementation of the interface the VSPERF core
+uses for controlling PODs using Kubernetes Python-API (PAPI)
+"""
diff --git a/pods/papi/papi.py b/pods/papi/papi.py
new file mode 100644
index 00000000..5a21f1d6
--- /dev/null
+++ b/pods/papi/papi.py
@@ -0,0 +1,143 @@
+# Copyright 2020 University Of Delhi.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""
+Automation of Pod Deployment with Kubernetes Python API
+"""
+
+# import os
+import logging
+import json
+import time
+import yaml
+from kubernetes import client, config
+from kubernetes.client.rest import ApiException
+
+from conf import settings as S
+from pods.pod.pod import IPod
+
+class Papi(IPod):
+ """
+ Class for controlling the pod through PAPI
+ """
+
+ def __init__(self):
+ """
+ Initialisation function.
+ """
+ #super(Papi, self).__init__()
+ super().__init__()
+
+ self._logger = logging.getLogger(__name__)
+ self._sriov_config = None
+ self._sriov_config_ns = None
+ config.load_kube_config(S.getValue('K8S_CONFIG_FILEPATH'))
+
+ def create(self):
+ """
+ Creation Process
+ """
+ # create vswitchperf namespace
+ api = client.CoreV1Api()
+ namespace = 'default'
+ #namespace = 'vswitchperf'
+ # replace_namespace(api, namespace)
+
+ # sriov configmap
+ if S.getValue('PLUGIN') == 'sriov':
+ configmap = load_manifest(S.getValue('CONFIGMAP_FILEPATH'))
+ self._sriov_config = configmap['metadata']['name']
+ self._sriov_config_ns = configmap['metadata']['namespace']
+ api.create_namespaced_config_map(self._sriov_config_ns, configmap)
+
+
+ # create nad(network attachent definitions)
+ group = 'k8s.cni.cncf.io'
+ version = 'v1'
+ kind_plural = 'network-attachment-definitions'
+ api = client.CustomObjectsApi()
+
+ for nad_filepath in S.getValue('NETWORK_ATTACHMENT_FILEPATH'):
+ nad_manifest = load_manifest(nad_filepath)
+
+ try:
+ response = api.create_namespaced_custom_object(group, version, namespace,
+ kind_plural, nad_manifest)
+ self._logger.info(str(response))
+ self._logger.info("Created Network Attachment Definition: %s", nad_filepath)
+ except ApiException as err:
+ raise Exception from err
+
+ #create pod workloads
+ pod_manifest = load_manifest(S.getValue('POD_MANIFEST_FILEPATH'))
+ api = client.CoreV1Api()
+
+ try:
+ response = api.create_namespaced_pod(namespace, pod_manifest)
+ self._logger.info(str(response))
+ self._logger.info("Created POD %d ...", self._number)
+ except ApiException as err:
+ raise Exception from err
+
+ time.sleep(12)
+
+ def terminate(self):
+ """
+ Cleanup Process
+ """
+ #self._logger.info(self._log_prefix + "Cleaning vswitchperf namespace")
+ self._logger.info("Terminating Pod")
+ api = client.CoreV1Api()
+ # api.delete_namespace(name="vswitchperf", body=client.V1DeleteOptions())
+
+ if S.getValue('PLUGIN') == 'sriov':
+ api.delete_namespaced_config_map(self._sriov_config, self._sriov_config_ns)
+
+
+def load_manifest(filepath):
+ """
+ Reads k8s manifest files and returns as string
+
+ :param str filepath: filename of k8s manifest file to read
+
+ :return: k8s resource definition as string
+ """
+ with open(filepath) as handle:
+ data = handle.read()
+
+ try:
+ manifest = json.loads(data)
+ except ValueError:
+ try:
+ manifest = yaml.safe_load(data)
+ except yaml.parser.ParserError as err:
+ raise Exception from err
+
+ return manifest
+
+def replace_namespace(api, namespace):
+ """
+ Creates namespace if does not exists
+ """
+ namespaces = api.list_namespace()
+ for nsi in namespaces.items:
+ if namespace == nsi.metadata.name:
+ api.delete_namespace(name=namespace,
+ body=client.V1DeleteOptions())
+ break
+
+ time.sleep(0.5)
+ api.create_namespace(client.V1Namespace(
+ metadata=client.V1ObjectMeta(name=namespace)))
diff --git a/pods/pod/__init__.py b/pods/pod/__init__.py
new file mode 100644
index 00000000..b91706e2
--- /dev/null
+++ b/pods/pod/__init__.py
@@ -0,0 +1,18 @@
+# Copyright 2020 Spirent Communications
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""POD interface and helpers.
+"""
+
+import pods
diff --git a/pods/pod/pod.py b/pods/pod/pod.py
new file mode 100644
index 00000000..c25744d2
--- /dev/null
+++ b/pods/pod/pod.py
@@ -0,0 +1,63 @@
+# Copyright 2020 Spirent Communications, University Of Delhi.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""
+Interface for POD
+"""
+
+#import time
+#import pexpect
+from tools import tasks
+
+class IPod(tasks.Process):
+ """
+ Interface for POD
+
+ Inheriting from Process helps in managing system process.
+ execute a command, wait, kill, etc.
+ """
+ _number_pods = 0
+
+ def __init__(self):
+ """
+ Initialization Method
+ """
+ self._number = IPod._number_pods
+ self._logger.debug('Initializing %s. Pod with index %s',
+ self._number + 1, self._number)
+ IPod._number_pods = IPod._number_pods + 1
+ self._log_prefix = 'pod_%d_cmd : ' % self._number
+ # raise NotImplementedError()
+
+ def create(self):
+ """
+ Start the Pod
+ """
+ raise NotImplementedError()
+
+
+ def terminate(self):
+ """
+ Stop the Pod
+ """
+ raise NotImplementedError()
+
+ @staticmethod
+ def reset_pod_counter():
+ """
+ Reset internal POD counter
+
+ This method is static
+ """
+ IPod._number_pods = 0
diff --git a/requirements.txt b/requirements.txt
index bd660605..92021014 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -40,3 +40,4 @@ PyYAML>=3.10.0
pyzmq>=16.0
six>=1.9.0
timeout-decorator>=0.4.0
+kubernetes
diff --git a/testcases/__init__.py b/testcases/__init__.py
index 0b6b77e4..736be883 100644
--- a/testcases/__init__.py
+++ b/testcases/__init__.py
@@ -17,3 +17,4 @@
from testcases.testcase import (TestCase)
from testcases.performance import (PerformanceTestCase)
from testcases.integration import (IntegrationTestCase)
+from testcases.k8s_performance import (K8sPerformanceTestCase)
diff --git a/testcases/k8s_performance.py b/testcases/k8s_performance.py
new file mode 100644
index 00000000..3c31430c
--- /dev/null
+++ b/testcases/k8s_performance.py
@@ -0,0 +1,39 @@
+# Copyright 2015-2017 Intel Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""PerformanceTestCase class
+"""
+
+import logging
+
+from testcases.testcase import TestCase
+#from tools.report import report
+
+class K8sPerformanceTestCase(TestCase):
+ """K8sPerformanceTestCase class
+
+ In this basic form runs RFC2544 throughput test
+ """
+ def __init__(self, cfg):
+ """ Testcase initialization
+ """
+ self._type = 'k8s_performance'
+ super().__init__(cfg)
+ self._logger = logging.getLogger(__name__)
+ self._k8s = True
+
+ def run_report(self):
+ pass
+ #super().run_report()
+ #if self._tc_results:
+ # report.generate(self)
diff --git a/testcases/testcase.py b/testcases/testcase.py
index a30558ff..51d212b4 100644
--- a/testcases/testcase.py
+++ b/testcases/testcase.py
@@ -73,6 +73,8 @@ class TestCase(object):
self._hugepages_mounted = False
self._traffic_ctl = None
self._vnf_ctl = None
+ self._pod_ctl = None
+ self._pod_list = None
self._vswitch_ctl = None
self._collector = None
self._loadgen = None
@@ -81,6 +83,7 @@ class TestCase(object):
self._settings_paths_modified = False
self._testcast_run_time = None
self._versions = []
+ self._k8s = False
# initialization of step driven specific members
self._step_check = False # by default don't check result for step driven testcases
self._step_vnf_list = {}
@@ -216,6 +219,12 @@ class TestCase(object):
self._vnf_list = self._vnf_ctl.get_vnfs()
+ self._pod_ctl = component_factory.create_pod(
+ self.deployment,
+ loader.get_pod_class())
+
+ self._pod_list = self._pod_ctl.get_pods()
+
# verify enough hugepages are free to run the testcase
if not self._check_for_enough_hugepages():
raise RuntimeError('Not enough hugepages free to run test.')
@@ -281,6 +290,10 @@ class TestCase(object):
# Stop all VNFs started by TestSteps in case that something went wrong
self.step_stop_vnfs()
+ if self._k8s:
+ self._pod_ctl.stop()
+
+
# Cleanup any LLC-allocations
if S.getValue('LLC_ALLOCATION'):
self._rmd.cleanup_llc_allocation()
@@ -350,15 +363,18 @@ class TestCase(object):
"""Run the test
All setup and teardown through controllers is included.
+
"""
# prepare test execution environment
self.run_initialize()
try:
with self._vswitch_ctl:
- with self._vnf_ctl, self._collector, self._loadgen:
- if not self._vswitch_none:
+ with self._vnf_ctl, self._pod_ctl, self._collector, self._loadgen:
+ if not self._vswitch_none and not self._k8s:
self._add_flows()
+ if self._k8s:
+ self._add_connections()
self._versions += self._vswitch_ctl.get_vswitch().get_version()
@@ -595,6 +611,43 @@ class TestCase(object):
return list(result.keys())
+ def _add_connections(self):
+ """
+ Add connections for Kubernetes Usecases
+ """
+ logging.info("Kubernetes: Adding Connections")
+ vswitch = self._vswitch_ctl.get_vswitch()
+ bridge = S.getValue('VSWITCH_BRIDGE_NAME')
+ if S.getValue('K8S') and 'sriov' not in S.getValue('PLUGIN'):
+ if 'Ovs' in S.getValue('VSWITCH'):
+ # Add OVS Flows
+ logging.info("Kubernetes: Adding OVS Connections")
+ flow = {'table':'0', 'in_port':'1',
+ 'idle_timeout':'0', 'actions': ['output:3']}
+ vswitch.add_flow(bridge, flow)
+ flow = {'table':'0', 'in_port':'3',
+ 'idle_timeout':'0', 'actions': ['output:1']}
+ vswitch.add_flow(bridge, flow)
+ flow = {'table':'0', 'in_port':'2',
+ 'idle_timeout':'0', 'actions': ['output:4']}
+ vswitch.add_flow(bridge, flow)
+ flow = {'table':'0', 'in_port':'4',
+ 'idle_timeout':'0', 'actions': ['output:2']}
+ vswitch.add_flow(bridge, flow)
+ elif 'vpp' in S.getValue('VSWITCH'):
+ phy_ports = vswitch.get_ports()
+ virt_port0 = 'memif1/0'
+ virt_port1 = 'memif2/0'
+ vswitch.add_connection(bridge, phy_ports[0],
+ virt_port0, None)
+ vswitch.add_connection(bridge, virt_port0,
+ phy_ports[0], None)
+ vswitch.add_connection(bridge, phy_ports[1],
+ virt_port1, None)
+ vswitch.add_connection(bridge, virt_port1,
+ phy_ports[1], None)
+
+
def _add_flows(self):
"""Add flows to the vswitch
"""
diff --git a/vsperf b/vsperf
index 95f2a740..51612da2 100755
--- a/vsperf
+++ b/vsperf
@@ -40,6 +40,7 @@ import core.component_factory as component_factory
from core.loader import Loader
from testcases import PerformanceTestCase
from testcases import IntegrationTestCase
+from testcases import K8sPerformanceTestCase
from tools import tasks
from tools import networkcard
from tools import functions
@@ -179,6 +180,8 @@ def parse_arguments():
help='list all system vnfs and exit')
parser.add_argument('--list-loadgens', action='store_true',
help='list all background load generators')
+ parser.add_argument('--list-pods', action='store_true',
+ help='list all system pods')
parser.add_argument('--list-settings', action='store_true',
help='list effective settings configuration and exit')
parser.add_argument('exact_test_name', nargs='*', help='Exact names of\
@@ -202,6 +205,7 @@ def parse_arguments():
group.add_argument('--verbosity', choices=list_logging_levels(),
help='debug level')
group.add_argument('--integration', action='store_true', help='execute integration tests')
+ group.add_argument('--k8s', action='store_true', help='execute Kubernetes tests')
group.add_argument('--openstack', action='store_true', help='Run VSPERF with openstack')
group.add_argument('--trafficgen', help='traffic generator to use')
group.add_argument('--vswitch', help='vswitch implementation to use')
@@ -579,6 +583,10 @@ def handle_list_options(args):
print(Loader().get_loadgens_printable())
sys.exit(0)
+ if args['list_pods']:
+ print(Loader().get_pods_printable())
+ sys.exit(0)
+
if args['list_settings']:
print(str(settings))
sys.exit(0)
@@ -596,6 +604,8 @@ def list_testcases(args):
# configure tests
if args['integration']:
testcases = settings.getValue('INTEGRATION_TESTS')
+ elif args['k8s']:
+ testcases = settings.getValue('K8SPERFORMANCE_TESTS')
else:
testcases = settings.getValue('PERFORMANCE_TESTS')
@@ -692,6 +702,8 @@ def main():
# load non performance/integration tests
if args['integration']:
settings.load_from_dir(os.path.join(_CURR_DIR, 'conf/integration'))
+ if args['k8s']:
+ settings.load_from_dir(os.path.join(_CURR_DIR, 'conf/kubernetes'))
# load command line parameters first in case there are settings files
# to be used
@@ -709,6 +721,11 @@ def main():
settings.setValue('mode', args['mode'])
+ if args['k8s']:
+ settings.setValue('K8S', True)
+ else:
+ settings.setValue('K8S', False)
+
if args['openstack']:
result = osdt.deploy_testvnf()
if result:
@@ -833,6 +850,8 @@ def main():
# configure tests
if args['integration']:
testcases = settings.getValue('INTEGRATION_TESTS')
+ elif args['k8s']:
+ testcases = settings.getValue('K8SPERFORMANCE_TESTS')
else:
testcases = settings.getValue('PERFORMANCE_TESTS')
@@ -875,6 +894,8 @@ def main():
if args['integration']:
test = IntegrationTestCase(cfg)
+ elif args['k8s']:
+ test = K8sPerformanceTestCase(cfg)
else:
test = PerformanceTestCase(cfg)
diff --git a/vswitches/vpp_dpdk_vhost.py b/vswitches/vpp_dpdk_vhost.py
index af5aca51..f88ed95e 100644
--- a/vswitches/vpp_dpdk_vhost.py
+++ b/vswitches/vpp_dpdk_vhost.py
@@ -462,4 +462,4 @@ class VppDpdkVhost(IVSwitch, tasks.Process):
def get_ports(self, switch_name):
"""See IVswitch for general description
"""
- raise NotImplementedError()
+ return self._phy_ports