Example #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)
Example #2
0
File: ssh.py Project: preym17/csit
    def exec_command_sudo(self, cmd, cmd_input=None, timeout=30,
                          log_stdout_err=True):
        """Execute SSH command with sudo on a new channel on the connected Node.

        :param cmd: Command to be executed.
        :param cmd_input: Input redirected to the command.
        :param timeout: Timeout.
        :param log_stdout_err: If True, stdout and stderr are logged.
        :type cmd: str
        :type cmd_input: str
        :type timeout: int
        :type log_stdout_err: bool
        :returns: return_code, stdout, stderr
        :rtype: tuple(int, str, str)

        :Example:

        >>> from ssh import SSH
        >>> ssh = SSH()
        >>> ssh.connect(node)
        >>> # Execute command without input (sudo -S cmd)
        >>> ssh.exec_command_sudo("ifconfig eth0 down")
        >>> # Execute command with input (sudo -S cmd <<< "input")
        >>> ssh.exec_command_sudo("vpp_api_test", "dump_interface_table")
        """
        if isinstance(cmd, (list, tuple)):
            cmd = OptionString(cmd)
        if cmd_input is None:
            command = 'sudo -S {c}'.format(c=cmd)
        else:
            command = 'sudo -S {c} <<< "{i}"'.format(c=cmd, i=cmd_input)
        return self.exec_command(command, timeout,
                                 log_stdout_err=log_stdout_err)
Example #3
0
File: Iperf3.py Project: gvnn3/csit
    def iperf3_cmdline(**kwargs):
        """Get iPerf3 server command line.

        :param kwargs: List of iPerf3 server parameters.
        :type kwargs: dict
        :returns: iPerf3 server command line.
        :rtype: OptionString
        """
        cmd = OptionString()
        if kwargs['namespace']:
            cmd.add(f"ip netns exec {kwargs['namespace']}")
        cmd.add(f"iperf3")

        cmd_options = OptionString(prefix=u"--")
        # Run iPerf in server mode. (This will only allow one iperf connection
        # at a time)
        cmd_options.add(u"server")

        # Run the server in background as a daemon.
        cmd_options.add_if_from_dict(u"daemon", u"daemon", kwargs, True)

        # Write a file with the process ID, most useful when running as a
        # daemon.
        cmd_options.add_with_value_from_dict(u"pidfile", u"pidfile", kwargs,
                                             f"/tmp/iperf3_server.pid")

        # Send output to a log file.
        cmd_options.add_with_value_from_dict(u"logfile", u"logfile", kwargs,
                                             f"/tmp/iperf3.log")

        # The server port for the server to listen on and the client to
        # connect to. This should be the same in both client and server.
        # Default is 5201.
        cmd_options.add_with_value_from_dict(u"port", u"port", kwargs, 5201)

        # Set the CPU affinity, if possible (Linux and FreeBSD only).
        cmd_options.add_with_value_from_dict(u"affinity", u"affinity", kwargs)

        # Output in JSON format.
        cmd_options.add_if_from_dict(u"json", u"json", kwargs, True)

        # Give more detailed output.
        cmd_options.add_if_from_dict(u"verbose", u"verbose", kwargs, True)

        return cmd.extend(cmd_options)
