blob: 40a157bb42a0ccb1428c63d6b1e70c6f7645720c [file] [log] [blame]
#!/usr/bin/env python
##############################################################################
# Copyright 2018 EuropeanSoftwareMarketingLtd.
# ===================================================================
# Licensed under the ApacheLicense, Version2.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
#
# 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
##############################################################################
# vnftest comment: this is a modified copy of
# yardstick/cmd/NSBperf.py
"""NSBPERF main script.
"""
from __future__ import absolute_import
from __future__ import print_function
import os
import argparse
import json
import subprocess
import signal
from oslo_serialization import jsonutils
from six.moves import input
CLI_PATH = os.path.dirname(os.path.realpath(__file__))
REPO_PATH = os.path.abspath(os.path.join(CLI_PATH, os.pardir))
def sigint_handler(*args, **kwargs):
""" Capture ctrl+c and exit cli """
subprocess.call(["pkill", "-9", "vnftest"])
raise SystemExit(1)
class VnftestNSCli(object):
""" This class handles vnftest network serivce testing """
def __init__(self):
super(VnftestNSCli, self).__init__()
@classmethod
def validate_input(cls, choice, choice_len):
""" Validate user inputs """
if not str(choice):
return 1
choice = int(choice)
if not 1 <= choice <= choice_len:
print("\nInvalid wrong choice...")
input("Press Enter to continue...")
return 1
subprocess.call(['clear'])
return 0
@classmethod
def parse_arguments(cls):
"""
Parse command line arguments.
"""
parser = \
argparse.ArgumentParser(
prog=__file__,
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('--version', action='version',
version='%(prog)s 0.1')
parser.add_argument('--list', '--list-tests', action='store_true',
help='list all tests and exit')
parser.add_argument('--list-vnfs', action='store_true',
help='list all system vnfs and exit')
group = parser.add_argument_group('test selection options')
group.add_argument('--vnf', help='vnf to use')
group.add_argument('--test', help='test in use')
args = vars(parser.parse_args())
return args
@classmethod
def generate_kpi_results(cls, tkey, tgen):
""" Generate report for vnf & traffic generator kpis """
if tgen:
print("\n%s stats" % tkey)
print("----------------------------")
for key, value in tgen.items():
if key != "collect_stats":
print(json.dumps({key: value}, indent=2))
@classmethod
def generate_nfvi_results(cls, nfvi):
""" Generate report for vnf & traffic generator kpis """
if nfvi:
nfvi_kpi = {k: v for k, v in nfvi.items() if k == 'collect_stats'}
if nfvi_kpi:
print("\nNFVi stats")
print("----------------------------")
for key, value in nfvi_kpi.items():
print(json.dumps({key: value}, indent=2))
def generate_final_report(self, test_case):
""" Function will check if partial test results are available
and generates final report in rst format.
"""
tc_name = os.path.splitext(test_case)[0]
report_caption = '{}\n{} ({})\n{}\n\n'.format(
'================================================================',
'Performance report for', tc_name.upper(),
'================================================================')
print(report_caption)
if os.path.isfile("/tmp/vnftest.out"):
lines = []
with open("/tmp/vnftest.out") as infile:
lines = jsonutils.load(infile)
if lines:
lines = \
lines['result']["testcases"][tc_name]["tc_data"]
tc_res = lines.pop(len(lines) - 1)
for key, value in tc_res["data"].items():
self.generate_kpi_results(key, value)
self.generate_nfvi_results(value)
@classmethod
def handle_list_options(cls, args, test_path):
""" Process --list cli arguments if needed
:param args: A dictionary with all CLI arguments
"""
if args['list_vnfs']:
vnfs = os.listdir(test_path)
print("VNF :")
print("================")
for index, vnf in enumerate(vnfs, 1):
print((' %-2s %s' % ('%s:' % str(index), vnf)))
raise SystemExit(0)
if args['list']:
vnfs = os.listdir(test_path)
print("Available Tests:")
print("*****************")
for vnf in vnfs:
testcases = os.listdir(test_path + vnf)
print(("VNF :(%s)" % vnf))
print("================")
test_cases = [tc for tc in testcases if "tc_" in tc and "template" not in tc]
print("\tBareMetal Testcase:")
print("\t===================")
for testcase in [tc for tc in test_cases if "baremetal" in tc]:
print("\t%s" % testcase)
print(os.linesep)
print("\tStandalone Virtualization Testcase:")
print("\t===================================")
for testcase in [tc for tc in test_cases if "ovs" in tc or "sriov" in tc]:
print("\t%s" % testcase)
print(os.linesep)
print("\tOpenstack Testcase:")
print("\t===================")
for testcase in [tc for tc in test_cases if "heat" in tc]:
print("\t%s" % testcase)
print(os.linesep)
raise SystemExit(0)
@classmethod
def terminate_if_less_options(cls, args):
""" terminate cli if cmdline options is invalid """
if not (args["vnf"] and args["test"]):
print("CLI needs option, make sure to pass vnf, test")
print("eg: NSBperf.py --vnf <vnf untertest> --test <test yaml>")
raise SystemExit(1)
def run_test(self, args, test_path):
""" run requested test """
try:
vnf = args.get("vnf", "")
test = args.get("test", "")
vnf_dir = test_path + os.sep + vnf
if not os.path.exists(vnf_dir):
raise ValueError("'%s', vnf not supported." % vnf)
testcases = [tc for tc in os.listdir(vnf_dir) if "tc" in tc]
subtest = set([test]).issubset(testcases)
if not subtest:
raise ValueError("'%s', testcase not supported." % test)
os.chdir(vnf_dir)
# fixme: Use REST APIs to initiate testcases
subprocess.check_output(["vnftest", "--debug",
"task", "start", test])
self.generate_final_report(test)
except (IOError, ValueError):
print("Value/I/O error...")
except BaseException:
print("Test failed. Please verify test inputs & re-run the test..")
print("eg: NSBperf.py --vnf <vnf untertest> --test <test yaml>")
def main(self):
"""Main function.
"""
test_path = os.path.join(REPO_PATH, "../samples/vnf_samples/nsut/")
os.chdir(os.path.join(REPO_PATH, "../"))
args = self.parse_arguments()
# if required, handle list-* operations
self.handle_list_options(args, test_path)
# check for input params
self.terminate_if_less_options(args)
# run test
self.run_test(args, test_path)
if __name__ == "__main__":
signal.signal(signal.SIGINT, sigint_handler)
NS_CLI = VnftestNSCli()
NS_CLI.main()