示例#1
0
文件: topogen.py 项目: wofanli/frr
    def vtysh_cmd(self, command, isjson=False, daemon=None):
        """
        Runs the provided command string in the vty shell and returns a string
        with the response.

        This function also accepts multiple commands, but this mode does not
        return output for each command. See vtysh_multicmd() for more details.
        """
        # Detect multi line commands
        if command.find('\n') != -1:
            return self.vtysh_multicmd(command, daemon=daemon)

        dparam = ''
        if daemon is not None:
            dparam += '-d {}'.format(daemon)

        vtysh_command = 'vtysh {} -c "{}" 2>/dev/null'.format(dparam, command)

        output = self.run(vtysh_command)
        self.logger.info('\nvtysh command => {}\nvtysh output <= {}'.format(
            command, output))
        if isjson is False:
            return output

        try:
            return json.loads(output)
        except ValueError:
            logger.warning('vtysh_cmd: failed to convert json output')
            return {}
def test_pe2_converge_evpn():
    "Wait for protocol convergence"

    tgen = get_topogen()
    # Don't run this test if we have any failure.
    if tgen.routers_have_failure():
        pytest.skip(tgen.errors)

    pe2 = tgen.gears["PE2"]
    json_file = "{}/{}/evpn.vni.json".format(CWD, pe2.name)
    expected = json.loads(open(json_file).read())

    test_func = partial(show_vni_json_elide_ifindex, pe2, 101, expected)
    _, result = topotest.run_and_expect(test_func, None, count=45, wait=1)
    assertmsg = '"{}" JSON output mismatches'.format(pe2.name)
    assert result is None, assertmsg

    test_func = partial(
        check_vni_macs_present,
        tgen,
        pe2,
        101,
        (("host1", "host1-eth0"), ("host2", "host2-eth0")),
    )
    _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
    if result:
        logger.warning("%s", result)
        assert None, '"{}" missing expected MACs'.format(pe2.name)
示例#3
0
文件: topogen.py 项目: ton31337/frr
    def vtysh_cmd(self, command, isjson=False, daemon=None):
        """
        Runs the provided command string in the vty shell and returns a string
        with the response.

        This function also accepts multiple commands, but this mode does not
        return output for each command. See vtysh_multicmd() for more details.
        """
        # Detect multi line commands
        if command.find('\n') != -1:
            return self.vtysh_multicmd(command, daemon=daemon)

        dparam = ''
        if daemon is not None:
            dparam += '-d {}'.format(daemon)

        vtysh_command = 'vtysh {} -c "{}" 2>/dev/null'.format(dparam, command)

        output = self.run(vtysh_command)
        self.logger.info('\nvtysh command => {}\nvtysh output <= {}'.format(
            command, output))
        if isjson is False:
            return output

        try:
            return json.loads(output)
        except ValueError:
            logger.warning('vtysh_cmd: failed to convert json output')
            return {}
示例#4
0
文件: ltemplate.py 项目: rgirada/frr
    def setup_module(self, mod):
        "Sets up the pytest environment"
        # This function initiates the topology build with Topogen...
        tgen = Topogen(customize.build_topo, mod.__name__)
        # ... and here it calls Mininet initialization functions.
        tgen.start_topology()

        self.logdir = tgen.logdir

        logger.info("Topology started")
        try:
            self.prestarthooksuccess = customize.ltemplatePreRouterStartHook()
        except AttributeError:
            # not defined
            logger.debug("ltemplatePreRouterStartHook() not defined")
        if self.prestarthooksuccess != True:
            logger.info("ltemplatePreRouterStartHook() failed, skipping test")
            return

        # This is a sample of configuration loading.
        router_list = tgen.routers()

        # For all registered routers, load the zebra configuration file
        for rname, router in router_list.items():
            logger.info("Setting up %s" % rname)
            for rd_val in TopoRouter.RD:
                config = os.path.join(
                    self.testdir, "{}/{}.conf".format(rname,
                                                      TopoRouter.RD[rd_val]))
                prog = os.path.join(tgen.net[rname].daemondir,
                                    TopoRouter.RD[rd_val])
                if os.path.exists(config):
                    if os.path.exists(prog):
                        router.load_config(rd_val, config)
                    else:
                        logger.warning(
                            "{} not found, but have {}.conf file".format(
                                prog, TopoRouter.RD[rd_val]))

        # After loading the configurations, this function loads configured daemons.
        logger.info("Starting routers")
        tgen.start_router()
        try:
            self.poststarthooksuccess = customize.ltemplatePostRouterStartHook(
            )
        except AttributeError:
            # not defined
            logger.debug("ltemplatePostRouterStartHook() not defined")
        luStart(baseScriptDir=self.scriptdir,
                baseLogDir=self.logdir,
                net=tgen.net)
