162306a36Sopenharmony_ciimport os 262306a36Sopenharmony_ciimport signal 362306a36Sopenharmony_cifrom string import Template 462306a36Sopenharmony_ciimport subprocess 562306a36Sopenharmony_ciimport time 662306a36Sopenharmony_cifrom TdcPlugin import TdcPlugin 762306a36Sopenharmony_ci 862306a36Sopenharmony_cifrom tdc_config import * 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ciclass SubPlugin(TdcPlugin): 1162306a36Sopenharmony_ci def __init__(self): 1262306a36Sopenharmony_ci self.sub_class = 'ns/SubPlugin' 1362306a36Sopenharmony_ci super().__init__() 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci def pre_suite(self, testcount, testidlist): 1662306a36Sopenharmony_ci '''run commands before test_runner goes into a test loop''' 1762306a36Sopenharmony_ci super().pre_suite(testcount, testidlist) 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci if self.args.namespace: 2062306a36Sopenharmony_ci self._ns_create() 2162306a36Sopenharmony_ci else: 2262306a36Sopenharmony_ci self._ports_create() 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci def post_suite(self, index): 2562306a36Sopenharmony_ci '''run commands after test_runner goes into a test loop''' 2662306a36Sopenharmony_ci super().post_suite(index) 2762306a36Sopenharmony_ci if self.args.verbose: 2862306a36Sopenharmony_ci print('{}.post_suite'.format(self.sub_class)) 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci if self.args.namespace: 3162306a36Sopenharmony_ci self._ns_destroy() 3262306a36Sopenharmony_ci else: 3362306a36Sopenharmony_ci self._ports_destroy() 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci def add_args(self, parser): 3662306a36Sopenharmony_ci super().add_args(parser) 3762306a36Sopenharmony_ci self.argparser_group = self.argparser.add_argument_group( 3862306a36Sopenharmony_ci 'netns', 3962306a36Sopenharmony_ci 'options for nsPlugin(run commands in net namespace)') 4062306a36Sopenharmony_ci self.argparser_group.add_argument( 4162306a36Sopenharmony_ci '-N', '--no-namespace', action='store_false', default=True, 4262306a36Sopenharmony_ci dest='namespace', help='Don\'t run commands in namespace') 4362306a36Sopenharmony_ci return self.argparser 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci def adjust_command(self, stage, command): 4662306a36Sopenharmony_ci super().adjust_command(stage, command) 4762306a36Sopenharmony_ci cmdform = 'list' 4862306a36Sopenharmony_ci cmdlist = list() 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci if not self.args.namespace: 5162306a36Sopenharmony_ci return command 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci if self.args.verbose: 5462306a36Sopenharmony_ci print('{}.adjust_command'.format(self.sub_class)) 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci if not isinstance(command, list): 5762306a36Sopenharmony_ci cmdform = 'str' 5862306a36Sopenharmony_ci cmdlist = command.split() 5962306a36Sopenharmony_ci else: 6062306a36Sopenharmony_ci cmdlist = command 6162306a36Sopenharmony_ci if stage == 'setup' or stage == 'execute' or stage == 'verify' or stage == 'teardown': 6262306a36Sopenharmony_ci if self.args.verbose: 6362306a36Sopenharmony_ci print('adjust_command: stage is {}; inserting netns stuff in command [{}] list [{}]'.format(stage, command, cmdlist)) 6462306a36Sopenharmony_ci cmdlist.insert(0, self.args.NAMES['NS']) 6562306a36Sopenharmony_ci cmdlist.insert(0, 'exec') 6662306a36Sopenharmony_ci cmdlist.insert(0, 'netns') 6762306a36Sopenharmony_ci cmdlist.insert(0, self.args.NAMES['IP']) 6862306a36Sopenharmony_ci else: 6962306a36Sopenharmony_ci pass 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci if cmdform == 'str': 7262306a36Sopenharmony_ci command = ' '.join(cmdlist) 7362306a36Sopenharmony_ci else: 7462306a36Sopenharmony_ci command = cmdlist 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if self.args.verbose: 7762306a36Sopenharmony_ci print('adjust_command: return command [{}]'.format(command)) 7862306a36Sopenharmony_ci return command 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci def _ports_create(self): 8162306a36Sopenharmony_ci cmd = '$IP link add $DEV0 type veth peer name $DEV1' 8262306a36Sopenharmony_ci self._exec_cmd('pre', cmd) 8362306a36Sopenharmony_ci cmd = '$IP link set $DEV0 up' 8462306a36Sopenharmony_ci self._exec_cmd('pre', cmd) 8562306a36Sopenharmony_ci if not self.args.namespace: 8662306a36Sopenharmony_ci cmd = '$IP link set $DEV1 up' 8762306a36Sopenharmony_ci self._exec_cmd('pre', cmd) 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci def _ports_destroy(self): 9062306a36Sopenharmony_ci cmd = '$IP link del $DEV0' 9162306a36Sopenharmony_ci self._exec_cmd('post', cmd) 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci def _ns_create(self): 9462306a36Sopenharmony_ci ''' 9562306a36Sopenharmony_ci Create the network namespace in which the tests will be run and set up 9662306a36Sopenharmony_ci the required network devices for it. 9762306a36Sopenharmony_ci ''' 9862306a36Sopenharmony_ci self._ports_create() 9962306a36Sopenharmony_ci if self.args.namespace: 10062306a36Sopenharmony_ci cmd = '$IP netns add {}'.format(self.args.NAMES['NS']) 10162306a36Sopenharmony_ci self._exec_cmd('pre', cmd) 10262306a36Sopenharmony_ci cmd = '$IP link set $DEV1 netns {}'.format(self.args.NAMES['NS']) 10362306a36Sopenharmony_ci self._exec_cmd('pre', cmd) 10462306a36Sopenharmony_ci cmd = '$IP -n {} link set $DEV1 up'.format(self.args.NAMES['NS']) 10562306a36Sopenharmony_ci self._exec_cmd('pre', cmd) 10662306a36Sopenharmony_ci if self.args.device: 10762306a36Sopenharmony_ci cmd = '$IP link set $DEV2 netns {}'.format(self.args.NAMES['NS']) 10862306a36Sopenharmony_ci self._exec_cmd('pre', cmd) 10962306a36Sopenharmony_ci cmd = '$IP -n {} link set $DEV2 up'.format(self.args.NAMES['NS']) 11062306a36Sopenharmony_ci self._exec_cmd('pre', cmd) 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci def _ns_destroy(self): 11362306a36Sopenharmony_ci ''' 11462306a36Sopenharmony_ci Destroy the network namespace for testing (and any associated network 11562306a36Sopenharmony_ci devices as well) 11662306a36Sopenharmony_ci ''' 11762306a36Sopenharmony_ci if self.args.namespace: 11862306a36Sopenharmony_ci cmd = '$IP netns delete {}'.format(self.args.NAMES['NS']) 11962306a36Sopenharmony_ci self._exec_cmd('post', cmd) 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci def _exec_cmd(self, stage, command): 12262306a36Sopenharmony_ci ''' 12362306a36Sopenharmony_ci Perform any required modifications on an executable command, then run 12462306a36Sopenharmony_ci it in a subprocess and return the results. 12562306a36Sopenharmony_ci ''' 12662306a36Sopenharmony_ci if '$' in command: 12762306a36Sopenharmony_ci command = self._replace_keywords(command) 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci self.adjust_command(stage, command) 13062306a36Sopenharmony_ci if self.args.verbose: 13162306a36Sopenharmony_ci print('_exec_cmd: command "{}"'.format(command)) 13262306a36Sopenharmony_ci proc = subprocess.Popen(command, 13362306a36Sopenharmony_ci shell=True, 13462306a36Sopenharmony_ci stdout=subprocess.PIPE, 13562306a36Sopenharmony_ci stderr=subprocess.PIPE, 13662306a36Sopenharmony_ci env=ENVIR) 13762306a36Sopenharmony_ci (rawout, serr) = proc.communicate() 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci if proc.returncode != 0 and len(serr) > 0: 14062306a36Sopenharmony_ci foutput = serr.decode("utf-8") 14162306a36Sopenharmony_ci else: 14262306a36Sopenharmony_ci foutput = rawout.decode("utf-8") 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci proc.stdout.close() 14562306a36Sopenharmony_ci proc.stderr.close() 14662306a36Sopenharmony_ci return proc, foutput 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci def _replace_keywords(self, cmd): 14962306a36Sopenharmony_ci """ 15062306a36Sopenharmony_ci For a given executable command, substitute any known 15162306a36Sopenharmony_ci variables contained within NAMES with the correct values 15262306a36Sopenharmony_ci """ 15362306a36Sopenharmony_ci tcmd = Template(cmd) 15462306a36Sopenharmony_ci subcmd = tcmd.safe_substitute(self.args.NAMES) 15562306a36Sopenharmony_ci return subcmd 156