Example #1
0
def check_for_memleaks():
    assert topotest_extra_config["valgrind_memleaks"]

    leaks = []
    tgen = get_topogen()
    latest = []
    existing = []
    if tgen is not None:
        logdir = tgen.logdir
        if hasattr(tgen, "valgrind_existing_files"):
            existing = tgen.valgrind_existing_files
        latest = glob.glob(os.path.join(logdir, "*.valgrind.*"))

    daemons = set()
    for vfile in latest:
        if vfile in existing:
            continue
        existing.append(vfile)
        with open(vfile, encoding="ascii") as vf:
            vfcontent = vf.read()
            match = re.search(r"ERROR SUMMARY: (\d+) errors", vfcontent)
            if match and match.group(1) != "0":
                emsg = "{} in {}".format(match.group(1), vfile)
                leaks.append(emsg)
                daemons.add(
                    re.match(r".*\.valgrind\.(.*)\.\d+", vfile).group(1))

    if tgen is not None:
        tgen.valgrind_existing_files = existing

    if leaks:
        logger.error("valgrind memleaks found:\n\t%s", "\n\t".join(leaks))
        pytest.fail("valgrind memleaks found for daemons: " +
                    " ".join(daemons))
Example #2
0
def _print_bgp_neighbors_cfg(frr_cfg, neighbor):
    neigh_ip = IpAddressMsg_to_str(neighbor.ip_address)
    neigh_cxt = 'neighbor ' + neigh_ip + ' '
    frr_cfg.bgp_neighbors.write(neigh_cxt + 'remote-as ' +
                                str(neighbor.remote_as) + '\n')
    frr_cfg.bgp_neighbors.write(neigh_cxt + 'activate\n')
    frr_cfg.bgp_neighbors.write(neigh_cxt + 'disable-connected-check\n')
    if neighbor.update_source != None:
        frr_cfg.bgp_neighbors.write(neigh_cxt + 'update-source ' +
                                    neighbor.update_source + ' \n')
    keep_alive = '60'
    hold_down = '180'
    if neighbor.keep_alive_time and neighbor.hold_down_time:
        keep_alive = str(neighbor.keep_alive_time)
        hold_down = str(neighbor.hold_down_time)
    frr_cfg.bgp_neighbors.write(neigh_cxt + 'timers ' + keep_alive + ' ' +
                                hold_down + '\n')
    if neighbor.password != None:
        frr_cfg.bgp_neighbors.write(neigh_cxt + 'password ' +
                                    neighbor.password + '\n')
    if neighbor.max_hop_limit > 1:
        frr_cfg.bgp_neighbors.write(neigh_cxt + 'ebgp-multihop ' +
                                    str(neighbor.max_hop_limit) + '\n')
        frr_cfg.bgp_neighbors.write(neigh_cxt + 'enforce-multihop\n')
    for addr_family in neighbor.address_families:
        if addr_family.type not in [IPv4_UNICAST, IPv6_UNICAST, VPNv4_UNICAST]:
            logger.error('unsupported address family')
            return False
        if addr_family.type == VPNv4_UNICAST and not addr_family.enabled:
            logger.error('vpnv4 family is not enabled')
            return False
        _print_bgp_address_family_cfg(frr_cfg, neigh_ip, addr_family)
Example #3
0
def pytest_runtest_makereport(item, call):
    "Log all assert messages to default logger with error level"
    # Nothing happened
    if call.excinfo is None:
        return

    parent = item.parent
    modname = parent.module.__name__

    # Treat skips as non errors
    if call.excinfo.typename != "AssertionError":
        logger.info('assert skipped at "{}/{}": {}'.format(
            modname, item.name, call.excinfo.value))
        return

    # Handle assert failures
    parent._previousfailed = item
    logger.error('assert failed at "{}/{}": {}'.format(modname, item.name,
                                                       call.excinfo.value))

    # (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))
Example #4
0
def create_common_configuration(tgen,
                                router,
                                data,
                                config_type=None,
                                build=False):
    """
    API to create object of class FRRConfig and also create frr_json.conf
    file. It will create interface and common configurations and save it to
    frr_json.conf and load to router

    Parameters
    ----------
    * `tgen`: tgen onject
    * `data`: Congiguration data saved in a list.
    * `router` : router id to be configured.
    * `config_type` : Syntactic information while writing configuration. Should
                      be one of the value as mentioned in the config_map below.
    * `build` : Only for initial setup phase this is set as True

    Returns
    -------
    True or False
    """
    TMPDIR = os.path.join(LOGDIR, tgen.modname)

    fname = "{}/{}/{}".format(TMPDIR, router, FRRCFG_FILE)

    config_map = OrderedDict({
        "general_config": "! FRR General Config\n",
        "interface_config": "! Interfaces Config\n",
        "static_route": "! Static Route Config\n",
        "prefix_list": "! Prefix List Config\n",
        "route_maps": "! Route Maps Config\n",
        "bgp": "! BGP Config\n"
    })

    if build:
        mode = "a"
    else:
        mode = "w"

    try:
        frr_cfg_fd = open(fname, mode)
        if config_type:
            frr_cfg_fd.write(config_map[config_type])
        for line in data:
            frr_cfg_fd.write("{} \n".format(str(line)))

    except IOError as err:
        logger.error("Unable to open FRR Config File. error(%s): %s" %
                     (err.errno, err.strerror))
        return False
    finally:
        frr_cfg_fd.close()

    # If configuration applied from build, it will done at last
    if not build:
        load_config_to_router(tgen, router)

    return True
