From e835aef3a0ebbc957abd38e54f8040f5b67157ce Mon Sep 17 00:00:00 2001 From: Thomas Mangin Date: Sat, 11 Apr 2020 14:27:57 +0100 Subject: ifconfig: T2223: rename Register to Section While the class does indeed all the registration, it work is really to map classes to interface section. ie: interface ethernet -> EthernetIf Therefore it can also list which interface are from which type, therefore the name change. Other function name will also be renamed as a consequence --- python/vyos/ifconfig/__init__.py | 1 + python/vyos/ifconfig/control.py | 4 +- python/vyos/ifconfig/register.py | 95 ---------------------------------------- python/vyos/ifconfig/section.py | 95 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+), 97 deletions(-) delete mode 100644 python/vyos/ifconfig/register.py create mode 100644 python/vyos/ifconfig/section.py (limited to 'python/vyos') diff --git a/python/vyos/ifconfig/__init__.py b/python/vyos/ifconfig/__init__.py index 1f9956af0..cd1696ca1 100644 --- a/python/vyos/ifconfig/__init__.py +++ b/python/vyos/ifconfig/__init__.py @@ -14,6 +14,7 @@ # License along with this library. If not, see . +from vyos.ifconfig.section import Section from vyos.ifconfig.interface import Interface from vyos.ifconfig.bond import BondIf diff --git a/python/vyos/ifconfig/control.py b/python/vyos/ifconfig/control.py index c7a2fa2d6..464cd585e 100644 --- a/python/vyos/ifconfig/control.py +++ b/python/vyos/ifconfig/control.py @@ -18,10 +18,10 @@ import os from vyos.util import debug, debug_msg from vyos.util import popen, cmd -from vyos.ifconfig.register import Register +from vyos.ifconfig.section import Section -class Control(Register): +class Control(Section): _command_get = {} _command_set = {} diff --git a/python/vyos/ifconfig/register.py b/python/vyos/ifconfig/register.py deleted file mode 100644 index c90782b70..000000000 --- a/python/vyos/ifconfig/register.py +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright 2020 VyOS maintainers and contributors -# -# 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 . - -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].definition['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,section=''): - interfaces = netifaces.interfaces() - - for ifname in interfaces: - # 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 - - ifsection = cls.section(ifname) - if not ifsection: - continue - - if section and ifsection != section: - continue - - yield ifname - - @classmethod - def listing(cls, section=''): - return list(cls._listing(section)) - - -# XXX: TODO - limit name for VRF interfaces - diff --git a/python/vyos/ifconfig/section.py b/python/vyos/ifconfig/section.py new file mode 100644 index 000000000..eeec1968a --- /dev/null +++ b/python/vyos/ifconfig/section.py @@ -0,0 +1,95 @@ +# Copyright 2020 VyOS maintainers and contributors +# +# 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 . + +import netifaces + + +class Section: + # 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].definition['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,section=''): + interfaces = netifaces.interfaces() + + for ifname in interfaces: + # 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 + + ifsection = cls.section(ifname) + if not ifsection: + continue + + if section and ifsection != section: + continue + + yield ifname + + @classmethod + def listing(cls, section=''): + return list(cls._listing(section)) + + +# XXX: TODO - limit name for VRF interfaces + -- cgit v1.2.3 From d3aa0bd68bb72bc35eb290b1c54cae4dfa4efb57 Mon Sep 17 00:00:00 2001 From: Thomas Mangin Date: Sat, 11 Apr 2020 14:43:28 +0100 Subject: ifconfig: T2223: rename Section.listing to interfaces update all code using the API. Interface.interfaces() could be used but the code was change to use Section.interfaces() which make more sense when reading it. --- python/vyos/ifconfig/section.py | 30 +++++++++++++++++++++++++----- src/completion/list_interfaces.py | 30 +++++++++++++++--------------- src/conf_mode/flow_accounting_conf.py | 7 ++++--- 3 files changed, 44 insertions(+), 23 deletions(-) (limited to 'python/vyos') diff --git a/python/vyos/ifconfig/section.py b/python/vyos/ifconfig/section.py index eeec1968a..4f76258a7 100644 --- a/python/vyos/ifconfig/section.py +++ b/python/vyos/ifconfig/section.py @@ -26,6 +26,11 @@ class Section: @classmethod def register(cls, klass): + """ + A function to use as decorator the interfaces classes + It register the prefix for the interface (eth, dum, vxlan, ...) + with the class which can handle it (EthernetIf, DummyIf,VXLANIf, ...) + """ if not klass.definition.get('prefixes',[]): raise RuntimeError(f'valid interface prefixes not defined for {klass.__name__}') @@ -38,7 +43,11 @@ class Section: @classmethod def _basename (cls, name, vlan): - # remove number from interface name + """ + remove the number at the end of interface name + name: name of the interface + vlan: if vlan is True, do not stop at the vlan number + """ name = name.rstrip('0123456789') name = name.rstrip('.') if vlan: @@ -47,7 +56,11 @@ class Section: @classmethod def section(cls, name, vlan=True): - # return the name of a section an interface should be under + """ + return the name of a section an interface should be under + name: name of the interface (eth0, dum1, ...) + vlan: should we try try to remove the VLAN from the number + """ name = cls._basename(name, vlan) # XXX: To leave as long as vti and input are not moved to vyos @@ -68,7 +81,10 @@ class Section: raise ValueError(f'No type found for interface name: {name}') @classmethod - def _listing (cls,section=''): + def _intf_under_section (cls,section=''): + """ + return a generator with the name of the interface which are under a section + """ interfaces = netifaces.interfaces() for ifname in interfaces: @@ -87,8 +103,12 @@ class Section: yield ifname @classmethod - def listing(cls, section=''): - return list(cls._listing(section)) + def interfaces(cls, section=''): + """ + return a list of the name of the interface which are under a section + if no section is provided, then it returns all configured interfaces + """ + return list(cls._intf_under_section(section)) # XXX: TODO - limit name for VRF interfaces diff --git a/src/completion/list_interfaces.py b/src/completion/list_interfaces.py index 98b32797a..64aecef60 100755 --- a/src/completion/list_interfaces.py +++ b/src/completion/list_interfaces.py @@ -2,7 +2,7 @@ import sys import argparse -from vyos.ifconfig import Interface +from vyos.ifconfig import Section parser = argparse.ArgumentParser() group = parser.add_mutually_exclusive_group() @@ -19,33 +19,33 @@ args = parser.parse_args() if args.type: try: - interfaces = Interface.listing(args.type) + interfaces = Section.interfaces(args.type) except ValueError as e: print(e, file=sys.stderr) print("") elif args.broadcast: - eth = Interface.listing("ethernet") - bridge = Interface.listing("bridge") - bond = Interface.listing("bonding") + eth = Section.interfaces("ethernet") + bridge = Section.interfaces("bridge") + bond = Section.interfaces("bonding") interfaces = eth + bridge + bond elif args.bridgeable: - eth = Interface.listing("ethernet") - bond = Interface.listing("bonding") - l2tpv3 = Interface.listing("l2tpv3") - openvpn = Interface.listing("openvpn") - wireless = Interface.listing("wireless") - tunnel = Interface.listing("tunnel") - vxlan = Interface.listing("vxlan") - geneve = Interface.listing("geneve") + eth = Section.interfaces("ethernet") + bond = Section.interfaces("bonding") + l2tpv3 = Section.interfaces("l2tpv3") + openvpn = Section.interfaces("openvpn") + wireless = Section.interfaces("wireless") + tunnel = Section.interfaces("tunnel") + vxlan = Section.interfaces("vxlan") + geneve = Section.interfaces("geneve") interfaces = eth + bond + l2tpv3 + openvpn + vxlan + tunnel + wireless + geneve elif args.bondable: interfaces = [] - eth = Interface.listing("ethernet") + eth = Section.interfaces("ethernet") # we need to filter out VLAN interfaces identified by a dot (.) in their name for intf in eth: @@ -53,6 +53,6 @@ elif args.bondable: interfaces.append(intf) else: - interfaces = Interface.listing() + interfaces = Section.interfaces() print(" ".join(interfaces)) diff --git a/src/conf_mode/flow_accounting_conf.py b/src/conf_mode/flow_accounting_conf.py index 1008f3fae..eef32687e 100755 --- a/src/conf_mode/flow_accounting_conf.py +++ b/src/conf_mode/flow_accounting_conf.py @@ -22,6 +22,7 @@ from ipaddress import ip_address from jinja2 import FileSystemLoader, Environment from sys import exit +from vyos.ifconfig import Section from vyos.ifconfig import Interface from vyos.config import Config from vyos.defaults import directories as vyos_data_dir @@ -60,7 +61,7 @@ def _sflow_default_agentip(config): return config.return_value('protocols ospfv3 parameters router-id') # if router-id was not found, use first available ip of any interface - for iface in Interface.listing(): + for iface in Section.interfaces(): for address in Interface(iface).get_addr(): # return an IP, if this is not loopback regex_filter = re.compile('^(?!(127)|(::1)|(fe80))(?P[a-f\d\.:]+)/\d+$') @@ -234,7 +235,7 @@ def verify(config): # check that all configured interfaces exists in the system for iface in config['interfaces']: - if not iface in Interface.listing(): + if not iface in Section.interfaces(): # chnged from error to warning to allow adding dynamic interfaces and interface templates # raise ConfigError("The {} interface is not presented in the system".format(iface)) print("Warning: the {} interface is not presented in the system".format(iface)) @@ -262,7 +263,7 @@ def verify(config): # check if configured sFlow agent-id exist in the system agent_id_presented = None - for iface in Interface.listing(): + for iface in Section.interfaces(): for address in Interface(iface).get_addr(): # check an IP, if this is not loopback regex_filter = re.compile('^(?!(127)|(::1)|(fe80))(?P[a-f\d\.:]+)/\d+$') -- cgit v1.2.3 From 8bc12847568582d3b34f3859946470af1344f9ea Mon Sep 17 00:00:00 2001 From: Thomas Mangin Date: Sat, 11 Apr 2020 16:42:40 +0100 Subject: completion: T2238: use interface data Use the data in the default dict of the interface to generate the output of list interface. --- python/vyos/ifconfig/section.py | 23 ++++++++++++++++++++-- src/completion/list_interfaces.py | 40 ++++++++++++--------------------------- 2 files changed, 33 insertions(+), 30 deletions(-) (limited to 'python/vyos') diff --git a/python/vyos/ifconfig/section.py b/python/vyos/ifconfig/section.py index 4f76258a7..234c9a6cc 100644 --- a/python/vyos/ifconfig/section.py +++ b/python/vyos/ifconfig/section.py @@ -19,6 +19,7 @@ import netifaces class Section: # the known interface prefixes _prefixes = {} + _classes = [] # class need to define: definition['prefixes'] # the interface prefixes declared by a class used to name interface with @@ -34,6 +35,8 @@ class Section: if not klass.definition.get('prefixes',[]): raise RuntimeError(f'valid interface prefixes not defined for {klass.__name__}') + cls._classes.append(klass) + for ifprefix in klass.definition['prefixes']: if ifprefix in cls._prefixes: raise RuntimeError(f'only one class can be registered for prefix "{ifprefix}" type') @@ -110,6 +113,22 @@ class Section: """ return list(cls._intf_under_section(section)) + @classmethod + def _intf_with_feature(cls, feature=''): + """ + return a generator with the name of the interface which have + a particular feature set in their definition such as: + bondable, broadcast, bridgeable, ... + """ + for klass in cls._classes: + if klass.definition[feature]: + yield klass.definition['section'] -# XXX: TODO - limit name for VRF interfaces - + @classmethod + def feature(cls, feature=''): + """ + return list with the name of the interface which have + a particular feature set in their definition such as: + bondable, broadcast, bridgeable, ... + """ + return list(cls._intf_with_feature(feature)) diff --git a/src/completion/list_interfaces.py b/src/completion/list_interfaces.py index 64aecef60..e27281433 100755 --- a/src/completion/list_interfaces.py +++ b/src/completion/list_interfaces.py @@ -4,6 +4,13 @@ import sys import argparse from vyos.ifconfig import Section + +def matching(feature): + for section in Section.feature(feature): + for intf in Section.interfaces(section): + yield intf + + parser = argparse.ArgumentParser() group = parser.add_mutually_exclusive_group() group.add_argument("-t", "--type", type=str, help="List interfaces of specific type") @@ -13,46 +20,23 @@ group.add_argument("-bo", "--bondable", action="store_true", help="List all bond args = parser.parse_args() -# XXX: Need to be rewritten using the data in the class definition -# XXX: It can be done once vti and input are moved into vyos -# XXX: We store for each class what type they are (broadcast, bridgeabe, ...) - if args.type: try: interfaces = Section.interfaces(args.type) - + print(" ".join(interfaces)) except ValueError as e: print(e, file=sys.stderr) print("") elif args.broadcast: - eth = Section.interfaces("ethernet") - bridge = Section.interfaces("bridge") - bond = Section.interfaces("bonding") - interfaces = eth + bridge + bond + print(" ".join(matching("broadcast"))) elif args.bridgeable: - eth = Section.interfaces("ethernet") - bond = Section.interfaces("bonding") - l2tpv3 = Section.interfaces("l2tpv3") - openvpn = Section.interfaces("openvpn") - wireless = Section.interfaces("wireless") - tunnel = Section.interfaces("tunnel") - vxlan = Section.interfaces("vxlan") - geneve = Section.interfaces("geneve") - - interfaces = eth + bond + l2tpv3 + openvpn + vxlan + tunnel + wireless + geneve + print(" ".join(matching("bridgeable"))) elif args.bondable: - interfaces = [] - eth = Section.interfaces("ethernet") - # we need to filter out VLAN interfaces identified by a dot (.) in their name - for intf in eth: - if not '.' in intf: - interfaces.append(intf) + print(" ".join([intf for intf in matching("bondable") if '.' not in intf])) else: - interfaces = Section.interfaces() - -print(" ".join(interfaces)) + print(" ".join(Section.interfaces())) -- cgit v1.2.3