示例#5
0
def show_isis_interface_detail(router, rname):
    """
    Get the show isis mpls ldp-sync info in a dictionary format.

    """
    out = topotest.normalize_text(
        router.vtysh_cmd("show isis interface detail")).splitlines()

    logger.warning(out)

    parsed = parse_show_isis_interface_detail(out, rname)

    logger.warning(parsed)

    return parsed
示例#6
0
    def vtysh_cmd(self, command, isjson=False, daemon=None):
        """
        Runs the provided command string in the vty shell and returns a string
        with the response.

        This function also accepts multiple commands, but this mode does not
        return output for each command. See vtysh_multicmd() for more details.
        """
        # Detect multi line commands
        if command.find("\n") != -1:
            return self.vtysh_multicmd(command, daemon=daemon)

        dparam = ""
        if daemon is not None:
            dparam += "-d {}".format(daemon)

        vtysh_command = 'vtysh {} -c "{}" 2>/dev/null'.format(dparam, command)

        self.logger.info('vtysh command => "{}"'.format(command))
        output = self.run(vtysh_command)

        dbgout = output.strip()
        if dbgout:
            if "\n" in dbgout:
                dbgout = dbgout.replace("\n", "\n\t")
                self.logger.info("vtysh result:\n\t{}".format(dbgout))
            else:
                self.logger.info('vtysh result: "{}"'.format(dbgout))

        if isjson is False:
            return output

        try:
            return json.loads(output)
        except ValueError as error:
            logger.warning(
                "vtysh_cmd: %s: failed to convert json output: %s: %s",
                self.name,
                str(output),
                str(error),
            )
            return {}
