feat(tests): IPv6 fixes
[csit.git] / resources / libraries / python / TelemetryUtil.py
1 # Copyright (c) 2021 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 """Telemetry utility."""
15
16 from robot.api import logger
17
18 from resources.libraries.python.Constants import Constants
19 from resources.libraries.python.OptionString import OptionString
20 from resources.libraries.python.ssh import exec_cmd, exec_cmd_no_error
21 from resources.libraries.python.topology import NodeType
22
23 __all__ = [u"TelemetryUtil"]
24
25
26 class TelemetryUtil:
27     """Class contains methods for telemetry utility."""
28
29     @staticmethod
30     def perf_stat(node, cpu_list=None, duration=1):
31         """Get perf stat read for duration.
32
33         :param node: Node in the topology.
34         :param cpu_list: CPU List as a string separated by comma.
35         :param duration: Measure time in seconds.
36         :type node: dict
37         :type cpu_list: str
38         :type duration: int
39         """
40         if cpu_list:
41             cpu_list = list(dict.fromkeys(cpu_list.split(u",")))
42             cpu_list = ",".join(str(cpu) for cpu in cpu_list)
43
44         cmd_opts = OptionString(prefix=u"--")
45         cmd_opts.add(u"no-aggr")
46         cmd_opts.add_with_value_if(
47             u"cpu", cpu_list, cpu_list
48         )
49         cmd_opts.add_if(
50             u"all-cpus", not(cpu_list)
51         )
52         cmd_opts.add_with_value_if(
53             u"event", f"'{{{Constants.PERF_STAT_EVENTS}}}'",
54             Constants.PERF_STAT_EVENTS
55         )
56         cmd_opts.add_with_value(
57             u"interval-print", 1000
58         )
59         cmd_opts.add_with_value(
60             u"field-separator", u"';'"
61         )
62
63         cmd_base = OptionString()
64         cmd_base.add(f"perf stat")
65         cmd_base.extend(cmd_opts)
66         cmd_base.add(u"--")
67         cmd_base.add_with_value(u"sleep", int(duration))
68
69         exec_cmd(node, cmd_base, sudo=True)
70
71     @staticmethod
72     def perf_stat_on_all_duts(nodes, cpu_list=None, duration=1):
73         """Get perf stat read for duration on all DUTs.
74
75         :param nodes: Nodes in the topology.
76         :param cpu_list: CPU List.
77         :param duration: Measure time in seconds.
78         :type nodes: dict
79         :type cpu_list: str
80         :type duration: int
81         """
82         for node in nodes.values():
83             if node[u"type"] == NodeType.DUT:
84                 TelemetryUtil.perf_stat(
85                     node, cpu_list=cpu_list, duration=duration
86                 )
87
88     @staticmethod
89     def run_telemetry(node, profile, hook=None):
90         """Get telemetry stat read for duration.
91
92         :param node: Node in the topology.
93         :param profile: Telemetry configuration profile.
94         :param hook: Process ID or socket path (optional).
95         :type node: dict
96         :type profile: str
97         :type hook: str
98         """
99         config = u""
100         config += f"{Constants.REMOTE_FW_DIR}/"
101         config += f"{Constants.RESOURCES_TPL_TELEMETRY}/"
102         config += f"{profile}"
103
104         cd_cmd = u""
105         cd_cmd += f"sh -c \"cd {Constants.REMOTE_FW_DIR}/"
106         cd_cmd += f"{Constants.RESOURCES_TOOLS}"
107
108         bin_cmd = f"python3 -m telemetry --config {config} --hook {hook}\""
109         hostname = node[u"host"]
110
111         exec_cmd_no_error(node, f"{cd_cmd} && {bin_cmd}", sudo=True)
112         stdout, _ = exec_cmd_no_error(
113             node, u"cat /tmp/metric.prom", sudo=True, log_stdout_err=False
114         )
115         logger.info(
116             u"# TYPE target info\n"
117             u"# HELP target Target metadata\n"
118             f"target_info{{hostname=\"{hostname}\",hook=\"{hook}\"}} 1\n"
119             f"{stdout}"
120         )
121
122     @staticmethod
123     def run_telemetry_on_all_duts(nodes, profile):
124         """Get telemetry stat read on all DUTs.
125
126         :param nodes: Nodes in the topology.
127         :param profile: Telemetry configuration profile.
128         :param hooks: Dict of Process IDs or socket paths (optional).
129         :type nodes: dict
130         :type profile: str
131         :type hooks: dict
132         """
133         for node in nodes.values():
134             if node[u"type"] == NodeType.DUT:
135                 try:
136                     for socket in node[u"sockets"][u"PAPI"].values():
137                         TelemetryUtil.run_telemetry(
138                             node, profile=profile, hook=socket
139                         )
140                 except IndexError:
141                     pass