1 # Copyright (c) 2016 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:
6 # http://www.apache.org/licenses/LICENSE-2.0
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.
14 """DUT setup library."""
16 from robot.api import logger
18 from resources.libraries.python.topology import NodeType, Topology
19 from resources.libraries.python.ssh import SSH
20 from resources.libraries.python.constants import Constants
21 from resources.libraries.python.VatExecutor import VatExecutor
24 class DUTSetup(object):
25 """Contains methods for setting up DUTs."""
27 def start_vpp_service_on_all_duts(nodes):
28 """Start up the VPP service on all nodes."""
30 for node in nodes.values():
31 if node['type'] == NodeType.DUT:
33 (ret_code, stdout, stderr) = \
34 ssh.exec_command_sudo('service vpp restart', timeout=120)
35 if int(ret_code) != 0:
36 logger.debug('stdout: {0}'.format(stdout))
37 logger.debug('stderr: {0}'.format(stderr))
38 raise Exception('DUT {0} failed to start VPP service'.
42 def vpp_show_version_verbose(node):
43 """Run "show version verbose" CLI command.
45 :param node: Node to run command on.
49 vat.execute_script("show_version_verbose.vat", node, json_out=False)
52 def show_vpp_version_on_all_duts(nodes):
53 """Show VPP version verbose on all DUTs.
55 :param nodes: VPP nodes
58 for node in nodes.values():
59 if node['type'] == NodeType.DUT:
60 DUTSetup.vpp_show_version_verbose(node)
63 def vpp_api_trace_save(node):
64 """Run "api trace save" CLI command.
66 :param node: Node to run command on.
70 vat.execute_script("api_trace_save.vat", node, json_out=False)
73 def vpp_api_trace_dump(node):
74 """Run "api trace custom-dump" CLI command.
76 :param node: Node to run command on.
80 vat.execute_script("api_trace_dump.vat", node, json_out=False)
83 def setup_all_duts(nodes):
84 """Prepare all DUTs in given topology for test execution."""
85 for node in nodes.values():
86 if node['type'] == NodeType.DUT:
87 DUTSetup.setup_dut(node)
91 """Run script over SSH to setup the DUT node.
93 :param node: DUT node to set up.
96 :raises Exception: If the DUT setup fails.
101 (ret_code, stdout, stderr) = \
102 ssh.exec_command('sudo -Sn bash {0}/{1}/dut_setup.sh'.
103 format(Constants.REMOTE_FW_DIR,
104 Constants.RESOURCES_LIB_SH), timeout=120)
107 if int(ret_code) != 0:
108 logger.debug('DUT {0} setup script failed: "{1}"'.
109 format(node['host'], stdout + stderr))
110 raise Exception('DUT test setup script failed at node {}'.
111 format(node['host']))
114 def get_vpp_pid(node):
115 """Get PID of running VPP process.
117 :param node: DUT node.
121 :raises RuntimeError if it is not possible to get the PID.
128 logger.trace('Try {}: Get VPP PID'.format(i))
129 ret_code, stdout, stderr = ssh.exec_command('pidof vpp')
131 if int(ret_code) != 0:
132 raise RuntimeError('Not possible to get PID of VPP process '
133 'on node: {0}\n {1}'.
134 format(node['host'], stdout + stderr))
136 if len(stdout.splitlines()) == 1:
138 elif len(stdout.splitlines()) == 0:
139 logger.debug("No VPP PID found on node {0}".
140 format(node['host']))
143 logger.debug("More then one VPP PID found on node {0}".
144 format(node['host']))
146 for line in stdout.splitlines():
147 ret_list.append(int(line))
153 def get_vpp_pids(nodes):
154 """Get PID of running VPP process on all DUTs.
156 :param nodes: DUT nodes.
163 for node in nodes.values():
164 if node['type'] == NodeType.DUT:
165 pids[node['host']] = DUTSetup.get_vpp_pid(node)
169 def vpp_show_crypto_device_mapping(node):
170 """Run "show crypto device mapping" CLI command.
172 :param node: Node to run command on.
176 vat.execute_script("show_crypto_device_mapping.vat", node,
180 def crypto_device_verify(node, force_init=False, numvfs=32):
181 """Verify if Crypto QAT device virtual functions are initialized on all
182 DUTs. If parameter force initialization is set to True, then try to
183 initialize or disable QAT.
185 :param node: DUT node.
186 :param force_init: If True then try to initialize to specific value.
187 :param numvfs: Number of VFs to initialize, 0 - disable the VFs.
189 :type force_init: bool
192 :raises RuntimeError: If QAT is not initialized or failed to initialize.
198 cryptodev = Topology.get_cryptodev(node)
199 cmd = 'cat /sys/bus/pci/devices/{}/sriov_numvfs'.\
200 format(cryptodev.replace(':', r'\:'))
202 # Try to read number of VFs from PCI address of QAT device
204 ret_code, stdout, _ = ssh.exec_command(cmd)
205 if int(ret_code) == 0:
207 sriov_numvfs = int(stdout)
209 logger.trace('Reading sriov_numvfs info failed on: {}'.
210 format(node['host']))
212 if sriov_numvfs != numvfs:
214 # QAT is not initialized and we want to initialize
216 DUTSetup.crypto_device_init(node, numvfs)
218 raise RuntimeError('QAT device {} is not '
219 'initialized to {} on host: {}'.
220 format(cryptodev, numvfs,
225 def crypto_device_init(node, numvfs):
226 """Init Crypto QAT device virtual functions on DUT.
228 :param node: DUT node.
229 :param numvfs: Number of VFs to initialize, 0 - disable the VFs.
233 :raises RuntimeError: If QAT failed to initialize.
239 cryptodev = Topology.get_cryptodev(node)
241 # QAT device must be bind to kernel driver before initialization
242 DUTSetup.pci_driver_unbind(node, cryptodev)
243 DUTSetup.pci_driver_bind(node, cryptodev, "dh895xcc")
246 ret_code, _, _ = ssh.exec_command(
247 "sudo sh -c 'echo {} | tee /sys/bus/pci/devices/{}/sriov_numvfs'"
248 .format(numvfs, cryptodev.replace(':', r'\:')))
250 if int(ret_code) != 0:
251 raise RuntimeError('Failed to initialize {} VFs on QAT device on '
252 'host: {}'.format(numvfs, node['host']))
255 def pci_driver_unbind(node, pci_addr):
256 """Unbind PCI device from current driver on node.
258 :param node: DUT node.
259 :param pci_addr: PCI device address.
263 :raises RuntimeError: If PCI device unbind failed.
269 ret_code, _, _ = ssh.exec_command(
270 "sudo sh -c 'echo {} | tee /sys/bus/pci/devices/{}/driver/unbind'"
271 .format(pci_addr, pci_addr.replace(':', r'\:')))
273 if int(ret_code) != 0:
274 raise RuntimeError('Failed to unbind PCI device from driver on '
275 'host: {}'.format(node['host']))
278 def pci_driver_bind(node, pci_addr, driver):
279 """Bind PCI device to driver on node.
281 :param node: DUT node.
282 :param pci_addr: PCI device address.
283 :param driver: Driver to bind.
288 :raises RuntimeError: If PCI device bind failed.
294 ret_code, _, _ = ssh.exec_command(
295 "sudo sh -c 'echo {} | tee /sys/bus/pci/drivers/{}/bind'"
296 .format(pci_addr, driver))
298 if int(ret_code) != 0:
299 raise RuntimeError('Failed to bind PCI device to {} driver on '
300 'host: {}'.format(driver, node['host']))
303 def kernel_module_verify(node, module, force_load=False):
304 """Verify if kernel module is loaded on all DUTs. If parameter force
305 load is set to True, then try to load the modules.
307 :param node: DUT node.
308 :param module: Module to verify.
309 :param force_load: If True then try to load module.
312 :type force_init: bool
314 :raises RuntimeError: If module is not loaded or failed to load.
320 cmd = 'grep -w {} /proc/modules'.format(module)
321 ret_code, _, _ = ssh.exec_command(cmd)
323 if int(ret_code) != 0:
325 # Module is not loaded and we want to load it
326 DUTSetup.kernel_module_load(node, module)
328 raise RuntimeError('Kernel module {} is not loaded on host: {}'.
329 format(module, node['host']))
332 def kernel_module_load(node, module):
333 """Load kernel module on node.
335 :param node: DUT node.
336 :param module: Module to load.
340 :raises RuntimeError: If loading failed.
346 ret_code, _, _ = ssh.exec_command_sudo("modprobe {}".format(module))
348 if int(ret_code) != 0:
349 raise RuntimeError('Failed to load {} kernel module on host: {}'.
350 format(module, node['host']))