tc-testing: Restore original behaviour for namespaces in tdc

This patch restores the original behaviour for tdc prior to the
introduction of the plugin system, where the network namespace
functionality was split from the main script.

It introduces the concept of required plugins for testcases,
and will automatically load any plugin that isn't already
enabled when said plugin is required by even one testcase.

Additionally, the -n option for the nsPlugin is deprecated
so the default action is to make use of the namespaces.
Instead, we introduce -N to not use them, but still create
the veth pair.

buildebpfPlugin's -B option is also deprecated.

If a test cases requires the features of a specific plugin
in order to pass, it should instead include a new key/value
pair describing plugin interactions:

        "plugins": {
                "requires": "buildebpfPlugin"
        },

A test case can have more than one required plugin: a list
can be inserted as the value for 'requires'.

Signed-off-by: Lucas Bates <lucasb@mojatatu.com>
Acked-by: Davide Caratti <dcaratti@redhat.com>
Tested-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Lucas Bates 2019-06-24 21:00:27 -04:00 committed by David S. Miller
parent 27d92807f8
commit 489ce2f425
8 changed files with 296 additions and 20 deletions

View file

@ -25,6 +25,9 @@ from tdc_helper import *
import TdcPlugin
from TdcResults import *
class PluginDependencyException(Exception):
def __init__(self, missing_pg):
self.missing_pg = missing_pg
class PluginMgrTestFail(Exception):
def __init__(self, stage, output, message):
@ -37,7 +40,7 @@ class PluginMgr:
super().__init__()
self.plugins = {}
self.plugin_instances = []
self.args = []
self.failed_plugins = {}
self.argparser = argparser
# TODO, put plugins in order
@ -53,6 +56,64 @@ class PluginMgr:
self.plugins[mn] = foo
self.plugin_instances.append(foo.SubPlugin())
def load_plugin(self, pgdir, pgname):
pgname = pgname[0:-3]
foo = importlib.import_module('{}.{}'.format(pgdir, pgname))
self.plugins[pgname] = foo
self.plugin_instances.append(foo.SubPlugin())
self.plugin_instances[-1].check_args(self.args, None)
def get_required_plugins(self, testlist):
'''
Get all required plugins from the list of test cases and return
all unique items.
'''
reqs = []
for t in testlist:
try:
if 'requires' in t['plugins']:
if isinstance(t['plugins']['requires'], list):
reqs.extend(t['plugins']['requires'])
else:
reqs.append(t['plugins']['requires'])
except KeyError:
continue
reqs = get_unique_item(reqs)
return reqs
def load_required_plugins(self, reqs, parser, args, remaining):
'''
Get all required plugins from the list of test cases and load any plugin
that is not already enabled.
'''
pgd = ['plugin-lib', 'plugin-lib-custom']
pnf = []
for r in reqs:
if r not in self.plugins:
fname = '{}.py'.format(r)
source_path = []
for d in pgd:
pgpath = '{}/{}'.format(d, fname)
if os.path.isfile(pgpath):
source_path.append(pgpath)
if len(source_path) == 0:
print('ERROR: unable to find required plugin {}'.format(r))
pnf.append(fname)
continue
elif len(source_path) > 1:
print('WARNING: multiple copies of plugin {} found, using version found')
print('at {}'.format(source_path[0]))
pgdir = source_path[0]
pgdir = pgdir.split('/')[0]
self.load_plugin(pgdir, fname)
if len(pnf) > 0:
raise PluginDependencyException(pnf)
parser = self.call_add_args(parser)
(args, remaining) = parser.parse_known_args(args=remaining, namespace=args)
return args
def call_pre_suite(self, testcount, testidlist):
for pgn_inst in self.plugin_instances:
pgn_inst.pre_suite(testcount, testidlist)
@ -98,6 +159,9 @@ class PluginMgr:
command = pgn_inst.adjust_command(stage, command)
return command
def set_args(self, args):
self.args = args
@staticmethod
def _make_argparser(args):
self.argparser = argparse.ArgumentParser(
@ -550,6 +614,7 @@ def filter_tests_by_category(args, testlist):
return answer
def get_test_cases(args):
"""
If a test case file is specified, retrieve tests from that file.
@ -611,7 +676,7 @@ def get_test_cases(args):
return allcatlist, allidlist, testcases_by_cats, alltestcases
def set_operation_mode(pm, args):
def set_operation_mode(pm, parser, args, remaining):
"""
Load the test case data and process remaining arguments to determine
what the script should do for this run, and call the appropriate
@ -649,6 +714,12 @@ def set_operation_mode(pm, args):
exit(0)
if len(alltests):
req_plugins = pm.get_required_plugins(alltests)
try:
args = pm.load_required_plugins(req_plugins, parser, args, remaining)
except PluginDependencyException as pde:
print('The following plugins were not found:')
print('{}'.format(pde.missing_pg))
catresults = test_runner(pm, args, alltests)
if args.format == 'none':
print('Test results output suppression requested\n')
@ -686,11 +757,12 @@ def main():
parser = pm.call_add_args(parser)
(args, remaining) = parser.parse_known_args()
args.NAMES = NAMES
pm.set_args(args)
check_default_settings(args, remaining, pm)
if args.verbose > 2:
print('args is {}'.format(args))
set_operation_mode(pm, args)
set_operation_mode(pm, parser, args, remaining)
exit(0)