Exemple #1
0
    def perf_stat(node, cpu_list=None, duration=1):
        """Get perf stat read for duration.

        :param node: Node in the topology.
        :param cpu_list: CPU List as a string separated by comma.
        :param duration: Measure time in seconds.
        :type node: dict
        :type cpu_list: str
        :type duration: int
        """
        if cpu_list:
            cpu_list = list(dict.fromkeys(cpu_list.split(u",")))
            cpu_list = ",".join(str(cpu) for cpu in cpu_list)

        cmd_opts = OptionString(prefix=u"--")
        cmd_opts.add(u"no-aggr")
        cmd_opts.add_with_value_if(u"cpu", cpu_list, cpu_list)
        cmd_opts.add_if(u"all-cpus", not (cpu_list))
        cmd_opts.add_with_value_if(u"event",
                                   f"'{{{Constants.PERF_STAT_EVENTS}}}'",
                                   Constants.PERF_STAT_EVENTS)
        cmd_opts.add_with_value(u"interval-print", 1000)
        cmd_opts.add_with_value(u"field-separator", u"';'")

        cmd_base = OptionString()
        cmd_base.add(f"perf stat")
        cmd_base.extend(cmd_opts)
        cmd_base.add(u"--")
        cmd_base.add_with_value(u"sleep", int(duration))

        exec_cmd(node, cmd_base, sudo=True)
Exemple #2
0
    def setup_dmm_dut(dut1_node, dut2_node, dut1_if_name, dut2_if_name,
                      script_name, dut1_ip, dut2_ip, prefix_len):
        """
        Setup DMM on DUT nodes.

        :param dut1_node: Node to setup DMM on.
        :param dut2_node: Node to setup DMM on.
        :param dut1_if_name: DUT1 to DUT2 interface name.
        :param dut2_if_name: DUT2 to DUT1 interface name.
        :param script_name: Name of the script to run.
        :param dut1_ip: IP address to configure on DUT1.
        :param dut2_ip: IP address to configure on DUT2.
        :param prefix_len: Prefix length.
        :type dut1_node: dict
        :type dut2_node: dict
        :type dut1_if_name: str
        :type dut2_if_name: str
        :type script_name: str
        :type dut1_ip: str
        :type dut2_ip: str
        :type prefix_len: int
        """
        SingleCliSer.set_dmm_interface_address(dut1_node, dut1_if_name,
                                               dut1_ip, prefix_len)
        SingleCliSer.set_dmm_interface_address(dut2_node, dut2_if_name,
                                               dut2_ip, prefix_len)
        cmd = 'cd {0}/{1} && ./{2} setup 0 {3} {4} {5}'\
            .format(con.REMOTE_FW_DIR, con.DMM_RUN_SCRIPTS, script_name,
                    dut1_if_name, dut1_ip, dut2_ip)
        exec_cmd(dut1_node, cmd)

        cmd = 'cd {0}/{1} && ./{2} setup 1 {3} {4} {5}'\
            .format(con.REMOTE_FW_DIR, con.DMM_RUN_SCRIPTS, script_name,
                    dut2_if_name, dut1_ip, dut2_ip)
        exec_cmd(dut2_node, cmd)
Exemple #3
0
    def execute_test(dut1_node, dut2_node, dut1_if_name, dut2_if_name,
                     script_name, dut1_ip, dut2_ip):
        """
        Run the given test case.

        :param dut1_node: Node to run an app with DMM on.
        :param dut2_node: Node to run an app with DMM on.
        :param dut1_if_name: DUT1 to DUT2 interface name.
        :param dut2_if_name: DUT2 to DUT1 interface name.
        :param script_name: Name of the script to run.
        :param dut1_ip: DUT1 IP address.
        :param dut2_ip: DUT2 IP address.
        :type dut1_node: dict
        :type dut2_node: dict
        :type dut1_if_name: str
        :type dut2_if_name: str
        :type script_name: str
        :type dut1_ip: str
        :type dut2_ip: str
        """
        cmd = 'cd {0}/{1} && ./{2} run 0 {3} {4} {5} ' \
            .format(con.REMOTE_FW_DIR, con.DMM_RUN_SCRIPTS, script_name,
                    dut1_if_name, dut1_ip, dut2_ip)
        cmd += '2>&1 | tee log_{0}.txt &'.format(script_name)
        exec_cmd(dut1_node, cmd)
        time.sleep(10)

        cmd = 'cd {0}/{1} && ./{2} run 1 {3} {4} {5} ' \
            .format(con.REMOTE_FW_DIR, con.DMM_RUN_SCRIPTS, script_name,
                    dut2_if_name, dut1_ip, dut2_ip)
        cmd += '2>&1 | tee log_{0}.txt'.format(script_name)
        exec_cmd(dut2_node, cmd)
