diff options
Diffstat (limited to 'src')
| -rwxr-xr-x | src/conf_mode/container.py | 9 | ||||
| -rwxr-xr-x | src/conf_mode/vrf.py | 21 | ||||
| -rwxr-xr-x | src/op_mode/neighbor.py | 5 | ||||
| -rwxr-xr-x | src/op_mode/vrf.py | 21 | 
4 files changed, 31 insertions, 25 deletions
| diff --git a/src/conf_mode/container.py b/src/conf_mode/container.py index ed7cc809c..478868a9a 100755 --- a/src/conf_mode/container.py +++ b/src/conf_mode/container.py @@ -33,6 +33,7 @@ from vyos.utils.process import call  from vyos.utils.process import cmd  from vyos.utils.process import run  from vyos.utils.process import rc_cmd +from vyos.template import bracketize_ipv6  from vyos.template import inc_ip  from vyos.template import is_ipv4  from vyos.template import is_ipv6 @@ -280,6 +281,14 @@ def generate_run_arguments(name, container_config):              protocol = container_config['port'][portmap]['protocol']              sport = container_config['port'][portmap]['source']              dport = container_config['port'][portmap]['destination'] +            listen_addresses = container_config['port'][portmap].get('listen_address', []) + +        # If listen_addresses is not empty, include them in the publish command +        if listen_addresses: +            for listen_address in listen_addresses: +                port += f' --publish {bracketize_ipv6(listen_address)}:{sport}:{dport}/{protocol}' +        else: +            # If listen_addresses is empty, just include the standard publish command              port += f' --publish {sport}:{dport}/{protocol}'      # Bind volume diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py index be867b208..37625142c 100755 --- a/src/conf_mode/vrf.py +++ b/src/conf_mode/vrf.py @@ -28,6 +28,8 @@ from vyos.template import render  from vyos.template import render_to_string  from vyos.utils.dict import dict_search  from vyos.utils.network import get_interface_config +from vyos.utils.network import get_vrf_members +from vyos.utils.network import interface_exists  from vyos.utils.process import call  from vyos.utils.process import cmd  from vyos.utils.process import popen @@ -143,7 +145,7 @@ def verify(vrf):                  raise ConfigError(f'VRF "{name}" table id is mandatory!')              # routing table id can't be changed - OS restriction -            if os.path.isdir(f'/sys/class/net/{name}'): +            if interface_exists(name):                  tmp = str(dict_search('linkinfo.info_data.table', get_interface_config(name)))                  if tmp and tmp != vrf_config['table']:                      raise ConfigError(f'VRF "{name}" table id modification not possible!') @@ -195,12 +197,23 @@ def apply(vrf):      sysctl_write('net.ipv4.udp_l3mdev_accept', bind_all)      for tmp in (dict_search('vrf_remove', vrf) or []): -        if os.path.isdir(f'/sys/class/net/{tmp}'): -            call(f'ip link delete dev {tmp}') +        if interface_exists(tmp): +            # T5492: deleting a VRF instance may leafe processes running +            # (e.g. dhclient) as there is a depedency ordering issue in the CLI. +            # We need to ensure that we stop the dhclient processes first so +            # a proper DHCLP RELEASE message is sent +            for interface in get_vrf_members(tmp): +                vrf_iface = Interface(interface) +                vrf_iface.set_dhcp(False) +                vrf_iface.set_dhcpv6(False) +              # Remove nftables conntrack zone map item              nft_del_element = f'delete element inet vrf_zones ct_iface_map {{ "{tmp}" }}'              cmd(f'nft {nft_del_element}') +            # Delete the VRF Kernel interface +            call(f'ip link delete dev {tmp}') +      if 'name' in vrf:          # Separate VRFs in conntrack table          # check if table already exists @@ -245,7 +258,7 @@ def apply(vrf):          for name, config in vrf['name'].items():              table = config['table'] -            if not os.path.isdir(f'/sys/class/net/{name}'): +            if not interface_exists(name):                  # For each VRF apart from your default context create a VRF                  # interface with a separate routing table                  call(f'ip link add {name} type vrf table {table}') diff --git a/src/op_mode/neighbor.py b/src/op_mode/neighbor.py index 1edeb0045..8b3c45c7c 100755 --- a/src/op_mode/neighbor.py +++ b/src/op_mode/neighbor.py @@ -31,14 +31,11 @@ import sys  import typing  import vyos.opmode +from vyos.utils.network import interface_exists  ArgFamily = typing.Literal['inet', 'inet6']  ArgState = typing.Literal['reachable', 'stale', 'failed', 'permanent'] -def interface_exists(interface): -    import os -    return os.path.exists(f'/sys/class/net/{interface}') -  def get_raw_data(family, interface=None, state=None):      from json import loads      from vyos.utils.process import cmd diff --git a/src/op_mode/vrf.py b/src/op_mode/vrf.py index 1f0bbbaeb..51032a4b5 100755 --- a/src/op_mode/vrf.py +++ b/src/op_mode/vrf.py @@ -20,11 +20,11 @@ import sys  import typing  from tabulate import tabulate +from vyos.utils.network import get_vrf_members  from vyos.utils.process import cmd  import vyos.opmode -  def _get_raw_data(name=None):      """      If vrf name is not set - get all VRFs @@ -45,21 +45,6 @@ def _get_raw_data(name=None):      return data -def _get_vrf_members(vrf: str) -> list: -    """ -    Get list of interface VRF members -    :param vrf: str -    :return: list -    """ -    output = cmd(f'ip --json --brief link show master {vrf}') -    answer = json.loads(output) -    interfaces = [] -    for data in answer: -        if 'ifname' in data: -            interfaces.append(data.get('ifname')) -    return interfaces if len(interfaces) > 0 else ['n/a'] - -  def _get_formatted_output(raw_data):      data_entries = []      for vrf in raw_data: @@ -67,7 +52,9 @@ def _get_formatted_output(raw_data):          state = vrf.get('operstate').lower()          hw_address = vrf.get('address')          flags = ','.join(vrf.get('flags')).lower() -        members = ','.join(_get_vrf_members(name)) +        tmp = get_vrf_members(name) +        if tmp: members = ','.join(get_vrf_members(name)) +        else: members = 'n/a'          data_entries.append([name, state, hw_address, flags, members])      headers = ["Name", "State", "MAC address", "Flags", "Interfaces"] | 