Example #4
0
    def __init__(self, node, qemu_id=1, smp=1, mem=512, vnf=None,
                 img=Constants.QEMU_VM_IMAGE):
        """Initialize QemuUtil class.

        :param node: Node to run QEMU on.
        :param qemu_id: QEMU identifier.
        :param smp: Number of virtual SMP units (cores).
        :param mem: Amount of memory.
        :param vnf: Network function workload.
        :param img: QEMU disk image or kernel image path.
        :type node: dict
        :type qemu_id: int
        :type smp: int
        :type mem: int
        :type vnf: str
        :type img: str
        """
        self._vhost_id = 0
        self._node = node
        self._vm_info = {
            'host': node['host'],
            'type': NodeType.VM,
            'port': 10021 + qemu_id,
            'serial': 4555 + qemu_id,
            'username': '******',
            'password': '******',
            'interfaces': {},
        }
        if node['port'] != 22:
            self._vm_info['host_port'] = node['port']
            self._vm_info['host_username'] = node['username']
            self._vm_info['host_password'] = node['password']
        # Input Options.
        self._opt = dict()
        self._opt['qemu_id'] = qemu_id
        self._opt['mem'] = int(mem)
        self._opt['smp'] = int(smp)
        self._opt['img'] = img
        self._opt['vnf'] = vnf
        # Temporary files.
        self._temp = dict()
        self._temp['pidfile'] = '/var/run/qemu_{id}.pid'.format(id=qemu_id)
        if '/var/lib/vm/' in img:
            self._opt['vm_type'] = 'nestedvm'
            self._temp['qmp'] = '/var/run/qmp_{id}.sock'.format(id=qemu_id)
            self._temp['qga'] = '/var/run/qga_{id}.sock'.format(id=qemu_id)
        elif '/opt/boot/vmlinuz' in img:
            self._opt['vm_type'] = 'kernelvm'
            self._temp['log'] = '/tmp/serial_{id}.log'.format(id=qemu_id)
            self._temp['ini'] = '/etc/vm_init_{id}.conf'.format(id=qemu_id)
        else:
            raise RuntimeError('QEMU: Unknown VM image option!')
        # Computed parameters for QEMU command line.
        self._params = OptionString(prefix='-')
        self.add_params()
Example #5
0
    def get_testpmd_pmd_options(**kwargs):
        """Create PMD parameters options for testpmd (without --).

        :param kwargs: List of testpmd parameters.
        :type kwargs: dict
        :returns: PMD parameters.
        :rtype: OptionString
        """
        options = OptionString(prefix=u"--")
        # Set the forwarding mode: io, mac, mac_retry, mac_swap, flowgen,
        # rxonly, txonly, csum, icmpecho, ieee1588
        options.add_equals_from_dict(u"forward-mode", u"pmd_fwd_mode", kwargs,
                                     u"io")
        # Set the number of packets per burst to N.
        options.add_equals(u"burst", 64)
        # Set the number of descriptors in the TX rings to N.
        options.add_equals_from_dict(u"txd", u"pmd_txd", kwargs, 1024)
        # Set the number of descriptors in the RX rings to N.
        options.add_equals_from_dict(u"rxd", u"pmd_rxd", kwargs, 1024)
        # Set the number of queues in the TX to N.
        options.add_equals_from_dict(u"txq", u"pmd_txq", kwargs, 1)
        # Set the number of queues in the RX to N.
        options.add_equals_from_dict(u"rxq", u"pmd_rxq", kwargs, 1)
        # Set the hexadecimal bitmask of offloads.
        options.add_equals_from_dict(u"tx-offloads", u"pmd_tx_offloads",
                                     kwargs, u"0x0")
        # Enables numa aware allocation of mbufs.
        options.add_if_from_dict(u"numa", u"pmd_numa", kwargs, True)
        # Run by default.
        options.add_if_from_dict(u"auto-start", u"pmd_auto_start", kwargs,
                                 True)
        # Set the number of mbufs to be allocated in the mbuf pools.
        options.add_equals_from_dict(u"total-num-mbufs", u"pmd_num_mbufs",
                                     kwargs)
        # Set the number of forwarding ports.
        options.add_equals_from_dict(u"nb-ports", u"pmd_nb_ports", kwargs)
        # Set the hexadecimal bitmask of the ports used by the packet
        # forwarding test.
        options.add_equals_from_dict(u"portmask", u"pmd_portmask", kwargs)
        # Disable link status check.
        options.add_if_from_dict(u"disable-link-check",
                                 u"pmd_disable_link_check", kwargs, True)
        # Set the MAC address XX:XX:XX:XX:XX:XX of the peer port N
        options.add_equals_from_dict(u"eth-peer", u"pmd_eth_peer_0", kwargs)
        options.add_equals_from_dict(u"eth-peer", u"pmd_eth_peer_1", kwargs)
        # Set the max packet length.
        options.add_equals_from_dict(u"max-pkt-len", u"pmd_max_pkt_len",
                                     kwargs)
        # Set the max packet length.
        options.add_equals_from_dict(u"mbuf-size", u"pmd_mbuf_size", kwargs)
        # Set the number of forwarding cores based on coremask.
        options.add_equals_from_dict(u"nb-cores", u"pmd_nb_cores", kwargs)
        return options
