Use ubuntu for containers
[samplevnf.git] / VNFs / DPPD-PROX / helper-scripts / rapid / rapid_k8s_deployment.py
1 ##
2 ## Copyright (c) 2019-2020 Intel Corporation
3 ##
4 ## Licensed under the Apache License, Version 2.0 (the "License");
5 ## you may not use this file except in compliance with the License.
6 ## You may obtain a copy of the License at
7 ##
8 ##     http://www.apache.org/licenses/LICENSE-2.0
9 ##
10 ## Unless required by applicable law or agreed to in writing, software
11 ## distributed under the License is distributed on an "AS IS" BASIS,
12 ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ## See the License for the specific language governing permissions and
14 ## limitations under the License.
15 ##
16
17 import sys
18 from kubernetes import client, config
19 try:
20     import configparser
21 except ImportError:
22     # Python 2.x fallback
23     import ConfigParser as configparser
24 import logging
25 from logging import handlers
26
27 from rapid_k8s_pod import Pod
28
29 class K8sDeployment:
30     """Deployment class to create containers for test execution in Kubernetes
31     environment. 
32     """
33     LOG_FILE_NAME = "createrapidk8s.log"
34     SSH_PRIVATE_KEY = "./rapid_rsa_key"
35     SSH_USER = "rapid"
36
37     POD_YAML_TEMPLATE_FILE_NAME = "pod-rapid.yaml"
38
39     _log = None
40     _create_config = None
41     _runtime_config = None
42     _total_number_of_pods = 0
43     _namespace = "rapid-testing"
44     _pods = []
45
46     def __init__(self):
47         # Configure logger
48         self._log = logging.getLogger("k8srapid")
49         self._log.setLevel(logging.DEBUG)
50
51         console_formatter = logging.Formatter("%(message)s")
52         console_handler = logging.StreamHandler(sys.stdout)
53         console_handler.setLevel(logging.DEBUG)
54         console_handler.setFormatter(console_formatter)
55
56         file_formatter = logging.Formatter("%(asctime)s - "
57                                            "%(levelname)s - "
58                                            "%(message)s")
59         file_handler = logging.handlers.RotatingFileHandler(self.LOG_FILE_NAME,
60                                                             backupCount=10)
61         file_handler.setLevel(logging.DEBUG)
62         file_handler.setFormatter(file_formatter)
63
64         self._log.addHandler(file_handler)
65         self._log.addHandler(console_handler)
66
67         # Initialize k8s plugin
68         try:
69             config.load_kube_config()
70         except:
71             config.load_incluster_config()
72
73         Pod.k8s_CoreV1Api = client.CoreV1Api()
74
75     def load_create_config(self, config_file_name):
76         """Read and parse configuration file for the test environment.
77         """
78         self._log.info("Loading configuration file %s", config_file_name)
79         self._create_config = configparser.RawConfigParser()
80         try:
81             self._create_config.read(config_file_name)
82         except Exception as e:
83             self._log.error("Failed to read config file!\n%s\n" % e)
84             return -1
85
86         # Now parse config file content
87         # Parse [DEFAULT] section
88         if self._create_config.has_option("DEFAULT", "total_number_of_pods"):
89             self._total_number_of_pods = self._create_config.getint(
90                 "DEFAULT", "total_number_of_pods")
91         else:
92             self._log.error("No option total_number_of_pods in DEFAULT section")
93             return -1
94
95         self._log.debug("Total number of pods %d" % self._total_number_of_pods)
96
97         if self._create_config.has_option("DEFAULT", "namespace"):
98             self._namespace = self._create_config.get(
99                 "DEFAULT", "namespace")
100         else:
101             self._log.error("No option namespace in DEFAULT section")
102             return -1
103
104         self._log.debug("Using namespace %s" % self._total_number_of_pods)
105
106         # Parse [PODx] sections
107         for i in range(1, int(self._total_number_of_pods) + 1):
108             # Search for POD name
109             if self._create_config.has_option("POD%d" % i,
110                                               "name"):
111                 pod_name = self._create_config.get(
112                     "POD%d" % i, "name")
113             else:
114                 pod_name = "prox-pod-%d" % i
115
116             # Search for POD hostname
117             if self._create_config.has_option("POD%d" % i,
118                                               "nodeSelector_hostname"):
119                 pod_nodeselector_hostname = self._create_config.get(
120                     "POD%d" % i, "nodeSelector_hostname")
121             else:
122                 pod_nodeselector_hostname = None
123
124             # Search for POD spec
125             if self._create_config.has_option("POD%d" % i,
126                                               "spec_file_name"):
127                 pod_spec_file_name = self._create_config.get(
128                     "POD%d" % i, "spec_file_name")
129             else:
130                 pod_spec_file_name = K8sDeployment.POD_YAML_TEMPLATE_FILE_NAME
131
132             # Search for POD dataplane static IP
133             if self._create_config.has_option("POD%d" % i,
134                                               "dp_ip"):
135                 pod_dp_ip = self._create_config.get(
136                     "POD%d" % i, "dp_ip")
137             else:
138                 pod_dp_ip = None
139
140             # Search for POD dataplane subnet
141             if self._create_config.has_option("POD%d" % i,
142                                               "dp_subnet"):
143                 pod_dp_subnet = self._create_config.get(
144                     "POD%d" % i, "dp_subnet")
145             else:
146                 pod_dp_subnet = "24"
147
148             pod = Pod(pod_name, self._namespace)
149             pod.set_nodeselector(pod_nodeselector_hostname)
150             pod.set_spec_file_name(pod_spec_file_name)
151             pod.set_dp_ip(pod_dp_ip)
152             pod.set_dp_subnet(pod_dp_subnet)
153             pod.set_id(i)
154
155             # Add POD to the list of PODs which need to be created
156             self._pods.append(pod)
157
158         return 0
159
160     def create_pods(self):
161         """ Create test PODs and wait for them to start.
162         Collect information for tests to run.
163         """
164         self._log.info("Creating PODs...")
165
166         # Create PODs using template from yaml file
167         for pod in self._pods:
168             self._log.info("Creating POD %s...", pod.get_name())
169             pod.create_from_yaml()
170
171         # Wait for PODs to start
172         for pod in self._pods:
173             pod.wait_for_start()
174
175         # Collect information from started PODs for test execution
176         for pod in self._pods:
177             pod.set_ssh_credentials(K8sDeployment.SSH_USER, K8sDeployment.SSH_PRIVATE_KEY)
178             pod.get_sriov_dev_mac()
179
180     def save_runtime_config(self, config_file_name):
181         self._log.info("Saving config %s for runrapid script...",
182                        config_file_name)
183         self._runtime_config = configparser.RawConfigParser()
184
185         # Section [DEFAULT]
186 #        self._runtime_config.set("DEFAULT",
187 #                                 "total_number_of_test_machines",
188 #                                 self._total_number_of_pods)
189
190         # Section [ssh]
191         self._runtime_config.add_section("ssh")
192         self._runtime_config.set("ssh",
193                                  "key",
194                                  K8sDeployment.SSH_PRIVATE_KEY)
195         self._runtime_config.set("ssh",
196                                  "user",
197                                  K8sDeployment.SSH_USER)
198
199         # Section [rapid]
200         self._runtime_config.add_section("rapid")
201         self._runtime_config.set("rapid",
202                                  "total_number_of_machines",
203                                  self._total_number_of_pods)
204
205         # Export information about each pod
206         # Sections [Mx]
207         for pod in self._pods:
208             self._runtime_config.add_section("M%d" % pod.get_id())
209             self._runtime_config.set("M%d" % pod.get_id(),
210                                      "admin_ip", pod.get_admin_ip())
211             self._runtime_config.set("M%d" % pod.get_id(),
212                                      "dp_mac1", pod.get_dp_mac())
213             self._runtime_config.set("M%d" % pod.get_id(),
214                                      "dp_pci_dev", pod.get_dp_pci_dev())
215             self._runtime_config.set("M%d" % pod.get_id(),
216                                      "dp_ip1", pod.get_dp_ip() + "/" +
217                                      pod.get_dp_subnet())
218
219         # Section [Varia]
220         self._runtime_config.add_section("Varia")
221         self._runtime_config.set("Varia",
222                                  "vim",
223                                  "kubernetes")
224
225         # Write runtime config file
226         with open(config_file_name, "w") as file:
227             self._runtime_config.write(file)
228
229     def delete_pods(self):
230         for pod in self._pods:
231             pod.terminate()