xref: /openbmc/linux/tools/testing/selftests/tc-testing/plugin-lib/nsPlugin.py (revision 976e3645923bdd2fe7893aae33fd7a21098bfb28)
1a13fedbeSBrenda J. Butlerimport os
2a13fedbeSBrenda J. Butlerimport signal
3a13fedbeSBrenda J. Butlerfrom string import Template
4a13fedbeSBrenda J. Butlerimport subprocess
5a13fedbeSBrenda J. Butlerimport time
6a13fedbeSBrenda J. Butlerfrom TdcPlugin import TdcPlugin
7a13fedbeSBrenda J. Butler
8a13fedbeSBrenda J. Butlerfrom tdc_config import *
9a13fedbeSBrenda J. Butler
10a13fedbeSBrenda J. Butlerclass SubPlugin(TdcPlugin):
11a13fedbeSBrenda J. Butler    def __init__(self):
12a13fedbeSBrenda J. Butler        self.sub_class = 'ns/SubPlugin'
13a13fedbeSBrenda J. Butler        super().__init__()
14a13fedbeSBrenda J. Butler
15a13fedbeSBrenda J. Butler    def pre_suite(self, testcount, testidlist):
16a13fedbeSBrenda J. Butler        '''run commands before test_runner goes into a test loop'''
17a13fedbeSBrenda J. Butler        super().pre_suite(testcount, testidlist)
18a13fedbeSBrenda J. Butler
19a13fedbeSBrenda J. Butler        if self.args.namespace:
20a13fedbeSBrenda J. Butler            self._ns_create()
21489ce2f4SLucas Bates        else:
22489ce2f4SLucas Bates            self._ports_create()
23a13fedbeSBrenda J. Butler
24a13fedbeSBrenda J. Butler    def post_suite(self, index):
25a13fedbeSBrenda J. Butler        '''run commands after test_runner goes into a test loop'''
26a13fedbeSBrenda J. Butler        super().post_suite(index)
27a13fedbeSBrenda J. Butler        if self.args.verbose:
28a13fedbeSBrenda J. Butler            print('{}.post_suite'.format(self.sub_class))
29a13fedbeSBrenda J. Butler
30a13fedbeSBrenda J. Butler        if self.args.namespace:
31a13fedbeSBrenda J. Butler            self._ns_destroy()
32489ce2f4SLucas Bates        else:
33489ce2f4SLucas Bates            self._ports_destroy()
34a13fedbeSBrenda J. Butler
35a13fedbeSBrenda J. Butler    def add_args(self, parser):
36a13fedbeSBrenda J. Butler        super().add_args(parser)
37a13fedbeSBrenda J. Butler        self.argparser_group = self.argparser.add_argument_group(
38a13fedbeSBrenda J. Butler            'netns',
39a13fedbeSBrenda J. Butler            'options for nsPlugin(run commands in net namespace)')
40a13fedbeSBrenda J. Butler        self.argparser_group.add_argument(
41489ce2f4SLucas Bates            '-N', '--no-namespace', action='store_false', default=True,
42489ce2f4SLucas Bates            dest='namespace', help='Don\'t run commands in namespace')
43a13fedbeSBrenda J. Butler        return self.argparser
44a13fedbeSBrenda J. Butler
45a13fedbeSBrenda J. Butler    def adjust_command(self, stage, command):
46a13fedbeSBrenda J. Butler        super().adjust_command(stage, command)
47a13fedbeSBrenda J. Butler        cmdform = 'list'
48a13fedbeSBrenda J. Butler        cmdlist = list()
49a13fedbeSBrenda J. Butler
50a13fedbeSBrenda J. Butler        if not self.args.namespace:
51a13fedbeSBrenda J. Butler            return command
52a13fedbeSBrenda J. Butler
53a13fedbeSBrenda J. Butler        if self.args.verbose:
54a13fedbeSBrenda J. Butler            print('{}.adjust_command'.format(self.sub_class))
55a13fedbeSBrenda J. Butler
56a13fedbeSBrenda J. Butler        if not isinstance(command, list):
57a13fedbeSBrenda J. Butler            cmdform = 'str'
58a13fedbeSBrenda J. Butler            cmdlist = command.split()
59a13fedbeSBrenda J. Butler        else:
60a13fedbeSBrenda J. Butler            cmdlist = command
61a13fedbeSBrenda J. Butler        if stage == 'setup' or stage == 'execute' or stage == 'verify' or stage == 'teardown':
62a13fedbeSBrenda J. Butler            if self.args.verbose:
63a13fedbeSBrenda J. Butler                print('adjust_command:  stage is {}; inserting netns stuff in command [{}] list [{}]'.format(stage, command, cmdlist))
64a13fedbeSBrenda J. Butler            cmdlist.insert(0, self.args.NAMES['NS'])
65a13fedbeSBrenda J. Butler            cmdlist.insert(0, 'exec')
66a13fedbeSBrenda J. Butler            cmdlist.insert(0, 'netns')
67*02a3f0d5SDavide Caratti            cmdlist.insert(0, self.args.NAMES['IP'])
68a13fedbeSBrenda J. Butler        else:
69a13fedbeSBrenda J. Butler            pass
70a13fedbeSBrenda J. Butler
71a13fedbeSBrenda J. Butler        if cmdform == 'str':
72a13fedbeSBrenda J. Butler            command = ' '.join(cmdlist)
73a13fedbeSBrenda J. Butler        else:
74a13fedbeSBrenda J. Butler            command = cmdlist
75a13fedbeSBrenda J. Butler
76a13fedbeSBrenda J. Butler        if self.args.verbose:
77a13fedbeSBrenda J. Butler            print('adjust_command:  return command [{}]'.format(command))
78a13fedbeSBrenda J. Butler        return command
79a13fedbeSBrenda J. Butler
80489ce2f4SLucas Bates    def _ports_create(self):
81*02a3f0d5SDavide Caratti        cmd = '$IP link add $DEV0 type veth peer name $DEV1'
82489ce2f4SLucas Bates        self._exec_cmd('pre', cmd)
83*02a3f0d5SDavide Caratti        cmd = '$IP link set $DEV0 up'
84489ce2f4SLucas Bates        self._exec_cmd('pre', cmd)
85489ce2f4SLucas Bates        if not self.args.namespace:
86*02a3f0d5SDavide Caratti            cmd = '$IP link set $DEV1 up'
87489ce2f4SLucas Bates            self._exec_cmd('pre', cmd)
88489ce2f4SLucas Bates
89489ce2f4SLucas Bates    def _ports_destroy(self):
90*02a3f0d5SDavide Caratti        cmd = '$IP link del $DEV0'
91489ce2f4SLucas Bates        self._exec_cmd('post', cmd)
92489ce2f4SLucas Bates
93a13fedbeSBrenda J. Butler    def _ns_create(self):
94a13fedbeSBrenda J. Butler        '''
95a13fedbeSBrenda J. Butler        Create the network namespace in which the tests will be run and set up
96a13fedbeSBrenda J. Butler        the required network devices for it.
97a13fedbeSBrenda J. Butler        '''
98489ce2f4SLucas Bates        self._ports_create()
99a13fedbeSBrenda J. Butler        if self.args.namespace:
100*02a3f0d5SDavide Caratti            cmd = '$IP netns add {}'.format(self.args.NAMES['NS'])
101a13fedbeSBrenda J. Butler            self._exec_cmd('pre', cmd)
102*02a3f0d5SDavide Caratti            cmd = '$IP link set $DEV1 netns {}'.format(self.args.NAMES['NS'])
103a13fedbeSBrenda J. Butler            self._exec_cmd('pre', cmd)
104*02a3f0d5SDavide Caratti            cmd = '$IP -n {} link set $DEV1 up'.format(self.args.NAMES['NS'])
105a13fedbeSBrenda J. Butler            self._exec_cmd('pre', cmd)
106a13fedbeSBrenda J. Butler            if self.args.device:
107*02a3f0d5SDavide Caratti                cmd = '$IP link set $DEV2 netns {}'.format(self.args.NAMES['NS'])
108a13fedbeSBrenda J. Butler                self._exec_cmd('pre', cmd)
109*02a3f0d5SDavide Caratti                cmd = '$IP -n {} link set $DEV2 up'.format(self.args.NAMES['NS'])
110a13fedbeSBrenda J. Butler                self._exec_cmd('pre', cmd)
111a13fedbeSBrenda J. Butler
112a13fedbeSBrenda J. Butler    def _ns_destroy(self):
113a13fedbeSBrenda J. Butler        '''
114a13fedbeSBrenda J. Butler        Destroy the network namespace for testing (and any associated network
115a13fedbeSBrenda J. Butler        devices as well)
116a13fedbeSBrenda J. Butler        '''
117a13fedbeSBrenda J. Butler        if self.args.namespace:
118*02a3f0d5SDavide Caratti            cmd = '$IP netns delete {}'.format(self.args.NAMES['NS'])
119a13fedbeSBrenda J. Butler            self._exec_cmd('post', cmd)
120a13fedbeSBrenda J. Butler
121a13fedbeSBrenda J. Butler    def _exec_cmd(self, stage, command):
122a13fedbeSBrenda J. Butler        '''
123a13fedbeSBrenda J. Butler        Perform any required modifications on an executable command, then run
124a13fedbeSBrenda J. Butler        it in a subprocess and return the results.
125a13fedbeSBrenda J. Butler        '''
126a13fedbeSBrenda J. Butler        if '$' in command:
127a13fedbeSBrenda J. Butler            command = self._replace_keywords(command)
128a13fedbeSBrenda J. Butler
129a13fedbeSBrenda J. Butler        self.adjust_command(stage, command)
130a13fedbeSBrenda J. Butler        if self.args.verbose:
131a13fedbeSBrenda J. Butler            print('_exec_cmd:  command "{}"'.format(command))
132a13fedbeSBrenda J. Butler        proc = subprocess.Popen(command,
133a13fedbeSBrenda J. Butler            shell=True,
134a13fedbeSBrenda J. Butler            stdout=subprocess.PIPE,
135a13fedbeSBrenda J. Butler            stderr=subprocess.PIPE,
136a13fedbeSBrenda J. Butler            env=ENVIR)
137a13fedbeSBrenda J. Butler        (rawout, serr) = proc.communicate()
138a13fedbeSBrenda J. Butler
139a13fedbeSBrenda J. Butler        if proc.returncode != 0 and len(serr) > 0:
140a13fedbeSBrenda J. Butler            foutput = serr.decode("utf-8")
141a13fedbeSBrenda J. Butler        else:
142a13fedbeSBrenda J. Butler            foutput = rawout.decode("utf-8")
143a13fedbeSBrenda J. Butler
144a13fedbeSBrenda J. Butler        proc.stdout.close()
145a13fedbeSBrenda J. Butler        proc.stderr.close()
146a13fedbeSBrenda J. Butler        return proc, foutput
147a13fedbeSBrenda J. Butler
148a13fedbeSBrenda J. Butler    def _replace_keywords(self, cmd):
149a13fedbeSBrenda J. Butler        """
150a13fedbeSBrenda J. Butler        For a given executable command, substitute any known
151a13fedbeSBrenda J. Butler        variables contained within NAMES with the correct values
152a13fedbeSBrenda J. Butler        """
153a13fedbeSBrenda J. Butler        tcmd = Template(cmd)
154a13fedbeSBrenda J. Butler        subcmd = tcmd.safe_substitute(self.args.NAMES)
155a13fedbeSBrenda J. Butler        return subcmd
156