Example #6
0
    def get_l3fwd_args(**kwargs):
        """Get DPDK l3fwd command line arguments.

        :param kwargs: Key-value l3fwd parameters.
        :type kwargs: dict
        :returns: Command line string.
        :rtype: OptionString
        """
        options = OptionString()
        options.extend(DpdkUtil.get_eal_options(**kwargs))
        options.add(u"--")
        options.extend(DpdkUtil.get_l3fwd_pmd_options(**kwargs))
        return options
Example #7
0
    def get_cmd_options(**kwargs):
        """Create  parameters options.

        :param kwargs: Dict of cmd parameters.
        :type kwargs: dict
        :returns: Cmd parameters.
        :rtype: OptionString
        """
        cmd = OptionString()
        cmd.add(u"python3")
        dirname = f"{Constants.REMOTE_FW_DIR}/resources/tools/ab"
        cmd.add(f"{dirname}/ABFork.py")
        cmd_options = OptionString(prefix=u"-")
        # Number of requests to perform.
        cmd_options.add_with_value_from_dict(u"r", u"requests", kwargs)
        # Server port number to use.
        cmd_options.add_with_value_from_dict(u"p", u"port", kwargs)
        # Number of clients being processed at the same time.
        cmd_options.add_with_value_from_dict(u"c", u"clients", kwargs)
        # Filename to be requested from the servers.
        cmd_options.add_with_value_from_dict(u"f", u"files", kwargs)
        # Server ip address.
        cmd_options.add_with_value_from_dict(u"i", u"ip", kwargs)
        # tg ip address.
        cmd_options.add_with_value_from_dict(u"g", u"tip", kwargs)
        # Specify SSL/TLS cipher suite.
        cmd_options.add_with_value_from_dict(u"z",
                                             u"cipher",
                                             kwargs,
                                             default=0)
        # Specify SSL/TLS protocol.
        cmd_options.add_with_value_from_dict(u"t",
                                             u"protocol",
                                             kwargs,
                                             default=0)
        # Mode: RPS or CPS.
        cmd_options.add_with_value_from_dict(u"m", u"mode", kwargs)
        return cmd.extend(cmd_options)
Example #8
0
    def get_testpmd_cmdline(**kwargs):
        """Get DPDK testpmd command line arguments with testpmd command.

        :param kwargs: Key-value testpmd parameters.
        :type kwargs: dict
        :returns: Command line string.
        :rtype: OptionString
        """
        options = OptionString()
        options.add(u"testpmd")
        options.extend(DpdkUtil.get_eal_options(**kwargs))
        options.add(u"--")
        options.extend(DpdkUtil.get_testpmd_pmd_options(**kwargs))
        return options
Example #9
0
    def dpdk_testpmd_start(node, **kwargs):
        """Start DPDK testpmd app on VM node.

        :param node: VM Node to start testpmd on.
        :param kwargs: Key-value testpmd parameters.
        :type node: dict
        :type kwargs: dict
        """
        cmd_options = OptionString()
        cmd_options.add(u"/start-testpmd.sh")
        cmd_options.extend(DpdkUtil.get_eal_options(**kwargs))
        cmd_options.add(u"--")
        cmd_options.extend(DpdkUtil.get_testpmd_pmd_options(**kwargs))
        exec_cmd_no_error(node, cmd_options, sudo=True, disconnect=True)
