diff options
| author | Christian Poessinger <christian@poessinger.com> | 2019-09-24 22:09:07 +0200 | 
|---|---|---|
| committer | Christian Poessinger <christian@poessinger.com> | 2019-09-24 22:09:07 +0200 | 
| commit | c24eb48c54b562fe7f78cdda82f2e245e9ab8506 (patch) | |
| tree | e51f4d72af89d7918ba5cd2adca01f4b4e5040b8 | |
| parent | 6b828200e698dbff5a3ee61a0c6c9906b0a8493f (diff) | |
| parent | 0588f5409f57a8d8577bc9bd23c393487fd2987b (diff) | |
| download | vyos-1x-c24eb48c54b562fe7f78cdda82f2e245e9ab8506.tar.gz vyos-1x-c24eb48c54b562fe7f78cdda82f2e245e9ab8506.zip | |
Merge branch 'ifconfig-api-change' of github.com:c-po/vyos-1x into current
* 'ifconfig-api-change' of github.com:c-po/vyos-1x: (26 commits)
  Python/ifconfig: T1557: add STPIf class (spanning tree) bridge member
  Python/ifconfig: T1557: bugfix removing Q-in-Q VLAN interfaces
  openvpn: T1548: setup interface alias
  Python/ifconfig: T1557: refactor BondIf 'mode' property to set_mode()
  Python/ifconfig: T1557: refactor BondIf 'arp_interval' property to set_arp_interval()
  Python/ifconfig: T1557: refactor BondIf 'arp_ip_target' property to set_arp_ip_target()/get_arp_ip_target()
  Python/ifconfig: T1557: refactor BondIf 'arp_interval' property to set_arp_interval()
  Python/ifconfig: T1557: refactor BondIf 'xmit_hash_policy' property to set_hash_policy()
  Python/ifconfig: T1557: remove unused has_autoneg() from EthernetIf
  Python/ifconfig: T1557: refactor Interface 'state' property to set_state()/get_state()
  Python/ifconfig: T1557: refactor Interface 'arp_cache_tmo' property to set_set_arp_cache_tmo()
  Python/ifconfig: T1557: refactor Interface 'proxy_arp_pvlan' property to set_proxy_arp_pvlan()
  Python/ifconfig: T1557: refactor Interface 'proxy_arp' property to set_proxy_arp()
  Python/ifconfig: T1557: loopback: implement derived remove()
  Python/ifconfig: T1557: refactor Interface 'ifalias' property to set_alias()
  Python/ifconfig: T1557: refactor Interface 'link_detect' property to set_link_detect()
  Python/ifconfig: T1557: refactor BridgeIf 'stp_state' property to set_stp()
  Python/ifconfig: T1557: refactor BridgeIf 'priority' property to set_priority()
  Python/ifconfig: T1557: refactor BridgeIf 'ageing_time' property to set_ageing_time()
  Python/ifconfig: T1557: refactor BridgeIf 'hello_time' property to set_hello_time()
  ...
