aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pods/papi/k8scmdrun.py112
-rw-r--r--pods/papi/papi.py51
-rw-r--r--tools/k8s/cluster-deployment/uscni/Dockerfile25
-rwxr-xr-xtools/k8s/cluster-deployment/uscni/entrypoint.sh18
-rw-r--r--tools/k8s/cluster-deployment/uscni/userspace-cni-daemonset.yml45
5 files changed, 243 insertions, 8 deletions
diff --git a/pods/papi/k8scmdrun.py b/pods/papi/k8scmdrun.py
new file mode 100644
index 00000000..2fb1a62e
--- /dev/null
+++ b/pods/papi/k8scmdrun.py
@@ -0,0 +1,112 @@
+# Copyright 2021 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.
+"""
+Run commands inside the pod for post-deployment configuration
+"""
+
+import re
+import os
+from kubernetes import client, config
+from kubernetes.client.rest import ApiException
+from kubernetes.stream import stream
+
+def execute_command(api_instance, pod_info, exec_command):
+ """
+ Execute a command inside a specified pod
+ exec_command = list of strings
+ """
+ name = pod_info['name']
+ resp = None
+ try:
+ resp = api_instance.read_namespaced_pod(name=name,
+ namespace='default')
+ except ApiException as e:
+ if e.status != 404:
+ print("Unknown error: %s" % e)
+ exit(1)
+ if not resp:
+ print("Pod %s does not exist. Creating it..." % name)
+ return -1
+
+ # Calling exec and waiting for response
+ resp = stream(api_instance.connect_get_namespaced_pod_exec,
+ name,
+ 'default',
+ command=exec_command,
+ stderr=True, stdin=False,
+ stdout=True, tty=False)
+ print("Response: " + resp)
+ return resp
+
+def get_virtual_sockets(api_instance, podname, namespace):
+ """
+ Memif or VhostUser Sockets
+ """
+ socket_files = []
+ pinfo = {'name': podname,
+ 'pod_ip':'',
+ 'namespace': namespace}
+ cmd = ['cat', '/etc/podnetinfo/annotations']
+ resp = execute_command(api_instance, pinfo, cmd)
+ # Remove unnecessary elements
+ results = re.sub(r"(\\n|\"|\n|\\|\]|\{|\}|\[)", "", resp).strip()
+ # Remove unnecessary spaces
+ results = re.sub(r"\s+","", results, flags=re.UNICODE)
+ # Get the RHS values
+ output = results.split('=')
+ for out in output:
+ if 'socketfile' in out:
+ out2 = out.split(',')
+ for rout in out2:
+ if 'socketfile' in rout:
+ print(rout[11:])
+ socket_files.append(rout[11:])
+
+
+def get_sriov_interfaces(api_instance, podname, namespace):
+ """
+ Get SRIOV PIDs.
+ """
+ pinfo = {'name': podname,
+ 'pod_ip':'',
+ 'namespace': namespace}
+ cmd = ['cat', '/etc/podnetinfo/annotations']
+ response = execute_command(api_instance, pinfo, cmd)
+ # Remove unnecessary elements
+ results = re.sub(r"(\\n|\"|\n|\\|\]|\{|\}|\[)", "", response).strip()
+ # Remove unnecessary spaces
+ results = re.sub(r"\s+","", results, flags=re.UNICODE)
+ # Get the RHS values
+ output = results.split('=')
+ names = []
+ ifs = []
+ for out in output:
+ if 'interface' in out:
+ out2 = out.split(',')
+ for rout in out2:
+ if 'interface' in rout:
+ ifs.append(rout[10:])
+ elif 'name' in rout:
+ names.append(rout[5:])
+ res = {names[i]: ifs[i] for i in range(len(names))}
+
+def start_fowarding_app(api_instance, podname, namespace, appname):
+ """
+ Start the Forwarding Application
+ """
+ pinfo = {'name': podname,
+ 'pod_ip':'',
+ 'namespace': namespace}
+ cmd = [appname, '&']
+ response = execute_command(api_instance, pinfo, cmd)
diff --git a/pods/papi/papi.py b/pods/papi/papi.py
index 5c15fa04..67cc3bc5 100644
--- a/pods/papi/papi.py
+++ b/pods/papi/papi.py
@@ -1,4 +1,4 @@
-# Copyright 2020 University Of Delhi.
+# Copyright 2021 University Of Delhi, Spirent Communications
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -55,8 +55,11 @@ class Papi(IPod):
namespace = 'default'
pod_manifests = S.getValue('POD_MANIFEST_FILEPATH')
pod_count = int(S.getValue('POD_COUNT'))
- #namespace = 'vswitchperf'
- # replace_namespace(api, namespace)
+ if S.hasValue('POD_NAMESPACE'):
+ namespace = S.getValue('POD_NAMESPACE')
+ else:
+ namespace = 'default'
+ dep_pod_list = []
# sriov configmap
if S.getValue('PLUGIN') == 'sriov':
@@ -70,8 +73,7 @@ class Papi(IPod):
group = 'k8s.cni.cncf.io'
version = 'v1'
kind_plural = 'network-attachment-definitions'
- api = client.CustomObjectsApi()
-
+ api = client.CustomObjectsApi()
assert pod_count <= len(pod_manifests)
for nad_filepath in S.getValue('NETWORK_ATTACHMENT_FILEPATH'):
@@ -87,10 +89,10 @@ class Papi(IPod):
#create pod workloads
api = client.CoreV1Api()
-
for count in range(pod_count):
+ dep_pod_info = {}
pod_manifest = load_manifest(pod_manifests[count])
-
+ dep_pod_info['name'] = pod_manifest["metadata"]["name"]
try:
response = api.create_namespaced_pod(namespace, pod_manifest)
self._logger.info(str(response))
@@ -98,7 +100,40 @@ class Papi(IPod):
except ApiException as err:
raise Exception from err
- time.sleep(12)
+ # Wait for the pod to start
+ time.sleep(5)
+ status = "Unknown"
+ count = 0
+ while True:
+ if count == 10:
+ break
+ try:
+ response = api.read_namespaced_pod_status(dep_pod_info['name'],
+ namespace)
+ status = response.status.phase
+ except ApiException as err:
+ raise Exception from err
+ if (status == "Running"
+ or status == "Failed"
+ or status == "Unknown"):
+ break
+ else:
+ time.sleep(5)
+ count = count + 1
+ # Now Get the Pod-IP
+ try:
+ response = api.read_namespaced_pod_status(dep_pod_info['name'],
+ namespace)
+ dep_pod_info['pod_ip'] = response.status.pod_ip
+ except ApiException as err:
+ raise Exception from err
+ dep_pod_info['namespace'] = namespace
+ dep_pod_list.append(dep_pod_info)
+ cmd = ['cat', '/etc/podnetinfo/annotations']
+ execute_command(api, dep_pod_info, cmd)
+
+ S.setValue('POD_LIST',dep_pod_list)
+ return dep_pod_list
def terminate(self):
"""
diff --git a/tools/k8s/cluster-deployment/uscni/Dockerfile b/tools/k8s/cluster-deployment/uscni/Dockerfile
new file mode 100644
index 00000000..ddfa3674
--- /dev/null
+++ b/tools/k8s/cluster-deployment/uscni/Dockerfile
@@ -0,0 +1,25 @@
+# docker build --rm -t uscni
+FROM centos:7
+SHELL ["/bin/bash", "-o", "pipefail", "-c"]
+RUN yum install -y epel-release wget; yum clean all
+RUN wget --no-check-certificate https://golang.org/dl/go1.16.6.linux-amd64.tar.gz
+RUN tar -C /usr/local -xzf go1.16.6.linux-amd64.tar.gz
+ENV PATH /usr/local/go/bin:$PATH
+RUN yum install -y git make sudo; yum clean all
+ENV GOPATH /root/go
+RUN mkdir -p "/root/go" "$GOPATH/bin" "$GOPATH/src" "$GOPATH/src" && chmod -R 777 "$GOPATH"
+WORKDIR /root/go/src/
+ENV GO111MODULE off
+RUN go get github.com/intel/userspace-cni-network-plugin > /tmp/UserspaceDockerBuild.log 2>&1 || echo "Can ignore no GO files."
+WORKDIR /root/go/src/github.com/intel/userspace-cni-network-plugin
+ENV GO111MODULE on
+ENV GOROOT /usr/local/go
+ENV GOPATH /root/go
+RUN make clean && make install-dep && make install && make
+RUN cp userspace/userspace /usr/bin/userspace
+
+FROM alpine:latest
+COPY --from=0 /usr/bin/userspace /userspace
+
+ADD entrypoint.sh /
+ENTRYPOINT ["/entrypoint.sh"]
diff --git a/tools/k8s/cluster-deployment/uscni/entrypoint.sh b/tools/k8s/cluster-deployment/uscni/entrypoint.sh
new file mode 100755
index 00000000..0658f150
--- /dev/null
+++ b/tools/k8s/cluster-deployment/uscni/entrypoint.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Always exit on errors.
+set -e
+
+# Check if /opt/cni/bin directory exists
+if [ ! -d "/host/opt/cni/bin" ]
+then
+ echo "Directory /opt/cni/bin/ does not exists."
+ exit 1;
+fi
+
+# Copy cni-plugin on host machine
+cp -f /userspace /host/opt/cni/bin/
+
+# Sleep for 50 years.
+# sleep infinity is not available in alpine;
+sleep 2147483647
diff --git a/tools/k8s/cluster-deployment/uscni/userspace-cni-daemonset.yml b/tools/k8s/cluster-deployment/uscni/userspace-cni-daemonset.yml
new file mode 100644
index 00000000..d598fc6d
--- /dev/null
+++ b/tools/k8s/cluster-deployment/uscni/userspace-cni-daemonset.yml
@@ -0,0 +1,45 @@
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+ name: userspace-cni-amd64
+ namespace: kube-system
+ labels:
+ tier: node
+ app: userspace-cni
+spec:
+ selector:
+ matchLabels:
+ app: userspace-cni
+ template:
+ metadata:
+ labels:
+ tier: node
+ app: userspace-cni
+ spec:
+ hostNetwork: true
+ nodeSelector:
+ beta.kubernetes.io/arch: amd64
+ tolerations:
+ - key: node-role.kubernetes.io/master
+ operator: Exists
+ effect: NoSchedule
+ containers:
+ - name: userspace-cni-plugin
+ image: uscni:latest
+ imagePullPolicy: Never
+ resources:
+ requests:
+ cpu: "100m"
+ memory: "50Mi"
+ limits:
+ cpu: "100m"
+ memory: "50Mi"
+ securityContext:
+ privileged: true
+ volumeMounts:
+ - name: cnibin
+ mountPath: /host/opt/cni/bin
+ volumes:
+ - name: cnibin
+ hostPath:
+ path: /opt/cni/bin