Exemple #4
0
    def verify_vpp_started(node):
        """Verify that VPP is started on the specified topology node.

        :param node: Topology node.
        :type node: dict
        """
        cmd = u"echo \"show pci\" | sudo socat - UNIX-CONNECT:/run/vpp/cli.sock"
        exec_cmd_no_error(node,
                          cmd,
                          sudo=False,
                          message=u"VPP failed to start!",
                          retries=120)

        cmd = u"vppctl show pci 2>&1 | fgrep -v \"Connection refused\" | " \
              u"fgrep -v \"No such file or directory\""
        exec_cmd_no_error(node,
                          cmd,
                          sudo=True,
                          message=u"VPP failed to start!",
                          retries=120)

        # Properly enable cards in case they were disabled. This will be
        # followed in https://jira.fd.io/browse/VPP-1934.
        cmd = u"for i in $(sudo vppctl sho int | grep Eth | cut -d' ' -f1); do"\
              u" sudo vppctl set int sta $i up; done"
        exec_cmd(node, cmd, sudo=False)
Exemple #5
0
    def get_logs_from_node(dut_node):
        """
        Get logs from node to the test executor machine.

        :param dut_node: Node to artifact the logs of.
        :type dut_node: dict
        """
        ssh = SSH()
        ssh.connect(dut_node)
        ssh.scp(".",
                '/var/log/nStack/*.log',
                get=True,
                timeout=60,
                wildcard=True)

        (ret, _, _) = exec_cmd(dut_node, 'ls -l /var/log/app*.log')
        if ret == 0:
            ssh.scp(".",
                    '/var/log/app*.log',
                    get=True,
                    timeout=60,
                    wildcard=True)

        exec_cmd(dut_node, 'rm -rf /var/log/nStack/*.log', sudo=True)
        exec_cmd(dut_node, 'rm -rf /var/log/app*.log', sudo=True)
Exemple #6
0
    def verify_test_result(dut1_node, dut2_node, script_name):
        """
        Verify the test and return result.

        :param dut1_node: Node to verify test result on.
        :param dut2_node: Node to verify test result on.
        :param script_name: Name of the script to run.
        :type dut1_node: dict
        :type dut2_node: dict
        :type script_name: str
        :returns: test result PASS/FAIL.
        :rtype: str
        """
        cmd = 'cd {0}/{1} && ./{2} verify 0' \
            .format(con.REMOTE_FW_DIR, con.DMM_RUN_SCRIPTS, script_name)
        (_, stdout_ser, _) = exec_cmd(dut1_node, cmd)

        cmd = 'cd {0}/{1} && ./{2} verify 1' \
            .format(con.REMOTE_FW_DIR, con.DMM_RUN_SCRIPTS, script_name)
        (_, stdout_cli, _) = exec_cmd(dut2_node, cmd)

        if stdout_ser.find('DMM_CSIT_TEST_PASSED') != -1 \
                and stdout_cli.find('DMM_CSIT_TEST_PASSED') != -1:
            return "PASS"
        else:
            return "FAIL"