示例#7
0
def diagnose_env_linux():
    """
    Run diagnostics in the running environment. Returns `True` when everything
    is ok, otherwise `False`.
    """
    ret = True

    # Test log path exists before installing handler.
    if not os.path.isdir("/tmp"):
        logger.warning("could not find /tmp for logs")
    else:
        os.system("mkdir /tmp/topotests")
        # Log diagnostics to file so it can be examined later.
        fhandler = logging.FileHandler(
            filename="/tmp/topotests/diagnostics.txt")
        fhandler.setLevel(logging.DEBUG)
        fhandler.setFormatter(
            logging.Formatter(fmt="%(asctime)s %(levelname)s: %(message)s"))
        logger.addHandler(fhandler)

    logger.info("Running environment diagnostics")

    # Load configuration
    config = configparser.ConfigParser(defaults=tgen_defaults)
    pytestini_path = os.path.join(CWD, "../pytest.ini")
    config.read(pytestini_path)

    # Assert that we are running as root
    if os.getuid() != 0:
        logger.error("you must run topotest as root")
        ret = False

    # Assert that we have mininet
    if os.system("which mn >/dev/null 2>/dev/null") != 0:
        logger.error(
            "could not find mininet binary (mininet is not installed)")
        ret = False

    # Assert that we have iproute installed
    if os.system("which ip >/dev/null 2>/dev/null") != 0:
        logger.error("could not find ip binary (iproute is not installed)")
        ret = False

    # Assert that we have gdb installed
    if os.system("which gdb >/dev/null 2>/dev/null") != 0:
        logger.error("could not find gdb binary (gdb is not installed)")
        ret = False

    # Assert that FRR utilities exist
    frrdir = config.get("topogen", "frrdir")
    if not os.path.isdir(frrdir):
        logger.error("could not find {} directory".format(frrdir))
        ret = False
    else:
        try:
            pwd.getpwnam("frr")[2]
        except KeyError:
            logger.warning('could not find "frr" user')

        try:
            grp.getgrnam("frr")[2]
        except KeyError:
            logger.warning('could not find "frr" group')

        try:
            if "frr" not in grp.getgrnam("frrvty").gr_mem:
                logger.error(
                    '"frr" user and group exist, but user is not under "frrvty"'
                )
        except KeyError:
            logger.warning('could not find "frrvty" group')

        for fname in [
                "zebra",
                "ospfd",
                "ospf6d",
                "bgpd",
                "ripd",
                "ripngd",
                "isisd",
                "pimd",
                "ldpd",
                "pbrd",
        ]:
            path = os.path.join(frrdir, fname)
            if not os.path.isfile(path):
                # LDPd is an exception
                if fname == "ldpd":
                    logger.info(
                        "could not find {} in {}".format(fname, frrdir) +
                        "(LDPd tests will not run)")
                    continue

                logger.warning("could not find {} in {}".format(fname, frrdir))
                ret = False
            else:
                if fname != "zebra":
                    continue

                os.system(
                    "{} -v 2>&1 >/tmp/topotests/frr_zebra.txt".format(path))

    # Test MPLS availability
    krel = platform.release()
    if topotest.version_cmp(krel, "4.5") < 0:
        logger.info(
            'LDPd tests will not run (have kernel "{}", but it requires 4.5)'.
            format(krel))

    # Test for MPLS Kernel modules available
    if not topotest.module_present("mpls-router", load=False) != 0:
        logger.info(
            "LDPd tests will not run (missing mpls-router kernel module)")
    if not topotest.module_present("mpls-iptunnel", load=False) != 0:
        logger.info(
            "LDPd tests will not run (missing mpls-iptunnel kernel module)")

    # TODO remove me when we start supporting exabgp >= 4
    try:
        p = os.popen("exabgp -v")
        line = p.readlines()
        version = line[0].split()
        if topotest.version_cmp(version[2], "4") >= 0:
            logger.warning(
                "BGP topologies are still using exabgp version 3, expect failures"
            )

    # We want to catch all exceptions
    # pylint: disable=W0702
    except:
        logger.warning("failed to find exabgp or returned error")

    # After we logged the output to file, remove the handler.
    logger.removeHandler(fhandler)

    return ret