Example #5
0
def check_for_memleaks():
    if not topotest_extra_config["valgrind_memleaks"]:
        return

    leaks = []
    tgen = get_topogen()
    latest = []
    existing = []
    if tgen is not None:
        logdir = "/tmp/topotests/{}".format(tgen.modname)
        if hasattr(tgen, "valgrind_existing_files"):
            existing = tgen.valgrind_existing_files
        latest = glob.glob(os.path.join(logdir, "*.valgrind.*"))

    for vfile in latest:
        if vfile in existing:
            continue
        with open(vfile) as vf:
            vfcontent = vf.read()
            match = re.search(r"ERROR SUMMARY: (\d+) errors", vfcontent)
            if match and match.group(1) != "0":
                emsg = '{} in {}'.format(match.group(1), vfile)
                leaks.append(emsg)

    if leaks:
        if leak_check_ok:
            pytest.fail("Memleaks found:\n\t" + "\n\t".join(leaks))
        else:
            logger.error("Memleaks found:\n\t" + "\n\t".join(leaks))
Example #6
0
def ltemplateTest(script, SkipIfFailed=True, CallOnFail=None, CheckFuncStr=None, KeepGoing=False):
    global _lt
    if _lt == None or _lt.prestarthooksuccess != True:
        return

    tgen = get_topogen()
    if not os.path.isfile(script):
        if not os.path.isfile(os.path.join(_lt.scriptdir, script)):
            logger.error('Could not find script file: ' + script)
            assert 'Could not find script file: ' + script
    logger.info("Starting template test: " + script)
    numEntry = luNumFail()

    if SkipIfFailed and tgen.routers_have_failure():
        pytest.skip(tgen.errors)
    if numEntry > 0:
	if not KeepGoing:
	    pytest.skip("Have %d errors" % numEntry)

    if CheckFuncStr != None:
        check = eval(CheckFuncStr)
        if check != True:
            pytest.skip("Check function '"+CheckFuncStr+"' returned: " + check)

    if CallOnFail != None:
        CallOnFail = eval(CallOnFail)
    luInclude(script, CallOnFail)
    numFail = luNumFail() - numEntry
    if numFail > 0:
        luShowFail()
        fatal_error = "%d tests failed" % numFail
	if not KeepGoing:
	    assert "scripts/cleanup_all.py failed" == "See summary output above", fatal_error
Example #7
0
def redist_cfg(frr_cfg, topo):
    """ 
    To redistribute static and connected  routes for given router. 
    
    * `topo` : json file data
    * `frrcfg` : frr config file to save router config
    """

    try:
        if frr_cfg.is_bgp_configured:
            if frr_cfg.routing_pb.redist_static_routes_flag == 'bgp':
                for router, number in number_to_router.iteritems():
                    if number == frr_cfg.router:
                        neighbors = topo['routers']['{}'.format(
                            router)]["bgp"]['bgp_neighbors']
                        for key, value in neighbors.iteritems():
                            peer = neighbors[key]['peer']
                            ADDR_TYPE = peer['addr_type']

                        if ADDR_TYPE == "ipv4":
                            # IPv4
                            frr_cfg.bgp_address_family[IPv4_UNICAST].write(
                                'redistribute static\n')
                            frr_cfg.bgp_address_family[IPv4_UNICAST].write(
                                'redistribute connected\n')
                        else:
                            # IPv6
                            frr_cfg.bgp_address_family[IPv6_UNICAST].write(
                                'redistribute static\n')
                            frr_cfg.bgp_address_family[IPv6_UNICAST].write(
                                'redistribute connected\n')
    except Exception as e:
        logger.error(traceback.format_exc())
Example #8
0
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_after"]
    else:
        pause = False

    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 != "AssertionError":
            pause = False
            error = False
            logger.info(
                'assert skipped at "{}/{}": {}'.format(
                    modname, item.name, call.excinfo.value
                )
            )
        else:
            error = True
            # Handle assert failures
            parent._previousfailed = item       # pylint: disable=W0212
            logger.error(
                'assert failed at "{}/{}": {}'.format(modname, item.name, call.excinfo.value)
            )

            # (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))


    if error and topotest_extra_config["shell_on_error"]:
        for router in tgen.routers():
            pause = True
            tgen.net[router].runInWindow(os.getenv("SHELL", "bash"))

    if error and topotest_extra_config["vtysh_on_error"]:
        for router in tgen.routers():
            pause = True
            tgen.net[router].runInWindow("vtysh")

    if error and topotest_extra_config["mininet_on_error"]:
        tgen.mininet_cli()

    if pause:
        try:
            user = raw_input('Testing paused, "pdb" to debug, "Enter" to continue: ')
        except NameError:
            user = input('Testing paused, "pdb" to debug, "Enter" to continue: ')
        if user.strip() == "pdb":
            pdb.set_trace()
Example #9
0
    def push_to_frr(self):
        for _ in range(3):
            if self._push_to_frr():
                logger.info('Successfully pushed the config to FRR')
                return True

        logger.error('Unable to push the config to FRR')
        return False