Exemple #7
0
    def linux_interface_has_ip(node,
                               interface,
                               ip_addr,
                               prefix_length,
                               namespace=None):
        """Return True if interface in linux has IP address.

        :param node: VPP/TG node.
        :param interface: Interface in namespace.
        :param ip_addr: IP to be queried on interface.
        :param prefix_length: IP prefix length.
        :param namespace: Execute command in namespace. Optional
        :type node: dict
        :type interface: str
        :type ip_addr: str
        :type prefix_length: int
        :type namespace: str
        :rtype boolean
        :raises RuntimeError: Request fails.
        """
        ip_addr_with_prefix = f"{ip_addr}/{prefix_length}"
        if namespace is not None:
            cmd = f"ip netns exec {namespace} ip addr show dev {interface}"
        else:
            cmd = f"ip addr show dev {interface}"

        cmd += u" | grep 'inet ' | awk -e '{print $2}'"
        cmd += f" | grep '{ip_addr_with_prefix}'"
        _, stdout, _ = exec_cmd(node, cmd, timeout=5, sudo=True)

        has_ip = stdout.rstrip()
        return bool(has_ip == ip_addr_with_prefix)
Exemple #8
0
    def get_linux_interface_name(node, pci_addr):
        """Get the interface name.

        :param node: Node where to execute command.
        :param pci_addr: PCI address
        :type node: dict
        :type pci_addr: str
        :returns: Interface name
        :rtype: str
        :raises RuntimeError: If cannot get the information about interfaces.
        """

        regex_intf_info = r"pci@" \
                          r"([0-9a-f]{4}:[0-9a-f]{2}:[0-9a-f]{2}.[0-9a-f])\s*" \
                          r"([a-zA-Z0-9]*)\s*network"

        cmd = "lshw -class network -businfo"
        ret_code, stdout, stderr = exec_cmd(node, cmd, timeout=30, sudo=True)
        if ret_code != 0:
            raise RuntimeError('Could not get information about interfaces, '
                               'reason:{0}'.format(stderr))

        for line in stdout.splitlines()[2:]:
            try:
                if re.search(regex_intf_info, line).group(1) == pci_addr:
                    return re.search(regex_intf_info, line).group(2)
            except AttributeError:
                continue
        return None
Exemple #9
0
    def set_linux_interface_ip(node,
                               interface,
                               ip_addr,
                               prefix,
                               namespace=None):
        """Set IP address to interface in linux.

        :param node: Node where to execute command.
        :param interface: Interface in namespace.
        :param ip_addr: IP to be set on interface.
        :param prefix: IP prefix.
        :param namespace: Execute command in namespace. Optional
        :type node: dict
        :type interface: str
        :type ip_addr: str
        :type prefix: int
        :type namespace: str
        :raises RuntimeError: IP could not be set.
        """
        if namespace is not None:
            cmd = 'ip netns exec {} ip addr add {}/{} dev {}'.format(
                namespace, ip_addr, prefix, interface)
        else:
            cmd = 'ip addr add {}/{} dev {}'.format(ip_addr, prefix, interface)
        (ret_code, _, stderr) = exec_cmd(node, cmd, timeout=5, sudo=True)
        if ret_code != 0:
            raise RuntimeError(
                'Could not set IP for interface, reason:{}'.format(stderr))
Exemple #10
0
    def cleanup_dmm_dut(dut1_node, dut2_node, script_name):
        """
        Cleanup DMM DUT node.

        :param dut1_node: DMM node to be cleaned up.
        :param dut2_node: DMM node to be cleaned up.
        :param script_name: Name of the script to run.
        :type dut1_node: dict
        :type dut2_node: dict
        :type script_name: str
        """
        cmd = 'cd {0}/{1} && ./{2} cleanup 0'\
            .format(con.REMOTE_FW_DIR, con.DMM_RUN_SCRIPTS, script_name)
        exec_cmd(dut1_node, cmd)
        exec_cmd(dut2_node, cmd)
        time.sleep(5)
Exemple #11
0
    def delete_namespace(node, namespace):
        """Delete namespace from the node and list.

        :param node: Where to delete namespace.
        :param namespace: Name for namespace.
        :param delete_before_create: Delete namespace prior to create
        :type node: dict
        :type namespace: str
        :type delete_before_create: bool
        """
        cmd_timeout = 5
        cmd = f"ip netns delete {namespace}"
        (ret_code, _, delete_errmsg) = \
            exec_cmd(node, cmd, timeout=cmd_timeout, sudo=True)
        if ret_code != 0:
            cmd = f"ip netns list {namespace}"
            (stdout, _) = \
                exec_cmd_no_error(node, cmd, timeout=cmd_timeout, sudo=True)
            if stdout == namespace:
                raise RuntimeError(f"Could not delete namespace "
                                   f"({namespace}): {delete_errmsg}")
        try:
            Namespaces.__namespaces.remove(namespace)
        except ValueError:
            pass
