X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=nfvbench%2Fnfvbench.py;h=37645aadb04f6ecd7bad150be69b4d97e0fe804b;hb=078f4bba85b5b873bb27dc48025892a7135ea61e;hp=bf39a44cf36964d71e254ebbf1aae332a7e6937c;hpb=2d66234fe3b8b3e104e63218b5120a35ca400ea5;p=nfvbench.git diff --git a/nfvbench/nfvbench.py b/nfvbench/nfvbench.py index bf39a44..37645aa 100644 --- a/nfvbench/nfvbench.py +++ b/nfvbench/nfvbench.py @@ -21,9 +21,11 @@ from chain_runner import ChainRunner from collections import defaultdict from config import config_load from config import config_loads +import copy import credentials import datetime from factory import BasicFactory +from fluentd import FluentLogHandler import importlib import json import log @@ -40,6 +42,8 @@ import traceback from traffic_client import TrafficGeneratorFactory import utils +fluent_logger = None + class NFVBench(object): """Main class of NFV benchmarking tool.""" @@ -72,10 +76,15 @@ class NFVBench(object): def set_notifier(self, notifier): self.notifier = notifier - def run(self, opts): + def run(self, opts, args): status = NFVBench.STATUS_OK result = None message = '' + if fluent_logger: + # take a snapshot of the current time for this new run + # so that all subsequent logs can relate to this run + fluent_logger.start_new_run() + LOG.info(args) try: self.update_config(opts) self.setup() @@ -87,7 +96,7 @@ class NFVBench(object): "vswitch": self.specs.openstack.vswitch, "encaps": self.specs.openstack.encaps }, - "config": self.config_plugin.prepare_results_config(dict(self.config)), + "config": self.config_plugin.prepare_results_config(copy.deepcopy(self.config)), "benchmarks": { "network": { "service_chain": self.chain_runner.run(), @@ -120,8 +129,8 @@ class NFVBench(object): def print_summary(self, result): """Print summary of the result""" - print NFVBenchSummarizer(result) - sys.stdout.flush() + summary = NFVBenchSummarizer(result) + LOG.info(str(summary)) def save(self, result): """Save results in json format file.""" @@ -204,7 +213,7 @@ class NFVBench(object): raise Exception('Please provide existing path for storing results in JSON file. ' 'Path used: {path}'.format(path=self.config.std_json_path)) - self.config_plugin.validate_config(self.config) + self.config_plugin.validate_config(self.config, self.specs.openstack) def parse_opts_from_cli(): @@ -364,6 +373,11 @@ def parse_opts_from_cli(): default=None, help='Override traffic profile direction (requires -fs)') + parser.add_argument('--log-file', '--logfile', dest='log_file', + action='store', + help='Filename for saving logs', + metavar='') + opts, unknown_opts = parser.parse_known_args() return opts, unknown_opts @@ -395,17 +409,21 @@ def override_custom_traffic(config, frame_sizes, unidir): "profile": traffic_profile_name } + def check_physnet(name, netattrs): if not netattrs.physical_network: raise Exception("SRIOV requires physical_network to be specified for the {n} network" - .format(n=name)) + .format(n=name)) if not netattrs.segmentation_id: raise Exception("SRIOV requires segmentation_id to be specified for the {n} network" - .format(n=name)) + .format(n=name)) + def main(): + global fluent_logger + run_summary_required = False try: - log.setup('nfvbench') + log.setup() # load default config file config, default_cfg = load_default_config() # create factory for platform specific classes @@ -420,8 +438,17 @@ def main(): config = config_plugin.get_config() openstack_spec = config_plugin.get_openstack_spec() + # setup the fluent logger as soon as possible right after the config plugin is called + if config.fluentd.logging_tag: + fluent_logger = FluentLogHandler(config.fluentd.logging_tag, + fluentd_ip=config.fluentd.ip, + fluentd_port=config.fluentd.port) + LOG.addHandler(fluent_logger) + else: + fluent_logger = None + opts, unknown_opts = parse_opts_from_cli() - log.set_level('nfvbench', debug=opts.debug) + log.set_level(debug=opts.debug) if opts.version: print pbr.version.VersionInfo('nfvbench').version_string_with_vcs() @@ -439,15 +466,17 @@ def main(): config.name = '' if opts.config: + # do not check extra_specs in flavor as it can contain any key/value pairs + whitelist_keys = ['extra_specs'] # override default config options with start config at path parsed from CLI # check if it is an inline yaml/json config or a file name if os.path.isfile(opts.config): LOG.info('Loading configuration file: ' + opts.config) - config = config_load(opts.config, config) + config = config_load(opts.config, config, whitelist_keys) config.name = os.path.basename(opts.config) else: LOG.info('Loading configuration string: ' + opts.config) - config = config_loads(opts.config, config) + config = config_loads(opts.config, config, whitelist_keys) # traffic profile override options override_custom_traffic(config, opts.frame_sizes, opts.unidir) @@ -456,6 +485,8 @@ def main(): config.generator_profile = opts.generator_profile if opts.sriov: config.sriov = True + if opts.log_file: + config.log_file = opts.log_file # show running config in json format if opts.show_config: @@ -474,11 +505,15 @@ def main(): # in a copy of the dict (config plugin still holds the original dict) config_plugin.set_config(config) + # add file log if requested + if config.log_file: + log.add_file_logger(config.log_file) + nfvbench = NFVBench(config, openstack_spec, config_plugin, factory) if opts.server: if os.path.isdir(opts.server): - server = WebSocketIoServer(opts.server, nfvbench) + server = WebSocketIoServer(opts.server, nfvbench, fluent_logger) nfvbench.set_notifier(server) try: port = int(opts.port) @@ -491,12 +526,17 @@ def main(): sys.exit(1) else: with utils.RunLock(): + run_summary_required = True if unknown_opts: - LOG.warning('Unknown options: ' + ' '.join(unknown_opts)) + err_msg = 'Unknown options: ' + ' '.join(unknown_opts) + LOG.error(err_msg) + raise Exception(err_msg) # remove unfilled values opts = {k: v for k, v in vars(opts).iteritems() if v is not None} - result = nfvbench.run(opts) + # get CLI args + params = ' '.join(str(e) for e in sys.argv[1:]) + result = nfvbench.run(opts, params) if 'error_message' in result: raise Exception(result['error_message']) @@ -504,12 +544,18 @@ def main(): nfvbench.save(result['result']) nfvbench.print_summary(result['result']) except Exception as exc: + run_summary_required = True LOG.error({ 'status': NFVBench.STATUS_ERROR, 'error_message': traceback.format_exc() }) print str(exc) - sys.exit(1) + finally: + if fluent_logger: + # only send a summary record if there was an actual nfvbench run or + # if an error/exception was logged. + fluent_logger.send_run_summary(run_summary_required) + if __name__ == '__main__': main()