Example #10
0
    def exec_command_sudo(self,
                          cmd,
                          cmd_input=None,
                          timeout=30,
                          log_stdout_err=True,
                          export=True):
        """Execute SSH command with sudo on a new channel on the connected Node.

        :param cmd: Command to be executed.
        :param cmd_input: Input redirected to the command.
        :param timeout: Timeout.
        :param log_stdout_err: If True, stdout and stderr are logged.
        :param export: If false, do not attempt JSON export.
            Needed for calls outside Robot (e.g. from reservation script).
        :type cmd: str
        :type cmd_input: str
        :type timeout: int
        :type log_stdout_err: bool
        :type export: bool
        :returns: return_code, stdout, stderr
        :rtype: tuple(int, str, str)

        :Example:

        >>> from ssh import SSH
        >>> ssh = SSH()
        >>> ssh.connect(node)
        >>> # Execute command without input (sudo -S cmd)
        >>> ssh.exec_command_sudo(u"ifconfig eth0 down")
        >>> # Execute command with input (sudo -S cmd <<< 'input')
        >>> ssh.exec_command_sudo(u"vpp_api_test", u"dump_interface_table")
        """
        if isinstance(cmd, (list, tuple)):
            cmd = OptionString(cmd)
        if cmd_input is None:
            command = f"sudo -E -S {cmd}"
        else:
            command = f"sudo -E -S {cmd} <<< \"{cmd_input}\""
        return self.exec_command(command,
                                 timeout,
                                 log_stdout_err=log_stdout_err,
                                 export=export)
Example #11
0
    def get_eal_options(**kwargs):
        """Create EAL parameters options (including -v).

        :param kwargs: Dict of testpmd parameters.
        :type kwargs: dict
        :returns: EAL parameters.
        :rtype: OptionString
        """
        options = OptionString(prefix='-')
        options.add('v')
        # Set the hexadecimal bitmask of the cores to run on.
        options.add_with_value_from_dict('l', 'eal_corelist', kwargs)
        # Set master core.
        options.add_with_value('-master-lcore', '0')
        # Load an external driver. Multiple -d options are allowed.
        options.add_with_value_if_from_dict('d',
                                            '/usr/lib/librte_pmd_virtio.so',
                                            'eal_driver', kwargs, True)
        options.add_if_from_dict('-in-memory', 'eal_in_memory', kwargs, False)
        return options
Example #12
0
    def get_l3fwd_pmd_options(**kwargs):
        """Create PMD parameters options for l3fwd (without --).

        :param kwargs: List of l3fwd parameters.
        :type kwargs: dict
        :returns: PMD parameters.
        :rtype: OptionString
        """
        options = OptionString(prefix=u"--")
        # Set to use software to analyze packet type.
        options.add_if_from_dict(u"parse-ptype", u"pmd_parse_ptype", kwargs,
                                 True)
        # Set the MAC address XX:XX:XX:XX:XX:XX of the peer port N.
        options.add_equals_from_dict(u"eth-dest", u"pmd_eth_dest_0", kwargs)
        options.add_equals_from_dict(u"eth-dest", u"pmd_eth_dest_1", kwargs)
        # Determines which queues from which ports are mapped to which cores.
        options.add_equals_from_dict(u"config", u"pmd_config", kwargs)
        # Set the max packet length.
        options.add_with_value_if_from_dict(u"max-pkt-len", u"9200",
                                            u"pmd_max_pkt_len", kwargs, False)
        return options