| -rw-r--r-- | python/vyos/ifconfig.py | 648 | ||||
| -rwxr-xr-x | src/conf_mode/interface-bonding.py | 51 | ||||
| -rwxr-xr-x | src/conf_mode/interface-bridge.py | 41 | ||||
| -rwxr-xr-x | src/conf_mode/interface-dummy.py | 23 | ||||
| -rwxr-xr-x | src/conf_mode/interface-ethernet.py | 32 | ||||
| -rwxr-xr-x | src/conf_mode/interface-loopback.py | 23 | ||||
| -rwxr-xr-x | src/conf_mode/interface-openvpn.py | 16 | ||||
| -rwxr-xr-x | src/conf_mode/interface-vxlan.py | 18 | ||||
| -rwxr-xr-x | src/conf_mode/interface-wireguard.py | 16 | 
9 files changed, 271 insertions, 597 deletions
| diff --git a/python/vyos/ifconfig.py b/python/vyos/ifconfig.py index 8d4923957..a77cde5e7 100644 --- a/python/vyos/ifconfig.py +++ b/python/vyos/ifconfig.py @@ -60,7 +60,6 @@ class Interface:          >>> i = Interface('eth0')          """          self._ifname = str(ifname) -        self._state = 'down'          if not os.path.exists('/sys/class/net/{}'.format(ifname)) and not type:              raise Exception('interface "{}" not found'.format(self._ifname)) @@ -145,28 +144,26 @@ class Interface:          cmd = 'ip link del dev {}'.format(self._ifname)          self._cmd(cmd) -    @property -    def mtu(self): +    def get_mtu(self):          """          Get/set interface mtu in bytes.          Example:          >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').mtu +        >>> Interface('eth0').get_mtu()          '1500'          """          return self._read_sysfs('/sys/class/net/{}/mtu'                                  .format(self._ifname)) -    @mtu.setter -    def mtu(self, mtu): +    def set_mtu(self, mtu):          """          Get/set interface mtu in bytes.          Example:          >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').mtu = 1400 -        >>> Interface('eth0').mtu +        >>> Interface('eth0').set_mtu(1400) +        >>> Interface('eth0').get_mtu()          '1400'          """          if mtu < 68 or mtu > 9000: @@ -175,29 +172,13 @@ class Interface:          return self._write_sysfs('/sys/class/net/{}/mtu'                                   .format(self._ifname), mtu) -    @property -    def mac(self): +    def set_mac(self, mac):          """ -        Get/set interface mac address +        Set interface MAC (Media Access Contrl) address to given value.          Example:          >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').mac -        '00:0c:29:11:aa:cc' -        """ -        return self._read_sysfs('/sys/class/net/{}/address' -                                .format(self._ifname)) - -    @mac.setter -    def mac(self, mac): -        """ -        Get/set interface mac address - -        Example: -        >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').mac = '00:90:43:fe:fe:1b' -        >>> Interface('eth0').mac -        '00:90:43:fe:fe:1b' +        >>> Interface('eth0').set_mac('00:50:ab:cd:ef:01')          """          # on interface removal (ethernet) an empty string is passed - ignore it          if not mac: @@ -226,50 +207,22 @@ class Interface:          cmd = 'ip link set dev {} address {}'.format(self._ifname, mac)          self._cmd(cmd) -    @property -    def arp_cache_tmo(self): -        """ -        Get configured ARP cache timeout value from interface in seconds. -        Internal Kernel representation is in milliseconds. - -        Example: -        >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').arp_cache_tmo -        '30' -        """ -        return (self._read_sysfs('/proc/sys/net/ipv4/neigh/{0}/base_reachable_time_ms' -                                 .format(self._ifname)) / 1000) -    @arp_cache_tmo.setter -    def arp_cache_tmo(self, tmo): +    def set_arp_cache_tmo(self, tmo):          """          Set ARP cache timeout value in seconds. Internal Kernel representation          is in milliseconds.          Example:          >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').arp_cache_tmo = '40' +        >>> Interface('eth0').set_arp_cache_tmo(40)          """          return self._write_sysfs('/proc/sys/net/ipv4/neigh/{0}/base_reachable_time_ms'                                   .format(self._ifname), (int(tmo) * 1000)) -    @property -    def link_detect(self): -        """ -        How does the kernel act when receiving packets on 'down' interfaces - -        Example: -        >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').link_detect -        '0' -        """ -        return self._read_sysfs('/proc/sys/net/ipv4/conf/{0}/link_filter' -                                .format(self._ifname)) - -    @link_detect.setter -    def link_detect(self, link_filter): +    def set_link_detect(self, link_filter):          """ -        Konfigure kernel response in packets received on interfaces that are 'down' +        Configure kernel response in packets received on interfaces that are 'down'          0 - Allow packets to be received for the address on this interface              even if interface is disabled or no carrier. @@ -285,44 +238,25 @@ class Interface:          Example:          >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').link_detect = '1' +        >>> Interface('eth0').set_link_detect(1)          """ -        if link_filter >= 0 and link_filter <= 2: +        if int(link_filter) >= 0 and int(link_filter) <= 2:              return self._write_sysfs('/proc/sys/net/ipv4/conf/{0}/link_filter'                                       .format(self._ifname), link_filter)          else:              raise ValueError("Value out of range") -    @property -    def ifalias(self): -        """ -        Get/set interface alias name - -        Example: - -        >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').ifalias -        '' -        """ -        return self._read_sysfs('/sys/class/net/{}/ifalias' -                                .format(self._ifname)) - -    @ifalias.setter -    def ifalias(self, ifalias=None): +    def set_alias(self, ifalias=None):          """ -        Get/set interface alias name +        Set interface alias name used by e.g. SNMP          Example:          >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').ifalias = 'VyOS upstream interface' -        >>> Interface('eth0').ifalias -        'VyOS upstream interface' +        >>> Interface('eth0').set_alias('VyOS upstream interface') -        to clear interface alias e.g. delete it use: +        to clear alias e.g. delete it use: -        >>> Interface('eth0').ifalias = '' -        >>> Interface('eth0').ifalias -        '' +        >>> Interface('eth0').set_ifalias('')          """          if not ifalias:              # clear interface alias @@ -331,63 +265,43 @@ class Interface:          self._write_sysfs('/sys/class/net/{}/ifalias'                            .format(self._ifname), ifalias) -    @property -    def state(self): +    def get_state(self):          """          Enable (up) / Disable (down) an interface          Example:          >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').state +        >>> Interface('eth0').get_state()          'up'          """          return self._read_sysfs('/sys/class/net/{}/operstate'                                  .format(self._ifname)) -    @state.setter -    def state(self, state): +    def set_state(self, state):          """          Enable (up) / Disable (down) an interface          Example:          >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').state = 'down' -        >>> Interface('eth0').state +        >>> Interface('eth0').set_state('down') +        >>> Interface('eth0').get_state()          'down'          """          if state not in ['up', 'down']:              raise ValueError('state must be "up" or "down"') -        self._state = state -          # Assemble command executed on system. Unfortunately there is no way          # to up/down an interface via sysfs          cmd = 'ip link set dev {} {}'.format(self._ifname, state)          self._cmd(cmd) -    @property -    def proxy_arp(self): -        """ -        Get current proxy ARP configuration from sysfs. Default: 0 - -        Example: -        >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').proxy_arp -        '0' -        """ -        return self._read_sysfs('/proc/sys/net/ipv4/conf/{}/proxy_arp' -                                .format(self._ifname)) - -    @proxy_arp.setter -    def proxy_arp(self, enable): +    def set_proxy_arp(self, enable):          """          Set per interface proxy ARP configuration          Example:          >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').proxy_arp = 1 -        >>> Interface('eth0').proxy_arp -        '1' +        >>> Interface('eth0').set_proxy_arp(1)          """          if int(enable) >= 0 and int(enable) <= 1:              return self._write_sysfs('/proc/sys/net/ipv4/conf/{}/proxy_arp' @@ -395,8 +309,7 @@ class Interface:          else:              raise ValueError("Value out of range") -    @property -    def proxy_arp_pvlan(self): +    def set_proxy_arp_pvlan(self, enable):          """          Private VLAN proxy arp.          Basically allow proxy arp replies back to the same interface @@ -418,38 +331,7 @@ class Interface:          Example:          >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').proxy_arp_pvlan -        '0' -        """ -        return self._read_sysfs('/proc/sys/net/ipv4/conf/{}/proxy_arp_pvlan' -                                .format(self._ifname)) - -    @proxy_arp_pvlan.setter -    def proxy_arp_pvlan(self, enable): -        """ -        Private VLAN proxy arp. -        Basically allow proxy arp replies back to the same interface -        (from which the ARP request/solicitation was received). - -        This is done to support (ethernet) switch features, like RFC -        3069, where the individual ports are NOT allowed to -        communicate with each other, but they are allowed to talk to -        the upstream router.  As described in RFC 3069, it is possible -        to allow these hosts to communicate through the upstream -        router by proxy_arp'ing. Don't need to be used together with -        proxy_arp. - -        This technology is known by different names: -        In RFC 3069 it is called VLAN Aggregation. -        Cisco and Allied Telesyn call it Private VLAN. -        Hewlett-Packard call it Source-Port filtering or port-isolation. -        Ericsson call it MAC-Forced Forwarding (RFC Draft). - -        Example: -        >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').proxy_arp_pvlan = 1 -        >>> Interface('eth0').proxy_arp_pvlan -        '1' +        >>> Interface('eth0').set_proxy_arp_pvlan(1)          """          if int(enable) >= 0 and int(enable) <= 1:              return self._write_sysfs('/proc/sys/net/ipv4/conf/{}/proxy_arp_pvlan' @@ -581,7 +463,7 @@ class Interface:          with open(self._dhcp_cfg_file, 'w') as f:              f.write(dhcp_text) -        if self._state == 'up': +        if self.get_state() == 'up':              cmd  = 'start-stop-daemon --start --quiet --pidfile ' + \                  self._dhcp_pid_file              cmd += ' --exec /sbin/dhclient --' @@ -659,7 +541,7 @@ class Interface:          with open(self._dhcpv6_cfg_file, 'w') as f:              f.write(dhcpv6_text) -        if self._state == 'up': +        if self.get_state() == 'up':              # https://bugs.launchpad.net/ubuntu/+source/ifupdown/+bug/1447715              #              # wee need to wait for IPv6 DAD to finish once and interface is added @@ -731,6 +613,21 @@ class LoopbackIf(Interface):      def __init__(self, ifname):          super().__init__(ifname, type='loopback') +    def remove(self): +        """ +        Loopback interface can not be deleted from operating system. We can +        only remove all assigned IP addresses. + +        Example: +        >>> from vyos.ifconfig import Interface +        >>> i = LoopbackIf('lo').remove() +        """ +        # remove all assigned IP addresses from interface +        for addr in self.get_addr(): +            self.del_addr(addr) + +        # question: do we also delerte the loopback address? 127.0.0.1/8 +  class DummyIf(Interface): @@ -744,6 +641,47 @@ class DummyIf(Interface):          super().__init__(ifname, type='dummy') +class STPIf(Interface): +    """ +    A spanning-tree capable interface. This applies only to bridge port member +    interfaces! +    """ +    def __init__(self, ifname): +        super().__init__(ifname) + +    def set_path_cost(self, cost): +        """ +        Set interface path cost, only relevant for STP enabled interfaces + +        Example: + +        >>> from vyos.ifconfig import Interface +        >>> Interface('eth0').set_path_cost(4) +        """ +        if not os.path.isfile('/sys/class/net/{}/brport/path_cost' +                              .format(self._ifname)): +            raise TypeError('{} is not a bridge port member'.format(self._ifname)) + +        return self._write_sysfs('/sys/class/net/{}/brport/path_cost' +                                 .format(self._ifname), cost) + +    def set_path_priority(self, priority): +        """ +        Set interface path priority, only relevant for STP enabled interfaces + +        Example: + +        >>> from vyos.ifconfig import Interface +        >>> Interface('eth0').set_path_priority(4) +        """ +        if not os.path.isfile('/sys/class/net/{}/brport/priority' +                              .format(self._ifname)): +            raise TypeError('{} is not a bridge port member'.format(self._ifname)) + +        return self._write_sysfs('/sys/class/net/{}/brport/priority' +                                 .format(self._ifname), priority) + +  class BridgeIf(Interface):      """ @@ -758,167 +696,73 @@ class BridgeIf(Interface):      def __init__(self, ifname):          super().__init__(ifname, type='bridge') -    @property -    def ageing_time(self): -        """ -        Return configured bridge interface MAC address aging time in seconds. -        Internal kernel representation is in centiseconds, thus its converted -        in the end. Kernel default is 300 seconds. - -        Example: -        >>> from vyos.ifconfig import Interface -        >>> BridgeIf('br0').aging_time -        '300' -        """ -        return (self._read_sysfs('/sys/class/net/{}/bridge/ageing_time' -                                 .format(self._ifname)) / 100) - -    @ageing_time.setter -    def ageing_time(self, time): +    def set_ageing_time(self, time):          """          Set bridge interface MAC address aging time in seconds. Internal kernel          representation is in centiseconds. Kernel default is 300 seconds.          Example: -        >>> from vyos.ifconfig import Interface -        >>> BridgeIf('br0').ageing_time = 2 +        >>> from vyos.ifconfig import BridgeIf +        >>> BridgeIf('br0').ageing_time(2)          """          time = int(time) * 100          return self._write_sysfs('/sys/class/net/{}/bridge/ageing_time'                                   .format(self._ifname), time) -    @property -    def forward_delay(self): -        """ -        Get bridge forwarding delay in seconds. Internal Kernel representation -        is in centiseconds. - -        Example: -        >>> from vyos.ifconfig import Interface -        >>> BridgeIf('br0').ageing_time -        '3' -        """ -        return (self._read_sysfs('/sys/class/net/{}/bridge/forward_delay' -                                 .format(self._ifname)) / 100) - -    @forward_delay.setter -    def forward_delay(self, time): +    def set_forward_delay(self, time):          """          Set bridge forwarding delay in seconds. Internal Kernel representation          is in centiseconds.          Example: -        >>> from vyos.ifconfig import Interface -        >>> BridgeIf('br0').forward_delay = 15 +        >>> from vyos.ifconfig import BridgeIf +        >>> BridgeIf('br0').forward_delay(15)          """          return self._write_sysfs('/sys/class/net/{}/bridge/forward_delay'                                   .format(self._ifname), (int(time) * 100)) -    @property -    def hello_time(self): -        """ -        Get bridge hello time in seconds. Internal Kernel representation -        is in centiseconds. - -        Example: -        >>> from vyos.ifconfig import Interface -        >>> BridgeIf('br0').hello_time -        '2' -        """ -        return (self._read_sysfs('/sys/class/net/{}/bridge/hello_time' -                                 .format(self._ifname)) / 100) - -    @hello_time.setter -    def hello_time(self, time): +    def set_hello_time(self, time):          """          Set bridge hello time in seconds. Internal Kernel representation          is in centiseconds.          Example: -        >>> from vyos.ifconfig import Interface -        >>> BridgeIf('br0').hello_time = 2 +        >>> from vyos.ifconfig import BridgeIf +        >>> BridgeIf('br0').set_hello_time(2)          """          return self._write_sysfs('/sys/class/net/{}/bridge/hello_time'                                   .format(self._ifname), (int(time) * 100)) -    @property -    def max_age(self): -        """ -        Get bridge max max message age in seconds. Internal Kernel representation -        is in centiseconds. - -        Example: -        >>> from vyos.ifconfig import Interface -        >>> BridgeIf('br0').max_age -        '20' -        """ - -        return (self._read_sysfs('/sys/class/net/{}/bridge/max_age' -                                 .format(self._ifname)) / 100) - -    @max_age.setter -    def max_age(self, time): +    def set_max_age(self, time):          """          Set bridge max message age in seconds. Internal Kernel representation          is in centiseconds.          Example:          >>> from vyos.ifconfig import Interface -        >>> BridgeIf('br0').max_age = 30 +        >>> BridgeIf('br0').set_max_age(30)          """          return self._write_sysfs('/sys/class/net/{}/bridge/max_age'                                   .format(self._ifname), (int(time) * 100)) -    @property -    def priority(self): -        """ -        Get bridge max aging time in seconds. - -        Example: -        >>> from vyos.ifconfig import Interface -        >>> BridgeIf('br0').priority -        '32768' -        """ -        return self._read_sysfs('/sys/class/net/{}/bridge/priority' -                                .format(self._ifname)) - -    @priority.setter -    def priority(self, priority): +    def set_priority(self, priority):          """          Set bridge max aging time in seconds.          Example: -        >>> from vyos.ifconfig import Interface -        >>> BridgeIf('br0').priority = 8192 +        >>> from vyos.ifconfig import BridgeIf +        >>> BridgeIf('br0').set_priority(8192)          """          return self._write_sysfs('/sys/class/net/{}/bridge/priority'                                   .format(self._ifname), priority) -    @property -    def stp_state(self): -        """ -        Get current bridge STP (Spanning Tree) state. - -        Example: -        >>> from vyos.ifconfig import Interface -        >>> BridgeIf('br0').stp_state -        '0' -        """ - -        state = 0 -        with open('/sys/class/net/{}/bridge/stp_state'.format(self._ifname), 'r') as f: -            state = int(f.read().rstrip('\n')) - -        return state - -    @stp_state.setter -    def stp_state(self, state): +    def set_stp(self, state):          """ -        Set bridge STP (Spannign Tree) state. 0 -> STP disabled, 1 -> STP enabled +        Set bridge STP (Spanning Tree) state. 0 -> STP disabled, 1 -> STP enabled          Example: -        >>> from vyos.ifconfig import Interface -        >>> BridgeIf('br0').stp_state = 1 +        >>> from vyos.ifconfig import BridgeIf +        >>> BridgeIf('br0').set_stp(1)          """          if int(state) >= 0 and int(state) <= 1: @@ -927,21 +771,8 @@ class BridgeIf(Interface):          else:              raise ValueError("Value out of range") -    @property -    def multicast_querier(self): -        """ -        Get bridge multicast querier membership state. - -        Example: -        >>> from vyos.ifconfig import Interface -        >>> BridgeIf('br0').multicast_querier -        '0' -        """ -        return self._read_sysfs('/sys/class/net/{}/bridge/multicast_querier' -                                .format(self._ifname)) -    @multicast_querier.setter -    def multicast_querier(self, enable): +    def set_multicast_querier(self, enable):          """          Sets whether the bridge actively runs a multicast querier or not. When a          bridge receives a 'multicast host membership' query from another network @@ -952,7 +783,7 @@ class BridgeIf(Interface):          Example:          >>> from vyos.ifconfig import Interface -        >>> BridgeIf('br0').multicast_querier = 1 +        >>> BridgeIf('br0').set_multicast_querier(1)          """          if int(enable) >= 0 and int(enable) <= 1:              return self._write_sysfs('/sys/class/net/{}/bridge/multicast_querier' @@ -960,6 +791,7 @@ class BridgeIf(Interface):          else:              raise ValueError("Value out of range") +      def add_port(self, interface):          """          Add physical interface to bridge (member port) @@ -983,31 +815,6 @@ class BridgeIf(Interface):          cmd = 'ip link set dev {} nomaster'.format(interface)          self._cmd(cmd) -    def set_cost(self, interface, cost): -        """ -        Set interface path cost, only relevant for STP enabled interfaces - -        Example: - -        >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').path_cost(4) -        """ -        return self._write_sysfs('/sys/class/net/{}/brif/{}/path_cost' -                                 .format(self._ifname, interface), cost) - -    def set_priority(self, interface, priority): -        """ -        Set interface path priority, only relevant for STP enabled interfaces - -        Example: - -        >>> from vyos.ifconfig import Interface -        >>> Interface('eth0').priority(4) -        """ -        return self._write_sysfs('/sys/class/net/{}/brif/{}/priority' -                                 .format(self._ifname, interface), priority) - -  class VLANIf(Interface):      """      This class handels the creation and removal of a VLAN interface. It serves @@ -1027,12 +834,22 @@ class VLANIf(Interface):          >>> i = Interface('eth0')          >>> i.remove()          """ -        # do we have sub interfaces (VLANs)? -        # we apply a regex matching subinterfaces (indicated by a .) of a -        # parent interface. 'bond0(?:\.\d+){1,2}' will match vif and vif-s/vif-c -        # subinterfaces +        # Do we have sub interfaces (VLANs)? We apply a regex matching +        # subinterfaces (indicated by a .) of a parent interface. +        # +        # As interfaces need to be deleted "in order" starting from Q-in-Q +        # we delete them first. +        vlan_ifs = [f for f in os.listdir(r'/sys/class/net') \ +                        if re.match(self._ifname + r'(?:\.\d+)(?:\.\d+)', f)] + +        for vlan in vlan_ifs: +            Interface(vlan).remove() + +        # After deleting all Q-in-Q interfaces delete other VLAN interfaces +        # which probably acted as parent to Q-in-Q or have been regular 802.1q +        # interface.          vlan_ifs = [f for f in os.listdir(r'/sys/class/net') \ -                       if re.match(self._ifname + r'(?:\.\d+){1,2}', f)] +                        if re.match(self._ifname + r'(?:\.\d+)', f)]          for vlan in vlan_ifs:              Interface(vlan).remove() @@ -1106,8 +923,7 @@ class VLANIf(Interface):          >>> i.del_vlan()          """          vlan_ifname = self._ifname + '.' + str(vlan_id) -        tmp = VLANIf(vlan_ifname) -        tmp.remove() +        VLANIf(vlan_ifname).remove()  class EthernetIf(VLANIf): @@ -1131,32 +947,6 @@ class EthernetIf(VLANIf):          link = os.readlink('/sys/class/net/{}/device/driver/module'.format(self._ifname))          return os.path.basename(link) - -    def has_autoneg(self): -        """ -        Not all drivers support autonegotiation. - -        returns True -> Autonegotiation is supported by driver -                False -> Autonegotiation is not supported by driver - -        Example: -        >>> from vyos.ifconfig import EthernetIf -        >>> i = EthernetIf('eth0') -        >>> i.has_autoneg() -        'True' -        """ -        regex = 'Supports auto-negotiation:[ ]\w+' -        tmp = self._cmd('/sbin/ethtool {}'.format(self._ifname)) -        tmp = re.search(regex, tmp.decode()) - -        # Output is either 'Supports auto-negotiation: Yes' or -        # 'Supports auto-negotiation: No' -        if tmp.group().split(':')[1].lstrip() == "Yes": -            return True -        else: -            return False - -      def set_flow_control(self, enable):          """          Changes the pause parameters of the specified Ethernet device. @@ -1319,7 +1109,7 @@ class BondIf(VLANIf):          for s in self.get_slaves():              slave = {                  'ifname' : s, -                'state': Interface(s).state +                'state': Interface(s).get_state()              }              slave_list.append(slave) @@ -1330,29 +1120,10 @@ class BondIf(VLANIf):          # physical interface          for slave in slave_list:               i = Interface(slave['ifname']) -             i.state = slave['state'] - -    @property -    def xmit_hash_policy(self): -        """ -        Selects the transmit hash policy to use for slave selection in -        balance-xor, 802.3ad, and tlb modes. Possible values are: layer2, -        layer2+3, layer3+4, encap2+3, encap3+4. +             i.set_state(slave['state']) -        The default value is layer2 - -        Example: -        >>> from vyos.ifconfig import BondIf -        >>> BondIf('bond0').xmit_hash_policy -        'layer3+4' -        """ -        # Linux Kernel appends has policy value to string, e.g. 'layer3+4 1', -        # so remove the later part and only return the mode as string. -        return self._read_sysfs('/sys/class/net/{}/bonding/xmit_hash_policy' -                                .format(self._ifname)).split()[0] -    @xmit_hash_policy.setter -    def xmit_hash_policy(self, mode): +    def set_hash_policy(self, mode):          """          Selects the transmit hash policy to use for slave selection in          balance-xor, 802.3ad, and tlb modes. Possible values are: layer2, @@ -1362,59 +1133,50 @@ class BondIf(VLANIf):          Example:          >>> from vyos.ifconfig import BondIf -        >>> BondIf('bond0').xmit_hash_policy = 'layer2+3' -        >>> BondIf('bond0').proxy_arp -        '1' +        >>> BondIf('bond0').set_hash_policy('layer2+3')          """          if not mode in ['layer2', 'layer2+3', 'layer3+4', 'encap2+3', 'encap3+4']:              raise ValueError("Value out of range")          return self._write_sysfs('/sys/class/net/{}/bonding/xmit_hash_policy'                                   .format(self._ifname), mode) -    @property -    def arp_interval(self): +    def set_arp_interval(self, interval):          """          Specifies the ARP link monitoring frequency in milliseconds. -        The ARP monitor works by periodically checking the slave devices to -        determine whether they have sent or received traffic recently (the -        precise criteria depends upon the bonding mode, and the state of the -        slave). Regular traffic is generated via ARP probes issued for the -        addresses specified by the arp_ip_target option. - -        The default value is 0. - -        Example: -        >>> from vyos.ifconfig import BondIf -        >>> BondIf('bond0').arp_interval -        '0' -        """ -        return self._read_sysfs('/sys/class/net/{}/bonding/arp_interval' -                                .format(self._ifname)) +        The ARP monitor works by periodically checking the slave devices +        to determine whether they have sent or received traffic recently +        (the precise criteria depends upon the bonding mode, and the +        state of the slave). Regular traffic is generated via ARP probes +        issued for the addresses specified by the arp_ip_target option. -    @arp_interval.setter -    def arp_interval(self, time): -        """ -        Specifies the IP addresses to use as ARP monitoring peers when -        arp_interval is > 0. These are the targets of the ARP request sent to -        determine the health of the link to the targets. Specify these values -        in ddd.ddd.ddd.ddd format. Multiple IP addresses must be separated by -        a comma. At least one IP address must be given for ARP monitoring to -        function. The maximum number of targets that can be specified is 16. +        If ARP monitoring is used in an etherchannel compatible mode +        (modes 0 and 2), the switch should be configured in a mode that +        evenly distributes packets across all links. If the switch is +        configured to distribute the packets in an XOR fashion, all +        replies from the ARP targets will be received on the same link +        which could cause the other team members to fail. -        The default value is no IP addresses. +        value of 0 disables ARP monitoring. The default value is 0.          Example:          >>> from vyos.ifconfig import BondIf -        >>> BondIf('bond0').arp_interval = '100' -        >>> BondIf('bond0').arp_interval -        '100' -        """ -        return self._write_sysfs('/sys/class/net/{}/bonding/arp_interval' -                                 .format(self._ifname), time) +        >>> BondIf('bond0').set_arp_interval('100') +        """ +        if int(interval) == 0: +            """ +            Specifies the MII link monitoring frequency in milliseconds. +            This determines how often the link state of each slave is +            inspected for link failures. A value of zero disables MII +            link monitoring. A value of 100 is a good starting point. +            """ +            return self._write_sysfs('/sys/class/net/{}/bonding/miimon' +                                     .format(self._ifname), interval) +        else: +            return self._write_sysfs('/sys/class/net/{}/bonding/arp_interval' +                                     .format(self._ifname), interval) -    @property -    def arp_ip_target(self): +    def get_arp_ip_target(self):          """          Specifies the IP addresses to use as ARP monitoring peers when          arp_interval is > 0. These are the targets of the ARP request sent to @@ -1427,14 +1189,13 @@ class BondIf(VLANIf):          Example:          >>> from vyos.ifconfig import BondIf -        >>> BondIf('bond0').arp_ip_target +        >>> BondIf('bond0').get_arp_ip_target()          '192.0.2.1'          """          return self._read_sysfs('/sys/class/net/{}/bonding/arp_ip_target'                                  .format(self._ifname)) -    @arp_ip_target.setter -    def arp_ip_target(self, target): +    def set_arp_ip_target(self, target):          """          Specifies the IP addresses to use as ARP monitoring peers when          arp_interval is > 0. These are the targets of the ARP request sent to @@ -1447,52 +1208,13 @@ class BondIf(VLANIf):          Example:          >>> from vyos.ifconfig import BondIf -        >>> BondIf('bond0').arp_ip_target = '192.0.2.1' -        >>> BondIf('bond0').arp_ip_target +        >>> BondIf('bond0').set_arp_ip_target('192.0.2.1') +        >>> BondIf('bond0').get_arp_ip_target()          '192.0.2.1'          """          return self._write_sysfs('/sys/class/net/{}/bonding/arp_ip_target'                                   .format(self._ifname), target) -    @property -    def miimon(self): -        """ -        Specifies the MII link monitoring frequency in milliseconds. -        This determines how often the link state of each slave is -        inspected for link failures. A value of zero disables MII -        link monitoring. A value of 100 is a good starting point. - -        The default value is 0. - -        Example: -        >>> from vyos.ifconfig import BondIf -        >>> BondIf('bond0').miimon -        '250' -        """ -        return self._read_sysfs('/sys/class/net/{}/bonding/miimon' -                                .format(self._ifname)) - - -    @miimon.setter -    def miimon(self, time): -        """ -        Specifies the MII link monitoring frequency in milliseconds. -        This determines how often the link state of each slave is -        inspected for link failures. A value of zero disables MII -        link monitoring. A value of 100 is a good starting point. - -        The default value is 0. - -        Example: -        >>> from vyos.ifconfig import BondIf -        >>> BondIf('bond0').miimon = 250 -        >>> BondIf('bond0').miimon -        '250' -        """ -        return self._write_sysfs('/sys/class/net/{}/bonding/miimon' -                                 .format(self._ifname), time) - -      def add_port(self, interface):          """          Enslave physical interface to bond. @@ -1505,7 +1227,7 @@ class BondIf(VLANIf):          # An interface can only be added to a bond if it is in 'down' state. If          # interface is in 'up' state, the following Kernel error will  be thrown:          # bond0: eth1 is up - this may be due to an out of date ifenslave. -        Interface(interface).state = 'down' +        Interface(interface).set_state('down')          return self._write_sysfs('/sys/class/net/{}/bonding/slaves'                                   .format(self._ifname), '+' + interface) @@ -1534,28 +1256,8 @@ class BondIf(VLANIf):                                    .format(self._ifname))          return list(map(str, slaves.split())) -    @property -    def primary(self): -        """ -        A string (eth0, eth2, etc) specifying which slave is the primary -        device. The specified device will always be the active slave while it -        is available. Only when the primary is off-line will alternate devices -        be used. This is useful when one slave is preferred over another, e.g., -        when one slave has higher throughput than another. -        The primary option is only valid for active-backup, balance-tlb and -        balance-alb mode. - -        Example: -        >>> from vyos.ifconfig import BondIf -        >>> BondIf('bond0').primary -        'eth1' -        """ -        return self._read_sysfs('/sys/class/net/{}/bonding/primary' -                                .format(self._ifname)) - -    @primary.setter -    def primary(self, interface): +    def set_primary(self, interface):          """          A string (eth0, eth2, etc) specifying which slave is the primary          device. The specified device will always be the active slave while it @@ -1568,9 +1270,7 @@ class BondIf(VLANIf):          Example:          >>> from vyos.ifconfig import BondIf -        >>> BondIf('bond0').primary = 'eth2' -        >>> BondIf('bond0').primary -        'eth2' +        >>> BondIf('bond0').set_primary('eth2')          """          if not interface:              # reset primary interface @@ -1579,25 +1279,7 @@ class BondIf(VLANIf):          return self._write_sysfs('/sys/class/net/{}/bonding/primary'                                   .format(self._ifname), interface) -    @property -    def mode(self): -        """ -        Specifies one of the bonding policies. The default is balance-rr -        (round robin). - -        Possible values are: balance-rr (0), active-backup (1), balance-xor (2), -        broadcast (3), 802.3ad (4), balance-tlb (5), balance-alb (6) - -        Example: -        >>> from vyos.ifconfig import BondIf -        >>> BondIf('bond0').mode -        'balance-rr' -        """ -        return self._read_sysfs('/sys/class/net/{}/bonding/mode' -                                .format(self._ifname)).split()[0] - -    @mode.setter -    def mode(self, mode): +    def set_mode(self, mode):          """          Specifies one of the bonding policies. The default is balance-rr          (round robin). @@ -1610,9 +1292,7 @@ class BondIf(VLANIf):          Example:          >>> from vyos.ifconfig import BondIf -        >>> BondIf('bond0').mode = '802.3ad' -        >>> BondIf('bond0').mode -        '802.3ad' +        >>> BondIf('bond0').set_mode('802.3ad')          """          if not mode in [              'balance-rr', 'active-backup', 'balance-xor', 'broadcast', diff --git a/src/conf_mode/interface-bonding.py b/src/conf_mode/interface-bonding.py index 9049913e6..4d5009c73 100755 --- a/src/conf_mode/interface-bonding.py +++ b/src/conf_mode/interface-bonding.py @@ -13,8 +13,6 @@  #  # You should have received a copy of the GNU General Public License  # along with this program.  If not, see <http://www.gnu.org/licenses/>. -# -#  import os @@ -86,20 +84,20 @@ def apply_vlan_config(vlan, config):          raise TypeError()      # update interface description used e.g. within SNMP -    vlan.ifalias = config['description'] +    vlan.set_alias(config['description'])      # ignore link state changes -    vlan.link_detect = config['disable_link_detect'] +    vlan.set_link_detect(config['disable_link_detect'])      # Maximum Transmission Unit (MTU) -    vlan.mtu = config['mtu'] +    vlan.set_mtu(config['mtu'])      # Change VLAN interface MAC address      if config['mac']: -        vlan.mac = config['mac'] +        vlan.set_mac(config['mac'])      # enable/disable VLAN interface      if config['disable']: -        vlan.state = 'down' +        vlan.set_state('down')      else: -        vlan.state = 'up' +        vlan.set_state('up')      # Configure interface address(es)      # - not longer required addresses get removed first @@ -339,7 +337,7 @@ def apply(bond):      else:          # Some parameters can not be changed when the bond is up.          # Always disable the bond prior changing anything -        b.state = 'down' +        b.set_state('down')          # The bonding mode can not be changed when there are interfaces enslaved          # to this bond, thus we will free all interfaces from the bond first! @@ -347,11 +345,8 @@ def apply(bond):              b.del_port(intf)          # ARP link monitoring frequency, reset miimon when arp-montior is inactive -        if bond['arp_mon_intvl'] == 0: -            # reset miimon to default -            b.miimon = 250 -        else: -            b.arp_interval = bond['arp_mon_intvl'] +        # this is done inside BondIf automatically +        b.set_arp_interval(bond['arp_mon_intvl'])          # ARP monitor targets need to be synchronized between sysfs and CLI.          # Unfortunately an address can't be send twice to sysfs as this will @@ -362,44 +357,44 @@ def apply(bond):          # from the kernel side this looks valid to me. We won't run into an error          # when a user added manual adresses which would result in having more          # then 16 adresses in total. -        arp_tgt_addr = list(map(str, b.arp_ip_target.split())) +        arp_tgt_addr = list(map(str, b.get_arp_ip_target().split()))          for addr in arp_tgt_addr: -            b.arp_ip_target = '-' + addr +            b.set_arp_ip_target('-' + addr)          # Add configured ARP target addresses          for addr in bond['arp_mon_tgt']: -            b.arp_ip_target = '+' + addr +            b.set_arp_ip_target('+' + addr)          # update interface description used e.g. within SNMP -        b.ifalias = bond['description'] +        b.set_alias(bond['description'])          #          # missing DHCP/DHCPv6 options go here          #          # ignore link state changes -        b.link_detect = bond['disable_link_detect'] +        b.set_link_detect(bond['disable_link_detect'])          # Bonding transmit hash policy -        b.xmit_hash_policy = bond['hash_policy'] +        b.set_hash_policy(bond['hash_policy'])          # configure ARP cache timeout in milliseconds -        b.arp_cache_tmp = bond['ip_arp_cache_tmo'] +        b.set_arp_cache_tmo(bond['ip_arp_cache_tmo'])          # Enable proxy-arp on this interface -        b.proxy_arp = bond['ip_proxy_arp'] +        b.set_proxy_arp(bond['ip_proxy_arp'])          # Enable private VLAN proxy ARP on this interface -        b.proxy_arp_pvlan = bond['ip_proxy_arp_pvlan'] +        b.set_proxy_arp_pvlan(bond['ip_proxy_arp_pvlan'])          # Change interface MAC address          if bond['mac']: -            b.mac = bond['mac'] +            b.set_mac(bond['mac'])          # Bonding policy -        b.mode = bond['mode'] +        b.set_mode(bond['mode'])          # Maximum Transmission Unit (MTU) -        b.mtu = bond['mtu'] +        b.set_mtu(bond['mtu'])          # Primary device interface          if bond['primary']: -            b.primary = bond['primary'] +            b.set_primary(bond['primary'])          # Add (enslave) interfaces to bond          for intf in bond['member']: @@ -409,7 +404,7 @@ def apply(bond):          # parameters we will only re-enable the interface if it is not          # administratively disabled          if not bond['disable']: -            b.state = 'up' +            b.set_state('up')          # Configure interface address(es)          # - not longer required addresses get removed first diff --git a/src/conf_mode/interface-bridge.py b/src/conf_mode/interface-bridge.py index 62589c798..37b5c4979 100755 --- a/src/conf_mode/interface-bridge.py +++ b/src/conf_mode/interface-bridge.py @@ -13,8 +13,6 @@  #  # You should have received a copy of the GNU General Public License  # along with this program.  If not, see <http://www.gnu.org/licenses/>. -# -#  import os @@ -22,7 +20,7 @@ from copy import deepcopy  from sys import exit  from netifaces import interfaces -from vyos.ifconfig import BridgeIf, Interface +from vyos.ifconfig import BridgeIf, STPIf  from vyos.configdict import list_diff  from vyos.config import Config  from vyos import ConfigError @@ -187,27 +185,27 @@ def apply(bridge):          br.remove()      else:          # enable interface -        br.state = 'up' +        br.set_state('up')          # set ageing time -        br.ageing_time = bridge['aging'] +        br.set_ageing_time(bridge['aging'])          # set bridge forward delay -        br.forward_delay = bridge['forwarding_delay'] +        br.set_forward_delay(bridge['forwarding_delay'])          # set hello time -        br.hello_time = bridge['hello_time'] +        br.set_hello_time(bridge['hello_time'])          # set max message age -        br.max_age = bridge['max_age'] +        br.set_max_age(bridge['max_age'])          # set bridge priority -        br.priority = bridge['priority'] +        br.set_priority(bridge['priority'])          # turn stp on/off -        br.stp_state = bridge['stp'] +        br.set_stp(bridge['stp'])          # enable or disable IGMP querier -        br.multicast_querier = bridge['igmp_querier'] +        br.set_multicast_querier(bridge['igmp_querier'])          # update interface description used e.g. within SNMP -        br.ifalias = bridge['description'] +        br.set_alias(bridge['description'])          # Change interface MAC address          if bridge['mac']: -            br.mac = bridge['mac'] +            br.set_mac(bridge['mac'])          # remove interface from bridge          for intf in bridge['member_remove']: @@ -219,7 +217,7 @@ def apply(bridge):          # up/down interface          if bridge['disable']: -            br.state = 'down' +            br.set_state('down')          # Configure interface address(es)          # - not longer required addresses get removed first @@ -231,16 +229,15 @@ def apply(bridge):          # configure additional bridge member options          for member in bridge['member']: -            # set bridge port cost -            br.set_cost(member['name'], member['cost']) -            # set bridge port priority -            br.set_priority(member['name'], member['priority']) - -            i = Interface(member['name']) +            i = STPIf(member['name'])              # configure ARP cache timeout -            i.arp_cache_tmo = bridge['arp_cache_tmo'] +            i.set_arp_cache_tmo(bridge['arp_cache_tmo'])              # ignore link state changes -            i.link_detect = bridge['disable_link_detect'] +            i.set_link_detect(bridge['disable_link_detect']) +            # set bridge port path cost +            i.set_path_cost(member['cost']) +            # set bridge port path priority +            i.set_path_priority(member['priority'])      return None diff --git a/src/conf_mode/interface-dummy.py b/src/conf_mode/interface-dummy.py index 614fe08db..16b716e61 100755 --- a/src/conf_mode/interface-dummy.py +++ b/src/conf_mode/interface-dummy.py @@ -13,10 +13,9 @@  #  # You should have received a copy of the GNU General Public License  # along with this program.  If not, see <http://www.gnu.org/licenses/>. -# -# -from os import environ +import os +  from copy import deepcopy  from sys import exit @@ -40,7 +39,7 @@ def get_config():      # determine tagNode instance      try: -        dummy['intf'] = environ['VYOS_TAGNODE_VALUE'] +        dummy['intf'] = os.environ['VYOS_TAGNODE_VALUE']      except KeyError as E:          print("Interface not specified") @@ -79,28 +78,28 @@ def generate(dummy):      return None  def apply(dummy): -    du = DummyIf(dummy['intf']) +    d = DummyIf(dummy['intf'])      # Remove dummy interface      if dummy['deleted']: -        du.remove() +        d.remove()      else: -        # enable interface -        du.state = 'up'          # update interface description used e.g. within SNMP -        du.ifalias = dummy['description'] +        d.set_alias(dummy['description'])          # Configure interface address(es)          # - not longer required addresses get removed first          # - newly addresses will be added second          for addr in dummy['address_remove']: -            du.del_addr(addr) +            d.del_addr(addr)          for addr in dummy['address']: -            du.add_addr(addr) +            d.add_addr(addr)          # disable interface on demand          if dummy['disable']: -            du.state = 'down' +            d.set_state('down') +        else +            d.set_state('up')      return None diff --git a/src/conf_mode/interface-ethernet.py b/src/conf_mode/interface-ethernet.py index 5d597fd0a..99450b19e 100755 --- a/src/conf_mode/interface-ethernet.py +++ b/src/conf_mode/interface-ethernet.py @@ -67,20 +67,20 @@ def apply_vlan_config(vlan, config):          raise TypeError()      # update interface description used e.g. within SNMP -    vlan.ifalias = config['description'] +    vlan.set_alias(config['description'])      # ignore link state changes -    vlan.link_detect = config['disable_link_detect'] +    vlan.set_link_detect(config['disable_link_detect'])      # Maximum Transmission Unit (MTU) -    vlan.mtu = config['mtu'] +    vlan.set_mtu(config['mtu'])      # Change VLAN interface MAC address      if config['mac']: -        vlan.mac = config['mac'] +        vlan.set_mac(config['mac'])      # enable/disable VLAN interface      if config['disable']: -        vlan.state = 'down' +        vlan.set_state('down')      else: -        vlan.state = 'up' +        vlan.set_state('up')      # Configure interface address(es)      # - not longer required addresses get removed first @@ -271,32 +271,32 @@ def apply(eth):          e.remove()      else:          # update interface description used e.g. within SNMP -        e.ifalias = eth['description'] +        e.set_alias(eth['description'])          #          # missing DHCP/DHCPv6 options go here          #          # ignore link state changes -        e.link_detect = eth['disable_link_detect'] +        e.set_link_detect(eth['disable_link_detect'])          # disable ethernet flow control (pause frames)          e.set_flow_control(eth['flow_control'])          # configure ARP cache timeout in milliseconds -        e.arp_cache_tmo = eth['ip_arp_cache_tmo'] +        e.set_arp_cache_tmo(eth['ip_arp_cache_tmo'])          # Enable proxy-arp on this interface -        e.proxy_arp = eth['ip_proxy_arp'] +        e.set_proxy_arp(eth['ip_proxy_arp'])          # Enable private VLAN proxy ARP on this interface -        e.proxy_arp_pvlan = eth['ip_proxy_arp_pvlan'] +        e.set_proxy_arp_pvlan(eth['ip_proxy_arp_pvlan'])          # Change interface MAC address - re-set to real hardware address (hw-id)          # if custom mac is removed          if eth['mac']: -            e.mac = eth['mac'] +            e.set_mac(eth['mac'])          else: -            e.mac = eth['hw_id'] +            e.set_mac(eth['hw_id'])          # Maximum Transmission Unit (MTU) -        e.mtu = eth['mtu'] +        e.set_mtu(eth['mtu'])          # GRO (generic receive offload)          e.set_gro(eth['offload_gro']) @@ -318,9 +318,9 @@ def apply(eth):          # Enable/Disable interface          if eth['disable']: -            e.state = 'down' +            e.set_state('down')          else: -            e.state = 'up' +            e.set_state('up')          # Configure interface address(es)          # - not longer required addresses get removed first diff --git a/src/conf_mode/interface-loopback.py b/src/conf_mode/interface-loopback.py index a1a807868..10722d137 100755 --- a/src/conf_mode/interface-loopback.py +++ b/src/conf_mode/interface-loopback.py @@ -13,9 +13,9 @@  #  # You should have received a copy of the GNU General Public License  # along with this program.  If not, see <http://www.gnu.org/licenses/>. -# -from os import environ +import os +  from sys import exit  from copy import deepcopy @@ -38,7 +38,7 @@ def get_config():      # determine tagNode instance      try: -        loopback['intf'] = environ['VYOS_TAGNODE_VALUE'] +        loopback['intf'] = os.environ['VYOS_TAGNODE_VALUE']      except KeyError as E:          print("Interface not specified") @@ -72,21 +72,20 @@ def generate(loopback):      return None  def apply(loopback): -    lo = LoopbackIf(loopback['intf']) -    if not loopback['deleted']: +    l = LoopbackIf(loopback['intf']) +    if loopback['deleted']: +        l.remove() +    else:          # update interface description used e.g. within SNMP -        # update interface description used e.g. within SNMP -        lo.ifalias = loopback['description'] +        l.set_alias(loopback['description'])          # Configure interface address(es)          # - not longer required addresses get removed first          # - newly addresses will be added second +        for addr in loopback['address_remove']: +            l.del_addr(addr)          for addr in loopback['address']: -            lo.add_addr(addr) - -    # remove interface address(es) -    for addr in loopback['address_remove']: -        lo.del_addr(addr) +            l.add_addr(addr)      return None diff --git a/src/conf_mode/interface-openvpn.py b/src/conf_mode/interface-openvpn.py index 35e7928c2..57d565749 100755 --- a/src/conf_mode/interface-openvpn.py +++ b/src/conf_mode/interface-openvpn.py @@ -13,8 +13,6 @@  #  # You should have received a copy of the GNU General Public License  # along with this program.  If not, see <http://www.gnu.org/licenses/>. -# -#  import os  import re @@ -31,8 +29,9 @@ from pwd import getpwnam  from subprocess import Popen, PIPE  from time import sleep -from vyos.config import Config  from vyos import ConfigError +from vyos.config import Config +from vyos.ifconfig import Interface  from vyos.validate import is_addr_assigned  user = 'openvpn' @@ -580,7 +579,7 @@ def get_config():      # Minimum required TLS version      if conf.exists('tls tls-version-min'):           openvpn['tls_version_min'] = conf.return_value('tls tls-version-min') -     +      if conf.exists('shared-secret-key-file'):          openvpn['shared_secret_file'] = conf.return_value('shared-secret-key-file') @@ -736,7 +735,7 @@ def verify(openvpn):          if openvpn['tls_auth']:              if not checkCertHeader('-----BEGIN OpenVPN Static key V1-----', openvpn['tls_auth']):                  raise ConfigError('Specified auth-file "{}" is invalid'.format(openvpn['tls_auth'])) -         +          if openvpn['tls_cert']:              if not checkCertHeader('-----BEGIN CERTIFICATE-----', openvpn['tls_cert']):                  raise ConfigError('Specified cert-file "{}" is invalid'.format(openvpn['tls_cert'])) @@ -901,6 +900,13 @@ def apply(openvpn):      # execute assembled command      subprocess_cmd(cmd) + +    # better late then sorry ... but we can only set interface alias after +    # OpenVPN has been launched and created the interface +    while openvpn['intf'] not in interfaces(): +        sleep(0.250) # 250ms +    Interface(openvpn['intf']).set_alias(openvpn['description']) +      return None diff --git a/src/conf_mode/interface-vxlan.py b/src/conf_mode/interface-vxlan.py index e97b4bf99..1097ae4d0 100755 --- a/src/conf_mode/interface-vxlan.py +++ b/src/conf_mode/interface-vxlan.py @@ -13,9 +13,9 @@  #  # You should have received a copy of the GNU General Public License  # along with this program.  If not, see <http://www.gnu.org/licenses/>. -# -from os import environ +import os +  from sys import exit  from copy import deepcopy @@ -48,7 +48,7 @@ def get_config():      # determine tagNode instance      try: -        vxlan['intf'] = environ['VYOS_TAGNODE_VALUE'] +        vxlan['intf'] = os.environ['VYOS_TAGNODE_VALUE']      except KeyError as E:          print("Interface not specified") @@ -127,7 +127,7 @@ def verify(vxlan):      if vxlan['link']:          # VXLAN adds a 50 byte overhead - we need to check the underlaying MTU          # if our configured MTU is at least 50 bytes less -        underlay_mtu = int(Interface(vxlan['link']).mtu) +        underlay_mtu = int(Interface(vxlan['link']).get_mtu())          if underlay_mtu < (vxlan['mtu'] + 50):              raise ConfigError('VXLAN has a 50 byte overhead, underlaying device ' \                                'MTU is to small ({})'.format(underlay_mtu)) @@ -163,14 +163,14 @@ def apply(vxlan):          # Finally create the new interface          v = VXLANIf(vxlan['intf'], config=conf)          # update interface description used e.g. by SNMP -        v.ifalias = vxlan['description'] +        v.set_alias(vxlan['description'])          # Maximum Transfer Unit (MTU) -        v.mtu = vxlan['mtu'] +        v.set_mtu(vxlan['mtu'])          # configure ARP cache timeout in milliseconds -        v.arp_cache_tmp = vxlan['ip_arp_cache_tmo'] +        v.set_arp_cache_tmo(vxlan['ip_arp_cache_tmo'])          # Enable proxy-arp on this interface -        v.proxy_arp = vxlan['ip_proxy_arp'] +        v.set_proxy_arp(vxlan['ip_proxy_arp'])          # Configure interface address(es) - no need to implicitly delete the          # old addresses as they have already been removed by deleting the @@ -182,7 +182,7 @@ def apply(vxlan):          # parameters we will only re-enable the interface if it is not          # administratively disabled          if not vxlan['disable']: -            v.state='up' +            v.set_state('up')      return None diff --git a/src/conf_mode/interface-wireguard.py b/src/conf_mode/interface-wireguard.py index 4ae3251fe..3fd29ad4d 100755 --- a/src/conf_mode/interface-wireguard.py +++ b/src/conf_mode/interface-wireguard.py @@ -13,8 +13,6 @@  #  # You should have received a copy of the GNU General Public License  # along with this program.  If not, see <http://www.gnu.org/licenses/>. -# -#  import sys  import os @@ -97,7 +95,7 @@ def get_config():          if c.exists(ifname + ' mtu'):              config_data[ifname]['mtu'] = c.return_value(ifname + ' mtu')          if c.exists(ifname + ' private-key'): -            config_data[ifname]['pk'] = "{0}/{1}/private.key".format(kdir,c.return_value(ifname + ' private-key'))  +            config_data[ifname]['pk'] = "{0}/{1}/private.key".format(kdir,c.return_value(ifname + ' private-key'))          if c.exists(ifname + ' peer'):              for p in c.list_nodes(ifname + ' peer'):                  if not c.exists(ifname + ' peer ' + p + ' disable'): @@ -175,11 +173,11 @@ def apply(c):      # interface state      if c[ifname]['state'] == 'disable':          sl.syslog(sl.LOG_NOTICE, "disable interface " + ifname) -        intfc.state = 'down' +        intfc.set_state('down')      else: -        if not intfc.state == 'up': +        if not intfc.get_state() == 'up':              sl.syslog(sl.LOG_NOTICE, "enable interface " + ifname) -            intfc.state = 'up' +            intfc.set_state('up')      # IP address      if not c_eff.exists_effective(ifname + ' address'): @@ -204,15 +202,15 @@ def apply(c):      # interface MTU      if c[ifname]['mtu'] != 1420: -        intfc.mtu = int(c[ifname]['mtu']) +        intfc.set_mtu(int(c[ifname]['mtu']))      else:      # default is set to 1420 in config_data -        intfc.mtu = int(c[ifname]['mtu']) +        intfc.set_mtu(int(c[ifname]['mtu']))      # ifalias for snmp from description      descr_eff = c_eff.return_effective_value(ifname + ' description')      if descr_eff != c[ifname]['descr']: -        intfc.ifalias = str(c[ifname]['descr']) +        intfc.set_alias(str(c[ifname]['descr']))      # peer deletion      peer_eff = c_eff.list_effective_nodes(ifname + ' peer') | 
