##
## 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
_dp_subnet = 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_subnet(self):
return self._dp_subnet
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"{
"__inputs": [
{
"name": "DS_YARDSTICK",
"label": "yardstick",
"description": "",
"type": "datasource",
"pluginId": "influxdb",
"pluginName": "InfluxDB"
}
],
"__requires": [
{
"type": "grafana",
"id": "grafana",
"name": "Grafana",
"version": "4.4.3"
},
{
"type": "panel",
"id": "graph",
"name": "Graph",
"version": ""
},
{
"type": "datasource",
"id": "influxdb",
"name": "InfluxDB",
"version": "1.0.0"
},
{
"type": "panel",
"id": "text",
"name": "Text",
"version": ""
}
],
"annotations": {
"list": []
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"hideControls": false,
"id": null,
"links": [],
"refresh": false,
"rows": [
{
"collapse": false,
"height": "25px",
"panels": [
{
"content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 32px '#31A7D3'\"><center>OPNFV_Yardstick_NSB_PROX_BM_LB_1to4Port</center> </a></h5>\n<center>\n<p>This transmits random packets on 1 port, and received them on 4 ports. The KPI is the number of packets per second with an accepted minimal packet loss for a specified packet size</p>\n</center>",
"editable": true,
"error": false,
"height": "25",
"id": 3,
"links": [],
"mode": "html",
"span": 12,
"title": "",
"type": "text"
},
{
"content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 22px '#31A7D3'\"><center>Prox Load Balancer VNF stats</center> </a></h5>\n",
"editable": true,
"error": false,
"height": "40",
"id": 7,
"links": [],
"mode": "html",
"span": 12,
"title": "",
"type": "text"
}
],
"repeat": null,
"repeatIteration": null,
"repeatRowId": null,
"showTitle": false,
"title": "Row",
"titleSize": "h6"
},
{
"collapse": false,
"height": "300px",
"panels": [
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_YARDSTICK}",
"editable": true,
"error": false,
"fill": 1,
"grid": {},
"height": "300",
"id": 10,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": true,
"rightSide": false,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"percentage": false,
"pointradius": 1,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"span": 12,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "VNF packets Forward",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tc_prox_baremetal_lb-4",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"vnf__0.packets_fwd"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
},
{
"alias": "VNF packets in",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tc_prox_baremetal_lb-4",
"orderByTime": "ASC",
"policy": "default",
"refId": "C",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"vnf__0.packets_in"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
},
{
"alias": "VNF packets dropped",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tc_prox_baremetal_lb-4",
"orderByTime": "ASC",
"policy": "default",
"refId": "B",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"vnf__0.packets_dropped"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [
{
"colorMode": "custom",
"fill": true,
"fillColor": "rgba(216, 200, 27, 0.27)",
"op": "gt",
"value": 2.5
},
{
"colorMode": "custom",
"fill": true,
"fillColor": "rgba(234, 112, 112, 0.22)",
"op": "gt",
"value": 2.5
}
],
"timeFrom": null,
"timeShift": null,
"title": "Load Balancer VNF stats",
"tooltip": {
"msResolution": true,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": "Packets",
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
]
}
],
"repeat": null,
"repeatIteration": null,
"repeatRowId": null,
"showTitle": false,
"title": "New row",
"titleSize": "h6"
},
{
"collapse": false,
"height": "300px",
"panels": [
{
"content": "<h5 style=\"font-family:Verdana\"> <a style=\"color:#31A7D3\"><a style=\"font: 22px '#31A7D3'\"><center>Prox Load Balancer Traffic Gen stats</center> </a></h5>\n",
"editable": true,
"error": false,
"height": "40",
"id": 8,
"links": [],
"mode": "html",
"span": 12,
"title": "",
"type": "text"
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_YARDSTICK}",
"editable": true,
"error": false,
"fill": 1,
"grid": {},
"id": 6,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": true,
"rightSide": false,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"span": 6,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "TG xe-0 Out packets",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tc_prox_baremetal_lb-4",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"tg__0.xe0.out_packets"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
},
{
"alias": "TG xe-1 Out packets",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tc_prox_baremetal_lb-4",
"orderByTime": "ASC",
"policy": "default",
"refId": "B",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"tg__0.xe1.out_packets"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
},
{
"alias": "TG xe-2 Out packets",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tc_prox_baremetal_lb-4",
"orderByTime": "ASC",
"policy": "default",
"refId": "C",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"tg__0.xe2.out_packets"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
},
{
"alias": "TG xe-3 Out packets",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tc_prox_baremetal_lb-4",
"orderByTime": "ASC",
"policy": "default",
"refId": "D",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"tg__0.xe3.out_packets"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [
{
"colorMode": "custom",
"fill": true,
"fillColor": "rgba(216, 200, 27, 0.27)",
"op": "gt",
"value": 2.5
},
{
"colorMode": "custom",
"fill": true,
"fillColor": "rgba(234, 112, 112, 0.22)",
"op": "gt",
"value": 2.5
}
],
"timeFrom": null,
"timeShift": null,
"title": "TG Port Stats: Out packets",
"tooltip": {
"msResolution": true,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": "Packets",
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
]
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_YARDSTICK}",
"editable": true,
"error": false,
"fill": 1,
"grid": {},
"id": 9,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"span": 6,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "TG xe-0 in packets",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tc_prox_baremetal_lb-4",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"tg__0.xe0.in_packets"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
},
{
"alias": "TG xe-1 in packets",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tc_prox_baremetal_lb-4",
"orderByTime": "ASC",
"policy": "default",
"refId": "B",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"tg__0.xe1.in_packets"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
},
{
"alias": "TG xe-2 in packets",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tc_prox_baremetal_lb-4",
"orderByTime": "ASC",
"policy": "default",
"refId": "C",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"tg__0.xe2.in_packets"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
},
{
"alias": "TG xe-3 in packets",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tc_prox_baremetal_lb-4",
"orderByTime": "ASC",
"policy": "default",
"refId": "D",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"tg__0.xe3.in_packets"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [
{
"colorMode": "custom",
"fill": true,
"fillColor": "rgba(216, 200, 27, 0.27)",
"op": "gt",
"value": 2.5
},
{
"colorMode": "custom",
"fill": true,
"fillColor": "rgba(234, 112, 112, 0.22)",
"op": "gt",
"value": 2.5
}
],
"timeFrom": null,
"timeShift": null,
"title": "TG Port Stats: In packets",
"tooltip": {
"msResolution": true,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": "Packets",
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
]
}
],
"repeat": null,
"repeatIteration": null,
"repeatRowId": null,
"showTitle": false,
"title": "New row",
"titleSize": "h6"
},
{
"collapse": false,
"height": "250px",
"panels": [
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_YARDSTICK}",
"editable": true,
"error": false,
"fill": 1,
"grid": {},
"id": 2,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"span": 6,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "TG TX Throughput",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tc_prox_baremetal_lb-4",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"tg__0.TxThroughput"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
},
{
"alias": "TG RX Throughput",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tc_prox_baremetal_lb-4",
"orderByTime": "ASC",
"policy": "default",
"refId": "B",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"tg__0.RxThroughput"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [
{
"colorMode": "custom",
"fill": true,
"fillColor": "rgba(216, 200, 27, 0.27)",
"op": "gt",
"value": 2.5
},
{
"colorMode": "custom",
"fill": true,
"fillColor": "rgba(234, 112, 112, 0.22)",
"op": "gt",
"value": 2.5
}
],
"timeFrom": null,
"timeShift": null,
"title": "TG Tx vs Rx Throughput",
"tooltip": {
"msResolution": true,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": "Throughput in MPPS",
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
]
},
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": "${DS_YARDSTICK}",
"editable": true,
"error": false,
"fill": 1,
"grid": {},
"id": 5,
"legend": {
"alignAsTable": true,
"avg": true,
"current": false,
"max": true,
"min": true,
"show": true,
"total": false,
"values": true
},
"lines": true,
"linewidth": 2,
"links": [],
"nullPointMode": "connected",
"percentage": false,
"pointradius": 5,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"span": 6,
"stack": false,
"steppedLine": false,
"targets": [
{
"alias": "TG Packet Size",
"dsType": "influxdb",
"groupBy": [
{
"params": [
"$interval"
],
"type": "time"
},
{
"params": [
"null"
],
"type": "fill"
}
],
"measurement": "tc_prox_baremetal_lb-4",
"orderByTime": "ASC",
"policy": "default",
"refId": "A",
"resultFormat": "time_series",
"select": [
[
{
"params": [
"tg__0.PktSize"
],
"type": "field"
},
{
"params": [],
"type": "mean"
}
]
],
"tags": []
}
],
"thresholds": [
{
"colorMode": "custom",
"fill": true,
"fillColor": "rgba(216, 200, 27, 0.27)",
"op": "gt",
"value": 2.5
},
{
"colorMode": "custom",
"fill": true,
"fillColor": "rgba(234, 112, 112, 0.22)",
"op": "gt",
"value": 2.5
}
],
"timeFrom": null,
"timeShift": null,
"title": "TG Packet size",
"tooltip": {
"msResolution": true,
"shared": true,
"sort": 0,
"value_type": "cumulative"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "decbytes",
"label": "Packet Size",
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
]
}
],
"repeat": null,
"repeatIteration": null,
"repeatRowId": null,
"showTitle": false,
"title": "New row",
"titleSize": "h6"
}
],
"schemaVersion": 14,
"style": "dark",
"tags": [
"yardstick",
"NSB",
"Prox",
"4Port",
"BM",
"LB"
],
"templating": {
"list": []
},
"time": {
"from": "2017-10-10T13:42:45.059Z",
"to": "2017-10-10T13:48:35.750Z"
},
"timepicker": {
"refresh_intervals": [
"5s",
"10s",
"30s",
"1m",
"5m",
"15m",
"30m",
"1h",
"2h",
"1d"
],
"time_options": [
"5m",
"15m",
"1h",
"6h",
"12h",
"24h",
"2d",
"7d",
"30d"
]
},
"timezone": "browser",
"title": "Prox_BM_LB_1to4-4Port",
"version": 10
}