Exemple #12
0
    def install_original_nginx_framework(node, pkg_dir, nginx_version):
        """
        Prepare the NGINX framework on the DUT node.

        :param node: Node from topology file.
        :param pkg_dir: Ldp NGINX install dir.
        :param nginx_version: NGINX Version.
        :type node: dict
        :type pkg_dir: str
        :type nginx_version: str
        :raises RuntimeError: If command returns nonzero return code.
        """
        nginx_path = f"{pkg_dir}/nginx-{nginx_version}/sbin/nginx"
        cmd_options = NginxUtil.get_cmd_options(path=nginx_path)
        ret_code, _, stderr = exec_cmd(node, cmd_options, sudo=True)
        if nginx_version in stderr and ret_code == 0:
            logger.info(f"NGINX Version: {stderr}")
            return
        command = f"{Constants.REMOTE_FW_DIR}/{Constants.RESOURCES_LIB_SH}" \
                  f"/entry/install_nginx.sh nginx-{nginx_version}"
        message = u"Install the NGINX failed!"
        exec_cmd_no_error(node, command, sudo=True, timeout=600,
                          message=message)
        _, stderr = exec_cmd_no_error(node, cmd_options, sudo=True,
                                      message=message)

        logger.info(f"NGINX Version: {stderr}")
Exemple #13
0
    def hoststack_test_program_finished(node, program_pid):
        """Wait for the specified HostStack test program process to complete.

        :param node: DUT node.
        :param program_pid: test program pid.
        :type node: dict
        :type program_pid: str
        :raises RuntimeError: If node subtype is not a DUT.
        """
        if node[u"type"] != u"DUT":
            raise RuntimeError(u"Node type is not a DUT!")

        cmd = f"sh -c 'strace -qqe trace=none -p {program_pid}'"
        exec_cmd(node, cmd, sudo=True)
        # Wait a bit for stdout/stderr to be flushed to log files
        # TODO: see if sub-second sleep works e.g. sleep(0.1)
        sleep(1)
Exemple #14
0
    def qemu_kill(self):
        """Kill qemu process."""
        exec_cmd(self._node, 'chmod +r {pidfile}'.
                 format(pidfile=self._temp.get('pidfile')), sudo=True)
        exec_cmd(self._node, 'kill -SIGKILL $(cat {pidfile})'.
                 format(pidfile=self._temp.get('pidfile')), sudo=True)

        for value in self._temp.values():
            exec_cmd(self._node, 'cat {value}'.format(value=value), sudo=True)
            exec_cmd(self._node, 'rm -f {value}'.format(value=value), sudo=True)
Exemple #15
0
    def qemu_kill(self):
        """Kill qemu process."""
        exec_cmd(self._node,
                 f"chmod +r {self._temp.get(u'pidfile')}",
                 sudo=True)
        exec_cmd(self._node,
                 f"kill -SIGKILL $(cat {self._temp.get(u'pidfile')})",
                 sudo=True)

        for value in self._temp.values():
            exec_cmd(self._node, f"cat {value}", sudo=True)
            exec_cmd(self._node, f"rm -f {value}", sudo=True)
Exemple #16
0
    def is_iperf_running(node):
        """Check if iPerf3 is running using pgrep.

        :param node: Topology node running iPerf3.
        :type node: dict
        :returns: True if iPerf3 is running otherwise False.
        :rtype: bool
        """
        ret, _, _ = exec_cmd(node, u"pgrep iperf3", sudo=True)
        return bool(int(ret) == 0)