Example #10
0
def luShowFail():
    printed = 0
    sf = open(LUtil.fsum_name, "r")
    for line in sf:
        if line[-2] != "0":
            printed += 1
            logger.error(line.rstrip())
    sf.close()
    if printed > 0:
        logger.error("See %s for details of errors" % LUtil.fout_name)
Example #11
0
File: ospf.py Project: stoza/frr
def __create_ospf6_global(tgen,
                          input_dict,
                          router,
                          build=False,
                          load_config=True):
    """
    Helper API to create ospf global configuration.

    Parameters
    ----------
    * `tgen` : Topogen object
    * `input_dict` : Input dict data, required when configuring from testcase
    * `router` : router id to be configured.
    * `build` : Only for initial setup phase this is set as True.

    Returns
    -------
    True or False
    """

    result = False
    logger.debug("Entering lib API: __create_ospf_global()")
    try:

        ospf_data = input_dict[router]["ospf6"]
        del_ospf_action = ospf_data.setdefault("delete", False)
        if del_ospf_action:
            config_data = ["no ipv6 router ospf"]
            result = create_common_configuration(tgen, router, config_data,
                                                 "ospf", build, load_config)
            return result

        config_data = []
        cmd = "router ospf"

        config_data.append(cmd)

        router_id = ospf_data.setdefault("router_id", None)
        del_router_id = ospf_data.setdefault("del_router_id", False)
        if del_router_id:
            config_data.append("no ospf router-id")
        if router_id:
            config_data.append("ospf router-id {}".format(router_id))

        result = create_common_configuration(tgen, router, config_data, "ospf",
                                             build, load_config)
    except InvalidCLIError:
        # Traceback
        errormsg = traceback.format_exc()
        logger.error(errormsg)
        return errormsg

    logger.debug("Exiting lib API: create_ospf_global()")
    return result
Example #12
0
 def run_shell_command(self, cmdline):
     logger.debug('executing command: %s', ' '.join(cmdline))
     try:
         output = subprocess.check_output(cmdline,
                                          stderr=subprocess.STDOUT,
                                          close_fds=True)
         logger.debug('output: %s', output)
         return True
     except subprocess.CalledProcessError as cpe:
         logger.error('Failed to execute: rc=%s, out=%s, err=%s',
                      cpe.returncode, cpe.output, cpe)
         return False
Example #13
0
def create_config_files(tgen, CWD, topo):
    """
    It will create BGP basic configuration(router-id only) 
    and save it to frr.conf, then it will call APIs to create
    BGP and interface configuration and all configuration would
    be saved in frr.conf file.

    * `tgen` : Topogen object
    * `CWD`  : caller's current working directory
    * `topo` : json file data 
    """

    try:
        listRouters = []
        for routerN in topo['routers'].iteritems():
            listRouters.append(routerN[0])

        listRouters.sort()
        assign_number_to_routers(listRouters)
        logger.info('Configuring nodes')
        for curRouter in number_to_router.keys():
            router = curRouter
            i = number_to_router[curRouter]
            if 'router_id' in topo['routers'][router]['bgp']:
                ip = topo['routers'][router]['bgp']['router-id']
                ip = Address(ADDR_TYPE_IPv4, ip, None)
                rid = int(socket.inet_aton(ip.ipv4).encode('hex'), 16)
                router_id = Address(ADDR_TYPE_IPv4, rid, None)
            else:
                router_id = None
            rt_cfg = RoutingPB(router_id)
            fname = '%s/r%d/frr.conf' % (CWD, i)
            frr_cfg[i] = FRRConfig(i, rt_cfg, fname)
            frr_cfg[i].is_standby = False

            frr_cfg[i].routing_pb.interfaces_config = create_interfaces_cfg(
                router, topo)
            frr_cfg[i].routing_pb.bgp_config = create_bgp_cfg(router, topo)

            interfaces_cfg(frr_cfg[i])
            bgp_cfg(frr_cfg[i])
            static_rt_cfg(frr_cfg[i])
            redist_cfg(frr_cfg[i], topo)
            frr_cfg[i].print_to_file(topo)
            # Load config to router
            load_config_to_router(tgen, CWD, router)

    except Exception as e:
        logger.error(traceback.format_exc())
        return False
    else:
        return frr_cfg
Example #14
0
def create_interfaces_cfg(tgen, topo, build=False):
    """
    Create interface configuration for created topology. Basic Interface
    configuration is provided in input json file.

    Parameters
    ----------
    * `tgen` : Topogen object
    * `topo` : json file data
    * `build` : Only for initial setup phase this is set as True.

    Returns
    -------
    True or False
    """
    result = False

    try:
        for c_router, c_data in topo.iteritems():
            interface_data = []
            for destRouterLink, data in sorted(c_data["links"].iteritems()):
                # Loopback interfaces
                if "type" in data and data["type"] == "loopback":
                    interface_name = destRouterLink
                else:
                    interface_name = data["interface"]
                interface_data.append("interface {}\n".format(
                    str(interface_name)
                ))
                if "ipv4" in data:
                    intf_addr = c_data["links"][destRouterLink]["ipv4"]
                    interface_data.append("ip address {}\n".format(
                        intf_addr
                    ))
                if "ipv6" in data:
                    intf_addr = c_data["links"][destRouterLink]["ipv6"]
                    interface_data.append("ipv6 address {}\n".format(
                        intf_addr
                    ))
            result = create_common_configuration(tgen, c_router,
                                                 interface_data,
                                                 "interface_config",
                                                 build=build)
    except InvalidCLIError:
        # Traceback
        errormsg = traceback.format_exc()
        logger.error(errormsg)
        return errormsg

    return result