Example #13
0
    def get_pmd_options(**kwargs):
        """Create PMD parameters options (without --).

        :param kwargs: List of testpmd parameters.
        :type kwargs: dict
        :returns: PMD parameters.
        :rtype: OptionString
        """
        options = OptionString(prefix='--')
        # Set the forwarding mode: io, mac, mac_retry, mac_swap, flowgen,
        # rxonly, txonly, csum, icmpecho, ieee1588
        options.add_equals_from_dict('forward-mode', 'pmd_fwd_mode', kwargs,
                                     'io')
        # Set the number of packets per burst to N.
        options.add_equals('burst', 64)
        # Set the number of descriptors in the TX rings to N.
        options.add_equals_from_dict('txd', 'pmd_txd', kwargs, 1024)
        # Set the number of descriptors in the RX rings to N.
        options.add_equals_from_dict('rxd', 'pmd_rxd', kwargs, 1024)
        # Set the number of queues in the TX to N.
        options.add_equals_from_dict('txq', 'pmd_txq', kwargs, 1)
        # Set the number of queues in the RX to N.
        options.add_equals_from_dict('rxq', 'pmd_rxq', kwargs, 1)
        # Set the hexadecimal bitmask of offloads.
        options.add_equals_if_from_dict('txqflags', '0xf00', 'pmd_tx_offloads',
                                        kwargs, True)
        # Set the number of mbufs to be allocated in the mbuf pools.
        options.add_equals_from_dict('total-num-mbufs', 'pmd_num_mbufs',
                                     kwargs)
        # Disable hardware VLAN.
        options.add_if_from_dict('disable-hw-vlan', 'pmd_disable_hw_vlan',
                                 kwargs, True)
        # Set the MAC address XX:XX:XX:XX:XX:XX of the peer port N
        options.add_equals_from_dict('eth-peer', 'pmd_eth_peer_0', kwargs)
        options.add_equals_from_dict('eth-peer', 'pmd_eth_peer_1', kwargs)
        # Set the max packet length.
        options.add_equals_from_dict('max-pkt-len', 'pmd_max_pkt_len', kwargs)
        # Set the number of forwarding cores based on coremask.
        options.add_equals_from_dict('nb-cores', 'pmd_nb_cores', kwargs)
        return options
Example #14
0
    def qemu_start(self):
        """Start QEMU and wait until VM boot.

        :returns: VM node info.
        :rtype: dict
        """
        cmd_opts = OptionString()
        cmd_opts.add(f"{Constants.QEMU_BIN_PATH}/qemu-system-{self._arch}")
        cmd_opts.extend(self._params)
        message = f"QEMU: Start failed on {self._node[u'host']}!"
        try:
            DUTSetup.check_huge_page(
                self._node, u"/dev/hugepages", int(self._opt.get(u"mem")))

            exec_cmd_no_error(
                self._node, cmd_opts, timeout=300, sudo=True, message=message
            )
            self._wait_until_vm_boot()
        except RuntimeError:
            self.qemu_kill_all()
            raise
        return self._vm_info
Example #15
0
    def get_eal_options(**kwargs):
        """Create EAL parameters options (including -v).

        :param kwargs: Dict of testpmd parameters.
        :type kwargs: dict
        :returns: EAL parameters.
        :rtype: OptionString
        """
        options = OptionString(prefix=u"-")
        options.add(u"v")
        # Set the hexadecimal bitmask of the cores to run on.
        options.add_with_value_from_dict(u"l", u"eal_corelist", kwargs)
        # Add a PCI device in white list.
        options.add_with_value_from_dict(u"a", u"eal_pci_whitelist0", kwargs)
        options.add_with_value_from_dict(u"a", u"eal_pci_whitelist1", kwargs)
        # Load an external driver. Multiple -d options are allowed.
        options.add_with_value_if_from_dict(u"d",
                                            u"/usr/lib/librte_pmd_virtio.so",
                                            u"eal_driver", kwargs, True)
        options.add_if_from_dict(u"-in-memory", u"eal_in_memory", kwargs,
                                 False)
        return options
Example #16
0
    def qemu_start(self):
        """Start QEMU and wait until VM boot.

        :returns: VM node info.
        :rtype: dict
        """
        cmd_opts = OptionString()
        cmd_opts.add('{bin_path}/qemu-system-{arch}'.format(
            bin_path=Constants.QEMU_BIN_PATH,
            arch=Topology.get_node_arch(self._node)))
        cmd_opts.extend(self._params)
        message = ('QEMU: Start failed on {host}!'.
                   format(host=self._node['host']))
        try:
            DUTSetup.check_huge_page(
                self._node, '/dev/hugepages', self._opt.get('mem'))

            exec_cmd_no_error(
                self._node, cmd_opts, timeout=300, sudo=True, message=message)
            self._wait_until_vm_boot()
        except RuntimeError:
            self.qemu_kill_all()
            raise
        return self._vm_info
