Example #1
0
    def create_guest(self, host_conf, guest_conf):
        """ Create a guest
        Args:
            host_conf: The host_conf (instance of BaseHostConf)
            guest_conf: The host_conf (instance of BaseGuestConf)
            """
        host = host_conf.host
        virtctl = guest_conf.virtctl
        guest_xml = guest_conf.libvirt_xml

        str_xml = ET.tostring(guest_xml, encoding='utf8', method='xml')
        virtctl.createXML(str_xml.decode('utf8'))

        guest_ip_job = host.run("gethostip -d {}".format(guest_conf.name))
        guest_ip = guest_ip_job.stdout.strip()
        if not guest_ip:
            raise LnstError("Could not determine guest's IP address")

        guest = self.ctl.connect_host(guest_ip, timeout=60, machine_id="guest1")
        guest_conf.host = guest

        for i, vnic in enumerate(guest_conf.virtio_devs):
            if not vnic.hwaddr:
                raise LnstError("Virtio NIC HW Address not configured")
            guest.map_device("eth{}".format(i), dict(hwaddr=vnic.hwaddr))
            device = getattr(guest, "eth{}".format(i))
            guest_conf.nics.append(device)

        return guest
Example #2
0
    def _parse_addr(self, addr):
        tmp_list = addr.split(':')
        if len(tmp_list) != 6:
            raise LnstError("Invalid HWAddress format")

        res = []
        for i in tmp_list:
            val = int(i, 16)
            if val > 255 or val < 0:
                raise LnstError("Invalid HWAddress format")
            res.append(val)
        return res
Example #3
0
    def format_command(self):
        if self.params.forward_mode == "macswap":
            testpmd_args = ["dpdk-testpmd", "--no-pci"]
        else:
            testpmd_args = ["testpmd"]

        testpmd_args.extend(
            ["-c", self.params.coremask, "-n", "4", "--socket-mem", "1024,0"])

        for i, nic in enumerate(self.params.nics):
            if self.params.forward_mode == "mac":
                testpmd_args.extend(["-w", nic])
            elif self.params.forward_mode == "macswap":
                testpmd_args.extend([
                    f"--vdev=net_virtio_user{i+1},path=/var/run/openvswitch/{nic}"
                ])
            else:
                LnstError(
                    "Unsupported forward-mode parameter selected for the TestPMD."
                )

        testpmd_args.extend([
            "--", "-i", "--forward-mode", self.params.forward_mode,
            "--coremask", self.params.pmd_coremask
        ])

        if self.params.forward_mode == "mac":
            for i, mac in enumerate(self.params.peer_macs):
                testpmd_args.extend(["--eth-peer", "{},{}".format(i, mac)])
        elif self.params.forward_mode == "macswap":
            testpmd_args.extend(["--port-topology=loop"])

        return " ".join(testpmd_args)
    def _deconfig_ip_fragmentation(self, config, host):
        ip_version = config["ip_version"]

        if ip_version == AF_INET:
            host.run(
                "echo {} > /proc/sys/net/ipv4/ipfrag_high_thresh".format(
                    config["original_threshold"]
                ),
                job_level=ResultLevel.NORMAL,
            )
            host.run(
                "echo {} > /proc/sys/net/ipv4/ipfrag_time".format(
                    config["original_time"]
                ),
                job_level=ResultLevel.NORMAL,
            )
        elif ip_version == AF_INET6:
            host.run(
                "echo {} > /proc/sys/net/ipv6/ip6frag_high_thresh".format(
                    config["original_threshold"]
                ),
                job_level=ResultLevel.NORMAL,
            )
            host.run(
                "echo {} > /proc/sys/net/ipv6/ip6frag_time".format(
                    config["original_time"]
                ),
                job_level=ResultLevel.NORMAL,
            )
        else:
            raise LnstError("Unknown ip version: {}".format(ip_version))