示例#8
0
文件: topogen.py 项目: wofanli/frr
def diagnose_env_linux():
    """
    Run diagnostics in the running environment. Returns `True` when everything
    is ok, otherwise `False`.
    """
    ret = True

    # Test log path exists before installing handler.
    if not os.path.isdir('/tmp'):
        logger.warning('could not find /tmp for logs')
    else:
        os.system('mkdir /tmp/topotests')
        # Log diagnostics to file so it can be examined later.
        fhandler = logging.FileHandler(filename='/tmp/topotests/diagnostics.txt')
        fhandler.setLevel(logging.DEBUG)
        fhandler.setFormatter(
            logging.Formatter(fmt='%(asctime)s %(levelname)s: %(message)s')
        )
        logger.addHandler(fhandler)

    logger.info('Running environment diagnostics')

    # Load configuration
    config = ConfigParser.ConfigParser(tgen_defaults)
    pytestini_path = os.path.join(CWD, '../pytest.ini')
    config.read(pytestini_path)

    # Assert that we are running as root
    if os.getuid() != 0:
        logger.error('you must run topotest as root')
        ret = False

    # Assert that we have mininet
    if os.system('which mn >/dev/null 2>/dev/null') != 0:
        logger.error('could not find mininet binary (mininet is not installed)')
        ret = False

    # Assert that we have iproute installed
    if os.system('which ip >/dev/null 2>/dev/null') != 0:
        logger.error('could not find ip binary (iproute is not installed)')
        ret = False

    # Assert that we have gdb installed
    if os.system('which gdb >/dev/null 2>/dev/null') != 0:
        logger.error('could not find gdb binary (gdb is not installed)')
        ret = False

    # Assert that FRR utilities exist
    frrdir = config.get('topogen', 'frrdir')
    hasfrr = False
    if not os.path.isdir(frrdir):
        logger.error('could not find {} directory'.format(frrdir))
        ret = False
    else:
        hasfrr = True
        try:
            pwd.getpwnam('frr')[2]
        except KeyError:
            logger.warning('could not find "frr" user')

        try:
            grp.getgrnam('frr')[2]
        except KeyError:
            logger.warning('could not find "frr" group')

        try:
            if 'frr' not in grp.getgrnam('frrvty').gr_mem:
                logger.error('"frr" user and group exist, but user is not under "frrvty"')
        except KeyError:
            logger.warning('could not find "frrvty" group')

        for fname in ['zebra', 'ospfd', 'ospf6d', 'bgpd', 'ripd', 'ripngd',
                      'isisd', 'pimd', 'ldpd']:
            path = os.path.join(frrdir, fname)
            if not os.path.isfile(path):
                # LDPd is an exception
                if fname == 'ldpd':
                    logger.info('could not find {} in {}'.format(fname, frrdir) +
                                '(LDPd tests will not run)')
                    continue

                logger.warning('could not find {} in {}'.format(fname, frrdir))
                ret = False
            else:
                if fname != 'zebra':
                    continue

                os.system(
                    '{} -v 2>&1 >/tmp/topotests/frr_zebra.txt'.format(path)
                )

    # Assert that Quagga utilities exist
    quaggadir = config.get('topogen', 'quaggadir')
    if hasfrr:
        # if we have frr, don't check for quagga
        pass
    elif not os.path.isdir(quaggadir):
        logger.info('could not find {} directory (quagga tests will not run)'.format(quaggadir))
    else:
        ret = True
        try:
            pwd.getpwnam('quagga')[2]
        except KeyError:
            logger.info('could not find "quagga" user')

        try:
            grp.getgrnam('quagga')[2]
        except KeyError:
            logger.info('could not find "quagga" group')

        try:
            if 'quagga' not in grp.getgrnam('quaggavty').gr_mem:
                logger.error('"quagga" user and group exist, but user is not under "quaggavty"')
        except KeyError:
            logger.warning('could not find "quaggavty" group')

        for fname in ['zebra', 'ospfd', 'ospf6d', 'bgpd', 'ripd', 'ripngd',
                      'isisd', 'pimd']:
            path = os.path.join(quaggadir, fname)
            if not os.path.isfile(path):
                logger.warning('could not find {} in {}'.format(fname, quaggadir))
                ret = False
            else:
                if fname != 'zebra':
                    continue

                os.system(
                    '{} -v 2>&1 >/tmp/topotests/quagga_zebra.txt'.format(path)
                )

    # Test MPLS availability
    krel = platform.release()
    if topotest.version_cmp(krel, '4.5') < 0:
        logger.info('LDPd tests will not run (have kernel "{}", but it requires 4.5)'.format(krel))

    # Test for MPLS Kernel modules available
    if not topotest.module_present('mpls-router', load=False) != 0:
        logger.info('LDPd tests will not run (missing mpls-router kernel module)')
    if not topotest.module_present('mpls-iptunnel', load=False) != 0:
        logger.info('LDPd tests will not run (missing mpls-iptunnel kernel module)')

    # TODO remove me when we start supporting exabgp >= 4
    try:
        output = subprocess.check_output(['exabgp', '-v'])
        line = output.split('\n')[0]
        version = line.split(' ')[2]
        if topotest.version_cmp(version, '4') >= 0:
            logger.warning('BGP topologies are still using exabgp version 3, expect failures')

    # We want to catch all exceptions
    # pylint: disable=W0702
    except:
        logger.warning('failed to find exabgp or returned error')

    # After we logged the output to file, remove the handler.
    logger.removeHandler(fhandler)

    return ret
