Bugfix: kubernetes context do not implement _get_network
[yardstick.git] / yardstick / cmd / NSBperf.py
1 #!/usr/bin/env python
2 # Copyright (c) 2016-2017 Intel Corporation
3 #
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
7 #
8 #      http://www.apache.org/licenses/LICENSE-2.0
9 #
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.
15
16
17 """NSBPERF main script.
18 """
19
20 from __future__ import absolute_import
21 from __future__ import print_function
22 import os
23 import argparse
24 import json
25 import subprocess
26 import signal
27 from oslo_serialization import jsonutils
28
29 from six.moves import input
30
31 CLI_PATH = os.path.dirname(os.path.realpath(__file__))
32 REPO_PATH = os.path.abspath(os.path.join(CLI_PATH, os.pardir))
33 PYTHONPATH = os.environ.get("PYTHONPATH", False)
34 VIRTUAL_ENV = os.environ.get("VIRTUAL_ENV", False)
35
36
37 if not PYTHONPATH or not VIRTUAL_ENV:
38     print("Please setup env PYTHONPATH & VIRTUAL_ENV environment varaible.")
39     raise SystemExit(1)
40
41
42 def sigint_handler(*args, **kwargs):
43     """ Capture ctrl+c and exit cli """
44     subprocess.call(["pkill", "-9", "yardstick"])
45     raise SystemExit(1)
46
47
48 class YardstickNSCli(object):
49     """ This class handles yardstick network serivce testing """
50
51     def __init__(self):
52         super(YardstickNSCli, self).__init__()
53
54     @classmethod
55     def validate_input(cls, choice, choice_len):
56         """ Validate user inputs """
57         if not str(choice):
58             return 1
59
60         choice = int(choice)
61         if not 1 <= choice <= choice_len:
62             print("\nInvalid wrong choice...")
63             input("Press Enter to continue...")
64             return 1
65         subprocess.call(['clear'])
66         return 0
67
68     @classmethod
69     def parse_arguments(cls):
70         """
71         Parse command line arguments.
72         """
73         parser = \
74             argparse.ArgumentParser(
75                 prog=__file__,
76                 formatter_class=argparse.ArgumentDefaultsHelpFormatter)
77         parser.add_argument('--version', action='version',
78                             version='%(prog)s 0.1')
79         parser.add_argument('--list', '--list-tests', action='store_true',
80                             help='list all tests and exit')
81         parser.add_argument('--list-vnfs', action='store_true',
82                             help='list all system vnfs and exit')
83
84         group = parser.add_argument_group('test selection options')
85         group.add_argument('--vnf', help='vnf to use')
86         group.add_argument('--test', help='test in use')
87
88         args = vars(parser.parse_args())
89
90         return args
91
92     @classmethod
93     def generate_kpi_results(cls, tkey, tgen):
94         """ Generate report for vnf & traffic generator kpis """
95         if tgen:
96             print("\n%s stats" % tkey)
97             print("----------------------------")
98             for key, value in tgen.items():
99                 if key != "collect_stats":
100                     print(json.dumps({key: value}, indent=2))
101
102     @classmethod
103     def generate_nfvi_results(cls, nfvi):
104         """ Generate report for vnf & traffic generator kpis """
105         if nfvi:
106             nfvi_kpi = {k: v for k, v in nfvi.items() if k == 'collect_stats'}
107             if nfvi_kpi:
108                 print("\nNFVi stats")
109                 print("----------------------------")
110                 for key, value in nfvi_kpi.items():
111                     print(json.dumps({key: value}, indent=2))
112
113     def generate_final_report(self, test_case):
114         """ Function will check if partial test results are available
115         and generates final report in rst format.
116         """
117
118         report_caption = '{}\n{} ({})\n{}\n\n'.format(
119             '================================================================',
120             'Performance report for',
121             os.path.splitext(test_case)[0].upper(),
122             '================================================================')
123         print(report_caption)
124         if os.path.isfile("/tmp/yardstick.out"):
125             lines = []
126             with open("/tmp/yardstick.out") as infile:
127                 lines = jsonutils.load(infile)
128
129             if lines:
130                 lines = lines['result']
131                 tc_res = lines.pop(len(lines) - 1)
132                 for key, value in tc_res["benchmark"]["data"].items():
133                     self.generate_kpi_results(key, value)
134                     self.generate_nfvi_results(value)
135
136     @classmethod
137     def handle_list_options(cls, args, test_path):
138         """ Process --list cli arguments if needed
139
140         :param args: A dictionary with all CLI arguments
141         """
142         if args['list_vnfs']:
143             vnfs = os.listdir(test_path)
144             print("VNF :")
145             print("================")
146             for index, vnf in enumerate(vnfs, 1):
147                 print((' %-2s %s' % ('%s:' % str(index), vnf)))
148             raise SystemExit(0)
149
150         if args['list']:
151             vnfs = os.listdir(test_path)
152
153             print("Available Tests:")
154             print("*****************")
155             for vnf in vnfs:
156                 testcases = os.listdir(test_path + vnf)
157                 print(("VNF :(%s)" % vnf))
158                 print("================")
159                 for testcase in [tc for tc in testcases if "tc" in tc]:
160                     print('%s' % testcase)
161                 print(os.linesep)
162             raise SystemExit(0)
163
164     @classmethod
165     def terminate_if_less_options(cls, args):
166         """ terminate cli if cmdline options is invalid """
167         if not (args["vnf"] and args["test"]):
168             print("CLI needs option, make sure to pass vnf, test")
169             print("eg: NSBperf.py --vnf <vnf untertest> --test <test yaml>")
170             raise SystemExit(1)
171
172     def run_test(self, args, test_path):
173         """ run requested test """
174         try:
175             vnf = args.get("vnf", "")
176             test = args.get("test", "")
177
178             vnf_dir = test_path + os.sep + vnf
179             if not os.path.exists(vnf_dir):
180                 raise ValueError("'%s', vnf not supported." % vnf)
181
182             testcases = [tc for tc in os.listdir(vnf_dir) if "tc" in tc]
183             subtest = set([test]).issubset(testcases)
184             if not subtest:
185                 raise ValueError("'%s', testcase not supported." % test)
186
187             os.chdir(vnf_dir)
188             # fixme: Use REST APIs to initiate testcases
189             subprocess.check_output(["yardstick", "--debug",
190                                      "task", "start", test])
191             self.generate_final_report(test)
192         except (IOError, ValueError):
193             print("Value/I/O error...")
194         except BaseException:
195             print("Test failed. Please verify test inputs & re-run the test..")
196             print("eg: NSBperf.py --vnf <vnf untertest> --test <test yaml>")
197
198     def main(self):
199         """Main function.
200         """
201         test_path = os.path.join(REPO_PATH, "../samples/vnf_samples/nsut/")
202         os.chdir(os.path.join(REPO_PATH, "../"))
203         args = self.parse_arguments()
204
205         # if required, handle list-* operations
206         self.handle_list_options(args, test_path)
207
208         # check for input params
209         self.terminate_if_less_options(args)
210
211         # run test
212         self.run_test(args, test_path)
213
214 if __name__ == "__main__":
215     signal.signal(signal.SIGINT, sigint_handler)
216     NS_CLI = YardstickNSCli()
217     NS_CLI.main()