+ """Contains methods for setting up DUTs."""
+
+ @staticmethod
+ def get_service_logs(node, service):
+ """Get specific service unit logs from node.
+
+ :param node: Node in the topology.
+ :param service: Service unit name.
+ :type node: dict
+ :type service: str
+ """
+ if DUTSetup.running_in_container(node):
+ command = ('echo $(< /var/log/supervisord.log);'
+ 'echo $(< /tmp/*supervisor*.log)')
+ else:
+ command = ('journalctl --no-pager --unit={name} '
+ '--since="$(echo `systemctl show -p '
+ 'ActiveEnterTimestamp {name}` | '
+ 'awk \'{{print $2 $3}}\')"'.
+ format(name=service))
+ message = 'Node {host} failed to get logs from unit {name}'.\
+ format(host=node['host'], name=service)
+
+ exec_cmd_no_error(node, command, timeout=30, sudo=True,
+ message=message)
+
+ @staticmethod
+ def get_service_logs_on_all_duts(nodes, service):
+ """Get specific service unit logs from all DUTs.
+
+ :param nodes: Nodes in the topology.
+ :param service: Service unit name.
+ :type nodes: dict
+ :type service: str
+ """
+ for node in nodes.values():
+ if node['type'] == NodeType.DUT:
+ DUTSetup.get_service_logs(node, service)
+
+ @staticmethod
+ def restart_service(node, service):
+ """Restart the named service on node.
+
+ :param node: Node in the topology.
+ :param service: Service unit name.
+ :type node: dict
+ :type service: str
+ """
+ if DUTSetup.running_in_container(node):
+ command = 'supervisorctl restart {name}'.format(name=service)
+ else:
+ command = 'service {name} restart'.format(name=service)
+ message = 'Node {host} failed to restart service {name}'.\
+ format(host=node['host'], name=service)
+
+ exec_cmd_no_error(
+ node, command, timeout=180, sudo=True, message=message)
+
+ DUTSetup.get_service_logs(node, service)
+
+ @staticmethod
+ def restart_service_on_all_duts(nodes, service):
+ """Restart the named service on all DUTs.
+
+ :param node: Nodes in the topology.
+ :param service: Service unit name.
+ :type node: dict
+ :type service: str
+ """
+ for node in nodes.values():
+ if node['type'] == NodeType.DUT:
+ DUTSetup.restart_service(node, service)
+
+ @staticmethod
+ def start_service(node, service):
+ """Start up the named service on node.
+
+ :param node: Node in the topology.
+ :param service: Service unit name.
+ :type node: dict
+ :type service: str
+ """
+ # TODO: change command to start once all parent function updated.
+ if DUTSetup.running_in_container(node):
+ command = 'supervisorctl restart {name}'.format(name=service)
+ else:
+ command = 'service {name} restart'.format(name=service)
+ message = 'Node {host} failed to start service {name}'.\
+ format(host=node['host'], name=service)
+
+ exec_cmd_no_error(
+ node, command, timeout=180, sudo=True, message=message)
+
+ DUTSetup.get_service_logs(node, service)
+
+ @staticmethod
+ def start_service_on_all_duts(nodes, service):
+ """Start up the named service on all DUTs.
+
+ :param node: Nodes in the topology.
+ :param service: Service unit name.
+ :type node: dict
+ :type service: str
+ """
+ for node in nodes.values():
+ if node['type'] == NodeType.DUT:
+ DUTSetup.start_service(node, service)
+
+ @staticmethod
+ def stop_service(node, service):
+ """Stop the named service on node.
+
+ :param node: Node in the topology.
+ :param service: Service unit name.
+ :type node: dict
+ :type service: str
+ """
+ if DUTSetup.running_in_container(node):
+ command = 'supervisorctl stop {name}'.format(name=service)
+ else:
+ command = 'service {name} stop'.format(name=service)
+ message = 'Node {host} failed to stop service {name}'.\
+ format(host=node['host'], name=service)
+
+ exec_cmd_no_error(
+ node, command, timeout=180, sudo=True, message=message)
+
+ DUTSetup.get_service_logs(node, service)
+
+ @staticmethod
+ def stop_service_on_all_duts(nodes, service):
+ """Stop the named service on all DUTs.
+
+ :param node: Nodes in the topology.
+ :param service: Service unit name.
+ :type node: dict
+ :type service: str
+ """
+ for node in nodes.values():
+ if node['type'] == NodeType.DUT:
+ DUTSetup.stop_service(node, service)
+
+ @staticmethod
+ def get_vpp_pid(node):
+ """Get PID of running VPP process.
+
+ :param node: DUT node.
+ :type node: dict
+ :returns: PID
+ :rtype: int
+ :raises RuntimeError: If it is not possible to get the PID.
+ """
+ ssh = SSH()
+ ssh.connect(node)
+
+ for i in range(3):
+ logger.trace('Try {}: Get VPP PID'.format(i))
+ ret_code, stdout, stderr = ssh.exec_command('pidof vpp')
+
+ if int(ret_code):
+ raise RuntimeError('Not possible to get PID of VPP process '
+ 'on node: {0}\n {1}'.
+ format(node['host'], stdout + stderr))
+
+ pid_list = stdout.split()
+ if len(pid_list) == 1:
+ return int(stdout)
+ elif not pid_list:
+ logger.debug("No VPP PID found on node {0}".
+ format(node['host']))
+ continue
+ else:
+ logger.debug("More then one VPP PID found on node {0}".
+ format(node['host']))
+ return [int(pid) for pid in pid_list]
+
+ return None
+
+ @staticmethod
+ def get_vpp_pids(nodes):
+ """Get PID of running VPP process on all DUTs.
+
+ :param nodes: DUT nodes.
+ :type nodes: dict
+ :returns: PIDs
+ :rtype: dict
+ """
+ pids = dict()
+ for node in nodes.values():
+ if node['type'] == NodeType.DUT:
+ pids[node['host']] = DUTSetup.get_vpp_pid(node)
+ return pids
+
+ @staticmethod
+ def crypto_device_verify(node, crypto_type, numvfs, force_init=False):
+ """Verify if Crypto QAT device virtual functions are initialized on all
+ DUTs. If parameter force initialization is set to True, then try to
+ initialize or remove VFs on QAT.
+
+ :param node: DUT node.
+ :crypto_type: Crypto device type - HW_DH895xcc or HW_C3xxx.
+ :param numvfs: Number of VFs to initialize, 0 - disable the VFs.
+ :param force_init: If True then try to initialize to specific value.
+ :type node: dict
+ :type crypto_type: string
+ :type numvfs: int
+ :type force_init: bool
+ :returns: nothing
+ :raises RuntimeError: If QAT VFs are not created and force init is set
+ to False.
+ """
+ pci_addr = Topology.get_cryptodev(node)
+ sriov_numvfs = DUTSetup.get_sriov_numvfs(node, pci_addr)
+
+ if sriov_numvfs != numvfs:
+ if force_init:
+ # QAT is not initialized and we want to initialize with numvfs
+ DUTSetup.crypto_device_init(node, crypto_type, numvfs)
+ else:
+ raise RuntimeError('QAT device failed to create VFs on {host}'.
+ format(host=node['host']))
+
+ @staticmethod
+ def crypto_device_init(node, crypto_type, numvfs):
+ """Init Crypto QAT device virtual functions on DUT.
+
+ :param node: DUT node.
+ :crypto_type: Crypto device type - HW_DH895xcc or HW_C3xxx.
+ :param numvfs: Number of VFs to initialize, 0 - disable the VFs.
+ :type node: dict
+ :type crypto_type: string
+ :type numvfs: int
+ :returns: nothing
+ :raises RuntimeError: If failed to stop VPP or QAT failed to initialize.
+ """
+ if crypto_type == "HW_DH895xcc":
+ kernel_mod = "qat_dh895xcc"
+ kernel_drv = "dh895xcc"
+ elif crypto_type == "HW_C3xxx":
+ kernel_mod = "qat_c3xxx"
+ kernel_drv = "c3xxx"
+ else:
+ raise RuntimeError('Unsupported crypto device type on {host}'.
+ format(host=node['host']))
+
+ pci_addr = Topology.get_cryptodev(node)
+
+ # QAT device must be re-bound to kernel driver before initialization.
+ DUTSetup.verify_kernel_module(node, kernel_mod, force_load=True)
+
+ # Stop VPP to prevent deadlock.
+ DUTSetup.stop_service(node, Constants.VPP_UNIT)
+
+ current_driver = DUTSetup.get_pci_dev_driver(
+ node, pci_addr.replace(':', r'\:'))
+ if current_driver is not None:
+ DUTSetup.pci_driver_unbind(node, pci_addr)
+
+ # Bind to kernel driver.
+ DUTSetup.pci_driver_bind(node, pci_addr, kernel_drv)
+
+ # Initialize QAT VFs.
+ if numvfs > 0:
+ DUTSetup.set_sriov_numvfs(node, pci_addr, numvfs)
+
+ @staticmethod
+ def get_virtfn_pci_addr(node, pf_pci_addr, vf_id):
+ """Get PCI address of Virtual Function.
+
+ :param node: DUT node.
+ :param pf_pci_addr: Physical Function PCI address.
+ :param vf_id: Virtual Function number.
+ :type node: dict
+ :type pf_pci_addr: str
+ :type vf_id: int
+ :returns: Virtual Function PCI address.
+ :rtype: int
+ :raises RuntimeError: If failed to get Virtual Function PCI address.
+ """
+ command = "sh -c "\
+ "'basename $(readlink /sys/bus/pci/devices/{pci}/virtfn{vf_id})'".\
+ format(pci=pf_pci_addr, vf_id=vf_id)
+ message = 'Failed to get virtual function PCI address.'
+
+ stdout, _ = exec_cmd_no_error(node, command, timeout=30, sudo=True,
+ message=message)
+
+ return stdout.strip()
+
+ @staticmethod
+ def get_sriov_numvfs(node, pf_pci_addr):
+ """Get number of SR-IOV VFs.
+
+ :param node: DUT node.
+ :param pf_pci_addr: Physical Function PCI device address.
+ :type node: dict
+ :type pf_pci_addr: str
+ :returns: Number of VFs.
+ :rtype: int
+ :raises RuntimeError: If PCI device is not SR-IOV capable.
+ """
+ command = 'cat /sys/bus/pci/devices/{pci}/sriov_numvfs'.\
+ format(pci=pf_pci_addr.replace(':', r'\:'))
+ message = 'PCI device {pci} is not a SR-IOV device.'.\
+ format(pci=pf_pci_addr)
+
+ for _ in range(3):
+ stdout, _ = exec_cmd_no_error(node, command, timeout=30, sudo=True,
+ message=message)
+ try:
+ sriov_numvfs = int(stdout)
+ except ValueError:
+ logger.trace('Reading sriov_numvfs info failed on {host}'.
+ format(host=node['host']))
+ else:
+ return sriov_numvfs
+
+ @staticmethod
+ def set_sriov_numvfs(node, pf_pci_addr, numvfs=0):
+ """Init or reset SR-IOV virtual functions by setting its number on PCI
+ device on DUT. Setting to zero removes all VFs.
+
+ :param node: DUT node.
+ :param pf_pci_addr: Physical Function PCI device address.
+ :param numvfs: Number of VFs to initialize, 0 - removes the VFs.
+ :type node: dict
+ :type pf_pci_addr: str
+ :type numvfs: int
+ :raises RuntimeError: Failed to create VFs on PCI.
+ """
+ command = "sh -c "\
+ "'echo {num} | tee /sys/bus/pci/devices/{pci}/sriov_numvfs'".\
+ format(num=numvfs, pci=pf_pci_addr.replace(':', r'\:'))
+ message = 'Failed to create {num} VFs on {pci} device on {host}'.\
+ format(num=numvfs, pci=pf_pci_addr, host=node['host'])
+
+ exec_cmd_no_error(node, command, timeout=120, sudo=True,
+ message=message)
+
+ @staticmethod
+ def pci_driver_unbind(node, pci_addr):
+ """Unbind PCI device from current driver on node.
+
+ :param node: DUT node.
+ :param pci_addr: PCI device address.
+ :type node: dict
+ :type pci_addr: str
+ :raises RuntimeError: If PCI device unbind failed.
+ """
+ command = "sh -c "\
+ "'echo {pci} | tee /sys/bus/pci/devices/{pcie}/driver/unbind'".\
+ format(pci=pci_addr, pcie=pci_addr.replace(':', r'\:'))
+ message = 'Failed to unbind PCI device {pci} on {host}'.\
+ format(pci=pci_addr, host=node['host'])
+
+ exec_cmd_no_error(node, command, timeout=120, sudo=True,
+ message=message)