Example #17
0
File: Iperf3.py Project: gvnn3/csit
    def iperf3_cmdline(**kwargs):
        """Get iperf_client driver command line.

        :param kwargs: List of iperf_client driver parameters.
        :type kwargs: dict
        :returns: iperf_client driver command line.
        :rtype: OptionString
        """
        cmd = OptionString()
        cmd.add(u"python3")
        dirname = f"{Constants.REMOTE_FW_DIR}/resources/tools/iperf"
        cmd.add(f"'{dirname}/iperf_client.py'")

        cmd_options = OptionString(prefix=u"--")
        # Namespace to execute iPerf3 client on.
        cmd_options.add_with_value_from_dict(u"namespace", u"namespace",
                                             kwargs)

        # Client connecting to an iPerf3 server running on host.
        cmd_options.add_with_value_from_dict(u"host", u"host", kwargs)

        # Client bind IP address.
        cmd_options.add_with_value_from_dict(u"bind", u"bind", kwargs)

        # Use UDP rather than TCP.
        cmd_options.add_if_from_dict(u"udp", u"udp", kwargs, False)

        # Set the CPU affinity, if possible.
        cmd_options.add_with_value_from_dict(u"affinity", u"affinity", kwargs)

        # Time expressed in seconds for how long to send traffic.
        cmd_options.add_with_value_from_dict(u"duration", u"duration", kwargs)

        # Send bi- (2) or uni- (1) directional traffic.
        cmd_options.add_with_value_from_dict(u"traffic_directions",
                                             u"traffic_directions", kwargs, 1)

        # Traffic warm-up time in seconds, (0=disable).
        cmd_options.add_with_value_from_dict(u"warmup_time", u"warmup_time",
                                             kwargs, 5.0)

        # L2 frame size to send (without padding and IPG).
        cmd_options.add_with_value_from_dict(u"frame_size", u"frame_size",
                                             kwargs)

        # Traffic rate expressed with units.
        cmd_options.add_with_value_from_dict(u"rate", u"rate", kwargs)

        # If enabled then don't wait for all incoming traffic.
        cmd_options.add_if_from_dict(u"async_start", u"async_call", kwargs,
                                     False)

        # Number of iPerf3 client parallel instances.
        cmd_options.add_with_value_from_dict(u"instances", u"instances",
                                             kwargs, 1)

        # Number of iPerf3 client parallel flows.
        cmd_options.add_with_value_from_dict(u"parallel", u"parallel", kwargs,
                                             8)

        return cmd.extend(cmd_options)
