f663c9df21195936a16040b31c1caf1d0aa127d8
[samplevnf.git] / VNFs / DPPD-PROX / helper-scripts / rapid / pod.py
1 #!/usr/bin/env python2.7
2
3 ##
4 ## Copyright (c) 2019 Intel Corporation
5 ##
6 ## Licensed under the Apache License, Version 2.0 (the "License");
7 ## you may not use this file except in compliance with the License.
8 ## You may obtain a copy of the License at
9 ##
10 ##     http://www.apache.org/licenses/LICENSE-2.0
11 ##
12 ## Unless required by applicable law or agreed to in writing, software
13 ## distributed under the License is distributed on an "AS IS" BASIS,
14 ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 ## See the License for the specific language governing permissions and
16 ## limitations under the License.
17 ##
18
19 from os import path
20 import time, yaml
21 import logging
22 from kubernetes import client, config
23
24 from sshclient import SSHClient
25
26 class Pod:
27     """Class which represents test pods.
28     For example with traffic gen, forward/swap applications, etc
29     """
30     k8s_CoreV1Api = None
31
32     _log = None
33
34     _name = "pod"
35     _namespace = "default"
36     _nodeSelector_hostname = None
37     _last_status = None
38     _id = None
39     _admin_ip = None
40     _dp_ip = None
41
42     _ssh_client = None
43
44     _sriov_vf = None
45     _sriov_vf_mac = None
46
47     def __init__(self, name, namespace = "default", logger_name = "k8srapid"):
48         self._log = logging.getLogger(logger_name)
49
50         self._name = name
51         self._namespace = namespace
52         self._ssh_client = SSHClient(logger_name = logger_name)
53
54     def __del__(self):
55         """Destroy POD. Do a cleanup.
56         """
57         if self._ssh_client is not None:
58             self._ssh_client.disconnect()
59
60     def create_from_yaml(self, file_name):
61         """Load POD description from yaml file.
62         """
63         with open(path.join(path.dirname(__file__), file_name)) as yaml_file:
64             self.body = yaml.safe_load(yaml_file)
65
66             self.body["metadata"]["name"] = self._name
67
68             if (self._nodeSelector_hostname is not None):
69                 if ("nodeSelector" not in self.body["spec"]):
70                     self.body["spec"]["nodeSelector"] = {}
71                 self.body["spec"]["nodeSelector"]["kubernetes.io/hostname"] = self._nodeSelector_hostname
72             self._log.debug("Creating POD, body:\n%s" % self.body)
73
74             try:
75                 self.k8s_CoreV1Api.create_namespaced_pod(body = self.body,
76                                                 namespace = self._namespace)
77             except client.rest.ApiException as e:
78                 self._log.error("Couldn't create POD %s!\n%s\n" % (self._name, e))
79
80     def terminate(self):
81         """Terminate POD. Close SSH connection.
82         """
83         if self._ssh_client is not None:
84             self._ssh_client.disconnect()
85
86         try:
87             self.k8s_CoreV1Api.delete_namespaced_pod(name = self._name,
88                                                      namespace = self._namespace)
89         except client.rest.ApiException as e:
90             if e.reason != "Not Found":
91                 self._log.error("Couldn't delete POD %s!\n%s\n" % (self._name, e.reason))
92
93     def update_admin_ip(self):
94         """Check for admin IP address assigned by k8s.
95         """
96         try:
97             pod = self.k8s_CoreV1Api.read_namespaced_pod_status(name = self._name, namespace = self._namespace)
98             self._admin_ip = pod.status.pod_ip
99         except client.rest.ApiException as e:
100             self._log.error("Couldn't update POD %s admin IP!\n%s\n" % (self._name, e))
101
102     def wait_for_start(self):
103         """Wait for POD to start.
104         """
105         self._log.info("Waiting for POD %s to start..." % self._name)
106         while True:
107             self.get_status()
108             if (self._last_status == "Running" or self._last_status == "Failed"
109                 or self._last_status == "Unknown"):
110                 break
111             else:
112                 time.sleep(3)
113
114         self.update_admin_ip()
115
116         return self._last_status
117
118     def ssh_run_cmd(self, cmd):
119         """Execute command for POD via SSH connection.
120         SSH credentials should be configured before use of this function.
121         """
122         self._ssh_client.run_cmd(cmd)
123
124     def get_name(self):
125         return self._name
126
127     def get_admin_ip(self):
128         return self._admin_ip
129
130     def get_dp_ip(self):
131         return self._dp_ip
132
133     def get_dp_mac(self):
134         return self._sriov_vf_mac
135
136     def get_dp_pci_dev(self):
137         return self._sriov_vf
138
139     def get_id(self):
140         return self._id
141
142     def get_status(self):
143         """Get current status fro the pod.
144         """
145         try:
146             pod = self.k8s_CoreV1Api.read_namespaced_pod_status(name = self._name,
147                                                                 namespace = self._namespace)
148         except client.rest.ApiException as e:
149             self._log.error("Couldn't read POD %s status!\n%s\n" % (self._name, e))
150
151         self._last_status = pod.status.phase
152         return self._last_status
153
154     def get_sriov_dev_mac(self):
155         """Get assigned by k8s SRIOV network device plugin SRIOV VF devices.
156         Return 0 in case of sucessfull configuration.
157         Otherwise return -1.
158         """
159         self._log.info("Checking assigned SRIOV VF for POD %s" % self._name)
160         ret = self._ssh_client.run_cmd("cat /opt/rapid/k8s_sriov_device_plugin_envs")
161         if ret != 0:
162             self._log.error("Failed to check assigned SRIOV VF!"
163                             "Error %s" % self._ssh_client.get_error())
164             return -1
165
166         cmd_output = self._ssh_client.get_output().decode("utf-8").rstrip()
167         self._log.debug("Environment variable %s" % cmd_output)
168
169         # Parse environment variable
170         cmd_output = cmd_output.split("=")[1]
171         self._sriov_vf = cmd_output.split(",")[0]
172         self._log.debug("Using first SRIOV VF %s" % self._sriov_vf)
173
174         self._log.info("Getting MAC address for assigned SRIOV VF %s" % self._sriov_vf)
175         self._ssh_client.run_cmd("sudo /opt/rapid/port_info_app -n 4 -w %s" % self._sriov_vf)
176         if ret != 0:
177             self._log.error("Failed to get MAC address!"
178                             "Error %s" % self._ssh_client.get_error())
179             return -1
180
181         # Parse MAC address
182         cmd_output = self._ssh_client.get_output().decode("utf-8").rstrip()
183         self._log.debug(cmd_output)
184         cmd_output = cmd_output.splitlines()
185         for line in cmd_output:
186             if line.startswith("Port 0 MAC: "):
187                 self._sriov_vf_mac = line[12:]
188
189         self._log.debug("MAC %s" % self._sriov_vf_mac)
190
191     def set_dp_ip(self, dp_ip):
192         self._dp_ip = dp_ip
193
194     def set_id(self, pod_id):
195         self._id = pod_id
196
197     def set_nodeselector(self, hostname):
198         """Set hostname on which POD will be executed.
199         """
200         self._nodeSelector_hostname = hostname
201
202     def set_ssh_credentials(self, user, rsa_private_key):
203         """Set SSH credentials for the SSH connection to the POD.
204         """
205         self.update_admin_ip()
206         self._ssh_client.set_credentials(ip = self._admin_ip,
207                                          user = user,
208                                          rsa_private_key = rsa_private_key)