CSIT python API introduction
[csit.git] / resources / libraries / python / VPPUtil.py
1 # Copyright (c) 2018 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 """VPP util library."""
15
16 import time
17
18 from robot.api import logger
19
20 from resources.libraries.python.constants import Constants
21 from resources.libraries.python.DUTSetup import DUTSetup
22 from resources.libraries.python.PapiExecutor import PapiExecutor
23 from resources.libraries.python.PapiErrors import PapiError
24 from resources.libraries.python.ssh import exec_cmd, exec_cmd_no_error
25 from resources.libraries.python.topology import NodeType
26 from resources.libraries.python.VatExecutor import VatExecutor
27
28
29 class VPPUtil(object):
30     """General class for any VPP related methods/functions."""
31
32     @staticmethod
33     def show_vpp_settings(node, *additional_cmds):
34         """Print default VPP settings. In case others are needed, can be
35         accepted as next parameters (each setting one parameter), preferably
36         in form of a string.
37
38         :param node: VPP node.
39         :param additional_cmds: Additional commands that the vpp should print
40             settings for.
41         :type node: dict
42         :type additional_cmds: tuple
43         """
44         def_setting_tb_displayed = {
45             'IPv6 FIB': 'ip6 fib',
46             'IPv4 FIB': 'ip fib',
47             'Interface IP': 'int addr',
48             'Interfaces': 'int',
49             'ARP': 'ip arp',
50             'Errors': 'err'
51         }
52
53         if additional_cmds:
54             for cmd in additional_cmds:
55                 def_setting_tb_displayed['Custom Setting: {}'.format(cmd)] = cmd
56
57         for _, cmd in def_setting_tb_displayed.items():
58             command = 'vppctl sh {cmd}'.format(cmd=cmd)
59             exec_cmd_no_error(node, command, timeout=30, sudo=True)
60
61     @staticmethod
62     def start_vpp_service(node, retries=60):
63         """Start VPP service on the specified node.
64
65         :param node: VPP node.
66         :param retries: Number of times (default 60) to re-try waiting.
67         :type node: dict
68         :type retries: int
69         :raises RuntimeError: If VPP service fails to start.
70         """
71         DUTSetup.start_service(node, Constants.VPP_UNIT)
72         # Sleep 1 second, up to <retry> times,
73         # and verify if VPP is running.
74         for _ in range(retries):
75             time.sleep(1)
76             command = 'vppctl show pci'
77             ret, stdout, _ = exec_cmd(node, command, timeout=30, sudo=True)
78             if not ret and 'Connection refused' not in stdout:
79                 break
80         else:
81             raise RuntimeError('VPP failed to start on host {name}'.
82                                    format(name=node['host']))
83         DUTSetup.get_service_logs(node, Constants.VPP_UNIT)
84
85     @staticmethod
86     def start_vpp_service_on_all_duts(nodes):
87         """Start up the VPP service on all nodes.
88
89         :param nodes: Nodes in the topology.
90         :type nodes: dict
91         """
92         for node in nodes.values():
93             if node['type'] == NodeType.DUT:
94                 VPPUtil.start_vpp_service(node)
95
96     @staticmethod
97     def stop_vpp_service(node):
98         """Stop VPP service on the specified node.
99
100         :param node: VPP node.
101         :type node: dict
102         :raises RuntimeError: If VPP service fails to stop.
103         """
104         DUTSetup.stop_service(node, Constants.VPP_UNIT)
105
106     @staticmethod
107     def stop_vpp_service_on_all_duts(nodes):
108         """Stop VPP service on all nodes.
109
110         :param nodes: Nodes in the topology.
111         :type nodes: dict
112         """
113         for node in nodes.values():
114             if node['type'] == NodeType.DUT:
115                 VPPUtil.stop_vpp_service(node)
116
117     @staticmethod
118     def verify_vpp_on_dut(node):
119         """Verify that VPP is installed on DUT node.
120
121         :param node: DUT node.
122         :type node: dict
123         :raises RuntimeError: If failed to restart VPP, get VPP version
124             or get VPP interfaces.
125         """
126         VPPUtil.vpp_show_version_verbose(node)
127         VPPUtil.vpp_show_interfaces(node)
128
129     @staticmethod
130     def verify_vpp_on_all_duts(nodes):
131         """Verify that VPP is installed on all DUT nodes.
132
133         :param nodes: Nodes in the topology.
134         :type nodes: dict
135         """
136         for node in nodes.values():
137             if node['type'] == NodeType.DUT:
138                 VPPUtil.start_vpp_service(node)
139                 VPPUtil.verify_vpp_on_dut(node)
140
141     @staticmethod
142     def vpp_show_version(node, verbose=False):
143         """Run "show_version" API command.
144
145         :param node: Node to run command on.
146         :param verbose: Show version, compile date and compile location if True
147             otherwise show only version.
148         :type node: dict
149         :type verbose: bool
150         :raises PapiError: If no reply received for show_version API command.
151         """
152         # TODO: move composition of api data to separate method
153         api_data = list()
154         api = dict(api_name='show_version')
155         api_args = dict()
156         api['api_args'] = api_args
157         api_data.append(api)
158
159         api_reply = None
160         with PapiExecutor(node) as papi_executor:
161             papi_executor.execute_papi(api_data)
162             try:
163                 papi_executor.papi_should_have_passed()
164             except AssertionError:
165                 raise RuntimeError('Failed to get VPP version on host: {host}'.
166                                    format(host=node['host']))
167             api_reply = papi_executor.get_papi_reply()
168
169         if api_reply is not None:
170             version_data = api_reply[0]['api_reply']['show_version_reply']
171             ver = version_data['version'].rstrip('\0x00')
172             if verbose:
173                 date = version_data['build_date'].rstrip('\0x00')
174                 loc = version_data['build_directory'].rstrip('\0x00')
175                 version = \
176                     'VPP Version:        {ver}\n' \
177                     'Compile date:       {date}\n' \
178                     'Compile location:   {loc}\n '\
179                     .format(ver=ver, date=date, loc=loc)
180             else:
181                 version = 'VPP version:{ver}'.format(ver=ver)
182             logger.info(version)
183         else:
184             raise PapiError('No reply received for show_version API command on '
185                             'host {host}'.format(host=node['host']))
186
187     @staticmethod
188     def vpp_show_version_verbose(node):
189         """Run "show_version" API command and return verbose string of version
190         data.
191
192         :param node: Node to run command on.
193         :type node: dict
194         """
195         VPPUtil.vpp_show_version(node, verbose=True)
196
197     @staticmethod
198     def show_vpp_version_on_all_duts(nodes):
199         """Show VPP version on all DUTs.
200
201         :param nodes: VPP nodes.
202         :type nodes: dict
203         """
204         for node in nodes.values():
205             if node['type'] == NodeType.DUT:
206                 VPPUtil.vpp_show_version_verbose(node)
207
208     @staticmethod
209     def vpp_show_interfaces(node):
210         """Run "show interface" CLI command.
211
212         :param node: Node to run command on.
213         :type node: dict
214         """
215         vat = VatExecutor()
216         vat.execute_script("show_interface.vat", node, json_out=False)
217
218         try:
219             vat.script_should_have_passed()
220         except AssertionError:
221             raise RuntimeError('Failed to get VPP interfaces on host: {name}'.
222                                format(name=node['host']))
223
224     @staticmethod
225     def vpp_show_crypto_device_mapping(node):
226         """Run "show crypto device mapping" CLI command.
227
228         :param node: Node to run command on.
229         :type node: dict
230         """
231         vat = VatExecutor()
232         vat.execute_script("show_crypto_device_mapping.vat", node,
233                            json_out=False)
234
235     @staticmethod
236     def vpp_api_trace_dump(node):
237         """Run "api trace custom-dump" CLI command.
238
239         :param node: Node to run command on.
240         :type node: dict
241         """
242         vat = VatExecutor()
243         vat.execute_script("api_trace_dump.vat", node, json_out=False)
244
245     @staticmethod
246     def vpp_api_trace_save(node):
247         """Run "api trace save" CLI command.
248
249         :param node: Node to run command on.
250         :type node: dict
251         """
252         vat = VatExecutor()
253         vat.execute_script("api_trace_save.vat", node, json_out=False)
254
255     @staticmethod
256     def vpp_enable_traces_on_dut(node):
257         """Enable vpp packet traces on the DUT node.
258
259         :param node: DUT node to set up.
260         :type node: dict
261         """
262         vat = VatExecutor()
263         vat.execute_script("enable_dpdk_traces.vat", node, json_out=False)
264         vat.execute_script("enable_vhost_user_traces.vat", node, json_out=False)
265         vat.execute_script("enable_memif_traces.vat", node, json_out=False)
266
267     @staticmethod
268     def vpp_enable_traces_on_all_duts(nodes):
269         """Enable vpp packet traces on all DUTs in the given topology.
270
271         :param nodes: Nodes in the topology.
272         :type nodes: dict
273         """
274         for node in nodes.values():
275             if node['type'] == NodeType.DUT:
276                 VPPUtil.vpp_enable_traces_on_dut(node)
277
278     @staticmethod
279     def vpp_enable_elog_traces_on_dut(node):
280         """Enable API/CLI/Barrier traces on the DUT node.
281
282         :param node: DUT node to set up.
283         :type node: dict
284         """
285         vat = VatExecutor()
286         vat.execute_script("elog_trace_api_cli_barrier.vat", node,
287                            json_out=False)
288
289     @staticmethod
290     def vpp_enable_elog_traces_on_all_duts(nodes):
291         """Enable API/CLI/Barrier traces on all DUTs in the given topology.
292
293         :param nodes: Nodes in the topology.
294         :type nodes: dict
295         """
296         for node in nodes.values():
297             if node['type'] == NodeType.DUT:
298                 VPPUtil.vpp_enable_elog_traces_on_dut(node)
299
300     @staticmethod
301     def show_event_logger_on_dut(node):
302         """Show event logger on the DUT node.
303
304         :param node: DUT node to show traces on.
305         :type node: dict
306         """
307         vat = VatExecutor()
308         vat.execute_script("show_event_logger.vat", node, json_out=False)
309
310     @staticmethod
311     def show_event_logger_on_all_duts(nodes):
312         """Show event logger on all DUTs in the given topology.
313
314         :param nodes: Nodes in the topology.
315         :type nodes: dict
316         """
317         for node in nodes.values():
318             if node['type'] == NodeType.DUT:
319                 VPPUtil.show_event_logger_on_dut(node)