1 import os 1 import os 2 import signal 2 import signal 3 from string import Template 3 from string import Template 4 import subprocess 4 import subprocess 5 import time 5 import time 6 from multiprocessing import Pool << 7 from functools import cached_property << 8 from TdcPlugin import TdcPlugin 6 from TdcPlugin import TdcPlugin 9 7 10 from tdc_config import * 8 from tdc_config import * 11 9 12 try: << 13 from pyroute2 import netns << 14 from pyroute2 import IPRoute << 15 netlink = True << 16 except ImportError: << 17 netlink = False << 18 print("!!! Consider installing pyroute2 !! << 19 << 20 class SubPlugin(TdcPlugin): 10 class SubPlugin(TdcPlugin): 21 def __init__(self): 11 def __init__(self): 22 self.sub_class = 'ns/SubPlugin' 12 self.sub_class = 'ns/SubPlugin' 23 super().__init__() 13 super().__init__() 24 14 25 def pre_suite(self, testcount, testlist): !! 15 def pre_suite(self, testcount, testidlist): 26 super().pre_suite(testcount, testlist) !! 16 '''run commands before test_runner goes into a test loop''' 27 !! 17 super().pre_suite(testcount, testidlist) 28 def prepare_test(self, test): << 29 if 'skip' in test and test['skip'] == << 30 return << 31 << 32 if 'nsPlugin' not in test['plugins']: << 33 return << 34 << 35 if netlink == True: << 36 self._nl_ns_create() << 37 else: << 38 self._ipr2_ns_create() << 39 << 40 # Make sure the netns is visible in th << 41 ticks = 20 << 42 while True: << 43 if ticks == 0: << 44 raise TimeoutError << 45 self._proc_check() << 46 try: << 47 ns = self.args.NAMES['NS'] << 48 f = open('/run/netns/{}'.forma << 49 f.close() << 50 break << 51 except: << 52 time.sleep(0.1) << 53 ticks -= 1 << 54 continue << 55 << 56 def pre_case(self, test, test_skip): << 57 if self.args.verbose: << 58 print('{}.pre_case'.format(self.su << 59 << 60 if test_skip: << 61 return << 62 18 63 self.prepare_test(test) !! 19 if self.args.namespace: 64 !! 20 self._ns_create() 65 def post_case(self): << 66 if self.args.verbose: << 67 print('{}.post_case'.format(self.s << 68 << 69 if netlink == True: << 70 self._nl_ns_destroy() << 71 else: << 72 self._ipr2_ns_destroy() << 73 21 74 def post_suite(self, index): 22 def post_suite(self, index): >> 23 '''run commands after test_runner goes into a test loop''' >> 24 super().post_suite(index) 75 if self.args.verbose: 25 if self.args.verbose: 76 print('{}.post_suite'.format(self. 26 print('{}.post_suite'.format(self.sub_class)) 77 27 78 # Make sure we don't leak resources !! 28 if self.args.namespace: 79 cmd = self._replace_keywords("$IP -a n !! 29 self._ns_destroy() 80 << 81 if self.args.verbose > 3: << 82 print('_exec_cmd: command "{}"'.f << 83 30 84 subprocess.run(cmd, shell=True, stdout !! 31 def add_args(self, parser): >> 32 super().add_args(parser) >> 33 self.argparser_group = self.argparser.add_argument_group( >> 34 'netns', >> 35 'options for nsPlugin(run commands in net namespace)') >> 36 self.argparser_group.add_argument( >> 37 '-n', '--namespace', action='store_true', >> 38 help='Run commands in namespace') >> 39 return self.argparser 85 40 86 def adjust_command(self, stage, command): 41 def adjust_command(self, stage, command): 87 super().adjust_command(stage, command) 42 super().adjust_command(stage, command) 88 cmdform = 'list' 43 cmdform = 'list' 89 cmdlist = list() 44 cmdlist = list() 90 45 >> 46 if not self.args.namespace: >> 47 return command >> 48 91 if self.args.verbose: 49 if self.args.verbose: 92 print('{}.adjust_command'.format(s 50 print('{}.adjust_command'.format(self.sub_class)) 93 51 94 if not isinstance(command, list): 52 if not isinstance(command, list): 95 cmdform = 'str' 53 cmdform = 'str' 96 cmdlist = command.split() 54 cmdlist = command.split() 97 else: 55 else: 98 cmdlist = command 56 cmdlist = command 99 if stage == 'setup' or stage == 'execu 57 if stage == 'setup' or stage == 'execute' or stage == 'verify' or stage == 'teardown': 100 if self.args.verbose: 58 if self.args.verbose: 101 print('adjust_command: stage 59 print('adjust_command: stage is {}; inserting netns stuff in command [{}] list [{}]'.format(stage, command, cmdlist)) 102 cmdlist.insert(0, self.args.NAMES[ 60 cmdlist.insert(0, self.args.NAMES['NS']) 103 cmdlist.insert(0, 'exec') 61 cmdlist.insert(0, 'exec') 104 cmdlist.insert(0, 'netns') 62 cmdlist.insert(0, 'netns') 105 cmdlist.insert(0, self.args.NAMES[ !! 63 cmdlist.insert(0, 'ip') 106 else: 64 else: 107 pass 65 pass 108 66 109 if cmdform == 'str': 67 if cmdform == 'str': 110 command = ' '.join(cmdlist) 68 command = ' '.join(cmdlist) 111 else: 69 else: 112 command = cmdlist 70 command = cmdlist 113 71 114 if self.args.verbose: 72 if self.args.verbose: 115 print('adjust_command: return com 73 print('adjust_command: return command [{}]'.format(command)) 116 return command 74 return command 117 75 118 def _nl_ns_create(self): !! 76 def _ns_create(self): 119 ns = self.args.NAMES["NS"]; << 120 dev0 = self.args.NAMES["DEV0"]; << 121 dev1 = self.args.NAMES["DEV1"]; << 122 dummy = self.args.NAMES["DUMMY"]; << 123 << 124 if self.args.verbose: << 125 print('{}._nl_ns_create'.format(se << 126 << 127 netns.create(ns) << 128 netns.pushns(newns=ns) << 129 with IPRoute() as ip: << 130 ip.link('add', ifname=dev1, kind=' << 131 ip.link('add', ifname=dummy, kind= << 132 ticks = 20 << 133 while True: << 134 if ticks == 0: << 135 raise TimeoutError << 136 try: << 137 dev1_idx = ip.link_lookup( << 138 dummy_idx = ip.link_lookup << 139 ip.link('set', index=dev1_ << 140 ip.link('set', index=dummy << 141 break << 142 except: << 143 time.sleep(0.1) << 144 ticks -= 1 << 145 continue << 146 netns.popns() << 147 << 148 with IPRoute() as ip: << 149 ticks = 20 << 150 while True: << 151 if ticks == 0: << 152 raise TimeoutError << 153 try: << 154 dev0_idx = ip.link_lookup( << 155 ip.link('set', index=dev0_ << 156 break << 157 except: << 158 time.sleep(0.1) << 159 ticks -= 1 << 160 continue << 161 << 162 def _ipr2_ns_create_cmds(self): << 163 cmds = [] << 164 << 165 ns = self.args.NAMES['NS'] << 166 << 167 cmds.append(self._replace_keywords('ne << 168 cmds.append(self._replace_keywords('li << 169 cmds.append(self._replace_keywords('li << 170 cmds.append(self._replace_keywords('li << 171 cmds.append(self._replace_keywords('li << 172 cmds.append(self._replace_keywords('ne << 173 cmds.append(self._replace_keywords('ne << 174 cmds.append(self._replace_keywords('li << 175 << 176 if self.args.device: << 177 cmds.append(self._replace_keywords << 178 cmds.append(self._replace_keywords << 179 << 180 return cmds << 181 << 182 def _ipr2_ns_create(self): << 183 ''' 77 ''' 184 Create the network namespace in which 78 Create the network namespace in which the tests will be run and set up 185 the required network devices for it. 79 the required network devices for it. 186 ''' 80 ''' 187 self._exec_cmd_batched('pre', self._ip !! 81 if self.args.namespace: 188 !! 82 cmd = 'ip netns add {}'.format(self.args.NAMES['NS']) 189 def _nl_ns_destroy(self): !! 83 self._exec_cmd('pre', cmd) 190 ns = self.args.NAMES['NS'] !! 84 cmd = 'ip link add $DEV0 type veth peer name $DEV1' 191 netns.remove(ns) !! 85 self._exec_cmd('pre', cmd) >> 86 cmd = 'ip link set $DEV1 netns {}'.format(self.args.NAMES['NS']) >> 87 self._exec_cmd('pre', cmd) >> 88 cmd = 'ip link set $DEV0 up' >> 89 self._exec_cmd('pre', cmd) >> 90 cmd = 'ip -n {} link set $DEV1 up'.format(self.args.NAMES['NS']) >> 91 self._exec_cmd('pre', cmd) >> 92 if self.args.device: >> 93 cmd = 'ip link set $DEV2 netns {}'.format(self.args.NAMES['NS']) >> 94 self._exec_cmd('pre', cmd) >> 95 cmd = 'ip -n {} link set $DEV2 up'.format(self.args.NAMES['NS']) >> 96 self._exec_cmd('pre', cmd) 192 97 193 def _ipr2_ns_destroy_cmd(self): !! 98 def _ns_destroy(self): 194 return self._replace_keywords('netns d << 195 << 196 def _ipr2_ns_destroy(self): << 197 ''' 99 ''' 198 Destroy the network namespace for test 100 Destroy the network namespace for testing (and any associated network 199 devices as well) 101 devices as well) 200 ''' 102 ''' 201 self._exec_cmd('post', self._ipr2_ns_d !! 103 if self.args.namespace: 202 !! 104 cmd = 'ip netns delete {}'.format(self.args.NAMES['NS']) 203 @cached_property !! 105 self._exec_cmd('post', cmd) 204 def _proc(self): << 205 ip = self._replace_keywords("$IP -b -" << 206 proc = subprocess.Popen(ip, << 207 shell=True, << 208 stdin=subprocess.PIPE, << 209 env=ENVIR) << 210 << 211 return proc << 212 << 213 def _proc_check(self): << 214 proc = self._proc << 215 << 216 proc.poll() << 217 << 218 if proc.returncode is not None and pro << 219 raise RuntimeError("iproute2 exite << 220 106 221 def _exec_cmd(self, stage, command): 107 def _exec_cmd(self, stage, command): 222 ''' 108 ''' 223 Perform any required modifications on 109 Perform any required modifications on an executable command, then run 224 it in a subprocess and return the resu 110 it in a subprocess and return the results. 225 ''' 111 ''' >> 112 if '$' in command: >> 113 command = self._replace_keywords(command) 226 114 227 if self.args.verbose > 3: !! 115 self.adjust_command(stage, command) >> 116 if self.args.verbose: 228 print('_exec_cmd: command "{}"'.f 117 print('_exec_cmd: command "{}"'.format(command)) >> 118 proc = subprocess.Popen(command, >> 119 shell=True, >> 120 stdout=subprocess.PIPE, >> 121 stderr=subprocess.PIPE, >> 122 env=ENVIR) >> 123 (rawout, serr) = proc.communicate() 229 124 230 proc = self._proc !! 125 if proc.returncode != 0 and len(serr) > 0: 231 !! 126 foutput = serr.decode("utf-8") 232 proc.stdin.write((command + '\n').enco !! 127 else: 233 proc.stdin.flush() !! 128 foutput = rawout.decode("utf-8") 234 << 235 if self.args.verbose > 3: << 236 print('_exec_cmd proc: {}'.format( << 237 << 238 self._proc_check() << 239 129 240 def _exec_cmd_batched(self, stage, command !! 130 proc.stdout.close() 241 for cmd in commands: !! 131 proc.stderr.close() 242 self._exec_cmd(stage, cmd) !! 132 return proc, foutput 243 133 244 def _replace_keywords(self, cmd): 134 def _replace_keywords(self, cmd): 245 """ 135 """ 246 For a given executable command, substi 136 For a given executable command, substitute any known 247 variables contained within NAMES with 137 variables contained within NAMES with the correct values 248 """ 138 """ 249 tcmd = Template(cmd) 139 tcmd = Template(cmd) 250 subcmd = tcmd.safe_substitute(self.arg 140 subcmd = tcmd.safe_substitute(self.args.NAMES) 251 return subcmd 141 return subcmd
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.