Example #15
0
    def print_to_file(self, topo):
        try:
            frrcfg = open(self.frrcfg_file, 'w')
        except IOError as err:
            logger.error('Unable to open FRR Config File. error(%s): %s' %
                         (err.errno, err.strerror))
            return False

        frrcfg.write('! FRR General Config\n')
        frrcfg.write(self.routing_common.getvalue())
        frrcfg.write('! Interfaces Config\n')
        frrcfg.write(self.interfaces_cfg.getvalue())

        # If bgp neighborship is being done using loopback interface -
        # - then we have make the loopback interface reachability up -
        # - for that we are adding static routes -
        for router, number in number_to_router.iteritems():
            if number == self.router:
                neighbors = topo['routers']['{}'.format(
                    router)]["bgp"]['bgp_neighbors']
                for key, value in neighbors.iteritems():
                    peer = neighbors[key]['peer']
                    ADDR_TYPE = peer['addr_type']
                    if "source" in peer and peer['source'] == 'lo':
                        add_static_route_for_loopback_interfaces(
                            ADDR_TYPE, router, topo, frrcfg)

        frrcfg.write('! Static Route Config\n')
        frrcfg.write(self.static_routes.getvalue())
        frrcfg.write('! Access List Config\n')
        frrcfg.write(self.access_lists.getvalue())
        frrcfg.write('! Prefix List Config\n')
        frrcfg.write(self.prefix_lists.getvalue())
        frrcfg.write('! Route Maps Config\n')
        frrcfg.write(self.route_maps.getvalue())
        frrcfg.write('! Community List Config\n')
        frrcfg.write(self.community_list.getvalue())
        if self.is_bgp_configured:
            frrcfg.write('! BGP Config\n')
            frrcfg.write(self.bgp_global.getvalue())
            frrcfg.write(self.bgp_neighbors.getvalue())
            for addr_family in self.bgp_address_family:
                frrcfg.write('address-family ' +
                             get_address_family(addr_family) + '\n')
                frrcfg.write(self.bgp_address_family[addr_family].getvalue())
                frrcfg.write('exit-address-family\n')

        frrcfg.write('line vty\n')
        frrcfg.close()
        return True
Example #16
0
def start_topology(tgen):
    """
    Starting topology, create tmp files which are loaded to routers
    to start deamons and then start routers
    * `tgen`  : topogen object
    """

    global TMPDIR
    # Starting topology
    tgen.start_topology()

    # Starting deamons
    router_list = tgen.routers()
    TMPDIR = os.path.join(LOGDIR, tgen.modname)

    for rname, router in router_list.iteritems():
        try:
            os.chdir(TMPDIR)

            # Creating rouer named dir and empty zebra.conf bgpd.conf files
            # inside the current directory

            if os.path.isdir('{}'.format(rname)):
                os.system("rm -rf {}".format(rname))
                os.mkdir('{}'.format(rname))
                os.system('chmod -R go+rw {}'.format(rname))
                os.chdir('{}/{}'.format(TMPDIR, rname))
                os.system('touch zebra.conf bgpd.conf')
            else:
                os.mkdir('{}'.format(rname))
                os.system('chmod -R go+rw {}'.format(rname))
                os.chdir('{}/{}'.format(TMPDIR, rname))
                os.system('touch zebra.conf bgpd.conf')

        except IOError as (errno, strerror):
            logger.error("I/O error({0}): {1}".format(errno, strerror))

        # Loading empty zebra.conf file to router, to start the zebra deamon
        router.load_config(
            TopoRouter.RD_ZEBRA,
            '{}/{}/zebra.conf'.format(TMPDIR, rname)
            # os.path.join(tmpdir, '{}/zebra.conf'.format(rname))
        )
        # Loading empty bgpd.conf file to router, to start the bgp deamon
        router.load_config(
            TopoRouter.RD_BGP,
            '{}/{}/bgpd.conf'.format(TMPDIR, rname)
            # os.path.join(tmpdir, '{}/bgpd.conf'.format(rname))
        )
Example #17
0
def run_and_expect_type(func, etype, count=20, wait=3, avalue=None):
    """
    Run `func` and compare the result with `etype`. Do it for `count` times
    waiting `wait` seconds between tries. By default it tries 20 times with
    3 seconds delay between tries.

    This function is used when you want to test the return type and,
    optionally, the return value.

    Returns (True, func-return) on success or
    (False, func-return) on failure.
    """
    start_time = time.time()
    func_name = "<unknown>"
    if func.__class__ == functools.partial:
        func_name = func.func.__name__
    else:
        func_name = func.__name__

    logger.info(
        "'{}' polling started (interval {} secs, maximum wait {} secs)".format(
            func_name, wait, int(wait * count)))

    while count > 0:
        result = func()
        if not isinstance(result, etype):
            logger.debug("Expected result type '{}' got '{}' instead".format(
                etype, type(result)))
            time.sleep(wait)
            count -= 1
            continue

        if etype != type(None) and avalue != None and result != avalue:
            logger.debug("Expected value '{}' got '{}' instead".format(
                avalue, result))
            time.sleep(wait)
            count -= 1
            continue

        end_time = time.time()
        logger.info("'{}' succeeded after {:.2f} seconds".format(
            func_name, end_time - start_time))
        return (True, result)

    end_time = time.time()
    logger.error("'{}' failed after {:.2f} seconds".format(
        func_name, end_time - start_time))
    return (False, result)
