From 5be0a76d76aefbfc7b0555482df2dada7a6e5a08 Mon Sep 17 00:00:00 2001 From: opensource-tnbt Date: Wed, 25 Nov 2020 15:11:47 +0530 Subject: Kubernetes: Infrastructure For K8S Net testing. This patch adds necessary code to perform K8S Networking performance benchmarking. Signed-off-by: Sridhar K. N. Rao Change-Id: I059ddd2e9ad3ee7c05e4620c64401f81474be195 --- pods/__init__.py | 19 +++++++ pods/papi/__init__.py | 19 +++++++ pods/papi/papi.py | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++ pods/pod/__init__.py | 18 +++++++ pods/pod/pod.py | 63 ++++++++++++++++++++++ 5 files changed, 262 insertions(+) create mode 100644 pods/__init__.py create mode 100644 pods/papi/__init__.py create mode 100644 pods/papi/papi.py create mode 100644 pods/pod/__init__.py create mode 100644 pods/pod/pod.py (limited to 'pods') 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 -- cgit 1.2.3-korg