Example #5
0
    def _parse_addr(addr):
        addr = addr.split('/')
        if len(addr) == 1:
            addr = addr[0]
            prefixlen = 128
        elif len(addr) == 2:
            addr, prefixlen = addr
            prefixlen = int(prefixlen)
        else:
            raise LnstError("Invalid IPv6 format.")

        try:
            type(inet_pton(AF_INET6, addr))
        except:
            raise LnstError("Invalid IPv6 format.")

        return addr, prefixlen
Example #6
0
    def packet_assert_test_stop(self):
        if not self.started_job:
            raise LnstError("No packet_assert job is running.")

        self.started_job.kill(signal=signal.SIGINT)
        self.started_job.wait()
        result = self.started_job.result
        self.started_job = None
        return result
Example #7
0
    def packet_assert_test_start(self, packet_assert_config):
        if self.started_job:
            raise LnstError(
                "Only 1 packet_assert job is allowed to run at a time.")

        host = packet_assert_config.host
        kwargs = self._generate_packet_assert_kwargs(packet_assert_config)
        packet_assert = PacketAssert(**kwargs)
        self.started_job = host.prepare_job(packet_assert).start(bg=True)
Example #8
0
 def obj_setattr(self, obj_ref, name, value):
     try:
         obj = self._dynamic_objects[obj_ref]
         return setattr(obj, name, value)
     except LnstError:
         raise
     except Exception as exc:
         log_exc_traceback()
         raise LnstError(exc)
Example #9
0
def hwaddress(addr):
    """Factory method to create a _HWAddress object"""
    if isinstance(addr, HWAddress):
        return addr
    elif isinstance(addr, str):
        return HWAddress(addr)
    else:
        raise LnstError("Value must be a HWAddress or string object."
                        " Not {}".format(type(addr)))
Example #10
0
def ping6(src, dst, options={}, expect="pass", bg=False):
    """ Perform an Icmp6Ping from source to destination

    Keyword arguments:
    src -- tuple of (HostAPI, InterfaceAPI/DeviceAPI, ip address index, ip addr selector)
    dst -- tuple of (HostAPI, InterfaceAPI/DeviceAPI, ip address index, ip addr selector)
    options -- dictionary of options for the IcmpPing module, can't contain
        keys 'addr' and 'iface'
    """

    options = dict(options)
    if 'addr' in options or 'iface' in options:
        raise LnstError("options can't contain keys 'addr' and 'iface'")

    if not isinstance(src, tuple) or len(src) < 2 or len(src) > 4:
        raise LnstError('Invalid source specification')
    try:
        if len(src) == 2:
            h1, if1 = src
            options["iface"] = if1.get_devname()
        elif len(src) == 3:
            h1, if1, addr_index1 = src
            options["iface"] = if1.get_ip(addr_index1)
        elif len(src) == 4:
            h1, if1, addr_index1, addr_selector1 = src
            options["iface"] = if1.get_ip(addr_index1, selector=addr_selector1)
    except:
        raise LnstError('Invalid source specification')

    if not isinstance(dst, tuple) or len(dst) < 3 or len(dst) > 4:
        raise LnstError('Invalid destination specification')
    try:
        if len(dst) == 3:
            h2, if2, addr_index2 = dst
            options["addr"] = if2.get_ip(addr_index2)
        elif len(dst) == 4:
            h2, if2, addr_index2, addr_selector2 = dst
            options["addr"] = if2.get_ip(addr_index2, selector=addr_selector2)
    except:
        raise LnstError('Invalid destination specification')

    ping_mod = ctl.get_module("Icmp6Ping", options=options)

    return h1.run(ping_mod, expect=expect, bg=bg)
