diff options
| author | Christian Poessinger <christian@poessinger.com> | 2020-03-25 09:57:21 +0100 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-03-25 09:57:21 +0100 | 
| commit | 6e7739e0b69e1d3371ebe36218604cbb1aca18b1 (patch) | |
| tree | c745b79a378c75e928931073bfddbf8cc76ca730 /python | |
| parent | 7c4d21639d9594ba4a0d96a5d6d90f25189c2817 (diff) | |
| parent | bbea850ea5f8ff0402cd276ab63963ece7e0c763 (diff) | |
| download | vyos-1x-6e7739e0b69e1d3371ebe36218604cbb1aca18b1.tar.gz vyos-1x-6e7739e0b69e1d3371ebe36218604cbb1aca18b1.zip | |
Merge pull request #265 from thomas-mangin/2057-dhcp-vlan
ifconfig: T2057: break down DHCP, add register, STP and VLAN as adapters
Diffstat (limited to 'python')
| -rw-r--r-- | python/vyos/ifconfig/__init__.py | 4 | ||||
| -rw-r--r-- | python/vyos/ifconfig/bond.py | 27 | ||||
| -rw-r--r-- | python/vyos/ifconfig/bridge.py | 17 | ||||
| -rw-r--r-- | python/vyos/ifconfig/control.py | 4 | ||||
| -rw-r--r-- | python/vyos/ifconfig/dhcp.py | 266 | ||||
| -rw-r--r-- | python/vyos/ifconfig/dummy.py | 8 | ||||
| -rw-r--r-- | python/vyos/ifconfig/ethernet.py | 28 | ||||
| -rw-r--r-- | python/vyos/ifconfig/geneve.py | 9 | ||||
| -rw-r--r-- | python/vyos/ifconfig/interface.py | 282 | ||||
| -rw-r--r-- | python/vyos/ifconfig/l2tpv3.py | 14 | ||||
| -rw-r--r-- | python/vyos/ifconfig/loopback.py | 11 | ||||
| -rw-r--r-- | python/vyos/ifconfig/macvlan.py | 16 | ||||
| -rw-r--r-- | python/vyos/ifconfig/pppoe.py | 33 | ||||
| -rw-r--r-- | python/vyos/ifconfig/register.py | 96 | ||||
| -rw-r--r-- | python/vyos/ifconfig/stp.py | 19 | ||||
| -rw-r--r-- | python/vyos/ifconfig/tunnel.py | 8 | ||||
| -rw-r--r-- | python/vyos/ifconfig/vlan.py | 43 | ||||
| -rw-r--r-- | python/vyos/ifconfig/vtun.py | 34 | ||||
| -rw-r--r-- | python/vyos/ifconfig/vxlan.py | 24 | ||||
| -rw-r--r-- | python/vyos/ifconfig/wireguard.py | 14 | ||||
| -rw-r--r-- | python/vyos/ifconfig/wireless.py | 31 | ||||
| -rw-r--r-- | python/vyos/ifconfig_vlan.py | 3 | ||||
| -rw-r--r-- | python/vyos/interfaces.py | 36 | 
23 files changed, 653 insertions, 374 deletions
| diff --git a/python/vyos/ifconfig/__init__.py b/python/vyos/ifconfig/__init__.py index 16c29a704..d08a8b528 100644 --- a/python/vyos/ifconfig/__init__.py +++ b/python/vyos/ifconfig/__init__.py @@ -23,10 +23,10 @@ from vyos.ifconfig.ethernet import EthernetIf  from vyos.ifconfig.geneve import GeneveIf  from vyos.ifconfig.loopback import LoopbackIf  from vyos.ifconfig.macvlan import MACVLANIf -from vyos.ifconfig.stp import STPIf -from vyos.ifconfig.vlan import VLANIf  from vyos.ifconfig.vxlan import VXLANIf  from vyos.ifconfig.wireguard import WireGuardIf +from vyos.ifconfig.vtun import VTunIf +from vyos.ifconfig.pppoe import PPPoEIf  from vyos.ifconfig.tunnel import GREIf  from vyos.ifconfig.tunnel import GRETapIf  from vyos.ifconfig.tunnel import IP6GREIf diff --git a/python/vyos/ifconfig/bond.py b/python/vyos/ifconfig/bond.py index c9dac891f..3c26b9b95 100644 --- a/python/vyos/ifconfig/bond.py +++ b/python/vyos/ifconfig/bond.py @@ -16,12 +16,14 @@  import os  from vyos.ifconfig.interface import Interface -from vyos.ifconfig.vlan import VLANIf +from vyos.ifconfig.vlan import VLAN  from vyos.validate import * -class BondIf(VLANIf): +@Interface.register +@VLAN.enable +class BondIf(Interface):      """      The Linux bonding driver provides a method for aggregating multiple network      interfaces into a single logical "bonded" interface. The behavior of the @@ -30,7 +32,20 @@ class BondIf(VLANIf):      monitoring may be performed.      """ -    _sysfs_set = {**VLANIf._sysfs_set, **{ +    default = { +        'type': 'bond', +    } +    definition = { +        **Interface.definition, +        ** { +            'section': 'bonding', +            'prefixes': ['bond', ], +            'broadcast': True, +            'bridgeable': True, +        }, +    } + +    _sysfs_set = {**Interface._sysfs_set, **{          'bond_hash_policy': {              'validate': lambda v: assert_list(v, ['layer2', 'layer2+3', 'layer3+4', 'encap2+3', 'encap3+4']),              'location': '/sys/class/net/{ifname}/bonding/xmit_hash_policy', @@ -63,16 +78,12 @@ class BondIf(VLANIf):          },      }} -    _sysfs_get = {**VLANIf._sysfs_get, **{ +    _sysfs_get = {**Interface._sysfs_get, **{          'bond_arp_ip_target': {              'location': '/sys/class/net/{ifname}/bonding/arp_ip_target',          }      }} -    default = { -        'type': 'bond', -    } -      def remove(self):          """          Remove interface from operating system. Removing the interface diff --git a/python/vyos/ifconfig/bridge.py b/python/vyos/ifconfig/bridge.py index 90c44af13..94b0075d8 100644 --- a/python/vyos/ifconfig/bridge.py +++ b/python/vyos/ifconfig/bridge.py @@ -18,6 +18,8 @@ from vyos.ifconfig.interface import Interface  from vyos.validate import * + +@Interface.register  class BridgeIf(Interface):      """      A bridge is a way to connect two Ethernet segments together in a protocol @@ -28,6 +30,18 @@ class BridgeIf(Interface):      The Linux bridge code implements a subset of the ANSI/IEEE 802.1d standard.      """ +    default = { +        'type': 'bridge', +    } +    definition = { +        **Interface.definition, +        **{ +            'section': 'bridge', +            'prefixes': ['br', ], +            'broadcast': True, +        }, +    } +      _sysfs_set = {**Interface._sysfs_set, **{          'ageing_time': {              'validate': assert_positive, @@ -72,9 +86,6 @@ class BridgeIf(Interface):          },      }} -    default = { -        'type': 'bridge', -    }      def set_ageing_time(self, time):          """ diff --git a/python/vyos/ifconfig/control.py b/python/vyos/ifconfig/control.py index 89deba40a..28adc80d1 100644 --- a/python/vyos/ifconfig/control.py +++ b/python/vyos/ifconfig/control.py @@ -17,8 +17,10 @@  import os  from subprocess import Popen, PIPE, STDOUT +from vyos.ifconfig.register import Register -class Control: + +class Control(Register):      _command_get = {}      _command_set = {} diff --git a/python/vyos/ifconfig/dhcp.py b/python/vyos/ifconfig/dhcp.py new file mode 100644 index 000000000..8d3653433 --- /dev/null +++ b/python/vyos/ifconfig/dhcp.py @@ -0,0 +1,266 @@ +# Copyright 2020 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/>. + +import os +import jinja2 + +from vyos.ifconfig.control import Control + +template_v4 = """ +# generated by ifconfig.py +option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; +timeout 60; +retry 300; + +interface "{{ intf }}" { +    send host-name "{{ hostname }}"; +    {% if client_id -%} +    send dhcp-client-identifier "{{ client_id }}"; +    {% endif -%} +    {% if vendor_class_id -%} +    send vendor-class-identifier "{{ vendor_class_id }}"; +    {% endif -%} +    request subnet-mask, broadcast-address, routers, domain-name-servers, +        rfc3442-classless-static-routes, domain-name, interface-mtu; +    require subnet-mask; +} + +""" + +template_v6 = """ +# generated by ifconfig.py +interface "{{ intf }}" { +    request routers, domain-name-servers, domain-name; +} + +""" + +class DHCP (Control): +    client_base = r'/var/lib/dhcp/dhclient_' + +    def __init__ (self, ifname): +        # per interface DHCP config files +        self._dhcp = { +            4: { +                'ifname': ifname, +                'conf': self.client_base + ifname + '.conf', +                'pid':  self.client_base + ifname + '.pid', +                'lease': self.client_base + ifname + '.leases', +                'options': { +                    'intf': ifname, +                    'hostname': '', +                    'client_id': '', +                    'vendor_class_id': '' +                }, +            }, +            6: { +                'ifname': ifname, +                'conf': self.client_base + ifname + '.v6conf', +                'pid':  self.client_base + ifname + '.v6pid', +                'lease': self.client_base + ifname + '.v6leases', +                'accept_ra': f'/proc/sys/net/ipv6/conf/{ifname}/accept_ra', +                'options': { +                    'intf': ifname, +                    'dhcpv6_prm_only': False, +                    'dhcpv6_temporary': False +                }, +            }, +        } + +    def get_dhcp_options(self): +        """ +        Return dictionary with supported DHCP options. + +        Dictionary should be altered and send back via set_dhcp_options() +        so those options are applied when DHCP is run. +        """ +        return self._dhcp[4]['options'] + +    def set_dhcp_options(self, options): +        """ +        Store new DHCP options used by next run of DHCP client. +        """ +        self._dhcp[4]['options'] = options + +    def get_dhcpv6_options(self): +        """ +        Return dictionary with supported DHCPv6 options. + +        Dictionary should be altered and send back via set_dhcp_options() +        so those options are applied when DHCP is run. +        """ +        return self._dhcp[6]['options'] + +    def set_dhcpv6_options(self, options): +        """ +        Store new DHCP options used by next run of DHCP client. +        """ +        self._dhcp[6]['options'] = options + +    # replace dhcpv4/v6 with systemd.networkd? +    def _set_dhcp(self): +        """ +        Configure interface as DHCP client. The dhclient binary is automatically +        started in background! + +        Example: + +        >>> from vyos.ifconfig import Interface +        >>> j = Interface('eth0') +        >>> j.set_dhcp() +        """ + +        dhcp = self.get_dhcp_options() +        if not dhcp['hostname']: +            # read configured system hostname. +            # maybe change to vyos hostd client ??? +            with open('/etc/hostname', 'r') as f: +                dhcp['hostname'] = f.read().rstrip('\n') + +        # render DHCP configuration +        tmpl = jinja2.Template(template_v4) +        dhcp_text = tmpl.render(dhcp) +        with open(self._dhcp[4]['conf'], 'w') as f: +            f.write(dhcp_text) + +        cmd = 'start-stop-daemon' +        cmd += ' --start' +        cmd += ' --oknodo' +        cmd += ' --quiet' +        cmd += ' --pidfile {pid}' +        cmd += ' --exec /sbin/dhclient' +        cmd += ' --' +        # now pass arguments to dhclient binary +        cmd += ' -4 -nw -cf {conf} -pf {pid} -lf {lease} {ifname}' +        return self._cmd(cmd.format(**self._dhcp[4])) + +    def _del_dhcp(self): +        """ +        De-configure interface as DHCP clinet. All auto generated files like +        pid, config and lease will be removed. + +        Example: + +        >>> from vyos.ifconfig import Interface +        >>> j = Interface('eth0') +        >>> j.del_dhcp() +        """ +        if not os.path.isfile(self._dhcp[4]['pid']): +            self._debug_msg('No DHCP client PID found') +            return None + +		# with open(self._dhcp[4]['pid'], 'r') as f: +		# 	pid = int(f.read()) + +        # stop dhclient, we need to call dhclient and tell it should release the +        # aquired IP address. tcpdump tells me: +        # 172.16.35.103.68 > 172.16.35.254.67: [bad udp cksum 0xa0cb -> 0xb943!] BOOTP/DHCP, Request from 00:50:56:9d:11:df, length 300, xid 0x620e6946, Flags [none] (0x0000) +        #  Client-IP 172.16.35.103 +        #  Client-Ethernet-Address 00:50:56:9d:11:df +        #  Vendor-rfc1048 Extensions +        #    Magic Cookie 0x63825363 +        #    DHCP-Message Option 53, length 1: Release +        #    Server-ID Option 54, length 4: 172.16.35.254 +        #    Hostname Option 12, length 10: "vyos" +        # +        cmd = '/sbin/dhclient -cf {conf} -pf {pid} -lf {lease} -r {ifname}' +        self._cmd(cmd.format(**self._dhcp[4])) + +        # cleanup old config files +        for name in ('conf', 'pid', 'lease'): +            if os.path.isfile(self._dhcp[4][name]): +                os.remove(self._dhcp[4][name]) + +    def _set_dhcpv6(self): +        """ +        Configure interface as DHCPv6 client. The dhclient binary is automatically +        started in background! + +        Example: + +        >>> from vyos.ifconfig import Interface +        >>> j = Interface('eth0') +        >>> j.set_dhcpv6() +        """ +        dhcpv6 = self.get_dhcpv6_options() + +        # better save then sorry .. should be checked in interface script +        # but if you missed it we are safe! +        if dhcpv6['dhcpv6_prm_only'] and dhcpv6['dhcpv6_temporary']: +            raise Exception( +                'DHCPv6 temporary and parameters-only options are mutually exclusive!') + +        # render DHCP configuration +        tmpl = jinja2.Template(template_v6) +        dhcpv6_text = tmpl.render(dhcpv6) +        with open(self._dhcp[6]['conf'], 'w') as f: +            f.write(dhcpv6_text) + +        # no longer accept router announcements on this interface +        self._write_sysfs(self._dhcp[6]['accept_ra'], 0) + +        # assemble command-line to start DHCPv6 client (dhclient) +        cmd = 'start-stop-daemon' +        cmd += ' --start' +        cmd += ' --oknodo' +        cmd += ' --quiet' +        cmd += ' --pidfile {pid}' +        cmd += ' --exec /sbin/dhclient' +        cmd += ' --' +        # now pass arguments to dhclient binary +        cmd += ' -6 -nw -cf {conf} -pf {pid} -lf {lease}' +        # add optional arguments +        if dhcpv6['dhcpv6_prm_only']: +            cmd += ' -S' +        if dhcpv6['dhcpv6_temporary']: +            cmd += ' -T' +        cmd += ' {ifname}' + +        return self._cmd(cmd.format(**self._dhcp[6])) + +    def _del_dhcpv6(self): +        """ +        De-configure interface as DHCPv6 clinet. All auto generated files like +        pid, config and lease will be removed. + +        Example: + +        >>> from vyos.ifconfig import Interface +        >>> j = Interface('eth0') +        >>> j.del_dhcpv6() +        """ +        if not os.path.isfile(self._dhcp[6]['pid']): +            self._debug_msg('No DHCPv6 client PID found') +            return None + +		# with open(self._dhcp[6]['pid'], 'r') as f: +		# 	pid = int(f.read()) + +        # stop dhclient +        cmd = 'start-stop-daemon' +        cmd += ' --start' +        cmd += ' --oknodo' +        cmd += ' --quiet' +        cmd += ' --pidfile {pid}' +        self._cmd(cmd.format(**self._dhcp[6])) + +        # accept router announcements on this interface +        self._write_sysfs(self._dhcp[6]['accept_ra'], 1) + +        # cleanup old config files +        for name in ('conf', 'pid', 'lease'): +            if os.path.isfile(self._dhcp[6][name]): +                os.remove(self._dhcp[6][name]) + diff --git a/python/vyos/ifconfig/dummy.py b/python/vyos/ifconfig/dummy.py index 58b89fe68..404c490c7 100644 --- a/python/vyos/ifconfig/dummy.py +++ b/python/vyos/ifconfig/dummy.py @@ -17,6 +17,7 @@  from vyos.ifconfig.interface import Interface +@Interface.register  class DummyIf(Interface):      """      A dummy interface is entirely virtual like, for example, the loopback @@ -27,3 +28,10 @@ class DummyIf(Interface):      default = {          'type': 'dummy',      } +    definition = { +        **Interface.definition, +        **{ +            'section': 'dummy', +            'prefixes': ['dum', ], +        }, +    } diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py index dbd618d32..b3e652409 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -16,17 +16,35 @@  import os  import re -from vyos.ifconfig.vlan import VLANIf +from vyos.ifconfig.interface import Interface +from vyos.ifconfig.vlan import VLAN  from vyos.validate import * -class EthernetIf(VLANIf): +@Interface.register +@VLAN.enable +class EthernetIf(Interface):      """      Abstraction of a Linux Ethernet Interface      """ -    _command_set = {**VLANIf._command_set, **{ +    default = { +        'type': 'ethernet', +    } +    definition = { +        **Interface.definition, +        **{ +            'section': 'ethernet', +            'prefixes': ['lan', 'eth', 'eno', 'ens', 'enp', 'enx'], +            'bondable': True, +            'broadcast': True, +            'bridgeable': True, +        } +    } + + +    _command_set = {**Interface._command_set, **{          'gro': {              'validate': lambda v: assert_list(v, ['on', 'off']),              'shellcmd': '/sbin/ethtool -K {ifname} gro {value}', @@ -49,10 +67,6 @@ class EthernetIf(VLANIf):          },      }} -    default = { -        'type': 'ethernet', -    } -      def _delete(self):          # Ethernet interfaces can not be removed          pass diff --git a/python/vyos/ifconfig/geneve.py b/python/vyos/ifconfig/geneve.py index a3b3a4c4a..f27786417 100644 --- a/python/vyos/ifconfig/geneve.py +++ b/python/vyos/ifconfig/geneve.py @@ -18,6 +18,7 @@ from copy import deepcopy  from vyos.ifconfig.interface import Interface +@Interface.register  class GeneveIf(Interface):      """      Geneve: Generic Network Virtualization Encapsulation @@ -34,6 +35,14 @@ class GeneveIf(Interface):          'vni': 0,          'remote': '',      } +    definition = { +        **Interface.definition, +        **{ +            'section': 'geneve', +            'prefixes': ['gnv', ], +            'bridgeable': True, +        } +    }      def _create(self):          cmd = 'ip link add name {ifname} type geneve id {vni} remote {remote}'.format(**self.config) diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 4f72271c9..f2b43fd35 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -15,14 +15,11 @@  import os  import re -import jinja2  import json  import glob  import time  from copy import deepcopy -import vyos.interfaces -  from vyos.validate import *     # should not * include  from vyos.config import Config  # not used anymore  from vyos import ConfigError @@ -35,46 +32,22 @@ from tabulate import tabulate  from hurry.filesize import size,alternative  from datetime import timedelta -from vyos.ifconfig.control import Control - -dhclient_base = r'/var/lib/dhcp/dhclient_' -dhcp_cfg = """ -# generated by ifconfig.py -option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; -timeout 60; -retry 300; - -interface "{{ intf }}" { -    send host-name "{{ hostname }}"; -    {% if client_id -%} -    send dhcp-client-identifier "{{ client_id }}"; -    {% endif -%} -    {% if vendor_class_id -%} -    send vendor-class-identifier "{{ vendor_class_id }}"; -    {% endif -%} -    request subnet-mask, broadcast-address, routers, domain-name-servers, -        rfc3442-classless-static-routes, domain-name, interface-mtu; -    require subnet-mask; -} - -""" - -dhcpv6_cfg = """ -# generated by ifconfig.py -interface "{{ intf }}" { -    request routers, domain-name-servers, domain-name; -} +from vyos.ifconfig.dhcp import DHCP -""" - - - -class Interface(Control): +class Interface(DHCP):      options = []      required = []      default = {          'type': '',      } +    definition = { +        'section': '', +        'prefixes': [], +        'vlan': False, +        'bondable': False, +        'broadcast': False, +        'bridgeable':  False, +    }      _command_set = {          'state': { @@ -165,6 +138,8 @@ class Interface(Control):          >>> i = Interface('eth0')          """ +        DHCP.__init__(self, ifname) +          self.config = deepcopy(self.default)          self.config['ifname'] = ifname @@ -183,31 +158,6 @@ class Interface(Control):              self._create() -        # per interface DHCP config files -        self._dhcp_cfg_file = dhclient_base + self.config['ifname'] + '.conf' -        self._dhcp_pid_file = dhclient_base + self.config['ifname'] + '.pid' -        self._dhcp_lease_file = dhclient_base + self.config['ifname'] + '.leases' - -        # per interface DHCPv6 config files -        self._dhcpv6_cfg_file = dhclient_base + self.config['ifname'] + '.v6conf' -        self._dhcpv6_pid_file = dhclient_base + self.config['ifname'] + '.v6pid' -        self._dhcpv6_lease_file = dhclient_base + self.config['ifname'] + '.v6leases' - -        # DHCP options -        self._dhcp_options = { -            'intf' : self.config['ifname'], -            'hostname' : '', -            'client_id' : '', -            'vendor_class_id' : '' -        } - -        # DHCPv6 options -        self._dhcpv6_options = { -            'intf' : self.config['ifname'], -            'dhcpv6_prm_only' : False, -            'dhcpv6_temporary' : False -        } -          # list of assigned IP addresses          self._addr = [] @@ -623,214 +573,6 @@ class Interface(Control):                  cmd = 'ip addr del "{}" dev "{}"'.format(addr, self.config['ifname'])                  return self._cmd(cmd) - -    def get_dhcp_options(self): -        """ -        Return dictionary with supported DHCP options. - -        Dictionary should be altered and send back via set_dhcp_options() -        so those options are applied when DHCP is run. -        """ -        return self._dhcp_options - -    def set_dhcp_options(self, options): -        """ -        Store new DHCP options used by next run of DHCP client. -        """ -        self._dhcp_options = options - -    def get_dhcpv6_options(self): -        """ -        Return dictionary with supported DHCPv6 options. - -        Dictionary should be altered and send back via set_dhcp_options() -        so those options are applied when DHCP is run. -        """ -        return self._dhcpv6_options - -    def set_dhcpv6_options(self, options): -        """ -        Store new DHCP options used by next run of DHCP client. -        """ -        self._dhcpv6_options = options - -    # replace dhcpv4/v6 with systemd.networkd? -    def _set_dhcp(self): -        """ -        Configure interface as DHCP client. The dhclient binary is automatically -        started in background! - -        Example: - -        >>> from vyos.ifconfig import Interface -        >>> j = Interface('eth0') -        >>> j.set_dhcp() -        """ - -        dhcp = self.get_dhcp_options() -        if not dhcp['hostname']: -            # read configured system hostname. -            # maybe change to vyos hostd client ??? -            with open('/etc/hostname', 'r') as f: -                dhcp['hostname'] = f.read().rstrip('\n') - -        # render DHCP configuration -        tmpl = jinja2.Template(dhcp_cfg) -        dhcp_text = tmpl.render(dhcp) -        with open(self._dhcp_cfg_file, 'w') as f: -            f.write(dhcp_text) - -        cmd = 'start-stop-daemon' -        cmd += ' --start ' -        cmd += ' --quiet' -        cmd += ' --oknodo' -        cmd += ' --pidfile ' + self._dhcp_pid_file -        cmd += ' --exec /sbin/dhclient --' -        # now pass arguments to dhclient binary -        cmd += ' -4 -nw -cf {} -pf {} -lf {} {}'.format( -            self._dhcp_cfg_file, self._dhcp_pid_file, self._dhcp_lease_file, self.config['ifname']) -        return self._cmd(cmd) - - -    def _del_dhcp(self): -        """ -        De-configure interface as DHCP clinet. All auto generated files like -        pid, config and lease will be removed. - -        Example: - -        >>> from vyos.ifconfig import Interface -        >>> j = Interface('eth0') -        >>> j.del_dhcp() -        """ -        pid = 0 -        if os.path.isfile(self._dhcp_pid_file): -            with open(self._dhcp_pid_file, 'r') as f: -                pid = int(f.read()) -        else: -            self._debug_msg('No DHCP client PID found') -            return None - -        # stop dhclient, we need to call dhclient and tell it should release the -        # aquired IP address. tcpdump tells me: -        # 172.16.35.103.68 > 172.16.35.254.67: [bad udp cksum 0xa0cb -> 0xb943!] BOOTP/DHCP, Request from 00:50:56:9d:11:df, length 300, xid 0x620e6946, Flags [none] (0x0000) -        #  Client-IP 172.16.35.103 -        #  Client-Ethernet-Address 00:50:56:9d:11:df -        #  Vendor-rfc1048 Extensions -        #    Magic Cookie 0x63825363 -        #    DHCP-Message Option 53, length 1: Release -        #    Server-ID Option 54, length 4: 172.16.35.254 -        #    Hostname Option 12, length 10: "vyos" -        # -        cmd = '/sbin/dhclient -cf {} -pf {} -lf {} -r {}'.format( -                self._dhcp_cfg_file, self._dhcp_pid_file, self._dhcp_lease_file, self.config['ifname']) -        self._cmd(cmd) - -        # cleanup old config file -        if os.path.isfile(self._dhcp_cfg_file): -            os.remove(self._dhcp_cfg_file) - -        # cleanup old pid file -        if os.path.isfile(self._dhcp_pid_file): -            os.remove(self._dhcp_pid_file) - -        # cleanup old lease file -        if os.path.isfile(self._dhcp_lease_file): -            os.remove(self._dhcp_lease_file) - - -    def _set_dhcpv6(self): -        """ -        Configure interface as DHCPv6 client. The dhclient binary is automatically -        started in background! - -        Example: - -        >>> from vyos.ifconfig import Interface -        >>> j = Interface('eth0') -        >>> j.set_dhcpv6() -        """ -        dhcpv6 = self.get_dhcpv6_options() - -        # better save then sorry .. should be checked in interface script -        # but if you missed it we are safe! -        if dhcpv6['dhcpv6_prm_only'] and dhcpv6['dhcpv6_temporary']: -            raise Exception('DHCPv6 temporary and parameters-only options are mutually exclusive!') - -        # render DHCP configuration -        tmpl = jinja2.Template(dhcpv6_cfg) -        dhcpv6_text = tmpl.render(dhcpv6) -        with open(self._dhcpv6_cfg_file, 'w') as f: -            f.write(dhcpv6_text) - -        # no longer accept router announcements on this interface -        self._write_sysfs('/proc/sys/net/ipv6/conf/{}/accept_ra' -              .format(self.config['ifname']), 0) - -        # assemble command-line to start DHCPv6 client (dhclient) -        cmd = 'start-stop-daemon' -        cmd += ' --start ' -        cmd += ' --quiet' -        cmd += ' --oknodo' -        cmd += ' --pidfile ' + self._dhcpv6_pid_file -        cmd += ' --exec /sbin/dhclient --' -        # now pass arguments to dhclient binary -        cmd += ' -6 -nw -cf {} -pf {} -lf {}'.format( -            self._dhcpv6_cfg_file, self._dhcpv6_pid_file, self._dhcpv6_lease_file) - -        # add optional arguments -        if dhcpv6['dhcpv6_prm_only']: -            cmd += ' -S' -        if dhcpv6['dhcpv6_temporary']: -            cmd += ' -T' - -        cmd += ' {}'.format(self.config['ifname']) -        return self._cmd(cmd) - - -    def _del_dhcpv6(self): -        """ -        De-configure interface as DHCPv6 clinet. All auto generated files like -        pid, config and lease will be removed. - -        Example: - -        >>> from vyos.ifconfig import Interface -        >>> j = Interface('eth0') -        >>> j.del_dhcpv6() -        """ -        pid = 0 -        if os.path.isfile(self._dhcpv6_pid_file): -            with open(self._dhcpv6_pid_file, 'r') as f: -                pid = int(f.read()) -        else: -            self._debug_msg('No DHCPv6 client PID found') -            return None - -        # stop dhclient -        cmd = 'start-stop-daemon' -        cmd += ' --stop' -        cmd += ' --oknodo' -        cmd += ' --quiet' -        cmd += ' --pidfile ' + self._dhcpv6_pid_file -        self._cmd(cmd) - -        # accept router announcements on this interface -        self._write_sysfs('/proc/sys/net/ipv6/conf/{}/accept_ra' -              .format(self.config['ifname']), 1) - -        # cleanup old config file -        if os.path.isfile(self._dhcpv6_cfg_file): -            os.remove(self._dhcpv6_cfg_file) - -        # cleanup old pid file -        if os.path.isfile(self._dhcpv6_pid_file): -            os.remove(self._dhcpv6_pid_file) - -        # cleanup old lease file -        if os.path.isfile(self._dhcpv6_lease_file): -            os.remove(self._dhcpv6_lease_file) -      def op_show_interface_stats(self):          stats = self.get_interface_stats()          rx = [['bytes','packets','errors','dropped','overrun','mcast'],[stats['rx_bytes'],stats['rx_packets'],stats['rx_errors'],stats['rx_dropped'],stats['rx_over_errors'],stats['multicast']]] diff --git a/python/vyos/ifconfig/l2tpv3.py b/python/vyos/ifconfig/l2tpv3.py index a87535277..fbfab4c6e 100644 --- a/python/vyos/ifconfig/l2tpv3.py +++ b/python/vyos/ifconfig/l2tpv3.py @@ -19,6 +19,7 @@ import os  from vyos.ifconfig.interface import Interface +@Interface.register  class L2TPv3If(Interface):      """      The Linux bonding driver provides a method for aggregating multiple network @@ -28,12 +29,19 @@ class L2TPv3If(Interface):      monitoring may be performed.      """ -    options = Interface.options + \ -        ['tunnel_id', 'peer_tunnel_id', 'local_port', 'remote_port', -            'encapsulation', 'local_address', 'remote_address']      default = {          'type': 'l2tp',      } +    definition = { +        **Interface.definition, +        **{ +            'section': 'l2tpeth', +            'prefixes': ['l2tpeth', ], +            'bridgeable': True, +        } +    } +    options = Interface.options + \ +        ['tunnel_id', 'peer_tunnel_id', 'local_port', 'remote_port', 'encapsulation', 'local_address', 'remote_address']      def _create(self):          # create tunnel interface diff --git a/python/vyos/ifconfig/loopback.py b/python/vyos/ifconfig/loopback.py index 37b8e9e3b..8e4438662 100644 --- a/python/vyos/ifconfig/loopback.py +++ b/python/vyos/ifconfig/loopback.py @@ -17,6 +17,7 @@  from vyos.ifconfig.interface import Interface +@Interface.register  class LoopbackIf(Interface):      """      The loopback device is a special, virtual network interface that your router @@ -26,6 +27,16 @@ class LoopbackIf(Interface):      default = {          'type': 'loopback',      } +    definition = { +        **Interface.definition, +        **{ +            'section': 'loopback', +            'prefixes': ['lo', ], +            'bridgeable': True, +        } +    } + +    name = 'loopback'      def remove(self):          """ diff --git a/python/vyos/ifconfig/macvlan.py b/python/vyos/ifconfig/macvlan.py index da3beea8b..4e4b563a1 100644 --- a/python/vyos/ifconfig/macvlan.py +++ b/python/vyos/ifconfig/macvlan.py @@ -14,18 +14,28 @@  # License along with this library.  If not, see <http://www.gnu.org/licenses/>. -from vyos.ifconfig.vlan import VLANIf +from vyos.ifconfig.interface import Interface +from vyos.ifconfig.vlan import VLAN -class MACVLANIf(VLANIf): +@Interface.register +@VLAN.enable +class MACVLANIf(Interface):      """      Abstraction of a Linux MACvlan interface      """ -    options = VLANIf.options + ['link', 'mode']      default = {          'type': 'macvlan',      } +    definition = { +        **Interface.definition, +        **{ +            'section': 'pseudo-ethernet', +            'prefixes': ['peth', ], +        }, +    } +    options = Interface.options + ['link', 'mode']      def _create(self):          cmd = 'ip link add {ifname} link {link} type macvlan mode {mode}'.format( diff --git a/python/vyos/ifconfig/pppoe.py b/python/vyos/ifconfig/pppoe.py new file mode 100644 index 000000000..7504408cf --- /dev/null +++ b/python/vyos/ifconfig/pppoe.py @@ -0,0 +1,33 @@ +# Copyright 2020 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/>. + + +from vyos.ifconfig.interface import Interface + + +@Interface.register +class PPPoEIf(Interface): +    default = { +        'type': 'pppoe', +    } +    definition = { +        **Interface.definition, +        **{ +            'section': 'pppoe', +            'prefixes': ['pppoe', ], +        }, +    } + +    # The _create and _delete need to be moved from interface-ppoe to here diff --git a/python/vyos/ifconfig/register.py b/python/vyos/ifconfig/register.py new file mode 100644 index 000000000..2d4b0d4c0 --- /dev/null +++ b/python/vyos/ifconfig/register.py @@ -0,0 +1,96 @@ +# Copyright 2020 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/>. + +import netifaces + + +class Register: +    # the known interface prefixes +    _prefixes = {} + +    # class need to define: definition['prefixes'] +    # the interface prefixes declared by a class used to name interface with +    # prefix[0-9]*(\.[0-9]+)?(\.[0-9]+)?, such as lo, eth0 or eth0.1.2 + +    @classmethod +    def register(cls, klass): +        if not klass.definition.get('prefixes',[]): +            raise RuntimeError(f'valid interface prefixes not defined for {klass.__name__}') + +        for ifprefix in klass.definition['prefixes']: +            if ifprefix in cls._prefixes: +                raise RuntimeError(f'only one class can be registered for prefix "{ifprefix}" type') +            cls._prefixes[ifprefix] = klass + +        return klass + +    @classmethod +    def _basename (cls, name, vlan): +        # remove number from interface name +        name = name.rstrip('0123456789') +        name = name.rstrip('.') +        if vlan: +            name = name.rstrip('0123456789') +        return name + +    @classmethod +    def section(cls, name, vlan=True): +        # return the name of a section an interface should be under +        name = cls._basename(name, vlan) + +        # XXX: To leave as long as vti and input are not moved to vyos +        if name == 'vti': +            return 'vti' +        if name == 'ifb': +            return 'input' + +        if name in cls._prefixes: +            return cls._prefixes[name].defintion['section'] +        return '' +  +    @classmethod +    def klass(cls, name, vlan=True): +        name = cls._basename(name, vlan) +        if name in cls._prefixes: +            return cls._prefixes[name] +        raise ValueError(f'No type found for interface name: {name}') + +    @classmethod +    def _listing (cls): +        interfaces = netifaces.interfaces() + +        for ifname in interfaces: +            if '@' in ifname: +                # Tunnels: sit0@NONE, gre0@NONE, gretap0@NONE, erspan0@NONE, tunl0@NONE, ip6tnl0@NONE, ip6gre0@NONE +                continue + +            # XXX: Temporary hack as vti and input are not yet moved from vyatta to vyos +            if ifname.startswith('vti') or ifname.startswith('input'): +                yield ifname +                continue + +            if not cls.section(ifname): +                continue +            yield ifname + +    @classmethod +    def listing(cls, section=''): +        if not section: +            return list(cls._listing()) +        return [_ for _ in cls._listing() if cls._basename(_,False) in self.prefixes] + + +# XXX: TODO - limit name for VRF interfaces + diff --git a/python/vyos/ifconfig/stp.py b/python/vyos/ifconfig/stp.py index 741322d0d..97a3c1ff3 100644 --- a/python/vyos/ifconfig/stp.py +++ b/python/vyos/ifconfig/stp.py @@ -19,12 +19,20 @@ from vyos.ifconfig.interface import Interface  from vyos.validate import * -class STPIf(Interface): +class STP:      """      A spanning-tree capable interface. This applies only to bridge port member      interfaces!      """ -    _sysfs_set = {**Interface._sysfs_set, **{ + +    @classmethod +    def enable (cls, adaptee): +        adaptee._sysfs_set = {**adaptee._sysfs_set, **cls._sysfs_set} +        adaptee.set_path_cost = cls.set_path_cost +        adaptee.set_path_priority = cls.set_path_priority +        return adaptee + +    _sysfs_set = {          'path_cost': {              # XXX: we should set a maximum              'validate': assert_positive, @@ -37,15 +45,8 @@ class STPIf(Interface):              'location': '/sys/class/net/{ifname}/brport/priority',              'errormsg': '{ifname} is not a bridge port member'          }, -    }} - -    default = { -        'type': 'stp',      } -    def __init__(self, ifname, **kargs): -        super().__init__(ifname, **kargs) -      def set_path_cost(self, cost):          """          Set interface path cost, only relevant for STP enabled interfaces diff --git a/python/vyos/ifconfig/tunnel.py b/python/vyos/ifconfig/tunnel.py index c82727eee..a49bdd51c 100644 --- a/python/vyos/ifconfig/tunnel.py +++ b/python/vyos/ifconfig/tunnel.py @@ -38,6 +38,14 @@ class _Tunnel(Interface):      https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/tunnel.c      https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/ip6tunnel.c      """ +    definition = { +        **Interface.definition, +        **{ +            'section': 'tunnel', +            'prefixes': ['tun',], +            'bridgeable': True, +        }, +    }      # TODO: This is surely used for more than tunnels      # TODO: could be refactored elsewhere diff --git a/python/vyos/ifconfig/vlan.py b/python/vyos/ifconfig/vlan.py index 4e0db83c7..7b1e00d87 100644 --- a/python/vyos/ifconfig/vlan.py +++ b/python/vyos/ifconfig/vlan.py @@ -20,15 +20,23 @@ import re  from vyos.ifconfig.interface import Interface -class VLANIf(Interface): +# This is an internal implementation class +class VLAN:      """      This class handels the creation and removal of a VLAN interface. It serves      as base class for BondIf and EthernetIf.      """ -    default = { -        'type': 'vlan', -    } +    _novlan_remove = lambda : None + +    @classmethod +    def enable (cls,adaptee): +        adaptee._novlan_remove = adaptee.remove +        adaptee.remove = cls.remove +        adaptee.add_vlan = cls.add_vlan +        adaptee.del_vlan = cls.del_vlan +        adaptee.definition['vlan'] = True +        return adaptee      def remove(self):          """ @@ -41,13 +49,15 @@ class VLANIf(Interface):          >>> i = Interface('eth0')          >>> i.remove()          """ +        ifname = self.config['ifname'] +          # 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.config['ifname'] + r'(?:\.\d+)(?:\.\d+)', f)] +                    if re.match(ifname + r'(?:\.\d+)(?:\.\d+)', f)]          for vlan in vlan_ifs:              Interface(vlan).remove() @@ -56,13 +66,14 @@ class VLANIf(Interface):          # 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.config['ifname'] + r'(?:\.\d+)', f)] +                    if re.match(ifname + r'(?:\.\d+)', f)]          for vlan in vlan_ifs: -            Interface(vlan).remove() +            # self.__class__ is already VLAN.enabled +            self.__class__(vlan)._novlan_remove()          # All subinterfaces are now removed, continue on the physical interface -        super().remove() +        self._novlan_remove()      def add_vlan(self, vlan_id, ethertype='', ingress_qos='', egress_qos=''):          """ @@ -85,12 +96,12 @@ class VLANIf(Interface):                              to VLAN header prio field but for outgoing frames.          Example: -        >>> from vyos.ifconfig import VLANIf -        >>> i = VLANIf('eth0') +        >>> from vyos.ifconfig import MACVLANIf +        >>> i = MACVLANIf('eth0')          >>> i.add_vlan(10)          """          vlan_ifname = self.config['ifname'] + '.' + str(vlan_id) -        if not os.path.exists('/sys/class/net/{}'.format(vlan_ifname)): +        if not os.path.exists(f'/sys/class/net/{vlan_ifname}'):              self._vlan_id = int(vlan_id)              if ethertype: @@ -114,7 +125,7 @@ class VLANIf(Interface):          # return new object mapping to the newly created interface          # we can now work on this object for e.g. IP address setting          # or interface description and so on -        return VLANIf(vlan_ifname) +        return self.__class__(vlan_ifname)      def del_vlan(self, vlan_id):          """ @@ -123,9 +134,9 @@ class VLANIf(Interface):          client processes.          Example: -        >>> from vyos.ifconfig import VLANIf -        >>> i = VLANIf('eth0.10') +        >>> from vyos.ifconfig import MACVLANIf +        >>> i = MACVLANIf('eth0.10')          >>> i.del_vlan()          """ -        vlan_ifname = self.config['ifname'] + '.' + str(vlan_id) -        VLANIf(vlan_ifname).remove() +        ifname = self.config['ifname'] +        self.__class__(f'{ifname}.{vlan_id}')._novlan_remove() diff --git a/python/vyos/ifconfig/vtun.py b/python/vyos/ifconfig/vtun.py new file mode 100644 index 000000000..07d39fcbb --- /dev/null +++ b/python/vyos/ifconfig/vtun.py @@ -0,0 +1,34 @@ +# Copyright 2020 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/>. + + +from vyos.ifconfig.interface import Interface + + +@Interface.register +class VTunIf(Interface): +    default = { +        'type': 'vtun', +    } +    definition = { +        **Interface.definition, +        **{ +            'section': 'openvpn', +            'prefixes': ['vtun', ], +            'bridgeable': True, +        }, +    } + +    # The _create and _delete need to be moved from interface-ppoe to here diff --git a/python/vyos/ifconfig/vxlan.py b/python/vyos/ifconfig/vxlan.py index 75cdf8957..5678ad62e 100644 --- a/python/vyos/ifconfig/vxlan.py +++ b/python/vyos/ifconfig/vxlan.py @@ -19,6 +19,7 @@ from vyos import ConfigError  from vyos.ifconfig.interface import Interface +@Interface.register  class VXLANIf(Interface):      """      The VXLAN protocol is a tunnelling protocol designed to solve the @@ -40,14 +41,6 @@ class VXLANIf(Interface):      https://www.kernel.org/doc/Documentation/networking/vxlan.txt      """ -    options = ['group', 'remote', 'dev', 'port', 'vni'] - -    mapping = { -        'ifname': 'add', -        'vni':    'id', -        'port':   'dstport', -    } -      default = {          'type': 'vxlan',          'vni': 0, @@ -57,6 +50,21 @@ class VXLANIf(Interface):          'port': 8472,   # The Linux implementation of VXLAN pre-dates                          # the IANA's selection of a standard destination port      } +    definition = { +        **Interface.definition, +        **{ +            'section': 'vxlan', +            'prefixes': ['vxlan', ], +            'bridgeable': True, +        } +    } +    options = ['group', 'remote', 'dev', 'port', 'vni'] + +    mapping = { +        'ifname': 'add', +        'vni':    'id', +        'port':   'dstport', +    }      def _create(self):          cmdline = set() diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py index 71ee67c98..8cf1ff58c 100644 --- a/python/vyos/ifconfig/wireguard.py +++ b/python/vyos/ifconfig/wireguard.py @@ -22,10 +22,8 @@ from datetime import timedelta  import time  from hurry.filesize import size,alternative +@Interface.register  class WireGuardIf(Interface): -    options = ['port', 'private-key', 'pubkey', 'psk', -               'allowed-ips', 'fwmark', 'endpoint', 'keepalive'] -      default = {          'type': 'wireguard',          'port': 0, @@ -37,6 +35,16 @@ class WireGuardIf(Interface):          'endpoint': None,          'keepalive': 0      } +    definition = { +        **Interface.definition, +        **{ +            'section': 'wireguard', +            'prefixes': ['wg', ], +            'bridgeable': True, +        } +    } +    options = ['port', 'private-key', 'pubkey', 'psk', +               'allowed-ips', 'fwmark', 'endpoint', 'keepalive']      """      Wireguard interface class, contains a comnfig dictionary since diff --git a/python/vyos/ifconfig/wireless.py b/python/vyos/ifconfig/wireless.py index 7f507ff6e..a1f50b71d 100644 --- a/python/vyos/ifconfig/wireless.py +++ b/python/vyos/ifconfig/wireless.py @@ -15,19 +15,30 @@  import os -from vyos.ifconfig.vlan import VLANIf +from vyos.ifconfig.interface import Interface +from vyos.ifconfig.vlan import VLAN -class WiFiIf(VLANIf): + +@Interface.register +@VLAN.enable +class WiFiIf(Interface):      """      Handle WIFI/WLAN interfaces.      """ -    options = ['phy', 'op_mode'] -      default = {          'type': 'wifi',          'phy': 'phy0'      } +    definition = { +        **Interface.definition, +        **{ +            'section': 'wireless', +            'prefixes': ['wlan', ], +            'bridgeable': True, +        } +    } +    options = ['phy', 'op_mode']      def _create(self):          # all interfaces will be added in monitor mode @@ -54,3 +65,15 @@ class WiFiIf(VLANIf):              'phy': 'phy0'          }          return config + + + +@Interface.register +class WiFiModemIf(WiFiIf): +    definition = { +        **WiFiIf.definition, +        **{ +            'section': 'wirelessmodem', +            'prefixes': ['wlm', ], +        } +    } diff --git a/python/vyos/ifconfig_vlan.py b/python/vyos/ifconfig_vlan.py index fe94a5af4..2b934cdfc 100644 --- a/python/vyos/ifconfig_vlan.py +++ b/python/vyos/ifconfig_vlan.py @@ -14,7 +14,6 @@  # License along with this library.  If not, see <http://www.gnu.org/licenses/>.  from netifaces import interfaces -from vyos.ifconfig import VLANIf  from vyos import ConfigError  def apply_vlan_config(vlan, config): @@ -23,7 +22,7 @@ def apply_vlan_config(vlan, config):      to a VLAN interface      """ -    if vlan.__class__ != VLANIf: +    if not vlan.definition['vlan']:          raise TypeError()      # get DHCP config dictionary and update values diff --git a/python/vyos/interfaces.py b/python/vyos/interfaces.py index 37c093aca..4697c0acc 100644 --- a/python/vyos/interfaces.py +++ b/python/vyos/interfaces.py @@ -16,44 +16,10 @@  import re  import json +from vyos.ifconfig import Interface  import subprocess  import netifaces -intf_type_data_file = '/usr/share/vyos/interface-types.json' - -def list_interfaces(): -    interfaces = netifaces.interfaces() - -    # Remove "fake" interfaces associated with drivers -    for i in ["dummy0", "ip6tnl0", "tunl0", "ip_vti0", "ip6_vti0"]: -        try: -            interfaces.remove(i) -        except ValueError: -            pass - -    return interfaces - -def list_interfaces_of_type(typ): -    with open(intf_type_data_file, 'r') as f: -        types_data = json.load(f) - -    all_intfs = list_interfaces() -    if not (typ in types_data.keys()): -        raise ValueError("Unknown interface type: {0}".format(typ)) -    else: -        r = re.compile('^{0}\d+'.format(types_data[typ])) -        return list(filter(lambda i: re.match(r, i), all_intfs)) - -def get_type_of_interface(intf): -    with open(intf_type_data_file, 'r') as f: -        types_data = json.load(f) - -    for key,val in types_data.items(): -        r = re.compile('^{0}\d+'.format(val)) -        if re.match(r, intf): -            return key - -    raise ValueError("No type found for interface name: {0}".format(intf))  def wireguard_dump():      """Dump wireguard data in a python friendly way.""" | 