Example #18
0
    def exec_command(self, cmd, timeout=10, log_stdout_err=True, export=True):
        """Execute SSH command on a new channel on the connected Node.

        :param cmd: Command to run on the Node.
        :param timeout: Maximal time in seconds to wait until the command is
            done. If set to None then wait forever.
        :param log_stdout_err: If True, stdout and stderr are logged. stdout
            and stderr are logged also if the return code is not zero
            independently of the value of log_stdout_err.
        :param export: If false, do not attempt JSON export.
            Needed for calls outside Robot (e.g. from reservation script).
        :type cmd: str or OptionString
        :type timeout: int
        :type log_stdout_err: bool
        :type export: bool
        :returns: return_code, stdout, stderr
        :rtype: tuple(int, str, str)
        :raises SSHTimeout: If command is not finished in timeout time.
        """
        if isinstance(cmd, (list, tuple)):
            cmd = OptionString(cmd)
        cmd = str(cmd)
        stdout = u""
        stderr = u""
        try:
            chan = self._ssh.get_transport().open_session(timeout=5)
            peer = self._ssh.get_transport().getpeername()
        except (AttributeError, SSHException):
            self._reconnect()
            chan = self._ssh.get_transport().open_session(timeout=5)
            peer = self._ssh.get_transport().getpeername()
        chan.settimeout(timeout)

        logger.trace(f"exec_command on {peer} with timeout {timeout}: {cmd}")

        if export:
            export_ssh_command(self._node[u"host"], self._node[u"port"], cmd)
        start = monotonic()
        chan.exec_command(cmd)
        while not chan.exit_status_ready() and timeout is not None:
            if chan.recv_ready():
                s_out = chan.recv(self.__MAX_RECV_BUF)
                stdout += s_out.decode(encoding=u'utf-8', errors=u'ignore') \
                    if isinstance(s_out, bytes) else s_out

            if chan.recv_stderr_ready():
                s_err = chan.recv_stderr(self.__MAX_RECV_BUF)
                stderr += s_err.decode(encoding=u'utf-8', errors=u'ignore') \
                    if isinstance(s_err, bytes) else s_err

            duration = monotonic() - start
            if duration > timeout:
                if export:
                    export_ssh_timeout(
                        host=self._node[u"host"],
                        port=self._node[u"port"],
                        stdout=stdout,
                        stderr=stderr,
                        duration=duration,
                    )
                raise SSHTimeout(
                    f"Timeout exception during execution of command: {cmd}\n"
                    f"Current contents of stdout buffer: "
                    f"{stdout}\n"
                    f"Current contents of stderr buffer: "
                    f"{stderr}\n")

            sleep(0.1)
        return_code = chan.recv_exit_status()

        while chan.recv_ready():
            s_out = chan.recv(self.__MAX_RECV_BUF)
            stdout += s_out.decode(encoding=u'utf-8', errors=u'ignore') \
                if isinstance(s_out, bytes) else s_out

        while chan.recv_stderr_ready():
            s_err = chan.recv_stderr(self.__MAX_RECV_BUF)
            stderr += s_err.decode(encoding=u'utf-8', errors=u'ignore') \
                if isinstance(s_err, bytes) else s_err

        duration = monotonic() - start
        logger.trace(f"exec_command on {peer} took {duration} seconds")

        logger.trace(f"return RC {return_code}")
        if log_stdout_err or int(return_code):
            logger.trace(f"return STDOUT {stdout}")
            logger.trace(f"return STDERR {stderr}")
        if export:
            export_ssh_result(
                host=self._node[u"host"],
                port=self._node[u"port"],
                code=return_code,
                stdout=stdout,
                stderr=stderr,
                duration=duration,
            )
        return return_code, stdout, stderr
Example #19
0
    def __init__(self,
                 node,
                 qemu_id=1,
                 smp=1,
                 mem=512,
                 vnf=None,
                 img=Constants.QEMU_VM_IMAGE):
        """Initialize QemuUtil class.

        :param node: Node to run QEMU on.
        :param qemu_id: QEMU identifier.
        :param smp: Number of virtual SMP units (cores).
        :param mem: Amount of memory.
        :param vnf: Network function workload.
        :param img: QEMU disk image or kernel image path.
        :type node: dict
        :type qemu_id: int
        :type smp: int
        :type mem: int
        :type vnf: str
        :type img: str
        """
        self._nic_id = 0
        self._node = node
        self._arch = Topology.get_node_arch(self._node)
        self._opt = dict()

        # Architecture specific options
        if self._arch == u"aarch64":
            dpdk_target = u"arm64-armv8a"
            self._opt[u"machine_args"] = \
                u"virt,accel=kvm,usb=off,mem-merge=off,gic-version=3"
            self._opt[u"console"] = u"ttyAMA0"
        else:
            dpdk_target = u"x86_64-native"
            self._opt[u"machine_args"] = u"pc,accel=kvm,usb=off,mem-merge=off"
            self._opt[u"console"] = u"ttyS0"
        self._testpmd_path = f"{Constants.QEMU_VM_DPDK}/" \
            f"{dpdk_target}-linux-gcc/app"
        self._vm_info = {
            u"host": node[u"host"],
            u"type": NodeType.VM,
            u"port": 10021 + qemu_id,
            u"serial": 4555 + qemu_id,
            u"username": '******',
            u"password": '******',
            u"interfaces": {},
        }
        if node[u"port"] != 22:
            self._vm_info[u"host_port"] = node[u"port"]
            self._vm_info[u"host_username"] = node[u"username"]
            self._vm_info[u"host_password"] = node[u"password"]
        # Input Options.
        self._opt[u"qemu_id"] = qemu_id
        self._opt[u"mem"] = int(mem)
        self._opt[u"smp"] = int(smp)
        self._opt[u"img"] = img
        self._opt[u"vnf"] = vnf
        # Temporary files.
        self._temp = dict()
        self._temp[u"log"] = f"/tmp/serial_{qemu_id}.log"
        self._temp[u"pidfile"] = f"/run/qemu_{qemu_id}.pid"
        if img == Constants.QEMU_VM_IMAGE:
            self._temp[u"qmp"] = f"/run/qmp_{qemu_id}.sock"
            self._temp[u"qga"] = f"/run/qga_{qemu_id}.sock"
        elif img == Constants.QEMU_VM_KERNEL:
            self._opt[u"img"], _ = exec_cmd_no_error(
                node,
                f"ls -1 {Constants.QEMU_VM_KERNEL}* | tail -1",
                message=u"Qemu Kernel VM image not found!")
            self._temp[u"ini"] = f"/etc/vm_init_{qemu_id}.conf"
            self._opt[u"initrd"], _ = exec_cmd_no_error(
                node,
                f"ls -1 {Constants.QEMU_VM_KERNEL_INITRD}* | tail -1",
                message=u"Qemu Kernel initrd image not found!")
        else:
            raise RuntimeError(f"QEMU: Unknown VM image option: {img}")
        # Computed parameters for QEMU command line.
        self._params = OptionString(prefix=u"-")