Example #18
0
    def stop_topology(self):
        """
        Stops the network topology. This function will call the stop() function
        of all gears before calling the mininet stop function, so they can have
        their oportunity to do a graceful shutdown. stop() is called twice. The
        first is a simple kill with no sleep, the second will sleep if not
        killed and try with a different signal.
        """
        logger.info("stopping topology: {}".format(self.modname))
        errors = ""
        for gear in self.gears.values():
            errors += gear.stop()
        if len(errors) > 0:
            logger.error(
                "Errors found post shutdown - details follow: {}".format(
                    errors))

        self.net.stop()
Example #19
0
def setup_module(mod):
    """
    Sets up the pytest environment
    
    * `mod`: module name
    """

    testsuite_run_time = time.asctime(time.localtime(time.time()))
    logger.info("Testsuite start time: {}".format(testsuite_run_time))
    logger.info("=" * 40)

    logger.info("Running setup_module to create topology")

    # This function initiates the topology build with Topogen...
    tgen = Topogen(TemplateTopo, mod.__name__)
    # ... and here it calls Mininet initialization functions.

    # Starting topology
    tgen.start_topology()

    # Uncomment following line to enable debug logs and comment - tgen.start_topology()
    #tgen.start_topology(log_level='debug')

    router_list = tgen.routers()
    for rname, router in router_list.iteritems():
        try:
            os.chdir(CWD)
            # Deleting router named dirs if exists
            if os.path.exists('{}'.format(rname)):
                os.system("rm -rf {}".format(rname))

            # Creating rouer named dir and emoty zebra.conf bgpd.conf files inside the current directory
            os.mkdir('{}'.format(rname))
            os.chdir("{}/{}".format(CWD, rname))
            os.system('touch zebra.conf bgpd.conf')
        except IOError as (errno, strerror):
            logger.error("I/O error({0}): {1}".format(errno, strerror))

# Loading empty zebra.conf file to router, to start the zebra deamon
        router.load_config(TopoRouter.RD_ZEBRA,
                           os.path.join(CWD, '{}/zebra.conf'.format(rname)))
        # Loading empty bgpd.conf file to router, to start the bgp deamon
        router.load_config(TopoRouter.RD_BGP,
                           os.path.join(CWD, '{}/bgpd.conf'.format(rname)))
Example #20
0
def pytest_runtest_makereport(item, call):
    "Log all assert messages to default logger with error level"
    # Nothing happened
    if call.excinfo is None:
        return

    parent = item.parent
    modname = parent.module.__name__

    # Treat skips as non errors
    if call.excinfo.typename != 'AssertionError':
        logger.info('assert skipped at "{}/{}": {}'.format(
            modname, item.name, call.excinfo.value))
        return

    # Handle assert failures
    parent._previousfailed = item
    logger.error('assert failed at "{}/{}": {}'.format(
        modname, item.name, call.excinfo.value))
Example #21
0
def pytest_runtest_makereport(item, call):
    "Log all assert messages to default logger with error level"
    # Nothing happened
    if call.excinfo is None:
        return

    parent = item.parent
    modname = parent.module.__name__

    # Treat skips as non errors
    if call.excinfo.typename != 'AssertionError':
        logger.info('assert skipped at "{}/{}": {}'.format(
            modname, item.name, call.excinfo.value))
        return

    # Handle assert failures
    parent._previousfailed = item
    logger.error('assert failed at "{}/{}": {}'.format(modname, item.name,
                                                       call.excinfo.value))
Example #22
0
def run_and_expect(func, what, count=20, wait=3):
    """
    Run `func` and compare the result with `what`. Do it for `count` times
    waiting `wait` seconds between tries. By default it tries 20 times with
    3 seconds delay between tries.

    Returns (True, func-return) on success or
    (False, func-return) on failure.

    ---

    Helper functions to use with this function:
    - router_output_cmp
    - router_json_cmp
    """
    start_time = time.time()
    func_name = "<unknown>"
    if func.__class__ == functools.partial:
        func_name = func.func.__name__
    else:
        func_name = func.__name__

    logger.info(
        "'{}' polling started (interval {} secs, maximum wait {} secs)".format(
            func_name, wait, int(wait * count)))

    while count > 0:
        result = func()
        if result != what:
            time.sleep(wait)
            count -= 1
            continue

        end_time = time.time()
        logger.info("'{}' succeeded after {:.2f} seconds".format(
            func_name, end_time - start_time))
        return (True, result)

    end_time = time.time()
    logger.error("'{}' failed after {:.2f} seconds".format(
        func_name, end_time - start_time))
    return (False, result)
