Esempio n. 1
0
    def __init__(self,
                 ifname,
                 tc_bin="tc",
                 handover_delta=500000,
                 phc2sys_bin="phc2sys",
                 proc=None):
        """
        Class constructor. The arguments are as follows.
          * ifname - name of the interface to use for scheduling network packets in the future.
          * tc_bin - path to the 'tc' tool that should be used for setting up the ETF qdisc.
          * handover_delta - the qdisc delta - the time offset in microseconds when the qdisc hands
                             the packet over to the network driver.
          * phc2sys_bin - path to the 'phc2sys' tool that will be run in background and periodically
                          synchronize the host and NIC clock.
          * proc - the 'Proc' or 'SSH' object that defines the host to configure the ETF qdisc on
                   (default is the local host). This object will keep a 'proc' reference and use it
                   in various methods.

        Note about phc2sys.

        When ETF qdisc offloads packets to the NIC, it is important to keep host and NIC times in
        sync, because Linux kernel API accept absolute time values to send the packets at, and these
        values are passed down to the NIC as-is. If NIC's time is different, the packets will be
        sent at incorrect time or just dropped causing errors like "missing deadline".
        """

        self._netif = None
        self._old_tc_err_msg = None
        self._phc2sys_proc = None

        self._ifname = ifname
        self._tc_bin = FSHelpers.which(tc_bin, proc=proc)
        self._handover_delta = int(handover_delta * 1000)
        self._phc2sys_bin = FSHelpers.which(phc2sys_bin, proc=proc)
        self._proc = proc

        self._netif = _NetIface.NetIface(ifname, proc=proc)

        self._old_tc_err_msg = f"the 'tc' tool installed{self._proc.hostmsg} is not new enough " \
                               f"and does not support the ETF qdisc.\nPlease, install 'tc' " \
                               f"version '181023' or greater.\nThe 'tc' tool is part of the " \
                               f"'iproute2' project. Run 'tc -V' to check its version."
Esempio n. 2
0
    def _check_ip_tool_present(self):
        """Verifies that the "ip" tool is available."""

        if self._ip_tool_present:
            return

        if not FSHelpers.which("ip", default=None, proc=self._proc):
            raise ErrorNotSupported(
                f"the 'ip' tool is not installed{self._proc.hostmsg}.\nThis "
                f"tool is part of the 'iproute2' project, please install it.")
        self._ip_tool_present = True
Esempio n. 3
0
    def __init__(self, proc=None):
        """Class constructor."""

        if not proc:
            proc = Procs.Proc()

        self._proc = proc
        self._lspci_bin = "lspci"

        if not FSHelpers.which(self._lspci_bin, default=None, proc=proc):
            raise ErrorNotSupported(
                f"the '{self._lspci_bin}' tool is not installed{proc.hostmsg}")
Esempio n. 4
0
    def __init__(self, proc=None):
        """
        Initialize a class instance for the host associated with the 'proc' object. By default it is
        is going to be the local host, but 'proc' can be used to pass a connected 'SSH' object, in
        which case all operation will be done on the remote host. This object will keep a 'proc'
        reference and use it in various methods.
        """

        if not proc:
            proc = Procs.Proc()

        self._proc = proc
        self._saved_managed = OrderedDict()

        if not FSHelpers.which("nmcli", default=None, proc=proc):
            raise ErrorNotSupported(
                f"the 'nmcli' tool is not installed{proc.hostmsg}")
Esempio n. 5
0
    def _cstate_stats_init(self):
        """Initialize information related to C-state statistics and the 'turbostat' tool."""

        if self._run_ts is False:
            if not self._ts_bin:
                return
            raise Error(
                "path to 'turbostat' tool given, but C-state statistics collection is "
                "disabled")

        if not self._ts_bin:
            self._ts_bin = FSHelpers.which("turbostat",
                                           default=None,
                                           proc=self._proc)

        if not self._ts_bin:
            msg = f"cannot collect C-state statistics: the 'turbostat' tool was not found" \
                  f"{self._proc.hostmsg}"
            if self._run_ts is True:
                raise ErrorNotSupported(msg)

            self._run_ts = False
            _LOG.info(msg)
            return

        # Make sure turbostat version is '19.08.31' or newer. Turbostat versions are dates (e.g.,
        # version '19.03.20' is Mar 20 2019), so we can use the 'datetime' module to compare the
        # versions.
        version = self._get_turbostat_version()
        vdate = (int(val) for val in version.split("."))
        if datetime.datetime(*vdate) < datetime.datetime(19, 8, 31):
            msg = f"cannot collect C-state statistics: too old turbostat version '{version}', " \
                  f"use turbostat version '19.08.31' or newer\n(checked {self._ts_bin}" \
                  f"{self._proc.hostmsg}"
            if self._run_ts:
                raise ErrorNotSupported(msg)

            self._run_ts = False
            _LOG.info(msg)
        else:
            self._run_ts = True
            self._build_colmap()