Example #11
0
    def generate_ping_configurations(self, config):
        """Base ping test configuration generator

        The generator loops over all endpoint pairs to test ping between
        (generated by the :any:`generate_ping_endpoints` method) then over all
        the selected :any:`ip_versions` and finally over all the IP addresses
        that fit those criteria.

        :return: list of Ping configurations to test in parallel
        :rtype: List[:any:`PingConf`]
        """
        for endpoints in self.generate_ping_endpoints(config):
            for ipv in self.params.ip_versions:
                if ipv == "ipv6" and not endpoints.reachable:
                    continue

                ip_filter = {}
                if ipv == "ipv4":
                    ip_filter.update(family=AF_INET)
                elif ipv == "ipv6":
                    ip_filter.update(family=AF_INET6)
                    ip_filter.update(is_link_local=False)

                endpoint1, endpoint2 = endpoints.endpoints
                endpoint1_ips = endpoint1.ips_filter(**ip_filter)
                endpoint2_ips = endpoint2.ips_filter(**ip_filter)

                if len(endpoint1_ips) != len(endpoint2_ips):
                    raise LnstError(
                        "Source/destination ip lists are of different size.")

                ping_conf_list = []
                for src_addr, dst_addr in zip(endpoint1_ips, endpoint2_ips):
                    pconf = PingConf(
                        client=endpoint1.netns,
                        client_bind=src_addr,
                        destination=endpoint2.netns,
                        destination_address=dst_addr,
                        count=self.params.ping_count,
                        interval=self.params.ping_interval,
                        size=self.params.ping_psize,
                    )

                    ping_evaluators = self.generate_ping_evaluators(
                        pconf, endpoints)
                    pconf.register_evaluators(ping_evaluators)

                    ping_conf_list.append(pconf)

                    if self.params.ping_bidirect:
                        ping_conf_list.append(self._create_reverse_ping(pconf))

                    if not self.params.ping_parallel:
                        break

                yield ping_conf_list
Example #12
0
    def __init__(self):
        try:
            import libvirt
            from libvirt import libvirtError
        except ModuleNotFoundError:
            msg = "Failed to import libvirt, please install libvirt if you want to use the LibvirtControl class."
            logging.error(msg)
            raise LnstError(msg)

        self._libvirt_conn = libvirt.open(None)
Example #13
0
 def obj_method(self, obj_ref, name, args, kwargs):
     try:
         obj = self._dynamic_objects[obj_ref]
         method = getattr(obj, name)
         return method(*args, **kwargs)
     except LnstError:
         raise
     except Exception as exc:
         log_exc_traceback()
         raise LnstError(exc)
Example #14
0
    def __init__(self, iterable=[]):
        for i, item in enumerate(iterable):
            self._validate_item_type(item)

            if i == 0:
                unit = item.unit

            if item.unit != unit:
                raise LnstError("PerfList items must have the same unit.")

        super(PerfList, self).__init__(iterable)
Example #15
0
    def __setitem__(self, i, item):
        if isinstance(item, list):
            if not isinstance(i, slice):
                raise LnstError("{} accepts list values in slice assignment "
                    "only".format(self.__class__.__name__))

            for j in item:
                self._validate_item(j)
        else:
            self._validate_item(item)

        super(PerfList, self).__setitem__(i, item)
Example #16
0
def init_libvirt_con():
    try:
        import libvirt
        from libvirt import libvirtError
    except ModuleNotFoundError:
        msg = "Failed to import libvirt, please install libvirt to use the libvirt network management features."
        logging.error(msg)
        raise LnstError(msg)

    global _libvirt_conn
    if _libvirt_conn is None:
        _libvirt_conn = libvirt.open(None)
Example #17
0
def ipaddress(addr, flags=None):
    """Factory method to create a BaseIpAddress object"""
    if isinstance(addr, BaseIpAddress):
        return addr
    elif isinstance(addr, str):
        try:
            return Ip4Address(addr, flags)
        except:
            return Ip6Address(addr, flags)
    else:
        raise LnstError("Value must be a BaseIpAddress or string object."
                        " Not {}".format(type(addr)))
Example #18
0
    def warmup_configuration(self, ping_config):
        if len(ping_config) > 255:
            raise LnstError("Too many warmup elements.")
        for i, elem in enumerate(ping_config):
            orig = elem[1]
            dest = elem[2]

            orig.ip_add(ipaddress('192.168.{}.1/24'.format(i)))
            dest.ip_add(ipaddress('192.168.{}.2/24'.format(i)))

            orig.up()
            dest.up()