示例#9
0
def diagnose_env_linux(rundir):
    """
    Run diagnostics in the running environment. Returns `True` when everything
    is ok, otherwise `False`.
    """
    ret = True

    # Load configuration
    config = configparser.ConfigParser(defaults=tgen_defaults)
    pytestini_path = os.path.join(CWD, "../pytest.ini")
    config.read(pytestini_path)

    # Test log path exists before installing handler.
    os.system("mkdir -p " + rundir)
    # Log diagnostics to file so it can be examined later.
    fhandler = logging.FileHandler(
        filename="{}/diagnostics.txt".format(rundir))
    fhandler.setLevel(logging.DEBUG)
    fhandler.setFormatter(logging.Formatter(fmt=topolog.FORMAT))
    logger.addHandler(fhandler)

    logger.info("Running environment diagnostics")

    # Assert that we are running as root
    if os.getuid() != 0:
        logger.error("you must run topotest as root")
        ret = False

    # Assert that we have mininet
    # if os.system("which mn >/dev/null 2>/dev/null") != 0:
    #     logger.error("could not find mininet binary (mininet is not installed)")
    #     ret = False

    # Assert that we have iproute installed
    if os.system("which ip >/dev/null 2>/dev/null") != 0:
        logger.error("could not find ip binary (iproute is not installed)")
        ret = False

    # Assert that we have gdb installed
    if os.system("which gdb >/dev/null 2>/dev/null") != 0:
        logger.error("could not find gdb binary (gdb is not installed)")
        ret = False

    # Assert that FRR utilities exist
    frrdir = config.get("topogen", "frrdir")
    if not os.path.isdir(frrdir):
        logger.error("could not find {} directory".format(frrdir))
        ret = False
    else:
        try:
            pwd.getpwnam("frr")[2]
        except KeyError:
            logger.warning('could not find "frr" user')

        try:
            grp.getgrnam("frr")[2]
        except KeyError:
            logger.warning('could not find "frr" group')

        try:
            if "frr" not in grp.getgrnam("frrvty").gr_mem:
                logger.error(
                    '"frr" user and group exist, but user is not under "frrvty"'
                )
        except KeyError:
            logger.warning('could not find "frrvty" group')

        for fname in [
                "zebra",
                "ospfd",
                "ospf6d",
                "bgpd",
                "ripd",
                "ripngd",
                "isisd",
                "pimd",
                "pim6d",
                "ldpd",
                "pbrd",
        ]:
            path = os.path.join(frrdir, fname)
            if not os.path.isfile(path):
                # LDPd is an exception
                if fname == "ldpd":
                    logger.info(
                        "could not find {} in {}".format(fname, frrdir) +
                        "(LDPd tests will not run)")
                    continue

                logger.warning("could not find {} in {}".format(fname, frrdir))
                ret = False
            else:
                if fname != "zebra":
                    continue

                os.system("{} -v 2>&1 >{}/frr_zebra.txt".format(path, rundir))

    # Test MPLS availability
    krel = platform.release()
    if topotest.version_cmp(krel, "4.5") < 0:
        logger.info(
            'LDPd tests will not run (have kernel "{}", but it requires 4.5)'.
            format(krel))

    # Test for MPLS Kernel modules available
    if not topotest.module_present("mpls-router", load=False) != 0:
        logger.info(
            "LDPd tests will not run (missing mpls-router kernel module)")
    if not topotest.module_present("mpls-iptunnel", load=False) != 0:
        logger.info(
            "LDPd tests will not run (missing mpls-iptunnel kernel module)")

    if not get_exabgp_cmd():
        logger.warning("Failed to find exabgp < 4")

    logger.removeHandler(fhandler)
    fhandler.close()

    return ret