Esempio n. 6
0
def _deploy_prepare(args, toolname, minkver):
    """
    Validate command-line arguments of the "deploy" command and prepare for builing the helpers and
    drivers. The arguments are as follows.
      o args - the command line arguments.
      o toolname - name of the tool being deployed (e.g., 'ndl').
      o minkver - the minimum required version number.
    """

    args.tmpdir = None
    args.kver = None

    if not args.ihost:
        args.ihost = "localhost"
    if not args.bhost:
        args.bhost = args.ihost

    if args.ihost != args.bhost and not args.bhost == "localhost":
        raise Error("build host (--build-host) must be the local host or the same as deploy host "
                    "(--host)")

    if args.ihost == "localhost" and args.bhost == "localhost":
        for attr in ("username", "privkey", "timeout"):
            if getattr(args, attr) is not None:
                _LOG.warning("ignoring the '--%s' option as it not useful for a local host", attr)

    if not args.timeout:
        args.timeout = 8
    else:
        args.timeout = Trivial.str_to_num(args.timeout)
    if not args.username:
        args.username = "******"

    if args.privkey and not args.privkey.is_dir():
        raise Error(f"path '{args.privkey}' does not exist or it is not a directory")

    if hasattr(args, "drvsrc"):
        if not args.drvsrc:
            args.drvsrc = FSHelpers.search_for_app_data("wult", _DRV_SRC_SUBPATH/f"{toolname}",
                                                        pathdescr=f"{toolname} drivers sources")

        if not args.drvsrc.is_dir():
            raise Error(f"path '{args.drvsrc}' does not exist or it is not a directory")

    if hasattr(args, "helpersrc"):
        if not args.helpersrc:
            args.helpersrc = FSHelpers.search_for_app_data("wult",
                                                           _HELPERS_SRC_SUBPATH/f"{toolname}",
                                                           pathdescr=f"{toolname} helper sources")
        if not args.helpersrc.is_dir():
            raise Error(f"path '{args.helpersrc}' does not exist or it is not a directory")

    with contextlib.closing(get_proc(args, args.bhost)) as proc:
        if not FSHelpers.which("make", default=None, proc=proc):
            raise Error(f"please, install the 'make' tool{proc.hostmsg}")

        if not args.ksrc:
            args.kver = KernelVersion.get_kver(proc=proc)
            if not args.ksrc:
                args.ksrc = Path(f"/lib/modules/{args.kver}/build")
        else:
            args.ksrc = FSHelpers.abspath(args.ksrc, proc=proc)

        if not FSHelpers.isdir(args.ksrc, proc=proc):
            raise Error(f"kernel sources directory '{args.ksrc}' does not exist{proc.hostmsg}")

        if not args.kver:
            args.kver = KernelVersion.get_kver_ktree(args.ksrc, proc=proc)

        _LOG.info("Kernel sources path: %s", args.ksrc)
        _LOG.info("Kernel version: %s", args.kver)

        if KernelVersion.kver_lt(args.kver, minkver):
            raise Error(f"version of the kernel{proc.hostmsg} is {args.kver}, and it is not new "
                        f"enough.\nPlease, use kernel version {minkver} or newer.")

        args.tmpdir = FSHelpers.mktemp(prefix=f"{toolname}-", proc=proc)

        if hasattr(args, "drvsrc"):
            _LOG.debug("copying the drivers to %s:\n   '%s' -> '%s'",
                       proc.hostname, args.drvsrc, args.tmpdir)
            proc.rsync(f"{args.drvsrc}/", args.tmpdir / "drivers", remotesrc=False, remotedst=True)
            args.drvsrc = args.tmpdir / "drivers"
            _LOG.info("Drivers will be compiled on host '%s'", proc.hostname)

        if hasattr(args, "helpersrc"):
            _LOG.debug("copying the helpers to %s:\n  '%s' -> '%s'",
                       proc.hostname, args.helpersrc, args.tmpdir)
            proc.rsync(f"{args.helpersrc}/", args.tmpdir / "helpers", remotesrc=False,
                       remotedst=True)
            args.helpersrc = args.tmpdir / "helpers"
            _LOG.info("Helpers will be compiled on host '%s'", proc.hostname)

    with contextlib.closing(get_proc(args, args.ihost)) as proc:
        if not args.kmodpath:
            args.kmodpath = Path(f"/lib/modules/{args.kver}")
        if not FSHelpers.isdir(args.kmodpath, proc=proc):
            raise Error(f"kernel modules directory '{args.kmodpath}' does not exist{proc.hostmsg}")

        _LOG.info("Drivers will be deployed to '%s'%s", args.kmodpath, proc.hostmsg)
        _LOG.info("Kernel modules path%s: %s", proc.hostmsg, args.kmodpath)

        if hasattr(args, "helpersrc"):
            if not args.helpers_path:
                args.helpers_path = get_helpers_deploy_path(proc, toolname)
            _LOG.info("Helpers will be deployed to '%s'%s", args.helpers_path, proc.hostmsg)