Example #19
0
def IpAddress(addr):
    """Factory method to create a BaseIpAddress object"""
    if isinstance(addr, BaseIpAddress):
        return addr
    #TODO add switches for host, interface etc...
    elif isinstance(addr, str):
        try:
            return Ip4Address(addr)
        except:
            return Ip6Address(addr)
    else:
        raise LnstError("Value must be a BaseIpAddress or string object."
                        "Not {}".format(type(addr)))
Example #20
0
    def run(self):
        self._res_data = {}
        if not is_installed("tcpdump"):
            self._res_data["msg"] = "tcpdump is not installed on this machine!"
            logging.error(self._res_data["msg"])
            return False

        self._prepare_grep_exprs()
        cmd = self._compose_cmd()
        logging.debug("compiled command: {}".format(cmd))

        packet_assert_process = subprocess.Popen(
            cmd,
            shell=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            close_fds=True,
        )

        try:
            self.wait_for_interrupt()
        except:
            raise LnstError("Could not handle interrupt properly.")

        stdout, stderr = packet_assert_process.communicate()
        stdout = stdout.decode()
        stderr = stderr.decode()

        self._res_data["stderr"] = stderr
        # tcpdump always reports information to stderr, there may be actual
        # errors but also just generic debug information
        logging.debug(self._res_data["stderr"])

        for line in stdout.split("\n"):
            self._check_line(line)

        logging.debug("Capturing finised. Received %d packets." % self._p_recv)
        self._res_data["p_recv"] = self._p_recv

        if packet_assert_process.returncode != 0:
            return False
        else:
            return True
Example #21
0
    def generate_ping_configurations(self, config):
        if not config.encrypt:
            client_nic = config.endpoint1
            server_nic = config.endpoint2
            ip_vers = ('ipv4',)
        else:
            client_nic = config.host1.msec0
            server_nic = config.host2.msec0
            ip_vers = self.params.ip_versions

        count = self.params.ping_count
        interval = self.params.ping_interval
        size = self.params.ping_psize
        common_args = {'count' : count, 'interval' : interval,
            'size' : size}

        for ipv in ip_vers:
            kwargs = {}
            if ipv == "ipv4":
                kwargs.update(family = AF_INET)
            elif ipv == "ipv6":
                kwargs.update(family = AF_INET6)
                kwargs.update(is_link_local = False)

            client_ips = client_nic.ips_filter(**kwargs)
            server_ips = server_nic.ips_filter(**kwargs)
            if ipv == "ipv6":
                client_ips = client_ips[::-1]
                server_ips = server_ips[::-1]

            if len(client_ips) != len(server_ips) or (len(client_ips) *
                len(server_ips) == 0):
                raise LnstError("Source/destination ip lists are of "
                    "different size or empty.")

            for src_addr, dst_addr in zip(client_ips, server_ips):
                pconf = PingConf(client = client_nic.netns,
                                 client_bind = src_addr,
                                 destination = server_nic.netns,
                                 destination_address = dst_addr,
                                 **common_args)

                yield [pconf]
Example #22
0
    def run(self):
        self._res_data = {}
        if not is_installed("tcpdump"):
            self._res_data["msg"] = "tcpdump is not installed on this machine!"
            logging.error(self._res_data["msg"])
            return False

        self._prepare_grep_exprs()
        cmd = self._compose_cmd()
        logging.debug("compiled command: {}".format(cmd))

        packet_assert_process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
                                        stderr=subprocess.PIPE, close_fds=True)

        try:
            self.wait_for_interrupt()
        except:
            raise LnstError("Could not handle interrupt properly.")

        with packet_assert_process.stdout, packet_assert_process.stderr:
            stderr=packet_assert_process.stderr.read().decode()
            stdout=packet_assert_process.stdout.read().decode()

        self._res_data["stderr"] = stderr

        if self._is_real_err(stderr):
            self._res_data["msg"] = "errors reported by tcpdump"
            logging.error(self._res_data["msg"])
            logging.error(self._res_data["stderr"])
            return False

        for line in stdout.split("\n"):
            self._check_line(line)

        logging.debug("Capturing finised. Received %d packets." % self._p_recv)
        self._res_data["p_recv"] = self._p_recv

        return True
