2 # Copyright (c) 2016-2017 Intel Corporation
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
8 # http://www.apache.org/licenses/LICENSE-2.0
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.
17 """NSBPERF main script.
20 from __future__ import absolute_import
21 from __future__ import print_function
28 CLI_PATH = os.path.dirname(os.path.realpath(__file__))
29 REPO_PATH = os.path.abspath(os.path.join(CLI_PATH, os.pardir))
30 PYTHONPATH = os.environ.get("PYTHONPATH", False)
31 VIRTUAL_ENV = os.environ.get("VIRTUAL_ENV", False)
33 if not PYTHONPATH or not VIRTUAL_ENV:
34 print("Please setup env PYTHONPATH & VIRTUAL_ENV environment varaible.")
39 """ Capture ctrl+c and exit cli """
40 subprocess.call(["pkill", "-9", "yardstick"])
43 signal.signal(signal.SIGINT, handler)
46 class YardstickNSCli(object):
47 """ This class handles yardstick network serivce testing """
50 super(YardstickNSCli, self).__init__()
53 def validate_input(cls, choice, choice_len):
54 """ Validate user inputs """
59 if not 1 <= choice <= choice_len:
60 print("\nInvalid wrong choice...")
61 raw_input("Press Enter to continue...")
63 subprocess.call(['clear'])
67 def parse_arguments(cls):
69 Parse command line arguments.
72 argparse.ArgumentParser(
74 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
75 parser.add_argument('--version', action='version',
76 version='%(prog)s 0.1')
77 parser.add_argument('--list', '--list-tests', action='store_true',
78 help='list all tests and exit')
79 parser.add_argument('--list-vnfs', action='store_true',
80 help='list all system vnfs and exit')
82 group = parser.add_argument_group('test selection options')
83 group.add_argument('--vnf', help='vnf to use')
84 group.add_argument('--test', help='test in use')
86 args = vars(parser.parse_args())
91 def generate_kpi_results(cls, tkey, tgen):
92 """ Generate report for vnf & traffic generator kpis """
94 print("\n%s stats" % tkey)
95 print("----------------------------")
96 for key, value in tgen.items():
97 if key != "collect_stats":
98 print(json.dumps({key: value}, indent=2))
101 def generate_nfvi_results(cls, nfvi):
102 """ Generate report for vnf & traffic generator kpis """
104 nfvi_kpi = {k: v for k, v in nfvi.items() if k == 'collect_stats'}
106 print("\nNFVi stats")
107 print("----------------------------")
108 for key, value in nfvi_kpi.items():
109 print(json.dumps({key: value}, indent=2))
111 def generate_final_report(self, test_case):
112 """ Function will check if partial test results are available
113 and generates final report in rst format.
116 report_caption = '{}\n{} ({})\n{}\n\n'.format(
117 '================================================================',
118 'Performance report for',
119 os.path.splitext(test_case)[0].upper(),
120 '================================================================')
121 print(report_caption)
122 if os.path.isfile("/tmp/yardstick.out"):
124 with open("/tmp/yardstick.out") as infile:
125 lines = infile.readlines()
128 tc_res = json.loads(lines.pop(len(lines) - 1))
129 for key, value in tc_res["benchmark"]["data"].items():
130 self.generate_kpi_results(key, value)
131 self.generate_nfvi_results(value)
134 def handle_list_options(cls, args, test_path):
135 """ Process --list cli arguments if needed
137 :param args: A dictionary with all CLI arguments
139 if args['list_vnfs']:
140 vnfs = os.listdir(test_path)
142 print("================")
143 for index, vnf in enumerate(vnfs, 1):
144 print((' %-2s %s' % ('%s:' % str(index), vnf)))
148 vnfs = os.listdir(test_path)
150 print("Available Tests:")
151 print("*****************")
153 testcases = os.listdir(test_path + vnf)
154 print(("VNF :(%s)" % vnf))
155 print("================")
156 for testcase in [tc for tc in testcases if "tc" in tc]:
157 print('%s' % testcase)
162 def terminate_if_less_options(cls, args):
163 """ terminate cli if cmdline options is invalid """
164 if not (args["vnf"] and args["test"]):
165 print("CLI needs option, make sure to pass vnf, test")
166 print("eg: NSBperf.py --vnf <vnf untertest> --test <test yaml>")
169 def run_test(self, args, test_path):
170 """ run requested test """
172 vnf = args.get("vnf", "")
173 test = args.get("test", "")
175 vnf_dir = test_path + os.sep + vnf
176 if not os.path.exists(vnf_dir):
177 raise ValueError("'%s', vnf not supported." % vnf)
179 testcases = [tc for tc in os.listdir(vnf_dir) if "tc" in tc]
180 subtest = set([test]).issubset(testcases)
182 raise ValueError("'%s', testcase not supported." % test)
185 # fixme: Use REST APIs to initiate testcases
186 subprocess.check_output(["yardstick", "--debug",
187 "task", "start", test])
188 self.generate_final_report(test)
189 except (IOError, ValueError):
190 print("Value/I/O error...")
191 except BaseException:
192 print("Test failed. Please verify test inputs & re-run the test..")
193 print("eg: NSBperf.py --vnf <vnf untertest> --test <test yaml>")
198 test_path = os.path.join(REPO_PATH, "../samples/vnf_samples/nsut/")
199 os.chdir(os.path.join(REPO_PATH, "../"))
200 args = self.parse_arguments()
202 # if required, handle list-* operations
203 self.handle_list_options(args, test_path)
205 # check for input params
206 self.terminate_if_less_options(args)
209 self.run_test(args, test_path)
211 if __name__ == "__main__":
212 NS_CLI = YardstickNSCli()