feat(model): Hoststack type
[csit.git] / resources / tools / ab / ABTools.py
1 # Copyright (c) 2023 Intel 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 """ab implementation into CSIT framework."""
15
16 from resources.libraries.python.Constants import Constants
17 from resources.libraries.python.model.ExportResult import (
18     export_hoststack_results
19 )
20 from resources.libraries.python.OptionString import OptionString
21 from resources.libraries.python.ssh import exec_cmd_no_error
22 from resources.libraries.python.topology import NodeType
23
24
25 class ABTools:
26     """This class implements:
27     - Get ab command.
28     - Check ab version.
29     """
30
31     @staticmethod
32     def get_cmd_options(**kwargs):
33         """Create  parameters options.
34
35         :param kwargs: Dict of cmd parameters.
36         :type kwargs: dict
37         :returns: Cmd parameters.
38         :rtype: OptionString
39         """
40         cmd = OptionString()
41         cmd.add(u"python3")
42         dirname = f"{Constants.REMOTE_FW_DIR}/resources/tools/ab"
43         cmd.add(f"{dirname}/ABFork.py")
44         cmd_options = OptionString(prefix=u"-")
45         # Number of requests to perform.
46         cmd_options.add_with_value_from_dict(u"r", u"requests", kwargs)
47         # Server port number to use.
48         cmd_options.add_with_value_from_dict(u"p", u"port", kwargs)
49         # Number of clients being processed at the same time.
50         cmd_options.add_with_value_from_dict(u"c", u"clients", kwargs)
51         # Filename to be requested from the servers.
52         cmd_options.add_with_value_from_dict(u"f", u"files", kwargs)
53         # Server ip address.
54         cmd_options.add_with_value_from_dict(u"i", u"ip", kwargs)
55         # tg ip address.
56         cmd_options.add_with_value_from_dict(u"g", u"tip", kwargs)
57         # Specify SSL/TLS cipher suite.
58         cmd_options.add_with_value_from_dict(u"z", u"cipher", kwargs, default=0)
59         # Specify SSL/TLS protocol.
60         cmd_options.add_with_value_from_dict(u"t", u"protocol", kwargs,
61                                              default=0)
62         # Mode: RPS or CPS.
63         cmd_options.add_with_value_from_dict(u"m", u"mode", kwargs)
64         return cmd.extend(cmd_options)
65
66     @staticmethod
67     def check_ab(tg_node):
68         """Check if ab is installed on the TG node.
69
70         :param tg_node: Topology node.
71         :type tg_node: dict
72         :raises: RuntimeError if the given node is not a TG node or if the
73             command is not available.
74         """
75
76         if tg_node[u"type"] != NodeType.TG:
77             raise RuntimeError(u"Node type is not a TG!")
78
79         cmd = u"command -v ab"
80         message = u"ab not installed on TG node!"
81         exec_cmd_no_error(tg_node, cmd, message=message)
82
83     @staticmethod
84     def get_ab_type(node):
85         """Log and return the installed traffic generator type.
86
87         :param node: Node from topology file.
88         :type node: dict
89         :returns: Traffic generator type string.
90         :rtype: str
91         """
92         return "AB"
93
94     @staticmethod
95     def get_ab_version(node):
96         """Log and return the installed traffic generator version.
97
98         :param node: Node from topology file.
99         :type node: dict
100         :returns: Traffic generator version string.
101         :rtype: str
102         """
103         command = f"ab -V | head -1 | cut -d',' -f2"
104         message = u"Get AB version failed!"
105         stdout, _ = exec_cmd_no_error(node, command, message=message)
106         return stdout.strip()
107
108     @staticmethod
109     def run_ab(tg_node, ip_addr, tg_addr, tls_tcp, cipher, files_num, rps_cps,
110                r_total, c_total, port, protocol=u"TLS1.3"):
111         """ Run ab test.
112
113         :param tg_node: Topology node.
114         :param ip_addr: Sut ip address.
115         :param tg_addr: Tg ip address.
116         :param tls_tcp: TLS or TCP.
117         :param cipher: Specify SSL/TLS cipher suite.
118         :param files_num: Filename to be requested from the servers.
119         The file is named after the file size.
120         :param rps_cps: RPS or CPS.
121         :param r_total: Requests total.
122         :param r_total: Clients total.
123         :param port: Server listen port.
124         :param protocol: TLS Protocol.
125         :type tg_node: dict
126         :type ip_addr: str
127         :type tg_addr: str
128         :type tls_tcp: str
129         :type cipher: str
130         :type files_num: int
131         :type rps_cps: str
132         :type r_total: int
133         :type c_total: int
134         :type port: int
135         :type protocol: str
136         :returns: Message with measured data.
137         :rtype: str
138         :raises: RuntimeError if node type is not a TG.
139         """
140         if files_num == 0:
141             files = u"return"
142         elif files_num >= 1024:
143             files = f"{int(files_num / 1024)}KB.json"
144         else:
145             files = f"{files_num}B.json"
146
147         cmd = ABTools.get_cmd_options(
148             requests=r_total,
149             clients=c_total,
150             ip=ip_addr,
151             tip=tg_addr,
152             files=files,
153             cipher=cipher,
154             protocol=protocol,
155             port=port,
156             mode=rps_cps,
157         )
158         stdout, _ = exec_cmd_no_error(
159             tg_node, cmd, timeout=180, sudo=True, message=u"ab runtime error!"
160         )
161
162         rate_unit = rps_cps
163         rate = None
164         bandwidth = None
165         latency = None
166         completed_requests = None
167         failed_requests = None
168         for line in stdout.splitlines():
169             if f"Connection {rps_cps} rate:" in line:
170                 rate = float(line.split(u" ")[3])
171             elif u"Transfer Rate:" in line:
172                 bandwidth = float(line.split(u" ")[2]) * 8000
173             elif u"Latency:" in line:
174                 latency = float(line.split(u" ")[1])
175             elif u"Completed requests:" in line:
176                 completed_requests = int(line.split(u" ")[2])
177             elif u"Failed requests" in line:
178                 failed_requests = int(line.split(u" ")[2])
179
180         export_hoststack_results(
181             rate, rate_unit, bandwidth, latency, failed_requests,
182             completed_requests
183         )
184
185         return stdout