Exemple #17
0
def diag_cmd(node, cmd):
    """Execute cmd, print cmd and stdout, ignore stderr and rc; return None.

    :param node: Node object as parsed from topology file to execute cmd on.
    :param cmd: Command to execute.
    :type ssh: dict
    :type cmd: str
    """
    print "+", cmd
    _, stdout, _ = exec_cmd(node, cmd)
    print stdout
    def attach_interface_to_namespace(node, namespace, interface):
        """Attach specific interface to namespace.

        :param node: Node where to execute command.
        :param namespace: Namespace to execute command on.
        :param interface: Interface in namespace.
        :type node: dict
        :type namespace: str
        :type interface: str
        :raises RuntimeError: Interface could not be attached.
        """
        cmd = 'ip link set {0} netns {1}'.format(interface, namespace)
        (ret_code, _, stderr) = exec_cmd(node, cmd, timeout=5, sudo=True)
        if ret_code != 0:
            raise RuntimeError(
                'Could not attach interface, reason:{}'.format(stderr))
        cmd = 'ip netns exec {} ip link set {} up'.format(namespace, interface)
        (ret_code, _, stderr) = exec_cmd(node, cmd, timeout=5, sudo=True)
        if ret_code != 0:
            raise RuntimeError(
                'Could not set interface state, reason:{}'.format(stderr))
Exemple #19
0
    def qemu_kill_all(self):
        """Kill all qemu processes on DUT node if specified."""
        exec_cmd(self._node, u"pkill -SIGKILL qemu", sudo=True)

        for value in self._temp.values():
            exec_cmd(self._node, f"cat {value}", sudo=True)
            exec_cmd(self._node, f"rm -f {value}", sudo=True)
Exemple #20
0
    def kill_program(node, program, namespace=None):
        """Kill program on the specified topology node.

        :param node: Topology node.
        :param program: Program name.
        :param namespace: Namespace program is running in.
        :type node: dict
        :type program: str
        :type namespace: str
        """
        host = node[u"host"]
        cmd_timeout = 5
        if namespace in (None, u"default"):
            shell_cmd = u"sh -c"
        else:
            shell_cmd = f"ip netns exec {namespace} sh -c"

        pgrep_cmd = f"{shell_cmd} \'pgrep -c {program}\'"
        _, stdout, _ = exec_cmd(node, pgrep_cmd, timeout=cmd_timeout,
                                sudo=True)
        if int(stdout) == 0:
            logger.trace(f"{program} is not running on {host}")
            return
        exec_cmd(node, f"{shell_cmd} \'pkill {program}\'",
                 timeout=cmd_timeout, sudo=True)
        for attempt in range(5):
            _, stdout, _ = exec_cmd(node, pgrep_cmd, timeout=cmd_timeout,
                                    sudo=True)
            if int(stdout) == 0:
                logger.trace(f"Attempt {attempt}: {program} is dead on {host}")
                return
            sleep(1)
        logger.trace(f"SIGKILLing {program} on {host}")
        exec_cmd(node, f"{shell_cmd} \'pkill -9 {program}\'",
                 timeout=cmd_timeout, sudo=True)
Exemple #21
0
    def qemu_kill_all(self):
        """Kill all qemu processes on DUT node if specified."""
        exec_cmd(self._node, 'pkill -SIGKILL qemu', sudo=True)

        for value in self._temp.values():
            exec_cmd(self._node, 'cat {value}'.format(value=value), sudo=True)
            exec_cmd(self._node, 'rm -f {value}'.format(value=value), sudo=True)
    def clean_up_namespaces(self, node):
        """Remove all old namespaces.

        :param node: Node where to execute command.
        :type node: dict
        :raises RuntimeError: Namespaces could not be cleaned properly.
        """
        for namespace in self._namespaces:
            print "Cleaning namespace {}".format(namespace)
            cmd = 'ip netns delete {}'.format(namespace)
            (ret_code, _, _) = exec_cmd(node, cmd, timeout=5, sudo=True)
            if ret_code != 0:
                raise RuntimeError('Could not delete namespace')
Exemple #23
0
    def set_linux_interface_up(node, interface):
        """Set the specified interface up.

        :param node: Node where to execute command.
        :param interface: Interface in namespace.
        :type node: dict
        :type interface: str
        :raises RuntimeError: If the interface could not be set up.
        """

        cmd = "ip link set {0} up".format(interface)
        ret_code, _, stderr = exec_cmd(node, cmd, timeout=30, sudo=True)
        if ret_code != 0:
            raise RuntimeError(
                'Could not set the interface up, reason:{0}'.format(stderr))
