From 919872a6ee1ddfd9105879175a1649c1444be8c3 Mon Sep 17 00:00:00 2001 From: Yury Kylulin Date: Thu, 10 Dec 2020 11:40:29 +0300 Subject: Moving to python 3 for kubernetes scripts Move to python version 3 in all scripts for kubernetes environment. Streamline file names to match existing libraries. Signed-off-by: Yury Kylulin Change-Id: Id875f4240a87ab600b445cb9a7fd97ec1335f88a --- .../helper-scripts/rapid/createrapidk8s.py | 4 +- .../helper-scripts/rapid/k8sdeployment.py | 196 ------------------- VNFs/DPPD-PROX/helper-scripts/rapid/pod.py | 208 --------------------- .../helper-scripts/rapid/rapid_k8s_deployment.py | 198 ++++++++++++++++++++ .../helper-scripts/rapid/rapid_k8s_pod.py | 206 ++++++++++++++++++++ .../helper-scripts/rapid/rapid_sshclient.py | 111 +++++++++++ VNFs/DPPD-PROX/helper-scripts/rapid/sshclient.py | 113 ----------- 7 files changed, 517 insertions(+), 519 deletions(-) delete mode 100644 VNFs/DPPD-PROX/helper-scripts/rapid/k8sdeployment.py delete mode 100644 VNFs/DPPD-PROX/helper-scripts/rapid/pod.py create mode 100644 VNFs/DPPD-PROX/helper-scripts/rapid/rapid_k8s_deployment.py create mode 100644 VNFs/DPPD-PROX/helper-scripts/rapid/rapid_k8s_pod.py create mode 100644 VNFs/DPPD-PROX/helper-scripts/rapid/rapid_sshclient.py delete mode 100644 VNFs/DPPD-PROX/helper-scripts/rapid/sshclient.py (limited to 'VNFs/DPPD-PROX') diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/createrapidk8s.py b/VNFs/DPPD-PROX/helper-scripts/rapid/createrapidk8s.py index 4285584d..c4667f1f 100755 --- a/VNFs/DPPD-PROX/helper-scripts/rapid/createrapidk8s.py +++ b/VNFs/DPPD-PROX/helper-scripts/rapid/createrapidk8s.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2.7 +#!/usr/bin/env python3 ## ## Copyright (c) 2019 Intel Corporation @@ -17,7 +17,7 @@ ## import argparse -from k8sdeployment import K8sDeployment +from rapid_k8s_deployment import K8sDeployment # Config file name for deployment creation CREATE_CONFIG_FILE_NAME = "rapid.pods" diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/k8sdeployment.py b/VNFs/DPPD-PROX/helper-scripts/rapid/k8sdeployment.py deleted file mode 100644 index 5e921d46..00000000 --- a/VNFs/DPPD-PROX/helper-scripts/rapid/k8sdeployment.py +++ /dev/null @@ -1,196 +0,0 @@ -#!/usr/bin/env python2.7 - -## -## Copyright (c) 2019-2020 Intel Corporation -## -## 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. -## - -import sys -from kubernetes import client, config -import ConfigParser -import logging -from logging import handlers - -from pod import Pod - -class K8sDeployment: - """Deployment class to create containers for test execution in Kubernetes - environment. - """ - LOG_FILE_NAME = "createrapidk8s.log" - SSH_PRIVATE_KEY = "./rapid_rsa_key" - SSH_USER = "centos" - - POD_YAML_TEMPLATE_FILE_NAME = "pod-rapid.yaml" - - _log = None - _create_config = None - _runtime_config = None - _total_number_of_pods = 0 - _pods = [] - - def __init__(self): - # Configure logger - self._log = logging.getLogger("k8srapid") - self._log.setLevel(logging.DEBUG) - - console_formatter = logging.Formatter("%(message)s") - console_handler = logging.StreamHandler(sys.stdout) - console_handler.setLevel(logging.DEBUG) - console_handler.setFormatter(console_formatter) - - file_formatter = logging.Formatter("%(asctime)s - " - "%(levelname)s - " - "%(message)s") - file_handler = logging.handlers.RotatingFileHandler(self.LOG_FILE_NAME, - backupCount=10) - file_handler.setLevel(logging.DEBUG) - file_handler.setFormatter(file_formatter) - - self._log.addHandler(file_handler) - self._log.addHandler(console_handler) - - # Initialize k8s plugin - config.load_kube_config() - Pod.k8s_CoreV1Api = client.CoreV1Api() - - def load_create_config(self, config_file_name): - """Read and parse configuration file for the test environment. - """ - self._log.info("Loading configuration file %s", config_file_name) - self._create_config = ConfigParser.RawConfigParser() - try: - self._create_config.read(config_file_name) - except Exception as e: - self._log.error("Failed to read config file!\n%s\n" % e) - return -1 - - # Now parse config file content - # Parse [DEFAULT] section - if self._create_config.has_option("DEFAULT", "total_number_of_pods"): - self._total_number_of_pods = self._create_config.getint( - "DEFAULT", "total_number_of_pods") - else: - self._log.error("No option total_number_of_pods in DEFAULT section") - return -1 - - self._log.debug("Total number of pods %d" % self._total_number_of_pods) - - # Parse [PODx] sections - for i in range(1, int(self._total_number_of_pods) + 1): - # Search for POD name - if self._create_config.has_option("POD%d" % i, - "name"): - pod_name = self._create_config.get( - "POD%d" % i, "name") - else: - pod_name = "pod-rapid-%d" % i - - # Search for POD hostname - if self._create_config.has_option("POD%d" % i, - "nodeSelector_hostname"): - pod_nodeselector_hostname = self._create_config.get( - "POD%d" % i, "nodeSelector_hostname") - else: - pod_nodeselector_hostname = None - - # Search for POD dataplane static IP - if self._create_config.has_option("POD%d" % i, - "dp_ip"): - pod_dp_ip = self._create_config.get( - "POD%d" % i, "dp_ip") - else: - pod_dp_ip = None - - pod = Pod(pod_name) - pod.set_nodeselector(pod_nodeselector_hostname) - pod.set_dp_ip(pod_dp_ip) - pod.set_id(i) - - # Add POD to the list of PODs which need to be created - self._pods.append(pod) - - return 0 - - def create_pods(self): - """ Create test PODs and wait for them to start. - Collect information for tests to run. - """ - self._log.info("Creating PODs...") - - # Create PODs using template from yaml file - for pod in self._pods: - self._log.info("Creating POD %s...", pod.get_name()) - pod.create_from_yaml(K8sDeployment.POD_YAML_TEMPLATE_FILE_NAME) - - # Wait for PODs to start - for pod in self._pods: - pod.wait_for_start() - - # Collect information from started PODs for test execution - for pod in self._pods: - pod.set_ssh_credentials(K8sDeployment.SSH_USER, K8sDeployment.SSH_PRIVATE_KEY) - pod.get_sriov_dev_mac() - - def save_runtime_config(self, config_file_name): - self._log.info("Saving config %s for runrapid script...", - config_file_name) - self._runtime_config = ConfigParser.RawConfigParser() - - # Section [DEFAULT] -# self._runtime_config.set("DEFAULT", -# "total_number_of_test_machines", -# self._total_number_of_pods) - - # Section [ssh] - self._runtime_config.add_section("ssh") - self._runtime_config.set("ssh", - "key", - K8sDeployment.SSH_PRIVATE_KEY) - self._runtime_config.set("ssh", - "user", - K8sDeployment.SSH_USER) - - # Section [rapid] - self._runtime_config.add_section("rapid") - self._runtime_config.set("rapid", - "total_number_of_machines", - self._total_number_of_pods) - - # Export information about each pod - # Sections [Mx] - for pod in self._pods: - self._runtime_config.add_section("M%d" % pod.get_id()) - self._runtime_config.set("M%d" % pod.get_id(), - "admin_ip", pod.get_admin_ip()) - self._runtime_config.set("M%d" % pod.get_id(), - "dp_mac1", pod.get_dp_mac()) - self._runtime_config.set("M%d" % pod.get_id(), - "dp_pci_dev", pod.get_dp_pci_dev()) - self._runtime_config.set("M%d" % pod.get_id(), - "dp_ip1", pod.get_dp_ip()) - - # Section [Varia] - self._runtime_config.add_section("Varia") - self._runtime_config.set("Varia", - "vim", - "kubernetes") - - # Write runtime config file - with open(config_file_name, "w") as file: - self._runtime_config.write(file) - - def delete_pods(self): - for pod in self._pods: - pod.terminate() diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/pod.py b/VNFs/DPPD-PROX/helper-scripts/rapid/pod.py deleted file mode 100644 index f663c9df..00000000 --- a/VNFs/DPPD-PROX/helper-scripts/rapid/pod.py +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/env python2.7 - -## -## Copyright (c) 2019 Intel Corporation -## -## 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. -## - -from os import path -import time, yaml -import logging -from kubernetes import client, config - -from sshclient import SSHClient - -class Pod: - """Class which represents test pods. - For example with traffic gen, forward/swap applications, etc - """ - k8s_CoreV1Api = None - - _log = None - - _name = "pod" - _namespace = "default" - _nodeSelector_hostname = None - _last_status = None - _id = None - _admin_ip = None - _dp_ip = None - - _ssh_client = None - - _sriov_vf = None - _sriov_vf_mac = None - - def __init__(self, name, namespace = "default", logger_name = "k8srapid"): - self._log = logging.getLogger(logger_name) - - self._name = name - self._namespace = namespace - self._ssh_client = SSHClient(logger_name = logger_name) - - def __del__(self): - """Destroy POD. Do a cleanup. - """ - if self._ssh_client is not None: - self._ssh_client.disconnect() - - def create_from_yaml(self, file_name): - """Load POD description from yaml file. - """ - with open(path.join(path.dirname(__file__), file_name)) as yaml_file: - self.body = yaml.safe_load(yaml_file) - - self.body["metadata"]["name"] = self._name - - if (self._nodeSelector_hostname is not None): - if ("nodeSelector" not in self.body["spec"]): - self.body["spec"]["nodeSelector"] = {} - self.body["spec"]["nodeSelector"]["kubernetes.io/hostname"] = self._nodeSelector_hostname - self._log.debug("Creating POD, body:\n%s" % self.body) - - try: - self.k8s_CoreV1Api.create_namespaced_pod(body = self.body, - namespace = self._namespace) - except client.rest.ApiException as e: - self._log.error("Couldn't create POD %s!\n%s\n" % (self._name, e)) - - def terminate(self): - """Terminate POD. Close SSH connection. - """ - if self._ssh_client is not None: - self._ssh_client.disconnect() - - try: - self.k8s_CoreV1Api.delete_namespaced_pod(name = self._name, - namespace = self._namespace) - except client.rest.ApiException as e: - if e.reason != "Not Found": - self._log.error("Couldn't delete POD %s!\n%s\n" % (self._name, e.reason)) - - def update_admin_ip(self): - """Check for admin IP address assigned by k8s. - """ - try: - pod = self.k8s_CoreV1Api.read_namespaced_pod_status(name = self._name, namespace = self._namespace) - self._admin_ip = pod.status.pod_ip - except client.rest.ApiException as e: - self._log.error("Couldn't update POD %s admin IP!\n%s\n" % (self._name, e)) - - def wait_for_start(self): - """Wait for POD to start. - """ - self._log.info("Waiting for POD %s to start..." % self._name) - while True: - self.get_status() - if (self._last_status == "Running" or self._last_status == "Failed" - or self._last_status == "Unknown"): - break - else: - time.sleep(3) - - self.update_admin_ip() - - return self._last_status - - def ssh_run_cmd(self, cmd): - """Execute command for POD via SSH connection. - SSH credentials should be configured before use of this function. - """ - self._ssh_client.run_cmd(cmd) - - def get_name(self): - return self._name - - def get_admin_ip(self): - return self._admin_ip - - def get_dp_ip(self): - return self._dp_ip - - def get_dp_mac(self): - return self._sriov_vf_mac - - def get_dp_pci_dev(self): - return self._sriov_vf - - def get_id(self): - return self._id - - def get_status(self): - """Get current status fro the pod. - """ - try: - pod = self.k8s_CoreV1Api.read_namespaced_pod_status(name = self._name, - namespace = self._namespace) - except client.rest.ApiException as e: - self._log.error("Couldn't read POD %s status!\n%s\n" % (self._name, e)) - - self._last_status = pod.status.phase - return self._last_status - - def get_sriov_dev_mac(self): - """Get assigned by k8s SRIOV network device plugin SRIOV VF devices. - Return 0 in case of sucessfull configuration. - Otherwise return -1. - """ - self._log.info("Checking assigned SRIOV VF for POD %s" % self._name) - ret = self._ssh_client.run_cmd("cat /opt/rapid/k8s_sriov_device_plugin_envs") - if ret != 0: - self._log.error("Failed to check assigned SRIOV VF!" - "Error %s" % self._ssh_client.get_error()) - return -1 - - cmd_output = self._ssh_client.get_output().decode("utf-8").rstrip() - self._log.debug("Environment variable %s" % cmd_output) - - # Parse environment variable - cmd_output = cmd_output.split("=")[1] - self._sriov_vf = cmd_output.split(",")[0] - self._log.debug("Using first SRIOV VF %s" % self._sriov_vf) - - self._log.info("Getting MAC address for assigned SRIOV VF %s" % self._sriov_vf) - self._ssh_client.run_cmd("sudo /opt/rapid/port_info_app -n 4 -w %s" % self._sriov_vf) - if ret != 0: - self._log.error("Failed to get MAC address!" - "Error %s" % self._ssh_client.get_error()) - return -1 - - # Parse MAC address - cmd_output = self._ssh_client.get_output().decode("utf-8").rstrip() - self._log.debug(cmd_output) - cmd_output = cmd_output.splitlines() - for line in cmd_output: - if line.startswith("Port 0 MAC: "): - self._sriov_vf_mac = line[12:] - - self._log.debug("MAC %s" % self._sriov_vf_mac) - - def set_dp_ip(self, dp_ip): - self._dp_ip = dp_ip - - def set_id(self, pod_id): - self._id = pod_id - - def set_nodeselector(self, hostname): - """Set hostname on which POD will be executed. - """ - self._nodeSelector_hostname = hostname - - def set_ssh_credentials(self, user, rsa_private_key): - """Set SSH credentials for the SSH connection to the POD. - """ - self.update_admin_ip() - self._ssh_client.set_credentials(ip = self._admin_ip, - user = user, - rsa_private_key = rsa_private_key) diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_k8s_deployment.py b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_k8s_deployment.py new file mode 100644 index 00000000..822ead51 --- /dev/null +++ b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_k8s_deployment.py @@ -0,0 +1,198 @@ +## +## Copyright (c) 2019-2020 Intel Corporation +## +## 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. +## + +import sys +from kubernetes import client, config +try: + import configparser +except ImportError: + # Python 2.x fallback + import ConfigParser as configparser +import logging +from logging import handlers + +from rapid_k8s_pod import Pod + +class K8sDeployment: + """Deployment class to create containers for test execution in Kubernetes + environment. + """ + LOG_FILE_NAME = "createrapidk8s.log" + SSH_PRIVATE_KEY = "./rapid_rsa_key" + SSH_USER = "centos" + + POD_YAML_TEMPLATE_FILE_NAME = "pod-rapid.yaml" + + _log = None + _create_config = None + _runtime_config = None + _total_number_of_pods = 0 + _pods = [] + + def __init__(self): + # Configure logger + self._log = logging.getLogger("k8srapid") + self._log.setLevel(logging.DEBUG) + + console_formatter = logging.Formatter("%(message)s") + console_handler = logging.StreamHandler(sys.stdout) + console_handler.setLevel(logging.DEBUG) + console_handler.setFormatter(console_formatter) + + file_formatter = logging.Formatter("%(asctime)s - " + "%(levelname)s - " + "%(message)s") + file_handler = logging.handlers.RotatingFileHandler(self.LOG_FILE_NAME, + backupCount=10) + file_handler.setLevel(logging.DEBUG) + file_handler.setFormatter(file_formatter) + + self._log.addHandler(file_handler) + self._log.addHandler(console_handler) + + # Initialize k8s plugin + config.load_kube_config() + Pod.k8s_CoreV1Api = client.CoreV1Api() + + def load_create_config(self, config_file_name): + """Read and parse configuration file for the test environment. + """ + self._log.info("Loading configuration file %s", config_file_name) + self._create_config = configparser.RawConfigParser() + try: + self._create_config.read(config_file_name) + except Exception as e: + self._log.error("Failed to read config file!\n%s\n" % e) + return -1 + + # Now parse config file content + # Parse [DEFAULT] section + if self._create_config.has_option("DEFAULT", "total_number_of_pods"): + self._total_number_of_pods = self._create_config.getint( + "DEFAULT", "total_number_of_pods") + else: + self._log.error("No option total_number_of_pods in DEFAULT section") + return -1 + + self._log.debug("Total number of pods %d" % self._total_number_of_pods) + + # Parse [PODx] sections + for i in range(1, int(self._total_number_of_pods) + 1): + # Search for POD name + if self._create_config.has_option("POD%d" % i, + "name"): + pod_name = self._create_config.get( + "POD%d" % i, "name") + else: + pod_name = "pod-rapid-%d" % i + + # Search for POD hostname + if self._create_config.has_option("POD%d" % i, + "nodeSelector_hostname"): + pod_nodeselector_hostname = self._create_config.get( + "POD%d" % i, "nodeSelector_hostname") + else: + pod_nodeselector_hostname = None + + # Search for POD dataplane static IP + if self._create_config.has_option("POD%d" % i, + "dp_ip"): + pod_dp_ip = self._create_config.get( + "POD%d" % i, "dp_ip") + else: + pod_dp_ip = None + + pod = Pod(pod_name) + pod.set_nodeselector(pod_nodeselector_hostname) + pod.set_dp_ip(pod_dp_ip) + pod.set_id(i) + + # Add POD to the list of PODs which need to be created + self._pods.append(pod) + + return 0 + + def create_pods(self): + """ Create test PODs and wait for them to start. + Collect information for tests to run. + """ + self._log.info("Creating PODs...") + + # Create PODs using template from yaml file + for pod in self._pods: + self._log.info("Creating POD %s...", pod.get_name()) + pod.create_from_yaml(K8sDeployment.POD_YAML_TEMPLATE_FILE_NAME) + + # Wait for PODs to start + for pod in self._pods: + pod.wait_for_start() + + # Collect information from started PODs for test execution + for pod in self._pods: + pod.set_ssh_credentials(K8sDeployment.SSH_USER, K8sDeployment.SSH_PRIVATE_KEY) + pod.get_sriov_dev_mac() + + def save_runtime_config(self, config_file_name): + self._log.info("Saving config %s for runrapid script...", + config_file_name) + self._runtime_config = configparser.RawConfigParser() + + # Section [DEFAULT] +# self._runtime_config.set("DEFAULT", +# "total_number_of_test_machines", +# self._total_number_of_pods) + + # Section [ssh] + self._runtime_config.add_section("ssh") + self._runtime_config.set("ssh", + "key", + K8sDeployment.SSH_PRIVATE_KEY) + self._runtime_config.set("ssh", + "user", + K8sDeployment.SSH_USER) + + # Section [rapid] + self._runtime_config.add_section("rapid") + self._runtime_config.set("rapid", + "total_number_of_machines", + self._total_number_of_pods) + + # Export information about each pod + # Sections [Mx] + for pod in self._pods: + self._runtime_config.add_section("M%d" % pod.get_id()) + self._runtime_config.set("M%d" % pod.get_id(), + "admin_ip", pod.get_admin_ip()) + self._runtime_config.set("M%d" % pod.get_id(), + "dp_mac1", pod.get_dp_mac()) + self._runtime_config.set("M%d" % pod.get_id(), + "dp_pci_dev", pod.get_dp_pci_dev()) + self._runtime_config.set("M%d" % pod.get_id(), + "dp_ip1", pod.get_dp_ip()) + + # Section [Varia] + self._runtime_config.add_section("Varia") + self._runtime_config.set("Varia", + "vim", + "kubernetes") + + # Write runtime config file + with open(config_file_name, "w") as file: + self._runtime_config.write(file) + + def delete_pods(self): + for pod in self._pods: + pod.terminate() diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_k8s_pod.py b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_k8s_pod.py new file mode 100644 index 00000000..b5fc8158 --- /dev/null +++ b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_k8s_pod.py @@ -0,0 +1,206 @@ +## +## Copyright (c) 2019 Intel Corporation +## +## 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. +## + +from os import path +import time, yaml +import logging +from kubernetes import client, config + +from rapid_sshclient import SSHClient + +class Pod: + """Class which represents test pods. + For example with traffic gen, forward/swap applications, etc + """ + k8s_CoreV1Api = None + + _log = None + + _name = "pod" + _namespace = "default" + _nodeSelector_hostname = None + _last_status = None + _id = None + _admin_ip = None + _dp_ip = None + + _ssh_client = None + + _sriov_vf = None + _sriov_vf_mac = None + + def __init__(self, name, namespace = "default", logger_name = "k8srapid"): + self._log = logging.getLogger(logger_name) + + self._name = name + self._namespace = namespace + self._ssh_client = SSHClient(logger_name = logger_name) + + def __del__(self): + """Destroy POD. Do a cleanup. + """ + if self._ssh_client is not None: + self._ssh_client.disconnect() + + def create_from_yaml(self, file_name): + """Load POD description from yaml file. + """ + with open(path.join(path.dirname(__file__), file_name)) as yaml_file: + self.body = yaml.safe_load(yaml_file) + + self.body["metadata"]["name"] = self._name + + if (self._nodeSelector_hostname is not None): + if ("nodeSelector" not in self.body["spec"]): + self.body["spec"]["nodeSelector"] = {} + self.body["spec"]["nodeSelector"]["kubernetes.io/hostname"] = self._nodeSelector_hostname + self._log.debug("Creating POD, body:\n%s" % self.body) + + try: + self.k8s_CoreV1Api.create_namespaced_pod(body = self.body, + namespace = self._namespace) + except client.rest.ApiException as e: + self._log.error("Couldn't create POD %s!\n%s\n" % (self._name, e)) + + def terminate(self): + """Terminate POD. Close SSH connection. + """ + if self._ssh_client is not None: + self._ssh_client.disconnect() + + try: + self.k8s_CoreV1Api.delete_namespaced_pod(name = self._name, + namespace = self._namespace) + except client.rest.ApiException as e: + if e.reason != "Not Found": + self._log.error("Couldn't delete POD %s!\n%s\n" % (self._name, e.reason)) + + def update_admin_ip(self): + """Check for admin IP address assigned by k8s. + """ + try: + pod = self.k8s_CoreV1Api.read_namespaced_pod_status(name = self._name, namespace = self._namespace) + self._admin_ip = pod.status.pod_ip + except client.rest.ApiException as e: + self._log.error("Couldn't update POD %s admin IP!\n%s\n" % (self._name, e)) + + def wait_for_start(self): + """Wait for POD to start. + """ + self._log.info("Waiting for POD %s to start..." % self._name) + while True: + self.get_status() + if (self._last_status == "Running" or self._last_status == "Failed" + or self._last_status == "Unknown"): + break + else: + time.sleep(3) + + self.update_admin_ip() + + return self._last_status + + def ssh_run_cmd(self, cmd): + """Execute command for POD via SSH connection. + SSH credentials should be configured before use of this function. + """ + self._ssh_client.run_cmd(cmd) + + def get_name(self): + return self._name + + def get_admin_ip(self): + return self._admin_ip + + def get_dp_ip(self): + return self._dp_ip + + def get_dp_mac(self): + return self._sriov_vf_mac + + def get_dp_pci_dev(self): + return self._sriov_vf + + def get_id(self): + return self._id + + def get_status(self): + """Get current status fro the pod. + """ + try: + pod = self.k8s_CoreV1Api.read_namespaced_pod_status(name = self._name, + namespace = self._namespace) + except client.rest.ApiException as e: + self._log.error("Couldn't read POD %s status!\n%s\n" % (self._name, e)) + + self._last_status = pod.status.phase + return self._last_status + + def get_sriov_dev_mac(self): + """Get assigned by k8s SRIOV network device plugin SRIOV VF devices. + Return 0 in case of sucessfull configuration. + Otherwise return -1. + """ + self._log.info("Checking assigned SRIOV VF for POD %s" % self._name) + ret = self._ssh_client.run_cmd("cat /opt/rapid/k8s_sriov_device_plugin_envs") + if ret != 0: + self._log.error("Failed to check assigned SRIOV VF!" + "Error %s" % self._ssh_client.get_error()) + return -1 + + cmd_output = self._ssh_client.get_output().decode("utf-8").rstrip() + self._log.debug("Environment variable %s" % cmd_output) + + # Parse environment variable + cmd_output = cmd_output.split("=")[1] + self._sriov_vf = cmd_output.split(",")[0] + self._log.debug("Using first SRIOV VF %s" % self._sriov_vf) + + self._log.info("Getting MAC address for assigned SRIOV VF %s" % self._sriov_vf) + self._ssh_client.run_cmd("sudo /opt/rapid/port_info_app -n 4 -w %s" % self._sriov_vf) + if ret != 0: + self._log.error("Failed to get MAC address!" + "Error %s" % self._ssh_client.get_error()) + return -1 + + # Parse MAC address + cmd_output = self._ssh_client.get_output().decode("utf-8").rstrip() + self._log.debug(cmd_output) + cmd_output = cmd_output.splitlines() + for line in cmd_output: + if line.startswith("Port 0 MAC: "): + self._sriov_vf_mac = line[12:] + + self._log.debug("MAC %s" % self._sriov_vf_mac) + + def set_dp_ip(self, dp_ip): + self._dp_ip = dp_ip + + def set_id(self, pod_id): + self._id = pod_id + + def set_nodeselector(self, hostname): + """Set hostname on which POD will be executed. + """ + self._nodeSelector_hostname = hostname + + def set_ssh_credentials(self, user, rsa_private_key): + """Set SSH credentials for the SSH connection to the POD. + """ + self.update_admin_ip() + self._ssh_client.set_credentials(ip = self._admin_ip, + user = user, + rsa_private_key = rsa_private_key) diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_sshclient.py b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_sshclient.py new file mode 100644 index 00000000..e9fe134c --- /dev/null +++ b/VNFs/DPPD-PROX/helper-scripts/rapid/rapid_sshclient.py @@ -0,0 +1,111 @@ +## +## Copyright (c) 2019 Intel Corporation +## +## 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. +## + +import paramiko +import logging + +class SSHClient: + """Wrapper class for paramiko module to connect via SSH + """ + _log = None + + _ip = None + _user = None + _rsa_private_key = None + _timeout = None + _ssh = None + _connected = False + + _output = None + _error = None + + def __init__(self, ip=None, user=None, rsa_private_key=None, timeout=15, logger_name=None): + self._ip = ip + self._user = user + self._rsa_private_key = rsa_private_key + self._timeout = timeout + + if (logger_name is not None): + self._log = logging.getLogger(logger_name) + + self._connected = False + + def set_credentials(self, ip, user, rsa_private_key): + self._ip = ip + self._user = user + self._rsa_private_key = rsa_private_key + + def connect(self): + if self._connected: + if (self._log is not None): + self._log.debug("Already connected!") + return + + if ((self._ip is None) or (self._user is None) or + (self._rsa_private_key is None)): + if (self._log is not None): + self._log.error("Wrong parameter! IP %s, user %s, RSA private key %s" + % (self._ip, self._user, self._rsa_private_key)) + self._connected = False + return + + self._ssh = paramiko.SSHClient() + self._ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + private_key = paramiko.RSAKey.from_private_key_file(self._rsa_private_key) + + try: + self._ssh.connect(hostname = self._ip, username = self._user, pkey = private_key) + except Exception as e: + if (self._log is not None): + self._log.error("Failed to connect to the host! IP %s, user %s, RSA private key %s\n%s" + % (self._ip, self._user, self._rsa_private_key, e)) + self._connected = False + self._ssh.close() + return + + self._connected = True + + def disconnect(self): + if self._connected: + self._connected = False + self._ssh.close() + + def run_cmd(self, cmd): + self.connect() + + if self._connected is not True: + return -1 + + try: + ret = 0 + _stdin, stdout, stderr = self._ssh.exec_command(cmd, timeout = self._timeout) + self._output = stdout.read() + self._error = stderr.read() + except Exception as e: + if (self._log is not None): + self._log.error("Failed to execute command! IP %s, cmd %s\n%s" + % (self._ip, cmd, e)) + ret = -1 + + self.disconnect() + + return ret + + def get_output(self): + return self._output + + def get_error(self): + return self._error diff --git a/VNFs/DPPD-PROX/helper-scripts/rapid/sshclient.py b/VNFs/DPPD-PROX/helper-scripts/rapid/sshclient.py deleted file mode 100644 index c781271e..00000000 --- a/VNFs/DPPD-PROX/helper-scripts/rapid/sshclient.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python2.7 - -## -## Copyright (c) 2019 Intel Corporation -## -## 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. -## - -import paramiko -import logging - -class SSHClient: - """Wrapper class for paramiko module to connect via SSH - """ - _log = None - - _ip = None - _user = None - _rsa_private_key = None - _timeout = None - _ssh = None - _connected = False - - _output = None - _error = None - - def __init__(self, ip=None, user=None, rsa_private_key=None, timeout=15, logger_name=None): - self._ip = ip - self._user = user - self._rsa_private_key = rsa_private_key - self._timeout = timeout - - if (logger_name is not None): - self._log = logging.getLogger(logger_name) - - self._connected = False - - def set_credentials(self, ip, user, rsa_private_key): - self._ip = ip - self._user = user - self._rsa_private_key = rsa_private_key - - def connect(self): - if self._connected: - if (self._log is not None): - self._log.debug("Already connected!") - return - - if ((self._ip is None) or (self._user is None) or - (self._rsa_private_key is None)): - if (self._log is not None): - self._log.error("Wrong parameter! IP %s, user %s, RSA private key %s" - % (self._ip, self._user, self._rsa_private_key)) - self._connected = False - return - - self._ssh = paramiko.SSHClient() - self._ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) - private_key = paramiko.RSAKey.from_private_key_file(self._rsa_private_key) - - try: - self._ssh.connect(hostname = self._ip, username = self._user, pkey = private_key) - except Exception as e: - if (self._log is not None): - self._log.error("Failed to connect to the host! IP %s, user %s, RSA private key %s\n%s" - % (self._ip, self._user, self._rsa_private_key, e)) - self._connected = False - self._ssh.close() - return - - self._connected = True - - def disconnect(self): - if self._connected: - self._connected = False - self._ssh.close() - - def run_cmd(self, cmd): - self.connect() - - if self._connected is not True: - return -1 - - try: - ret = 0 - _stdin, stdout, stderr = self._ssh.exec_command(cmd, timeout = self._timeout) - self._output = stdout.read() - self._error = stderr.read() - except Exception as e: - if (self._log is not None): - self._log.error("Failed to execute command! IP %s, cmd %s\n%s" - % (self._ip, cmd, e)) - ret = -1 - - self.disconnect() - - return ret - - def get_output(self): - return self._output - - def get_error(self): - return self._error -- cgit 1.2.3-korg