示例#10
0
文件: conftest.py 项目: patrasar/frr
def pytest_runtest_makereport(item, call):
    "Log all assert messages to default logger with error level"

    # Nothing happened
    if call.when == "call":
        pause = topotest_extra_config["pause"]
    else:
        pause = False

    title = "unset"

    if call.excinfo is None:
        error = False
    else:
        parent = item.parent
        modname = parent.module.__name__

        # Treat skips as non errors, don't pause after
        if call.excinfo.typename == "Skipped":
            pause = False
            error = False
            logger.info('test skipped at "{}/{}": {}'.format(
                modname, item.name, call.excinfo.value))
        else:
            error = True
            # Handle assert failures
            parent._previousfailed = item  # pylint: disable=W0212
            logger.error('test failed at "{}/{}": {}'.format(
                modname, item.name, call.excinfo.value))
            title = "{}/{}".format(modname, item.name)

            # We want to pause, if requested, on any error not just test cases
            # (e.g., call.when == "setup")
            if not pause:
                pause = (topotest_extra_config["pause_on_error"]
                         or topotest_extra_config["pause"])

            # (topogen) Set topology error to avoid advancing in the test.
            tgen = get_topogen()
            if tgen is not None:
                # This will cause topogen to report error on `routers_have_failure`.
                tgen.set_error("{}/{}".format(modname, item.name))

    commander = Commander("pytest")
    isatty = sys.stdout.isatty()
    error_cmd = None

    if error and topotest_extra_config["vtysh_on_error"]:
        error_cmd = commander.get_exec_path(["vtysh"])
    elif error and topotest_extra_config["shell_on_error"]:
        error_cmd = os.getenv("SHELL", commander.get_exec_path(["bash"]))

    if error_cmd:
        is_tmux = bool(os.getenv("TMUX", ""))
        is_screen = not is_tmux and bool(os.getenv("STY", ""))
        is_xterm = not is_tmux and not is_screen and bool(
            os.getenv("DISPLAY", ""))

        channel = None
        win_info = None
        wait_for_channels = []
        wait_for_procs = []
        # Really would like something better than using this global here.
        # Not all tests use topogen though so get_topogen() won't work.
        for node in Mininet.g_mnet_inst.hosts.values():
            pause = True

            if is_tmux:
                channel = ("{}-{}".format(os.getpid(), Commander.tmux_wait_gen)
                           if not isatty else None)
                Commander.tmux_wait_gen += 1
                wait_for_channels.append(channel)

            pane_info = node.run_in_window(
                error_cmd,
                new_window=win_info is None,
                background=True,
                title="{} ({})".format(title, node.name),
                name=title,
                tmux_target=win_info,
                wait_for=channel,
            )
            if is_tmux:
                if win_info is None:
                    win_info = pane_info
            elif is_xterm:
                assert isinstance(pane_info, subprocess.Popen)
                wait_for_procs.append(pane_info)

        # Now wait on any channels
        for channel in wait_for_channels:
            logger.debug("Waiting on TMUX channel %s", channel)
            commander.cmd_raises(
                [commander.get_exec_path("tmux"), "wait", channel])
        for p in wait_for_procs:
            logger.debug("Waiting on TMUX xterm process %s", p)
            o, e = p.communicate()
            if p.wait():
                logger.warning("xterm proc failed: %s:", proc_error(p, o, e))

    if error and topotest_extra_config["cli_on_error"]:
        # Really would like something better than using this global here.
        # Not all tests use topogen though so get_topogen() won't work.
        if Mininet.g_mnet_inst:
            cli(Mininet.g_mnet_inst, title=title, background=False)
        else:
            logger.error("Could not launch CLI b/c no mininet exists yet")

    while pause and isatty:
        try:
            user = raw_input(
                'PAUSED, "cli" for CLI, "pdb" to debug, "Enter" to continue: ')
        except NameError:
            user = input(
                'PAUSED, "cli" for CLI, "pdb" to debug, "Enter" to continue: ')
        user = user.strip()

        if user == "cli":
            cli(Mininet.g_mnet_inst)
        elif user == "pdb":
            pdb.set_trace()
        elif user:
            print('Unrecognized input: "%s"' % user)
        else:
            break
