Manage netperf namespace to enforce baseline
[functest-kubernetes.git] / functest_kubernetes / netperf / netperf.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2021 Orange and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9
10 """
11 Benchmarking Kubernetes Networking Performance
12 """
13
14 import glob
15 import logging
16 import os
17 from pathlib import Path
18 import shutil
19 import subprocess
20 import time
21
22 from kubernetes import client
23 from kubernetes import config
24 from xtesting.core import testcase
25
26
27 class Netperf(testcase.TestCase):
28     """Run Benchmarking Kubernetes Networking Performance"""
29
30     ns_generate_name = "netperf-"
31     __logger = logging.getLogger(__name__)
32
33     def __init__(self, **kwargs):
34         super().__init__(**kwargs)
35         config.load_kube_config()
36         self.corev1 = client.CoreV1Api()
37         self.output_log_name = 'functest-kubernetes.log'
38         self.output_debug_log_name = 'functest-kubernetes.debug.log'
39
40     def check_requirements(self):
41         """Check if launch is in $PATH"""
42         self.is_skipped = not (
43             shutil.which("launch") and shutil.which("plotperf"))
44         if self.is_skipped:
45             self.__logger.warning("launch or plotperf is missing")
46
47     def run(self, **kwargs):
48         self.start_time = time.time()
49         try:
50             if not os.path.exists(self.res_dir):
51                 os.makedirs(self.res_dir)
52             os.chdir(self.res_dir)
53             api_response = self.corev1.create_namespace(
54                 client.V1Namespace(metadata=client.V1ObjectMeta(
55                     generate_name=self.ns_generate_name,
56                     labels={
57                         "pod-security.kubernetes.io/enforce": "baseline"})))
58             self.namespace = api_response.metadata.name
59             self.__logger.debug("create_namespace: %s", api_response)
60             cmd = ['launch', '-iterations', '1', '-kubeConfig',
61                    f'{Path.home()}/.kube/config', '-v', '3',
62                    '-namespace', self.namespace]
63             output = subprocess.check_output(
64                 cmd, stderr=subprocess.STDOUT, timeout=3600)
65             self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
66             lfiles = glob.glob(os.path.join(
67                 f'results_{self.namespace}-latest',
68                 f'{self.namespace}-latest*.csv'))
69             results = max(lfiles, key=os.path.getmtime)
70             cmd = ['plotperf', '-c', results,
71                    '-o', self.res_dir, '-s', 'netperf']
72             output = subprocess.check_output(
73                 cmd, stderr=subprocess.STDOUT, timeout=60)
74             self.__logger.info("%s\n%s", " ".join(cmd), output.decode("utf-8"))
75             self.result = 100
76             status = testcase.TestCase.EX_OK
77         except (subprocess.TimeoutExpired,
78                 subprocess.CalledProcessError) as exc:
79             self.__logger.exception(
80                 "Cannot run %s:\n%s", ' '.join(exc.cmd),
81                 exc.output.decode("utf-8"))
82             self.result = 0
83             status = testcase.TestCase.EX_RUN_ERROR
84         self.stop_time = time.time()
85         return status
86
87     def clean(self):
88         if self.namespace:
89             try:
90                 api_response = self.corev1.delete_namespace(self.namespace)
91                 self.__logger.debug("delete_namespace: %s", self.namespace)
92             except client.rest.ApiException:
93                 pass