Example #23
0
    def generate_ping_configurations(self, config):
        for endpoint1, endpoint2 in self.generate_ping_endpoints(config):
            for ipv in self.params.ip_versions:
                ip_filter = {}
                if ipv == "ipv4":
                    ip_filter.update(family=AF_INET)
                elif ipv == "ipv6":
                    ip_filter.update(family=AF_INET6)
                    ip_filter.update(is_link_local=False)

                endpoint1_ips = endpoint1.ips_filter(**ip_filter)
                endpoint2_ips = endpoint2.ips_filter(**ip_filter)

                if len(endpoint1_ips) != len(endpoint2_ips):
                    raise LnstError(
                        "Source/destination ip lists are of different size.")

                ping_conf_list = []
                for src_addr, dst_addr in zip(endpoint1_ips, endpoint2_ips):
                    pconf = PingConf(
                        client=endpoint1.netns,
                        client_bind=src_addr,
                        destination=endpoint2.netns,
                        destination_address=dst_addr,
                        count=self.params.ping_count,
                        interval=self.params.ping_interval,
                        size=self.params.ping_psize,
                    )

                    ping_conf_list.append(pconf)

                    if self.params.ping_bidirect:
                        ping_conf_list.append(self._create_reverse_ping(pconf))

                    if not self.params.ping_parallel:
                        break

                yield ping_conf_list
Example #24
0
    def _process_msg(self, msg):
        if msg["type"] == "command":
            method = getattr(self._methods, msg["method_name"], None)
            if method != None:
                if_manager = self._methods._if_manager
                if if_manager is not None:
                    args = deviceref_to_device(if_manager, msg["args"])
                    kwargs = deviceref_to_device(if_manager, msg["kwargs"])
                else:
                    args = msg["args"]
                    kwargs = msg["kwargs"]

                try:
                    result = method(*args, **kwargs)
                except LnstError as e:
                    log_exc_traceback()
                    response = {"type": "exception", "Exception": e}

                    self._server_handler.send_data_to_ctl(response)
                    return

                response = {"type": "result", "result": result}
                response = device_to_deviceref(response)
                self._server_handler.send_data_to_ctl(response)
            else:
                err = LnstError("Method '%s' not supported." % msg["method_name"])
                response = {"type": "exception", "Exception": err}
                self._server_handler.send_data_to_ctl(response)
        elif msg["type"] == "log":
            logger = logging.getLogger()
            record = logging.makeLogRecord(msg["record"])
            logger.handle(record)
        elif msg["type"] == "exception":
            if msg["cmd_id"] != None:
                logging.debug("Recieved an exception from command with id: %s"
                                % msg["cmd_id"])
            else:
                logging.debug("Recieved an exception from foreground command")
            logging.debug(msg["Exception"])
            job = self._job_context.get_cmd(msg["job_id"])
            job.join()
            self._job_context.del_cmd(job)
            self._server_handler.send_data_to_ctl(msg)
        elif msg["type"] == "job_finished":
            job = self._job_context.get_job(msg["job_id"])
            job.join()

            job.set_finished(msg["result"])
            self._server_handler.send_data_to_ctl(msg)

            self._job_context.del_job(job)

        elif msg["type"] == "from_netns":
            self._server_handler.send_data_to_ctl(msg["data"])
        elif msg["type"] == "to_netns":
            netns = msg["netns"]
            try:
                self._server_handler.send_data_to_netns(netns, msg["data"])
            except LnstError as e:
                log_exc_traceback()
                response = {"type": "exception", "Exception": e}

                self._server_handler.send_data_to_ctl(response)
                return
        else:
            raise Exception("Recieved unknown command")

        pipes = self._job_context.get_parent_pipes()
        self._server_handler.update_connections(pipes)
Example #25
0
    def _validate_item(self, item):
        self._validate_item_type(item)

        if len(self) > 0 and item.unit != self[0].unit:
            raise LnstError("PerfList items must have the same unit.")