Example #23
0
def run_and_expect(func, what, count=20, wait=3):
    """
    Run `func` and compare the result with `what`. Do it for `count` times
    waiting `wait` seconds between tries. By default it tries 20 times with
    3 seconds delay between tries.

    Returns (True, func-return) on success or
    (False, func-return) on failure.

    ---

    Helper functions to use with this function:
    - router_output_cmp
    - router_json_cmp
    """
    start_time = time.time()
    func_name = "<unknown>"
    if func.__class__ == functools.partial:
        func_name = func.func.__name__
    else:
        func_name = func.__name__

    logger.info(
        "'{}' polling started (interval {} secs, maximum wait {} secs)".format(
            func_name, wait, int(wait * count)))

    while count > 0:
        result = func()
        if result != what:
            time.sleep(wait)
            count -= 1
            continue

        end_time = time.time()
        logger.info("'{}' succeeded after {:.2f} seconds".format(
            func_name, end_time - start_time))
        return (True, result)

    end_time = time.time()
    logger.error("'{}' failed after {:.2f} seconds".format(
        func_name, end_time - start_time))
    return (False, result)
Example #24
0
def check_for_memleaks():
    assert topotest_extra_config["valgrind_memleaks"]

    leaks = []
    tgen = get_topogen()  # pylint: disable=redefined-outer-name
    latest = []
    existing = []
    if tgen is not None:
        logdir = tgen.logdir
        if hasattr(tgen, "valgrind_existing_files"):
            existing = tgen.valgrind_existing_files
        latest = glob.glob(os.path.join(logdir, "*.valgrind.*"))
        latest = [x for x in latest if "core" not in x]

    daemons = set()
    for vfile in latest:
        if vfile in existing:
            continue
        # do not consider memleaks from parent fork (i.e., owned by root)
        if os.stat(vfile).st_uid == 0:
            existing.append(vfile)  # do not check again
            logger.debug("Skipping valgrind file %s owned by root", vfile)
            continue
        logger.debug("Checking valgrind file %s not owned by root", vfile)
        with open(vfile, encoding="ascii") as vf:
            vfcontent = vf.read()
            match = re.search(r"ERROR SUMMARY: (\d+) errors", vfcontent)
            if match:
                existing.append(vfile)  # have summary don't check again
            if match and match.group(1) != "0":
                emsg = "{} in {}".format(match.group(1), vfile)
                leaks.append(emsg)
                daemon = re.match(r".*\.valgrind\.(.*)\.\d+", vfile).group(1)
                daemons.add("{}({})".format(daemon, match.group(1)))

    if tgen is not None:
        tgen.valgrind_existing_files = existing

    if leaks:
        logger.error("valgrind memleaks found:\n\t%s", "\n\t".join(leaks))
        pytest.fail("valgrind memleaks found for daemons: " +
                    " ".join(daemons))
Example #25
0
def check_address_types(addr_type):
    """
    Checks environment variable set and compares with the current address type
    """
    global ADDRESS_TYPES
    if ADDRESS_TYPES is None:
        ADDRESS_TYPES = "dual"

    if ADDRESS_TYPES == "dual":
        ADDRESS_TYPES = ["ipv4", "ipv6"]
    elif ADDRESS_TYPES == "ipv4":
        ADDRESS_TYPES = ["ipv4"]
    elif ADDRESS_TYPES == "ipv6":
        ADDRESS_TYPES = ["ipv6"]

    if addr_type not in ADDRESS_TYPES:
        logger.error("{} not in supported/configured address types {}".
                     format(addr_type, ADDRESS_TYPES))
        return False

    return ADDRESS_TYPES
Example #26
0
def test_shutdown_check_stderr():
    if os.environ.get('TOPOTESTS_CHECK_STDERR') is None:
        pytest.skip('Skipping test for Stderr output and memory leaks')

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

    logger.info("Verifying unexpected STDERR output from daemons")

    router_list = tgen.routers().values()
    for router in router_list:
        router.stop()

        log = tgen.net[router.name].getStdErr('eigrpd')
        if log:
            logger.error('EIGRPd StdErr Log:' + log)
        log = tgen.net[router.name].getStdErr('zebra')
        if log:
            logger.error('Zebra StdErr Log:' + log)
Example #27
0
def teardown_module(mod):
    """
    Teardown the pytest environment
   
    * `mod`: module name
    """

    logger.info("Running teardown_module to delete topology")

    tgen = get_topogen()

    # This function tears down the whole topology.
    tgen.stop_topology()

    # Removing tmp dirs and files
    router_list = tgen.routers()
    for rname, router in router_list.iteritems():
        try:
            os.chdir(CWD)
            os.system("rm -rf {}".format(rname))
        except IOError as (errno, strerror):
            logger.error("I/O error({0}): {1}".format(errno, strerror))
