diff options
| author | Christian Breunig <christian@breunig.cc> | 2024-12-11 21:37:34 +0100 | 
|---|---|---|
| committer | Christian Breunig <christian@breunig.cc> | 2024-12-16 22:24:50 +0100 | 
| commit | 76b74d62b607961f08bd0284a9dbc5427ba48e1d (patch) | |
| tree | 3cd715d1c8407aab1a4334b2aa7650c6f793d78c | |
| parent | 4d0774e534766d70961975933635e6c54dcc1982 (diff) | |
| download | vyos-1x-76b74d62b607961f08bd0284a9dbc5427ba48e1d.tar.gz vyos-1x-76b74d62b607961f08bd0284a9dbc5427ba48e1d.zip | |
frr: T6746: remove superseeded vyos.frr module
| -rw-r--r-- | python/vyos/frr.py | 569 | ||||
| -rw-r--r-- | python/vyos/frrender.py | 1 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_interfaces_bonding.py | 2 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_interfaces_ethernet.py | 2 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_protocols_bgp.py | 2 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_protocols_isis.py | 2 | ||||
| -rw-r--r-- | smoketest/scripts/cli/test_protocols_openfabric.py | 2 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_protocols_segment-routing.py | 2 | ||||
| -rwxr-xr-x | smoketest/scripts/cli/test_system_ipv6.py | 2 | 
9 files changed, 8 insertions, 576 deletions
| diff --git a/python/vyos/frr.py b/python/vyos/frr.py deleted file mode 100644 index 67279a6f7..000000000 --- a/python/vyos/frr.py +++ /dev/null @@ -1,569 +0,0 @@ -# Copyright 2020-2024 VyOS maintainers and contributors <maintainers@vyos.io> -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this library.  If not, see <http://www.gnu.org/licenses/>. - -r""" -A Library for interracting with the FRR daemon suite. -It supports simple configuration manipulation and loading using the official tools -supplied with FRR (vtysh and frr-reload) - -All configuration management and manipulation is done using strings and regex. - - -Example Usage -##### - -# Reading configuration from frr: -``` ->>> original_config = get_configuration() ->>> repr(original_config) -'!\nfrr version 7.3.1\nfrr defaults traditional\nhostname debian\n...... -``` - - -# Modify a configuration section: -``` ->>> new_bgp_section = 'router bgp 65000\n neighbor 192.0.2.1 remote-as 65000\n' ->>> modified_config = replace_section(original_config, new_bgp_section, replace_re=r'router bgp \d+') ->>> repr(modified_config) -'............router bgp 65000\n neighbor 192.0.2.1 remote-as 65000\n...........' -``` - -Remove a configuration section: -``` ->>> modified_config = remove_section(original_config, r'router ospf') -``` - -Test the new configuration: -``` ->>> try: ->>>     mark_configuration(modified configuration) ->>> except ConfigurationNotValid as e: ->>>     print('resulting configuration is not valid') ->>>     sys.exit(1) -``` - -Apply the new configuration: -``` ->>> try: ->>>     replace_configuration(modified_config) ->>> except CommitError as e: ->>>     print('Exception while commiting the supplied configuration') ->>>     print(e) ->>>     exit(1) -``` -""" - -import tempfile -import re - -from vyos import ConfigError -from vyos.defaults import frr_debug_enable -from vyos.utils.process import cmd -from vyos.utils.process import popen -from vyos.utils.process import STDOUT - -import logging -from logging.handlers import SysLogHandler -import os -import sys - -LOG = logging.getLogger(__name__) -DEBUG = False - -ch = SysLogHandler(address='/dev/log') -ch2 = logging.StreamHandler(stream=sys.stdout) -LOG.addHandler(ch) -LOG.addHandler(ch2) - -babel_daemon = 'babeld' -bfd_daemon = 'bfdd' -bgp_daemon = 'bgpd' -eigrp_daemon = 'eigrpd' -isis_daemon = 'isisd' -ldpd_daemon = 'ldpd' -mgmt_daemon = 'mgmtd' -openfabric_daemon = 'fabricd' -ospf_daemon = 'ospfd' -ospf6_daemon = 'ospf6d' -pim_daemon = 'pimd' -pim6_daemon = 'pim6d' -rip_daemon = 'ripd' -ripng_daemon = 'ripngd' -static_daemon = 'staticd' -zebra_daemon = 'zebra' - -_frr_daemons = [zebra_daemon, static_daemon, bgp_daemon, ospf_daemon, ospf6_daemon, rip_daemon, ripng_daemon, mgmt_daemon, -                isis_daemon, pim_daemon, pim6_daemon, ldpd_daemon, eigrp_daemon, babel_daemon, bfd_daemon, openfabric_daemon] - -path_vtysh = '/usr/bin/vtysh' -path_frr_reload = '/usr/lib/frr/frr-reload.py' -path_config = '/run/frr' - -default_add_before = r'(ip prefix-list .*|route-map .*|line vty|end)' - - -class FrrError(Exception): -    pass - - -class ConfigurationNotValid(FrrError): -    """ -    The configuratioin supplied to vtysh is not valid -    """ -    pass - - -class CommitError(FrrError): -    """ -    Commiting the supplied configuration failed to commit by a unknown reason -    see commit error and/or run mark_configuration on the specified configuration -    to se error generated - -    used by: reload_configuration() -    """ -    pass - - -class ConfigSectionNotFound(FrrError): -    """ -    Removal of configuration failed because it is not existing in the supplied configuration -    """ -    pass - -def init_debugging(): -    global DEBUG - -    DEBUG = os.path.exists(frr_debug_enable) -    if DEBUG: -        LOG.setLevel(logging.DEBUG) - -def get_configuration(daemon=None, marked=False): -    """ Get current running FRR configuration -    daemon:  Collect only configuration for the specified FRR daemon, -             supplying daemon=None retrieves the complete configuration -    marked:  Mark the configuration with "end" tags - -    return:  string containing the running configuration from frr - -    """ -    if daemon and daemon not in _frr_daemons: -        raise ValueError(f'The specified daemon type is not supported {repr(daemon)}') - -    cmd = f"{path_vtysh} -c 'show run'" -    if daemon: -        cmd += f' -d {daemon}' - -    output, code = popen(cmd, stderr=STDOUT) -    if code: -        raise OSError(code, output) - -    config = output.replace('\r', '') -    # Remove first header lines from FRR config -    config = config.split("\n", 3)[-1] -    # Mark the configuration with end tags -    if marked: -        config = mark_configuration(config) - -    return config - - -def mark_configuration(config): -    """ Add end marks and Test the configuration for syntax faults -    If the configuration is valid a marked version of the configuration is returned, -    or else it failes with a ConfigurationNotValid Exception - -    config:  The configuration string to mark/test -    return:  The marked configuration from FRR -    """ -    output, code = popen(f"{path_vtysh} -m -f -", stderr=STDOUT, input=config) - -    if code == 2: -        raise ConfigurationNotValid(str(output)) -    elif code: -        raise OSError(code, output) - -    config = output.replace('\r', '') -    return config - - -def reload_configuration(config, daemon=None): -    """ Execute frr-reload with the new configuration -    This will try to reapply the supplied configuration inside FRR. -    The configuration needs to be a complete configuration from the integrated config or -    from a daemon. - -    config:  The configuration to apply -    daemon:  Apply the conigutaion to the specified FRR daemon, -             supplying daemon=None applies to the integrated configuration -    return:  None -    """ -    if daemon and daemon not in _frr_daemons: -        raise ValueError(f'The specified daemon type is not supported {repr(daemon)}') - -    f = tempfile.NamedTemporaryFile('w') -    f.write(config) -    f.flush() - -    LOG.debug(f'reload_configuration: Reloading config using temporary file: {f.name}') -    cmd = f'{path_frr_reload} --reload' -    if daemon: -        cmd += f' --daemon {daemon}' - -    if DEBUG: -        cmd += f' --debug --stdout' - -    cmd += f' {f.name}' - -    LOG.debug(f'reload_configuration: Executing command against frr-reload: "{cmd}"') -    output, code = popen(cmd, stderr=STDOUT) -    f.close() - -    for i, e in enumerate(output.split('\n')): -        LOG.debug(f'frr-reload output: {i:3} {e}') - -    if code == 1: -        raise ConfigError(output) -    elif code: -        raise OSError(code, output) - -    return output - - -def save_configuration(): -    """ T3217: Save FRR configuration to /run/frr/config/frr.conf """ -    return cmd(f'{path_vtysh} -n -w') - - -def execute(command): -    """ Run commands inside vtysh -    command:  str containing commands to execute inside a vtysh session -    """ -    if not isinstance(command, str): -        raise ValueError(f'command needs to be a string: {repr(command)}') - -    cmd = f"{path_vtysh} -c '{command}'" - -    output, code = popen(cmd, stderr=STDOUT) -    if code: -        raise OSError(code, output) - -    config = output.replace('\r', '') -    return config - - -def configure(lines, daemon=False): -    """ run commands inside config mode vtysh -    lines:  list or str conaining commands to execute inside a configure session -            only one command executed on each configure() -            Executing commands inside a subcontext uses the list to describe the context -            ex: ['router bgp 6500', 'neighbor 192.0.2.1 remote-as 65000'] -    return: None -    """ -    if isinstance(lines, str): -        lines = [lines] -    elif not isinstance(lines, list): -        raise ValueError('lines needs to be string or list of commands') - -    if daemon and daemon not in _frr_daemons: -        raise ValueError(f'The specified daemon type is not supported {repr(daemon)}') - -    cmd = f'{path_vtysh}' -    if daemon: -        cmd += f' -d {daemon}' - -    cmd += " -c 'configure terminal'" -    for x in lines: -        cmd += f" -c '{x}'" - -    output, code = popen(cmd, stderr=STDOUT) -    if code == 1: -        raise ConfigurationNotValid(f'Configuration FRR failed: {repr(output)}') -    elif code: -        raise OSError(code, output) - -    config = output.replace('\r', '') -    return config - - -def _replace_section(config, replacement, replace_re, before_re): -    r"""Replace a section of FRR config -    config:      full original configuration -    replacement: replacement configuration section -    replace_re:  The regex to replace -                 example: ^router bgp \d+$.?*^!$ -                 this will replace everything between ^router bgp X$ and ^!$ -    before_re:   When replace_re is not existant, the config will be added before this tag -                 example: ^line vty$ - -    return:      modified configuration as a text file -    """ -    # DEPRECATED, this is replaced by a new implementation -    # Check if block is configured, remove the existing instance else add a new one -    if re.findall(replace_re, config, flags=re.MULTILINE | re.DOTALL): -        # Section is in the configration, replace it -        return re.sub(replace_re, replacement, config, count=1, -                      flags=re.MULTILINE | re.DOTALL) -    if before_re: -        if not re.findall(before_re, config, flags=re.MULTILINE | re.DOTALL): -            raise ConfigSectionNotFound(f"Config section {before_re} not found in config") - -        # If no section is in the configuration, add it before the line vty line -        return re.sub(before_re, rf'{replacement}\n\g<1>', config, count=1, -                      flags=re.MULTILINE | re.DOTALL) - -    raise ConfigSectionNotFound(f"Config section {replacement} not found in config") - - -def replace_section(config, replacement, from_re, to_re=r'!', before_re=r'line vty'): -    r"""Replace a section of FRR config -    config:      full original configuration -    replacement: replacement configuration section -    from_re:     Regex for the start of section matching -                 example: 'router bgp \d+' -    to_re:       Regex for stop of section matching -                 default: '!' -                 example: '!'  or  'end' -    before_re:   When from_re/to_re  does not return a match, the config will -                 be added before this tag -                 default: ^line vty$ - -    startline and endline tags will be automatically added to the resulting from_re/to_re and before_re regex'es -    """ -    # DEPRECATED, this is replaced by a new implementation -    return _replace_section(config, replacement, replace_re=rf'^{from_re}$.*?^{to_re}$', before_re=rf'^({before_re})$') - - -def remove_section(config, from_re, to_re='!'): -    # DEPRECATED, this is replaced by a new implementation -    return _replace_section(config, '', replace_re=rf'^{from_re}$.*?^{to_re}$', before_re=None) - - -def _find_first_block(config, start_pattern, stop_pattern, start_at=0): -    '''Find start and stop line numbers for a config block -    config:        (list) A list conaining the configuration that is searched -    start_pattern: (raw-str) The pattern searched for a a start of block tag -    stop_pattern:  (raw-str) The pattern searched for to signify the end of the block -    start_at:      (int) The index to start searching at in the <config> - -    Returns: -        None: No complete block could be found -        set(int, int): A complete block found between the line numbers returned in the set - -    The object <config> is searched from the start for the regex <start_pattern> until the first match is found. -    On a successful match it continues the search for the regex <stop_pattern> until it is found. -    After a successful run a set is returned containing the start and stop line numbers. -    ''' -    LOG.debug(f'_find_first_block: find start={repr(start_pattern)} stop={repr(stop_pattern)} start_at={start_at}') -    _start = None -    for i, element in enumerate(config[start_at:], start=start_at): -        # LOG.debug(f'_find_first_block: running line {i:3} "{element}"') -        if not _start: -            if not re.match(start_pattern, element): -                LOG.debug(f'_find_first_block: no match     {i:3} "{element}"') -                continue -            _start = i -            LOG.debug(f'_find_first_block: Found start  {i:3} "{element}"') -            continue - -        if not re.match(stop_pattern, element): -            LOG.debug(f'_find_first_block: no match     {i:3} "{element}"') -            continue - -        LOG.debug(f'_find_first_block: Found stop   {i:3} "{element}"') -        return (_start, i) - -    LOG.debug('_find_first_block: exit start={repr(start_pattern)} stop={repr(stop_pattern)} start_at={start_at}') -    return None - - -def _find_first_element(config, pattern, start_at=0): -    '''Find the first element that matches the current pattern in config -    config:        (list) A list containing the configuration that is searched -    start_pattern: (raw-str) The pattern searched for -    start_at:      (int) The index to start searching at in the <config> - -    return:   Line index of the line containing the searched pattern - -    TODO: for now it returns -1 on a no-match because 0 also returns as False -    TODO: that means that we can not use False matching to tell if its -    ''' -    LOG.debug(f'_find_first_element: find start="{pattern}" start_at={start_at}') -    for i, element in enumerate(config[start_at:], start=0): -        if re.match(pattern + '$', element): -            LOG.debug(f'_find_first_element: Found stop {i:3} "{element}"') -            return i -        LOG.debug(f'_find_first_element: no match   {i:3} "{element}"') -    LOG.debug(f'_find_first_element: Did not find any match, exiting') -    return -1 - - -def _find_elements(config, pattern, start_at=0): -    '''Find all instances of pattern and return a list containing all element indexes -    config:        (list) A list containing the configuration that is searched -    start_pattern: (raw-str) The pattern searched for -    start_at:      (int) The index to start searching at in the <config> - -    return:    A list of line indexes containing the searched pattern -    TODO: refactor this to return a generator instead -    ''' -    return [i for i, element in enumerate(config[start_at:], start=0) if re.match(pattern + '$', element)] - - -class FRRConfig: -    '''Main FRR Configuration manipulation object -    Using this object the user could load, manipulate and commit the configuration to FRR -    ''' -    def __init__(self, config=[]): -        self.imported_config = '' - -        if isinstance(config, list): -            self.config = config.copy() -            self.original_config = config.copy() -        elif isinstance(config, str): -            self.config = config.split('\n') -            self.original_config = self.config.copy() -        else: -            raise ValueError( -                'The config element needs to be a string or list type object') - -        if config: -            LOG.debug(f'__init__: frr library initiated with initial config') -            for i, e in enumerate(self.config): -                LOG.debug(f'__init__: initial              {i:3} {e}') - -    def load_configuration(self, daemon=None): -        '''Load the running configuration from FRR into the config object -        daemon: str with name of the FRR Daemon to load configuration from or -                None to load the consolidated config - -        Using this overwrites the current loaded config objects and replaces the original loaded config -        ''' -        init_debugging() - -        self.imported_config = get_configuration(daemon=daemon) -        if daemon: -            LOG.debug(f'load_configuration: Configuration loaded from FRR daemon {daemon}') -        else: -            LOG.debug(f'load_configuration: Configuration loaded from FRR integrated config') - -        self.original_config = self.imported_config.split('\n') -        self.config = self.original_config.copy() - -        for i, e in enumerate(self.imported_config.split('\n')): -            LOG.debug(f'load_configuration:  loaded    {i:3} {e}') -        return - -    def test_configuration(self): -        '''Test the current configuration against FRR -        This will exception if FRR failes to load the current configuration object -        ''' -        LOG.debug('test_configation: Testing configuration') -        mark_configuration('\n'.join(self.config)) - -    def commit_configuration(self, daemon=None): -        ''' -        Commit the current configuration to FRR daemon: str with name of the -        FRR daemon to commit to or None to use the consolidated config. - -        Configuration is automatically saved after apply -        ''' -        LOG.debug('commit_configuration:  Commiting configuration') -        for i, e in enumerate(self.config): -            LOG.debug(f'commit_configuration: new_config {i:3} {e}') - -        # https://github.com/FRRouting/frr/issues/10132 -        # https://github.com/FRRouting/frr/issues/10133 -        count = 0 -        count_max = 5 -        emsg = '' -        while count < count_max: -            count += 1 -            try: -                reload_configuration('\n'.join(self.config), daemon=daemon) -                break -            except ConfigError as e: -                emsg = str(e) -            except: -                # we just need to re-try the commit of the configuration -                # for the listed FRR issues above -                pass -        if count >= count_max: -            if emsg: -                raise ConfigError(emsg) -            raise ConfigurationNotValid(f'Config commit retry counter ({count_max}) exceeded for {daemon} daemon!') - -        # Save configuration to /run/frr/config/frr.conf -        save_configuration() - - -    def modify_section(self, start_pattern, replacement='!', stop_pattern=r'\S+', remove_stop_mark=False, count=0): -        if isinstance(replacement, str): -            replacement = replacement.split('\n') -        elif not isinstance(replacement, list): -            return ValueError("The replacement element needs to be a string or list type object") -        LOG.debug(f'modify_section: starting search for {repr(start_pattern)} until {repr(stop_pattern)}') - -        _count = 0 -        _next_start = 0 -        while True: -            if count and count <= _count: -                # Break out of the loop after specified amount of matches -                LOG.debug(f'modify_section: reached limit ({_count}), exiting loop at line {_next_start}') -                break -            # While searching, always assume that the user wants to search for the exact pattern he entered -            # To be more specific the user needs a override, eg. a "pattern.*" -            _w = _find_first_block( -                self.config, start_pattern+'$', stop_pattern, start_at=_next_start) -            if not _w: -                # Reached the end, no more elements to remove -                LOG.debug(f'modify_section: No more config sections found, exiting') -                break -            start_element, end_element = _w -            LOG.debug(f'modify_section:   found match between {start_element} and {end_element}') -            for i, e in enumerate(self.config[start_element:end_element+1 if remove_stop_mark else end_element], -                                  start=start_element): -                LOG.debug(f'modify_section:   remove       {i:3} {e}') -            del self.config[start_element:end_element + -                            1 if remove_stop_mark else end_element] -            if replacement: -                # Append the replacement config at the current position -                for i, e in enumerate(replacement, start=start_element): -                    LOG.debug(f'modify_section:   add          {i:3} {e}') -                self.config[start_element:start_element] = replacement -            _count += 1 -            _next_start = start_element + len(replacement) - -        return _count - -    def add_before(self, before_pattern, addition): -        '''Add config block before this element in the configuration''' -        if isinstance(addition, str): -            addition = addition.split('\n') -        elif not isinstance(addition, list): -            return ValueError("The replacement element needs to be a string or list type object") - -        start = _find_first_element(self.config, before_pattern) -        if start < 0: -            return False -        for i, e in enumerate(addition, start=start): -            LOG.debug(f'add_before:   add          {i:3} {e}') -        self.config[start:start] = addition -        return True - -    def __str__(self): -        return '\n'.join(self.config) - -    def __repr__(self): -        return f'frr({repr(str(self))})' diff --git a/python/vyos/frrender.py b/python/vyos/frrender.py index 7a0b661a3..ead893ff9 100644 --- a/python/vyos/frrender.py +++ b/python/vyos/frrender.py @@ -39,6 +39,7 @@ frr_protocols = ['babel', 'bfd', 'bgp', 'eigrp', 'isis', 'mpls', 'nhrp',  bgp_daemon = 'bgpd'  isis_daemon = 'isisd'  mgmt_daemon = 'mgmtd' +openfabric_daemon = 'fabricd'  pim_daemon = 'pimd'  zebra_daemon = 'zebra' diff --git a/smoketest/scripts/cli/test_interfaces_bonding.py b/smoketest/scripts/cli/test_interfaces_bonding.py index 418744712..735e4f3c5 100755 --- a/smoketest/scripts/cli/test_interfaces_bonding.py +++ b/smoketest/scripts/cli/test_interfaces_bonding.py @@ -24,7 +24,7 @@ from vyos.ifconfig.interface import Interface  from vyos.configsession import ConfigSessionError  from vyos.utils.network import get_interface_config  from vyos.utils.file import read_file -from vyos.frr import mgmt_daemon +from vyos.frrender import mgmt_daemon  class BondingInterfaceTest(BasicInterfaceTest.TestCase):      @classmethod diff --git a/smoketest/scripts/cli/test_interfaces_ethernet.py b/smoketest/scripts/cli/test_interfaces_ethernet.py index 218fa0759..c02ca613b 100755 --- a/smoketest/scripts/cli/test_interfaces_ethernet.py +++ b/smoketest/scripts/cli/test_interfaces_ethernet.py @@ -27,7 +27,7 @@ from netifaces import ifaddresses  from base_interfaces_test import BasicInterfaceTest  from vyos.configsession import ConfigSessionError  from vyos.ifconfig import Section -from vyos.frr import mgmt_daemon +from vyos.frrender import mgmt_daemon  from vyos.utils.process import cmd  from vyos.utils.process import popen  from vyos.utils.file import read_file diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py index 6eeac37a7..1b6c30dfe 100755 --- a/smoketest/scripts/cli/test_protocols_bgp.py +++ b/smoketest/scripts/cli/test_protocols_bgp.py @@ -25,7 +25,7 @@ from vyos.configsession import ConfigSessionError  from vyos.template import is_ipv6  from vyos.utils.process import process_named_running  from vyos.utils.process import cmd -from vyos.frr import bgp_daemon +from vyos.frrender import bgp_daemon  PROCESS_NAME = 'bgpd'  ASN = '64512' diff --git a/smoketest/scripts/cli/test_protocols_isis.py b/smoketest/scripts/cli/test_protocols_isis.py index 5b86dd53a..2fddbfeba 100755 --- a/smoketest/scripts/cli/test_protocols_isis.py +++ b/smoketest/scripts/cli/test_protocols_isis.py @@ -20,7 +20,7 @@ from base_vyostest_shim import VyOSUnitTestSHIM  from vyos.configsession import ConfigSessionError  from vyos.ifconfig import Section  from vyos.utils.process import process_named_running -from vyos.frr import isis_daemon +from vyos.frrender import isis_daemon  PROCESS_NAME = 'isisd'  base_path = ['protocols', 'isis'] diff --git a/smoketest/scripts/cli/test_protocols_openfabric.py b/smoketest/scripts/cli/test_protocols_openfabric.py index 889cba135..3e99656ec 100644 --- a/smoketest/scripts/cli/test_protocols_openfabric.py +++ b/smoketest/scripts/cli/test_protocols_openfabric.py @@ -19,7 +19,7 @@ import unittest  from base_vyostest_shim import VyOSUnitTestSHIM  from vyos.configsession import ConfigSessionError  from vyos.utils.process import process_named_running -from vyos.frr import openfabric_daemon +from vyos.frrender import openfabric_daemon  PROCESS_NAME = 'fabricd'  base_path = ['protocols', 'openfabric'] diff --git a/smoketest/scripts/cli/test_protocols_segment-routing.py b/smoketest/scripts/cli/test_protocols_segment-routing.py index eb563db93..8905d5e45 100755 --- a/smoketest/scripts/cli/test_protocols_segment-routing.py +++ b/smoketest/scripts/cli/test_protocols_segment-routing.py @@ -20,7 +20,7 @@ from base_vyostest_shim import VyOSUnitTestSHIM  from vyos.configsession import ConfigSessionError  from vyos.ifconfig import Section -from vyos.frr import zebra_daemon +from vyos.frrender import zebra_daemon  from vyos.utils.process import process_named_running  from vyos.utils.system import sysctl_read diff --git a/smoketest/scripts/cli/test_system_ipv6.py b/smoketest/scripts/cli/test_system_ipv6.py index be9751c4d..ebf620204 100755 --- a/smoketest/scripts/cli/test_system_ipv6.py +++ b/smoketest/scripts/cli/test_system_ipv6.py @@ -152,4 +152,4 @@ class TestSystemIPv6(VyOSUnitTestSHIM.TestCase):          self.assertNotIn(f'no ipv6 nht resolve-via-default', frrconfig)  if __name__ == '__main__': -    unittest.main(verbosity=2, failfast=True) +    unittest.main(verbosity=2) | 