Example #26
0
def netperf(src, dst, server_opts={}, client_opts={}, baseline={}, timeout=60):
    """ Start a Netserver on the given machine and ip address

    Keyword arguments:
    src -- tuple of (HostAPI, InterfaceAPI/DeviceAPI, ip address index, ip addr selector)
    dst -- tuple of (HostAPI, InterfaceAPI/DeviceAPI, ip address index, ip addr selector)
    server_opts -- dictionary of additional options for the netperf server
        can't contain 'bind' or 'role'
    client_opts -- dictionary of additional options for the netperf client
        can't contain 'bind', 'role', 'netperf_server', 'threshold'
        or 'threshold_deviation'
    baseline -- optional dictionary with keys 'threshold' and 'threshold_deviation'
        that specifies the baseline of the netperf test
    timeout -- integer number of seconds specifing the maximum amount of time
        for the test, defaults to 60
    """

    server_opts = dict(server_opts)
    if 'bind' in server_opts or 'role' in server_opts:
        raise LnstError("server_opts can't contain keys 'bind' and 'role'")

    client_opts = dict(client_opts)
    if 'bind' in client_opts or\
       'role' in client_opts or\
       'netperf_server' in client_opts:
        raise LnstError("client_opts can't contain keys 'bind', 'role' "\
                        "and 'netperf_server'")

    if not isinstance(src, tuple) or len(src) < 2 or len(src) > 4:
        raise LnstError('Invalid source specification')
    try:
        if len(src) == 3:
            h1, if1, addr_index1 = src
            client_ip = if1.get_ip(addr_index1)
        elif len(src) == 4:
            h1, if1, addr_index1, addr_selector1 = src
            client_ip = if1.get_ip(addr_index1, selector=addr_selector1)
    except:
        raise LnstError('Invalid source specification')

    if not isinstance(dst, tuple) or len(dst) < 3 or len(dst) > 4:
        raise LnstError('Invalid destination specification')
    try:
        if len(dst) == 3:
            h2, if2, addr_index2 = dst
            server_ip = if2.get_ip(addr_index2)
        elif len(dst) == 4:
            h2, if2, addr_index2, addr_selector2 = dst
            server_ip = if2.get_ip(addr_index2, addr_selector2)
    except:
        raise LnstError('Invalid destination specification')

    server_opts["role"] = "server"
    server_opts["bind"] = server_ip

    client_opts["role"] = "client"
    client_opts["bind"] = client_ip
    client_opts["netperf_server"] = server_ip

    if "threshold" in baseline:
        client_opts["threshold"] = baseline["threshold"]
    if "threshold_deviation" in baseline:
        client_opts["threshold_deviation"] = baseline["threshold_deviation"]

    netserver_mod = ctl.get_module("Netperf", options=server_opts)
    netclient_mod = ctl.get_module("Netperf", options=client_opts)

    netserver = h2.run(netserver_mod, bg=True)
    ctl.wait(2)
    result = h1.run(netclient_mod, timeout=timeout)

    netserver.intr()
    return result
Example #27
0
    def register_evaluators(self, measurement, evaluators):
        if measurement not in self.measurements:
            raise LnstError("Can't register evaluators for an unknown measurement")

        self._evaluators[measurement] = list(evaluators)
Example #28
0
 def _validate_item_type(self, item):
     if (not isinstance(item, PerfInterval) and
         not isinstance(item, PerfList)):
         raise LnstError("{} only accepts PerfInterval or PerfList objects."
                         .format(self.__class__.__name__))
Example #29
0
 def get_dev_by_ip(self, netns, ip):
     for dev in netns.device_database:
         if ip in dev.ips:
             return dev
     raise LnstError("Could not match ip %s to any device of %s." %
                     (ip, netns.name))
Example #30
0
 def __init__(self, virt_type=None, hwaddr="", config=None):
     if not isinstance(virt_type, (VirtioType, None)):
         raise LnstError('Wrong virtio type')
     self.type = virt_type   # The virtio type
     self.hwaddr = hwaddr    # The MAC address of the device
     self.config = config    # Type-specific configuration