1*a13fedbeSBrenda J. Butlerimport os 2*a13fedbeSBrenda J. Butlerimport signal 3*a13fedbeSBrenda J. Butlerfrom string import Template 4*a13fedbeSBrenda J. Butlerimport subprocess 5*a13fedbeSBrenda J. Butlerimport time 6*a13fedbeSBrenda J. Butlerfrom TdcPlugin import TdcPlugin 7*a13fedbeSBrenda J. Butler 8*a13fedbeSBrenda J. Butlerfrom tdc_config import * 9*a13fedbeSBrenda J. Butler 10*a13fedbeSBrenda J. Butlerclass SubPlugin(TdcPlugin): 11*a13fedbeSBrenda J. Butler def __init__(self): 12*a13fedbeSBrenda J. Butler self.sub_class = 'ns/SubPlugin' 13*a13fedbeSBrenda J. Butler super().__init__() 14*a13fedbeSBrenda J. Butler 15*a13fedbeSBrenda J. Butler def pre_suite(self, testcount, testidlist): 16*a13fedbeSBrenda J. Butler '''run commands before test_runner goes into a test loop''' 17*a13fedbeSBrenda J. Butler super().pre_suite(testcount, testidlist) 18*a13fedbeSBrenda J. Butler 19*a13fedbeSBrenda J. Butler if self.args.namespace: 20*a13fedbeSBrenda J. Butler self._ns_create() 21*a13fedbeSBrenda J. Butler 22*a13fedbeSBrenda J. Butler def post_suite(self, index): 23*a13fedbeSBrenda J. Butler '''run commands after test_runner goes into a test loop''' 24*a13fedbeSBrenda J. Butler super().post_suite(index) 25*a13fedbeSBrenda J. Butler if self.args.verbose: 26*a13fedbeSBrenda J. Butler print('{}.post_suite'.format(self.sub_class)) 27*a13fedbeSBrenda J. Butler 28*a13fedbeSBrenda J. Butler if self.args.namespace: 29*a13fedbeSBrenda J. Butler self._ns_destroy() 30*a13fedbeSBrenda J. Butler 31*a13fedbeSBrenda J. Butler def add_args(self, parser): 32*a13fedbeSBrenda J. Butler super().add_args(parser) 33*a13fedbeSBrenda J. Butler self.argparser_group = self.argparser.add_argument_group( 34*a13fedbeSBrenda J. Butler 'netns', 35*a13fedbeSBrenda J. Butler 'options for nsPlugin(run commands in net namespace)') 36*a13fedbeSBrenda J. Butler self.argparser_group.add_argument( 37*a13fedbeSBrenda J. Butler '-n', '--namespace', action='store_true', 38*a13fedbeSBrenda J. Butler help='Run commands in namespace') 39*a13fedbeSBrenda J. Butler return self.argparser 40*a13fedbeSBrenda J. Butler 41*a13fedbeSBrenda J. Butler def adjust_command(self, stage, command): 42*a13fedbeSBrenda J. Butler super().adjust_command(stage, command) 43*a13fedbeSBrenda J. Butler cmdform = 'list' 44*a13fedbeSBrenda J. Butler cmdlist = list() 45*a13fedbeSBrenda J. Butler 46*a13fedbeSBrenda J. Butler if not self.args.namespace: 47*a13fedbeSBrenda J. Butler return command 48*a13fedbeSBrenda J. Butler 49*a13fedbeSBrenda J. Butler if self.args.verbose: 50*a13fedbeSBrenda J. Butler print('{}.adjust_command'.format(self.sub_class)) 51*a13fedbeSBrenda J. Butler 52*a13fedbeSBrenda J. Butler if not isinstance(command, list): 53*a13fedbeSBrenda J. Butler cmdform = 'str' 54*a13fedbeSBrenda J. Butler cmdlist = command.split() 55*a13fedbeSBrenda J. Butler else: 56*a13fedbeSBrenda J. Butler cmdlist = command 57*a13fedbeSBrenda J. Butler if stage == 'setup' or stage == 'execute' or stage == 'verify' or stage == 'teardown': 58*a13fedbeSBrenda J. Butler if self.args.verbose: 59*a13fedbeSBrenda J. Butler print('adjust_command: stage is {}; inserting netns stuff in command [{}] list [{}]'.format(stage, command, cmdlist)) 60*a13fedbeSBrenda J. Butler cmdlist.insert(0, self.args.NAMES['NS']) 61*a13fedbeSBrenda J. Butler cmdlist.insert(0, 'exec') 62*a13fedbeSBrenda J. Butler cmdlist.insert(0, 'netns') 63*a13fedbeSBrenda J. Butler cmdlist.insert(0, 'ip') 64*a13fedbeSBrenda J. Butler else: 65*a13fedbeSBrenda J. Butler pass 66*a13fedbeSBrenda J. Butler 67*a13fedbeSBrenda J. Butler if cmdform == 'str': 68*a13fedbeSBrenda J. Butler command = ' '.join(cmdlist) 69*a13fedbeSBrenda J. Butler else: 70*a13fedbeSBrenda J. Butler command = cmdlist 71*a13fedbeSBrenda J. Butler 72*a13fedbeSBrenda J. Butler if self.args.verbose: 73*a13fedbeSBrenda J. Butler print('adjust_command: return command [{}]'.format(command)) 74*a13fedbeSBrenda J. Butler return command 75*a13fedbeSBrenda J. Butler 76*a13fedbeSBrenda J. Butler def _ns_create(self): 77*a13fedbeSBrenda J. Butler ''' 78*a13fedbeSBrenda J. Butler Create the network namespace in which the tests will be run and set up 79*a13fedbeSBrenda J. Butler the required network devices for it. 80*a13fedbeSBrenda J. Butler ''' 81*a13fedbeSBrenda J. Butler if self.args.namespace: 82*a13fedbeSBrenda J. Butler cmd = 'ip netns add {}'.format(self.args.NAMES['NS']) 83*a13fedbeSBrenda J. Butler self._exec_cmd('pre', cmd) 84*a13fedbeSBrenda J. Butler cmd = 'ip link add $DEV0 type veth peer name $DEV1' 85*a13fedbeSBrenda J. Butler self._exec_cmd('pre', cmd) 86*a13fedbeSBrenda J. Butler cmd = 'ip link set $DEV1 netns {}'.format(self.args.NAMES['NS']) 87*a13fedbeSBrenda J. Butler self._exec_cmd('pre', cmd) 88*a13fedbeSBrenda J. Butler cmd = 'ip link set $DEV0 up' 89*a13fedbeSBrenda J. Butler self._exec_cmd('pre', cmd) 90*a13fedbeSBrenda J. Butler cmd = 'ip -n {} link set $DEV1 up'.format(self.args.NAMES['NS']) 91*a13fedbeSBrenda J. Butler self._exec_cmd('pre', cmd) 92*a13fedbeSBrenda J. Butler if self.args.device: 93*a13fedbeSBrenda J. Butler cmd = 'ip link set $DEV2 netns {}'.format(self.args.NAMES['NS']) 94*a13fedbeSBrenda J. Butler self._exec_cmd('pre', cmd) 95*a13fedbeSBrenda J. Butler cmd = 'ip -n {} link set $DEV2 up'.format(self.args.NAMES['NS']) 96*a13fedbeSBrenda J. Butler self._exec_cmd('pre', cmd) 97*a13fedbeSBrenda J. Butler 98*a13fedbeSBrenda J. Butler def _ns_destroy(self): 99*a13fedbeSBrenda J. Butler ''' 100*a13fedbeSBrenda J. Butler Destroy the network namespace for testing (and any associated network 101*a13fedbeSBrenda J. Butler devices as well) 102*a13fedbeSBrenda J. Butler ''' 103*a13fedbeSBrenda J. Butler if self.args.namespace: 104*a13fedbeSBrenda J. Butler cmd = 'ip netns delete {}'.format(self.args.NAMES['NS']) 105*a13fedbeSBrenda J. Butler self._exec_cmd('post', cmd) 106*a13fedbeSBrenda J. Butler 107*a13fedbeSBrenda J. Butler def _exec_cmd(self, stage, command): 108*a13fedbeSBrenda J. Butler ''' 109*a13fedbeSBrenda J. Butler Perform any required modifications on an executable command, then run 110*a13fedbeSBrenda J. Butler it in a subprocess and return the results. 111*a13fedbeSBrenda J. Butler ''' 112*a13fedbeSBrenda J. Butler if '$' in command: 113*a13fedbeSBrenda J. Butler command = self._replace_keywords(command) 114*a13fedbeSBrenda J. Butler 115*a13fedbeSBrenda J. Butler self.adjust_command(stage, command) 116*a13fedbeSBrenda J. Butler if self.args.verbose: 117*a13fedbeSBrenda J. Butler print('_exec_cmd: command "{}"'.format(command)) 118*a13fedbeSBrenda J. Butler proc = subprocess.Popen(command, 119*a13fedbeSBrenda J. Butler shell=True, 120*a13fedbeSBrenda J. Butler stdout=subprocess.PIPE, 121*a13fedbeSBrenda J. Butler stderr=subprocess.PIPE, 122*a13fedbeSBrenda J. Butler env=ENVIR) 123*a13fedbeSBrenda J. Butler (rawout, serr) = proc.communicate() 124*a13fedbeSBrenda J. Butler 125*a13fedbeSBrenda J. Butler if proc.returncode != 0 and len(serr) > 0: 126*a13fedbeSBrenda J. Butler foutput = serr.decode("utf-8") 127*a13fedbeSBrenda J. Butler else: 128*a13fedbeSBrenda J. Butler foutput = rawout.decode("utf-8") 129*a13fedbeSBrenda J. Butler 130*a13fedbeSBrenda J. Butler proc.stdout.close() 131*a13fedbeSBrenda J. Butler proc.stderr.close() 132*a13fedbeSBrenda J. Butler return proc, foutput 133*a13fedbeSBrenda J. Butler 134*a13fedbeSBrenda J. Butler def _replace_keywords(self, cmd): 135*a13fedbeSBrenda J. Butler """ 136*a13fedbeSBrenda J. Butler For a given executable command, substitute any known 137*a13fedbeSBrenda J. Butler variables contained within NAMES with the correct values 138*a13fedbeSBrenda J. Butler """ 139*a13fedbeSBrenda J. Butler tcmd = Template(cmd) 140*a13fedbeSBrenda J. Butler subcmd = tcmd.safe_substitute(self.args.NAMES) 141*a13fedbeSBrenda J. Butler return subcmd 142