Exemple #24
0
    def attach_interface_to_namespace(node, namespace, interface):
        """Attach specific interface to namespace.

        :param node: Node where to execute command.
        :param namespace: Namespace to execute command on.
        :param interface: Interface in namespace.
        :type node: dict
        :type namespace: str
        :type interface: str
        :raises RuntimeError: Interface could not be attached.
        """
        cmd = f"ip link set {interface} netns {namespace}"

        ret_code, _, stderr = exec_cmd(node, cmd, timeout=5, sudo=True)
        if ret_code != 0:
            raise RuntimeError(
                f"Could not attach interface, reason:\n{stderr}")

        cmd = f"ip netns exec {namespace} ip link set {interface} up"

        ret_code, _, stderr = exec_cmd(node, cmd, timeout=5, sudo=True)
        if ret_code != 0:
            raise RuntimeError(
                f"Could not set interface state, reason:\n{stderr}")
Exemple #25
0
    def patch_l3fwd(node, patch):
        """
        Patch l3fwd application and recompile.

        :param node: DUT node.
        :param patch: Patch to apply.
        :type node: dict
        :type patch: str
        :raises RuntimeError: Patching of l3fwd failed.
        """
        command = f"{Constants.REMOTE_FW_DIR}/{Constants.RESOURCES_LIB_SH}"\
            f"/entry/patch_l3fwd.sh " \
            f"{Constants.REMOTE_FW_DIR}/{Constants.RESOURCES_LIB_SH}"\
            f"/entry/{patch}"
        message = f"Failed to patch l3fwd at node {node['host']}"
        ret_code, stdout, _ = exec_cmd(node, command, timeout=1800)
        if ret_code != 0 and u"Skipping patch." not in stdout:
            raise RuntimeError(message)
Exemple #26
0
    def get_pci_dev_driver(node, pci_addr):
        """Get current PCI device driver on node.

        :param node: DUT node.
        :param pci_addr: PCI device address.
        :type node: dict
        :type pci_addr: str
        :returns: Driver or None
        :raises RuntimeError: If it is not possible to get the interface driver
            information from the node.
        """
        driver_path = f"/sys/bus/pci/devices/{pci_addr}/driver"
        cmd = f"test -d {driver_path}"
        ret_code, ret_val, _ = exec_cmd(node, cmd)
        if int(ret_code):
            # the directory doesn't exist which means the device is not bound
            # to any driver
            return None
        cmd = f"basename $(readlink -f {driver_path})"
        ret_val, _ = exec_cmd_no_error(node, cmd)
        return ret_val.strip()
Exemple #27
0
    def print_dmm_log(dut1_node, dut2_node, script_name):
        """
        Print DMM logs.

        :param dut1_node: Node to print DMM logs of.
        :param dut2_node: Node to print DMM logs of.
        :param script_name: Name of the script to run.
        :type dut1_node: dict
        :type dut2_node: dict
        :type script_name: str
        """
        cmd = 'cd {0}/{1} && ./{2} log 0'\
            .format(con.REMOTE_FW_DIR, con.DMM_RUN_SCRIPTS, script_name)
        exec_cmd(dut1_node, cmd)

        cmd = 'cd {0}/{1} && ./{2} log 1'\
            .format(con.REMOTE_FW_DIR, con.DMM_RUN_SCRIPTS, script_name)
        exec_cmd(dut2_node, cmd)
        cmd = 'mv /var/log/nStack/running.log /var/log/nStack/{0}_ser.log'\
            .format(script_name)
        exec_cmd(dut1_node, cmd, sudo=True)
        cmd = 'mv /var/log/nStack/running.log /var/log/nStack/{0}_cli.log'\
            .format(script_name)
        exec_cmd(dut2_node, cmd, sudo=True)