示例#11
0
文件: topogen.py 项目: ton31337/frr
def diagnose_env_linux():
    """
    Run diagnostics in the running environment. Returns `True` when everything
    is ok, otherwise `False`.
    """
    ret = True

    # Test log path exists before installing handler.
    if not os.path.isdir('/tmp'):
        logger.warning('could not find /tmp for logs')
    else:
        os.system('mkdir /tmp/topotests')
        # Log diagnostics to file so it can be examined later.
        fhandler = logging.FileHandler(filename='/tmp/topotests/diagnostics.txt')
        fhandler.setLevel(logging.DEBUG)
        fhandler.setFormatter(
            logging.Formatter(fmt='%(asctime)s %(levelname)s: %(message)s')
        )
        logger.addHandler(fhandler)

    logger.info('Running environment diagnostics')

    # Load configuration
    config = configparser.ConfigParser(tgen_defaults)
    pytestini_path = os.path.join(CWD, '../pytest.ini')
    config.read(pytestini_path)

    # Assert that we are running as root
    if os.getuid() != 0:
        logger.error('you must run topotest as root')
        ret = False

    # Assert that we have mininet
    if os.system('which mn >/dev/null 2>/dev/null') != 0:
        logger.error('could not find mininet binary (mininet is not installed)')
        ret = False

    # Assert that we have iproute installed
    if os.system('which ip >/dev/null 2>/dev/null') != 0:
        logger.error('could not find ip binary (iproute is not installed)')
        ret = False

    # Assert that we have gdb installed
    if os.system('which gdb >/dev/null 2>/dev/null') != 0:
        logger.error('could not find gdb binary (gdb is not installed)')
        ret = False

    # Assert that FRR utilities exist
    frrdir = config.get('topogen', 'frrdir')
    hasfrr = False
    if not os.path.isdir(frrdir):
        logger.error('could not find {} directory'.format(frrdir))
        ret = False
    else:
        hasfrr = True
        try:
            pwd.getpwnam('frr')[2]
        except KeyError:
            logger.warning('could not find "frr" user')

        try:
            grp.getgrnam('frr')[2]
        except KeyError:
            logger.warning('could not find "frr" group')

        try:
            if 'frr' not in grp.getgrnam('frrvty').gr_mem:
                logger.error('"frr" user and group exist, but user is not under "frrvty"')
        except KeyError:
            logger.warning('could not find "frrvty" group')

        for fname in ['zebra', 'ospfd', 'ospf6d', 'bgpd', 'ripd', 'ripngd',
                      'isisd', 'pimd', 'ldpd']:
            path = os.path.join(frrdir, fname)
            if not os.path.isfile(path):
                # LDPd is an exception
                if fname == 'ldpd':
                    logger.info('could not find {} in {}'.format(fname, frrdir) +
                                '(LDPd tests will not run)')
                    continue

                logger.warning('could not find {} in {}'.format(fname, frrdir))
                ret = False
            else:
                if fname != 'zebra':
                    continue

                os.system(
                    '{} -v 2>&1 >/tmp/topotests/frr_zebra.txt'.format(path)
                )

    # Assert that Quagga utilities exist
    quaggadir = config.get('topogen', 'quaggadir')
    if hasfrr:
        # if we have frr, don't check for quagga
        pass
    elif not os.path.isdir(quaggadir):
        logger.info('could not find {} directory (quagga tests will not run)'.format(quaggadir))
    else:
        ret = True
        try:
            pwd.getpwnam('quagga')[2]
        except KeyError:
            logger.info('could not find "quagga" user')

        try:
            grp.getgrnam('quagga')[2]
        except KeyError:
            logger.info('could not find "quagga" group')

        try:
            if 'quagga' not in grp.getgrnam('quaggavty').gr_mem:
                logger.error('"quagga" user and group exist, but user is not under "quaggavty"')
        except KeyError:
            logger.warning('could not find "quaggavty" group')

        for fname in ['zebra', 'ospfd', 'ospf6d', 'bgpd', 'ripd', 'ripngd',
                      'isisd', 'pimd']:
            path = os.path.join(quaggadir, fname)
            if not os.path.isfile(path):
                logger.warning('could not find {} in {}'.format(fname, quaggadir))
                ret = False
            else:
                if fname != 'zebra':
                    continue

                os.system(
                    '{} -v 2>&1 >/tmp/topotests/quagga_zebra.txt'.format(path)
                )

    # Test MPLS availability
    krel = platform.release()
    if topotest.version_cmp(krel, '4.5') < 0:
        logger.info('LDPd tests will not run (have kernel "{}", but it requires 4.5)'.format(krel))

    # Test for MPLS Kernel modules available
    if not topotest.module_present('mpls-router', load=False) != 0:
        logger.info('LDPd tests will not run (missing mpls-router kernel module)')
    if not topotest.module_present('mpls-iptunnel', load=False) != 0:
        logger.info('LDPd tests will not run (missing mpls-iptunnel kernel module)')

    # TODO remove me when we start supporting exabgp >= 4
    try:
        output = subprocess.check_output(['exabgp', '-v'])
        line = output.split('\n')[0]
        version = line.split(' ')[2]
        if topotest.version_cmp(version, '4') >= 0:
            logger.warning('BGP topologies are still using exabgp version 3, expect failures')

    # We want to catch all exceptions
    # pylint: disable=W0702
    except:
        logger.warning('failed to find exabgp or returned error')

    # After we logged the output to file, remove the handler.
    logger.removeHandler(fhandler)

    return ret