Example #20
0
    def exec_command(self, cmd, timeout=10, log_stdout_err=True):
        """Execute SSH command on a new channel on the connected Node.

        :param cmd: Command to run on the Node.
        :param timeout: Maximal time in seconds to wait until the command is
            done. If set to None then wait forever.
        :param log_stdout_err: If True, stdout and stderr are logged. stdout
            and stderr are logged also if the return code is not zero
            independently of the value of log_stdout_err.
        :type cmd: str or OptionString
        :type timeout: int
        :type log_stdout_err: bool
        :returns: return_code, stdout, stderr
        :rtype: tuple(int, str, str)
        :raises SSHTimeout: If command is not finished in timeout time.
        """
        if isinstance(cmd, (list, tuple)):
            cmd = OptionString(cmd)
        cmd = str(cmd)
        stdout = StringIO.StringIO()
        stderr = StringIO.StringIO()
        try:
            chan = self._ssh.get_transport().open_session(timeout=5)
            peer = self._ssh.get_transport().getpeername()
        except (AttributeError, SSHException):
            self._reconnect()
            chan = self._ssh.get_transport().open_session(timeout=5)
            peer = self._ssh.get_transport().getpeername()
        chan.settimeout(timeout)

        logger.trace(
            'exec_command on {peer} with timeout {timeout}: {cmd}'.format(
                peer=peer, timeout=timeout, cmd=cmd))

        start = time()
        chan.exec_command(cmd)
        while not chan.exit_status_ready() and timeout is not None:
            if chan.recv_ready():
                stdout.write(chan.recv(self.__MAX_RECV_BUF))

            if chan.recv_stderr_ready():
                stderr.write(chan.recv_stderr(self.__MAX_RECV_BUF))

            if time() - start > timeout:
                raise SSHTimeout(
                    'Timeout exception during execution of command: {cmd}\n'
                    'Current contents of stdout buffer: {stdout}\n'
                    'Current contents of stderr buffer: {stderr}\n'.format(
                        cmd=cmd,
                        stdout=stdout.getvalue(),
                        stderr=stderr.getvalue()))

            sleep(0.1)
        return_code = chan.recv_exit_status()

        while chan.recv_ready():
            stdout.write(chan.recv(self.__MAX_RECV_BUF))

        while chan.recv_stderr_ready():
            stderr.write(chan.recv_stderr(self.__MAX_RECV_BUF))

        end = time()
        logger.trace('exec_command on {peer} took {total} seconds'.format(
            peer=peer, total=end - start))

        logger.trace('return RC {rc}'.format(rc=return_code))
        if log_stdout_err or int(return_code):
            logger.trace(
                'return STDOUT {stdout}'.format(stdout=stdout.getvalue()))
            logger.trace(
                'return STDERR {stderr}'.format(stderr=stderr.getvalue()))
        return return_code, stdout.getvalue(), stderr.getvalue()