Example #28
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(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
Example #29
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
Example #30
0
def create_route_maps(tgen, input_dict, build=False):
    """
    Create route-map on the devices as per the arguments passed

    Parameters
    ----------
    * `tgen` : Topogen object
    * `input_dict` : Input dict data, required when configuring from testcase
    * `build` : Only for initial setup phase this is set as True.

    Usage
    -----
    # route_maps: key, value pair for route-map name and its attribute
    # rmap_match_prefix_list_1: user given name for route-map
    # action: PERMIT/DENY
    # match: key,value pair for match criteria. prefix_list, community-list,
             large-community-list or tag. Only one option at a time.
    # prefix_list: name of prefix list
    # large-community-list: name of large community list
    # community-ist: name of community list
    # tag: tag id for static routes
    # set: key, value pair for modifying route attributes
    # localpref: preference value for the network
    # med: metric value advertised for AS
    # aspath: set AS path value
    # weight: weight for the route
    # community: standard community value to be attached
    # large_community: large community value to be attached
    # community_additive: if set to "additive", adds community/large-community
                          value to the existing values of the network prefix

    Example:
    --------
    input_dict = {
        "r1": {
            "route_maps": {
                "rmap_match_prefix_list_1": [
                    {
                        "action": "PERMIT",
                        "match": {
                            "ipv4": {
                                "prefix_list": "pf_list_1"
                            }
                            "ipv6": {
                                "prefix_list": "pf_list_1"
                            }

                            "large-community-list": "{
                                "id": "community_1",
                                "exact_match": True
                            }
                            "community": {
                                "id": "community_2",
                                "exact_match": True
                            }
                            "tag": "tag_id"
                        },
                        "set": {
                            "localpref": 150,
                            "med": 30,
                            "aspath": {
                                "num": 20000,
                                "action": "prepend",
                            },
                            "weight": 500,
                            "community": {
                                "num": "1:2 2:3",
                                "action": additive
                            }
                            "large_community": {
                                "num": "1:2:3 4:5;6",
                                "action": additive
                            },
                        }
                    }
                ]
            }
        }
    }

    Returns
    -------
    errormsg(str) or True
    """

    result = False
    logger.debug("Entering lib API: create_route_maps()")

    try:
        for router in input_dict.keys():
            if "route_maps" not in input_dict[router]:
                errormsg = "route_maps not present in input_dict"
                logger.info(errormsg)
                continue
            rmap_data = []
            for rmap_name, rmap_value in \
                    input_dict[router]["route_maps"].iteritems():

                for rmap_dict in rmap_value:
                    del_action = rmap_dict.setdefault("delete", False)

                    if del_action:
                        rmap_data.append("no route-map {}".format(rmap_name))
                        continue

                    if "action" not in rmap_dict:
                        errormsg = "action not present in input_dict"
                        logger.error(errormsg)
                        return False

                    rmap_action = rmap_dict.setdefault("action", "deny")

                    seq_id = rmap_dict.setdefault("seq_id", None)
                    if seq_id is None:
                        seq_id = get_seq_id("route_maps", router, rmap_name)
                    else:
                        set_seq_id("route_maps", router, seq_id, rmap_name)

                    rmap_data.append("route-map {} {} {}".format(
                        rmap_name, rmap_action, seq_id
                    ))

                    # Verifying if SET criteria is defined
                    if "set" in rmap_dict:
                        set_data = rmap_dict["set"]

                        local_preference = set_data.setdefault("localpref",
                                                               None)
                        metric = set_data.setdefault("med", None)
                        as_path = set_data.setdefault("aspath", {})
                        weight = set_data.setdefault("weight", None)
                        community = set_data.setdefault("community", {})
                        large_community = set_data.setdefault(
                            "large_community", {})
                        set_action = set_data.setdefault("set_action", None)

                        # Local Preference
                        if local_preference:
                            rmap_data.append("set local-preference {}".
                                             format(local_preference))

                        # Metric
                        if metric:
                            rmap_data.append("set metric {} \n".format(metric))

                        # AS Path Prepend
                        if as_path:
                            as_num = as_path.setdefault("as_num", None)
                            as_action = as_path.setdefault("as_action", None)
                            if as_action and as_num:
                                rmap_data.append("set as-path {} {}".
                                                 format(as_action, as_num))

                        # Community
                        if community:
                            num = community.setdefault("num", None)
                            comm_action = community.setdefault("action", None)
                            if num:
                                cmd = "set community {}".format(num)
                                if comm_action:
                                    cmd = "{} {}".format(cmd, comm_action)
                                rmap_data.append(cmd)
                            else:
                                logger.error("In community, AS Num not"
                                             " provided")
                                return False

                        if large_community:
                            num = large_community.setdefault("num", None)
                            comm_action = large_community.setdefault("action",
                                                                     None)
                            if num:
                                cmd = "set large-community {}".format(num)
                                if comm_action:
                                    cmd = "{} {}".format(cmd, comm_action)

                                rmap_data.append(cmd)
                            else:
                                logger.errror("In large_community, AS Num not"
                                              " provided")
                                return False

                        # Weight
                        if weight:
                            rmap_data.append("set weight {} \n".format(
                                weight))

                    # Adding MATCH and SET sequence to RMAP if defined
                    if "match" in rmap_dict:
                        match_data = rmap_dict["match"]
                        ipv4_data = match_data.setdefault("ipv4", {})
                        ipv6_data = match_data.setdefault("ipv6", {})
                        community = match_data.setdefault("community-list",
                                                          {})
                        large_community = match_data.setdefault(
                            "large-community-list", {}
                        )
                        tag = match_data.setdefault("tag", None)

                        if ipv4_data:
                            prefix_name = ipv4_data.setdefault("prefix_lists",
                                                               None)
                            if prefix_name:
                                rmap_data.append("match ip address prefix-list"
                                                 " {}".format(prefix_name))
                        if ipv6_data:
                            prefix_name = ipv6_data.setdefault("prefix_lists",
                                                               None)
                            if prefix_name:
                                rmap_data.append("match ipv6 address "
                                                 "prefix-list {}".
                                                 format(prefix_name))
                        if tag:
                            rmap_data.append("match tag {}".format(tag))

                        if community:
                            if "id" not in community:
                                logger.error("'id' is mandatory for "
                                             "community-list in match"
                                             " criteria")
                                return False
                            cmd = "match community {}".format(community["id"])
                            exact_match = community.setdefault("exact_match",
                                                               False)
                            if exact_match:
                                cmd = "{} exact-match".format(cmd)

                            rmap_data.append(cmd)

                        if large_community:
                            if "id" not in large_community:
                                logger.error("'num' is mandatory for "
                                             "large-community-list in match "
                                             "criteria")
                                return False
                            cmd = "match large-community {}".format(
                                large_community["id"])
                            exact_match = large_community.setdefault(
                                "exact_match", False)
                            if exact_match:
                                cmd = "{} exact-match".format(cmd)

                            rmap_data.append(cmd)

            result = create_common_configuration(tgen, router,
                                                 rmap_data,
                                                 "route_maps",
                                                 build=build)

    except InvalidCLIError:
        # Traceback
        errormsg = traceback.format_exc()
        logger.error(errormsg)
        return errormsg

    logger.debug("Exiting lib API: create_prefix_lists()")
    return result
Example #31
0
File: ospf.py Project: stoza/frr
def __create_ospf_global(tgen,
                         input_dict,
                         router,
                         build=False,
                         load_config=True):
    """
    Helper API to create ospf global configuration.

    Parameters
    ----------
    * `tgen` : Topogen object
    * `input_dict` : Input dict data, required when configuring from testcase
    * `router` : router to be configured.
    * `build` : Only for initial setup phase this is set as True.
    * `load_config` : Loading the config to router this is set as True.

    Returns
    -------
    True or False
    """

    result = False
    logger.debug("Entering lib API: __create_ospf_global()")
    try:

        ospf_data = input_dict[router]["ospf"]
        del_ospf_action = ospf_data.setdefault("delete", False)
        if del_ospf_action:
            config_data = ["no router ospf"]
            result = create_common_configuration(tgen, router, config_data,
                                                 "ospf", build, load_config)
            return result

        config_data = []
        cmd = "router ospf"

        config_data.append(cmd)

        # router id
        router_id = ospf_data.setdefault("router_id", None)
        del_router_id = ospf_data.setdefault("del_router_id", False)
        if del_router_id:
            config_data.append("no ospf router-id")
        if router_id:
            config_data.append("ospf router-id {}".format(router_id))

        # redistribute command
        redistribute_data = ospf_data.setdefault("redistribute", {})
        if redistribute_data:
            for redistribute in redistribute_data:
                if "redist_type" not in redistribute:
                    logger.debug(
                        "Router %s: 'redist_type' not present in "
                        "input_dict", router)
                else:
                    cmd = "redistribute {}".format(redistribute["redist_type"])
                    for red_type in redistribute_data:
                        if "route_map" in red_type:
                            cmd = cmd + " route-map {}".format(
                                red_type["route_map"])
                    del_action = redistribute.setdefault("delete", False)
                    if del_action:
                        cmd = "no {}".format(cmd)
                    config_data.append(cmd)
        # area information
        area_data = ospf_data.setdefault("area", {})
        if area_data:
            for area in area_data:
                if "id" not in area:
                    logger.debug(
                        "Router %s: 'area id' not present in "
                        "input_dict", router)
                else:
                    cmd = "area {}".format(area["id"])

                    if "type" in area:
                        cmd = cmd + " {}".format(area["type"])

                    del_action = area.setdefault("delete", False)
                    if del_action:
                        cmd = "no {}".format(cmd)
                    config_data.append(cmd)

        # summary information
        summary_data = ospf_data.setdefault("summary-address", {})
        if summary_data:
            for summary in summary_data:
                if "prefix" not in summary:
                    logger.debug(
                        "Router %s: 'summary-address' not present in "
                        "input_dict",
                        router,
                    )
                else:
                    cmd = "summary {}/{}".format(summary["prefix"],
                                                 summary["mask"])

                    _tag = summary.setdefault("tag", None)
                    if _tag:
                        cmd = "{} tag {}".format(cmd, _tag)

                    _advertise = summary.setdefault("advertise", True)
                    if not _advertise:
                        cmd = "{} no-advertise".format(cmd)

                    del_action = summary.setdefault("delete", False)
                    if del_action:
                        cmd = "no {}".format(cmd)
                    config_data.append(cmd)
        result = create_common_configuration(tgen, router, config_data, "ospf",
                                             build, load_config)

    except InvalidCLIError:
        # Traceback
        errormsg = traceback.format_exc()
        logger.error(errormsg)
        return errormsg

    logger.debug("Exiting lib API: create_ospf_global()")
    return result
Example #32
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
Example #33
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(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