Exemple #28
0
    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.
        """
        cmd = f"test -f /sys/bus/pci/devices/{pf_pci_addr}/sriov_numvfs"
        sriov_unsupported, _, _ = exec_cmd(node, cmd)
        # if sriov_numvfs doesn't exist, then sriov_unsupported != 0
        if int(sriov_unsupported):
            if numvfs == 0:
                # sriov is not supported and we want 0 VFs
                # no need to do anything
                return

            raise RuntimeError(
                f"Can't configure {numvfs} VFs on {pf_pci_addr} device "
                f"on {node[u'host']} since it doesn't support SR-IOV.")

        pci = pf_pci_addr.replace(u":", r"\:")
        command = f"sh -c \"echo {numvfs} | " \
            f"tee /sys/bus/pci/devices/{pci}/sriov_numvfs\""
        message = f"Failed to create {numvfs} VFs on {pf_pci_addr} device " \
            f"on {node[u'host']}"

        exec_cmd_no_error(node,
                          command,
                          timeout=120,
                          sudo=True,
                          message=message)
Exemple #29
0
def main():
    """Parse arguments, perform the action, write useful output, propagate RC.

    If the intended action is cancellation, reservation dir is deleted.

    If the intended action is reservation, the list is longer:
    1. List contents of reservation dir.
    2. List contents of test.url file in the dir.
    3. Create reservation dir.
    4. Touch file according to -r option.
    5. Put -u option string to file test.url
    From these 5 steps, 1 and 2 are performed always, their RC ignored.
    RC of step 3 gives the overall result.
    If the result is success, steps 4-5 are executed without any output,
    their RC is ignored.

    The two files in reservation dir are there for reporting
    which test run holds the reservation, so people can manually fix the testbed
    if the rest run has been aborted, or otherwise failed to unregister.

    The two files have different audiences.

    The URL content is useful for people scheduling their test runs
    and wondering why the reservation takes so long.
    For them, a URL (if available) to copy and paste into browser
    to see which test runs are blocking testbeds is the most convenient.

    The "run tag" as a filename is useful for admins accessing the testbed
    via a graphical terminal, which does not allow copying of text,
    as they need less keypresses to identify the test run holding the testbed.
    Also, the listing shows timestamps, which is useful for both audiences.
    """
    parser = argparse.ArgumentParser()
    parser.add_argument("-t", "--topo", required=True,
                        help="Topology file")
    parser.add_argument("-c", "--cancel", help="Cancel reservation",
                        action="store_true")
    parser.add_argument("-r", "--runtag", required=False, default="Unknown",
                        help="Identifier for test run suitable as filename")
    parser.add_argument("-u", "--url", required=False, default="Unknown",
                        help="Identifier for test run suitable as URL")
    args = parser.parse_args()

    with open(args.topo, "r") as topo_file:
        topology = yaml.load(topo_file.read())['nodes']

    # Even if TG is not guaranteed to be a Linux host,
    # we are using it, because testing shows SSH access to DUT
    # during test affects its performance (bursts of lost packets).
    try:
        tgn = topology["TG"]
    except KeyError:
        print "Topology file does not contain 'TG' node"
        return 1

    # For system reservation we use mkdir it is an atomic operation and we can
    # store additional data (time, client_ID, ..) within reservation directory.
    if args.cancel:
        ret, _, err = exec_cmd(tgn, "rm -r {}".format(RESERVATION_DIR))
        if ret:
            print "Cancellation unsuccessful:\n{}".format(err)
        return ret
    # Before critical section, output can be outdated already.
    print "Diagnostic commands:"
    # -d and * are to supress "total <size>", see https://askubuntu.com/a/61190
    diag_cmd(tgn, "ls --full-time -cd '{dir}'/*".format(dir=RESERVATION_DIR))
    diag_cmd(tgn, "head -1 '{dir}/run.url'".format(dir=RESERVATION_DIR))
    print "Attempting reservation."
    # Entering critical section.
    # TODO: Add optional argument to exec_cmd_no_error to make it
    # sys.exit(ret) instead raising? We do not want to deal with stacktrace.
    ret, _, err = exec_cmd(tgn, "mkdir '{dir}'".format(dir=RESERVATION_DIR))
    # Critical section is over.
    if ret:
        print "Reservation unsuccessful:\n{}".format(err)
        return ret
    # Here the script knows it is the only owner of the testbed.
    print "Success, writing test run info to reservation dir."
    # TODO: Add optional argument to exec_cmd_no_error to print message
    # to console instead raising? We do not want to deal with stacktrace.
    ret2, _, err = exec_cmd(
        tgn, "touch '{dir}/{runtag}' && ( echo '{url}' > '{dir}/run.url' )"\
        .format(dir=RESERVATION_DIR, runtag=args.runtag, url=args.url))
    if ret2:
        print "Writing test run info failed, but continuing anyway:\n{}".format(
            err)
    return ret
Exemple #30
0
def main():
    """Parse arguments, perform the action, write useful output, propagate RC.

    If the intended action is cancellation, reservation dir is deleted.

    If the intended action is reservation, the list is longer:
    1. List contents of reservation dir.
    2. List contents of test.url file in the dir.
    3. Create reservation dir.
    4. Touch file according to -r option.
    From these 4 steps, 1 and 2 are performed always, their RC ignored.
    RC of step 3 gives the overall result.
    If the result is success, step 4 is executed without any output,
    their RC is ignored.

    The "run tag" as a filename is useful for admins accessing the testbed
    via a graphical terminal, which does not allow copying of text,
    as they need less keypresses to identify the test run holding the testbed.
    Also, the listing shows timestamps, which is useful for both audiences.

    This all assumes the target system accepts ssh connections.
    If it does not, the caller probably wants to stop trying
    to reserve this system. Therefore this script can return 3 different codes.
    Return code 0 means the reservation was successful.
    Return code 1 means the system is inaccessible (or similarly unsuitable).
    Return code 2 means the system is accessible, but already reserved.
    The reason unsuitable systems return 1 is because that is also the value
    Python returns on encountering and unexcepted exception.
    """
    parser = argparse.ArgumentParser()
    parser.add_argument(u"-t", u"--topo", required=True, help=u"Topology file")
    parser.add_argument(
        u"-c", u"--cancel", help=u"Cancel reservation", action=u"store_true"
    )
    parser.add_argument(
        u"-r", u"--runtag", required=False, default=u"Unknown",
        help=u"Identifier for test run suitable as filename"
    )
    args = parser.parse_args()

    with open(args.topo, u"rt") as topo_file:
        topology = yaml.safe_load(topo_file.read())[u"nodes"]

    # Even if TG is not guaranteed to be a Linux host,
    # we are using it, because testing shows SSH access to DUT
    # during test affects its performance (bursts of lost packets).
    try:
        node = topology[RESERVATION_NODE]
    except KeyError:
        print(f"Topology file does not contain '{RESERVATION_NODE}' node")
        return 1

    # For system reservation we use mkdir it is an atomic operation and we can
    # store additional data (time, client_ID, ..) within reservation directory.
    if args.cancel:
        ret, _, err = exec_cmd(node, f"rm -r {RESERVATION_DIR}")
        # If connection is refused, ret==None.
        if ret != 0:
            print(f"Cancellation unsuccessful:\n{err!r}")
            return 1
        return 0
    # Before critical section, output can be outdated already.
    print(u"Diagnostic commands:")
    # -d and * are to suppress "total <size>", see https://askubuntu.com/a/61190
    diag_cmd(node, f"ls --full-time -cd '{RESERVATION_DIR}'/*")
    print(u"Attempting testbed reservation.")
    # Entering critical section.
    ret, _, _ = exec_cmd(node, f"mkdir '{RESERVATION_DIR}'")
    # Critical section is over.
    if ret is None:
        print(u"Failed to connect to testbed.")
        return 1
    if ret != 0:
        _, stdo, _ = exec_cmd(node, f"ls '{RESERVATION_DIR}'/*")
        print(f"Testbed already reserved by:\n{stdo}")
        return 2
    # Here the script knows it is the only owner of the testbed.
    print(u"Reservation success, writing additional info to reservation dir.")
    ret, _, err = exec_cmd(
        node, f"touch '{RESERVATION_DIR}/{args.runtag}'")
    if ret != 0:
        print(f"Writing test run info failed, but continuing anyway:\n{err!r}")
    return 0