Refactor getting telemetry
[csit.git] / resources / libraries / python / VppCounters.py
1 # Copyright (c) 2019 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 counters utilities library."""
15
16 from pprint import pformat
17
18 from robot.api import logger
19 from resources.libraries.python.PapiExecutor import PapiExecutor
20 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
21 from resources.libraries.python.topology import Topology, SocketType, NodeType
22
23
24 class VppCounters(object):
25     """VPP counters utilities."""
26
27     def __init__(self):
28         self._stats_table = None
29
30     @staticmethod
31     def vpp_show_errors(node):
32         """Run "show errors" debug CLI command.
33
34         :param node: Node to run command on.
35         :type node: dict
36         """
37         PapiSocketExecutor.run_cli_cmd_on_all_sockets(
38             node, 'show errors')
39
40     @staticmethod
41     def vpp_show_errors_on_all_duts(nodes):
42         """Show errors on all DUTs.
43
44         :param nodes: VPP nodes.
45         :type nodes: dict
46         """
47         for node in nodes.values():
48             if node['type'] == NodeType.DUT:
49                 VppCounters.vpp_show_errors(node)
50
51     @staticmethod
52     def vpp_show_runtime(node, log_zeros=False):
53         """Run "show runtime" CLI command.
54
55         :param node: Node to run command on.
56         :param log_zeros: Log also items with zero values.
57         :type node: dict
58         :type log_zeros: bool
59         """
60         args = dict(path='^/sys/node')
61         sockets = Topology.get_node_sockets(node, socket_type=SocketType.STATS)
62         if sockets:
63             for socket in sockets.values():
64                 with PapiExecutor(node) as papi_exec:
65                     stats = papi_exec.add("vpp-stats", **args).\
66                         get_stats(socket=socket)[0]
67
68                 names = stats['/sys/node/names']
69
70                 if not names:
71                     return
72
73                 runtime = []
74                 runtime_non_zero = []
75
76                 for name in names:
77                     runtime.append({'name': name})
78
79                 for idx, runtime_item in enumerate(runtime):
80
81                     calls_th = []
82                     for thread in stats['/sys/node/calls']:
83                         calls_th.append(thread[idx])
84                     runtime_item["calls"] = calls_th
85
86                     vectors_th = []
87                     for thread in stats['/sys/node/vectors']:
88                         vectors_th.append(thread[idx])
89                     runtime_item["vectors"] = vectors_th
90
91                     suspends_th = []
92                     for thread in stats['/sys/node/suspends']:
93                         suspends_th.append(thread[idx])
94                     runtime_item["suspends"] = suspends_th
95
96                     clocks_th = []
97                     for thread in stats['/sys/node/clocks']:
98                         clocks_th.append(thread[idx])
99                     runtime_item["clocks"] = clocks_th
100
101                     if (sum(calls_th) or sum(vectors_th) or
102                             sum(suspends_th) or sum(clocks_th)):
103                         runtime_non_zero.append(runtime_item)
104
105                 if log_zeros:
106                     logger.info(
107                         "stats runtime ({host} - {socket}):\n{runtime}".format(
108                         host=node['host'], runtime=pformat(runtime),
109                         socket=socket))
110                 else:
111                     logger.info(
112                         "stats runtime ({host} - {socket}):\n{runtime}".format(
113                         host=node['host'], runtime=pformat(runtime_non_zero),
114                         socket=socket))
115
116     @staticmethod
117     def vpp_show_runtime_counters_on_all_duts(nodes):
118         """Clear VPP runtime counters on all DUTs.
119
120         :param nodes: VPP nodes.
121         :type nodes: dict
122         """
123         for node in nodes.values():
124             if node['type'] == NodeType.DUT:
125                 VppCounters.vpp_show_runtime(node)
126
127     @staticmethod
128     def vpp_show_hardware_verbose(node):
129         """Run "show hardware-interfaces verbose" debug CLI command.
130
131         :param node: Node to run command on.
132         :type node: dict
133         """
134         PapiSocketExecutor.run_cli_cmd_on_all_sockets(
135             node, 'show hardware verbose')
136
137     @staticmethod
138     def vpp_show_memory(node):
139         """Run "show memory" debug CLI command.
140
141         Currently, every flag is hardcoded, giving the longest output.
142
143         :param node: Node to run command on.
144         :type node: dict
145         """
146         PapiSocketExecutor.run_cli_cmd(
147             node, 'show memory verbose api-segment stats-segment main-heap')
148
149     @staticmethod
150     def vpp_clear_runtime(node):
151         """Run "clear runtime" CLI command.
152
153         :param node: Node to run command on.
154         :type node: dict
155         """
156         PapiSocketExecutor.run_cli_cmd_on_all_sockets(
157             node, 'clear runtime', log=False)
158
159     @staticmethod
160     def vpp_clear_runtime_counters_on_all_duts(nodes):
161         """Run "clear runtime" CLI command on all DUTs.
162
163         :param nodes: VPP nodes.
164         :type nodes: dict
165         """
166         for node in nodes.values():
167             if node['type'] == NodeType.DUT:
168                 VppCounters.vpp_clear_runtime(node)
169
170     @staticmethod
171     def vpp_clear_hardware_counters(node):
172         """Run "clear hardware" CLI command.
173
174         :param node: Node to run command on.
175         :type node: dict
176         :returns: Verified data from PAPI response.
177         :rtype: dict
178         """
179         PapiSocketExecutor.run_cli_cmd_on_all_sockets(
180             node, 'clear hardware', log=False)
181
182     @staticmethod
183     def vpp_clear_hardware_counters_on_all_duts(nodes):
184         """Clear hardware counters on all DUTs.
185
186         :param nodes: VPP nodes.
187         :type nodes: dict
188         """
189         for node in nodes.values():
190             if node['type'] == NodeType.DUT:
191                 VppCounters.vpp_clear_hardware_counters(node)
192
193     @staticmethod
194     def vpp_clear_errors_counters(node):
195         """Run "clear errors" CLI command.
196
197         :param node: Node to run command on.
198         :type node: dict
199         """
200         PapiSocketExecutor.run_cli_cmd_on_all_sockets(
201             node, 'clear errors', log=False)
202
203     @staticmethod
204     def vpp_clear_error_counters_on_all_duts(nodes):
205         """Clear VPP errors counters on all DUTs.
206
207         :param nodes: VPP nodes.
208         :type nodes: dict
209         """
210         for node in nodes.values():
211             if node['type'] == NodeType.DUT:
212                 VppCounters.vpp_clear_errors_counters(node)
213
214     @staticmethod
215     def show_vpp_statistics(node):
216         """Show [error, hardware, interface] stats.
217
218         :param node: VPP node.
219         :type node: dict
220         """
221         VppCounters.vpp_show_errors(node)
222         VppCounters.vpp_show_hardware_verbose(node)
223         VppCounters.vpp_show_runtime(node)
224         VppCounters.vpp_show_memory(node)
225
226     @staticmethod
227     def show_statistics_on_all_duts(nodes):
228         """Show statistics on all DUTs.
229
230         :param nodes: DUT nodes.
231         :type nodes: dict
232         """
233         for node in nodes.values():
234             if node['type'] == NodeType.DUT:
235                 VppCounters.show_vpp_statistics(node)
236
237     @staticmethod
238     def clear_vpp_statistics(node):
239         """Clear [error, hardware, interface] stats.
240
241         :param node: VPP node.
242         :type node: dict
243         """
244         VppCounters.vpp_clear_errors_counters(node)
245         VppCounters.vpp_clear_hardware_counters(node)
246         VppCounters.vpp_clear_runtime(node)
247
248     @staticmethod
249     def clear_statistics_on_all_duts(nodes):
250         """Clear statistics on all DUTs.
251
252         :param nodes: DUT nodes.
253         :type nodes: dict
254         """
255         for node in nodes.values():
256             if node['type'] == NodeType.DUT:
257                 VppCounters.clear_vpp_statistics(node)