├── tests ├── __init__.py ├── scp │ ├── bridge_new_attribute_igmp_mld.after.eni │ ├── bridge_new_attribute_vlan_protocol_stats.after.eni │ ├── bridge_new_attribute_igmp_mld.before.eni │ ├── bridge_new_attribute_vlan_protocol_stats.before.eni │ ├── bridge_attr_back_to_default.after.eni │ ├── bridge_new_attribute_ucast_mcast_flood.after.eni │ ├── bridge_new_attribute_ucast_mcast_flood.before.eni │ ├── bridge_new_attribute_ipforward_vlan_protocol_mcstats.after.eni │ ├── bridge_new_attribute_ipforward_vlan_protocol_mcstats.before.eni │ ├── bridge_new_attribute_learning_arp_nd_suppress.after.eni │ ├── bond.default.eni │ ├── bridge_new_attribute_learning_arp_nd_suppress.before.eni │ ├── interfaces_link_state.before.eni │ └── interfaces_link_state.after.eni ├── eni │ ├── bridge_new_attribute.eni │ ├── interfaces_link_state.eni │ ├── mac1.eni │ ├── bridge1.eni │ ├── bridge6_multiple_bridge_ports_lines.eni │ ├── bridge8_reserved_vlans.eni │ ├── bridge2.eni │ ├── address.eni │ ├── bridge5.eni │ ├── address_gateway.eni │ ├── bridge3.eni │ ├── bridge_igmp_version.eni │ ├── bridge4.eni │ ├── bridge_l2protocol_tunnel.eni │ ├── interfaces_vrr_vrf.eni │ ├── bridge_access.eni │ ├── cm_11485_vlan_device_name_vlan.eni │ ├── bond_lacp.eni │ ├── vxlandev_sanity.eni │ ├── bridge_attr_back_to_default.eni │ ├── bond.eni │ ├── evpn_vab_clag_riot_flood_sup_off_config_tors2.eni │ └── bridge7_macvlans.eni ├── test_ifupdown2.py ├── output │ ├── bridge_access.vlan.show.json │ ├── bridge3.vlan.show.json │ ├── bridge1.ifquery.ac.json │ ├── bridge6_multiple_bridge_ports_lines.ifquery.ac.json │ ├── bridge2.ifquery.ac.json │ ├── mac1.ifquery.ac.json │ ├── bridge_attr_back_to_default.after.ifquery.ac.json │ ├── bridge_new_attribute_igmp_mld.after.ifquery.ac.json │ ├── address.ifquery.ac.json │ ├── address_gateway.empty_addrs.ifquery.ac.json │ ├── bridge5.ifquery.ac.json │ ├── address_gateway.ifquery.ac.json │ ├── bridge_new_attribute_vlan_protocol_stats.after.ifquery.ac.json │ ├── bridge_new_attribute_igmp_mld.before.ifquery.ac.json │ ├── bridge3.ifquery.ac.json │ ├── bridge_new_attribute_vlan_protocol_stats.before.ifquery.ac.json │ ├── bridge4.vlan.show.json │ ├── bridge4.ifquery.ac.json │ ├── bridge_access.ifquery.ac.json │ ├── bridge_new_attribute_ucast_mcast_flood.before.ifquery.ac.json │ ├── bridge_igmp_version.ifquery.ac.json │ ├── bridge_new_attribute_ucast_mcast_flood.after.ifquery.ac.json │ ├── bridge_new_attribute_ipforward_vlan_protocol_mcstats.after.ifquery.ac.json │ ├── interfaces.vrr_vrf.ifquery.ac.6.json │ ├── bridge_l2protocol_tunnel.ifquery.ac.json │ ├── interfaces.vrr_vrf.ifquery.ac.8.json │ ├── bridge_new_attribute_learning_arp_nd_suppress.after.ifquery.ac.json │ ├── interfaces.vrr_vrf.ifquery.ac.7.json │ ├── interfaces.vrr_vrf.ifquery.ac.5.json │ ├── bridge_new_attribute_ipforward_vlan_protocol_mcstats.before.ifquery.ac.json │ ├── interfaces.vrr_vrf.ifquery.ac.2.json │ ├── interfaces.vrr_vrf.ifquery.ac.4.json │ ├── interfaces_link_state.before.ifquery.ac.json │ ├── interfaces.vrr_vrf.ifquery.ac.3.json │ ├── interfaces_link_state.after.ifquery.ac.json │ ├── interfaces.vrr_vrf.ifquery.ac.1.json │ ├── bridge_new_attribute_learning_arp_nd_suppress.before.ifquery.ac.json │ ├── cm_11485_vlan_device_name_vlan.ifquery.ac.json │ ├── bond_lacp.flipped.values.ifquery.ac.json │ ├── bond_lacp.ifquery.ac.json │ ├── bridge1.vlan.show.json │ ├── bridge2.vlan.show.json │ ├── vxlan_sanity.ifquery.ac.json │ ├── bridge_attr_back_to_default.ifquery.ac.json │ ├── bond.flipped.values.ifquery.ac.json │ └── EvpnVabClagRiotFloodSupOffConfig.ifquery.ac.json └── test_coverage.py ├── debian ├── compat ├── watch ├── source │ └── format ├── ifupdown2.docs ├── ifupdown2.examples ├── ifupdown2.lintian-overrides ├── ifupdown2.dirs ├── ifupdown2.install ├── ifupdown2.manpages ├── ifupdown2.links ├── ifup@.service ├── ifupdown2.networking.service ├── rules ├── copyright ├── ifupdown2.postrm ├── control └── ifupdown2.postinst ├── ifupdown2 ├── addons │ ├── __init__.py │ └── usercmds.py ├── lib │ ├── __init__.py │ ├── exceptions.py │ ├── status.py │ └── base_objects.py ├── ifupdown │ ├── __init__.py │ ├── ifupdownconfig.py │ ├── ifupdownflags.py │ ├── exceptions.py │ ├── config.py │ ├── template.py │ └── graph.py ├── ifupdownaddons │ ├── __init__.py │ ├── systemutils.py │ └── utilsbase.py ├── nlmanager │ ├── __init__.py │ └── README ├── man │ ├── genmanpages.sh │ └── ifreload.8.rst └── __init__.py ├── docs ├── source │ ├── images │ │ ├── interfaces.png │ │ └── interfaces_all.png │ ├── index.rst │ ├── addonshelperapiref.rst │ ├── gettingstarted.rst │ ├── addonsapiref.rst │ ├── apiref.rst │ ├── intro.rst │ └── developmentcorner.rst ├── examples │ ├── batman_adv │ │ ├── interfaces_batman │ │ └── configure_batman_adv.sh │ ├── mgmt-vrf │ ├── interfaces_with_template │ ├── vlan_aware_bridges │ │ ├── interfaces.basic │ │ ├── interfaces.vlan_prune_and_access_ports │ │ ├── interfaces.with_bonds │ │ └── interfaces.with_clag │ ├── interfaces_bridge_template_func │ ├── interfaces │ ├── interfaces_bridge_igmp_mstp │ └── interfaces_bridge_vlan_bond_vxlan_vrf └── README.rst ├── requirements.txt ├── etc ├── default │ └── networking └── network │ └── ifupdown2 │ ├── addons.conf │ └── ifupdown2.conf ├── .gitignore ├── setup.py └── Makefile /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /debian/watch: -------------------------------------------------------------------------------- 1 | version=3 2 | -------------------------------------------------------------------------------- /ifupdown2/addons/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ifupdown2/lib/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ifupdown2/ifupdown/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /ifupdown2/ifupdownaddons/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ifupdown2/nlmanager/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /debian/ifupdown2.docs: -------------------------------------------------------------------------------- 1 | docs/README.rst 2 | -------------------------------------------------------------------------------- /debian/ifupdown2.examples: -------------------------------------------------------------------------------- 1 | docs/examples/* 2 | -------------------------------------------------------------------------------- /debian/ifupdown2.lintian-overrides: -------------------------------------------------------------------------------- 1 | ifupdown2: systemd-service-file-refers-to-unusual-wantedby-target 2 | -------------------------------------------------------------------------------- /docs/source/images/interfaces.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CumulusNetworks/ifupdown2/HEAD/docs/source/images/interfaces.png -------------------------------------------------------------------------------- /docs/source/images/interfaces_all.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CumulusNetworks/ifupdown2/HEAD/docs/source/images/interfaces_all.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pytest~=8.0.0 2 | pytest-order 3 | paramiko~=3.4.0 4 | scp~=0.14.5 5 | setuptools~=58.1.0 6 | six~=1.16.0 7 | deepdiff 8 | -------------------------------------------------------------------------------- /debian/ifupdown2.dirs: -------------------------------------------------------------------------------- 1 | etc/network/interfaces.d/ 2 | etc/network/ifupdown2/policy.d/ 3 | var/lib/ifupdown2/hooks/ 4 | var/lib/ifupdown2/policy.d/ 5 | -------------------------------------------------------------------------------- /debian/ifupdown2.install: -------------------------------------------------------------------------------- 1 | etc/network/ifupdown2/addons.conf /etc/network/ifupdown2/ 2 | etc/network/ifupdown2/ifupdown2.conf /etc/network/ifupdown2/ 3 | -------------------------------------------------------------------------------- /debian/ifupdown2.manpages: -------------------------------------------------------------------------------- 1 | man/ifup.8 2 | man/ifdown.8 3 | man/ifquery.8 4 | man/ifreload.8 5 | man/ifupdown-addons-interfaces.5 6 | man/interfaces.5 7 | -------------------------------------------------------------------------------- /tests/scp/bridge_new_attribute_igmp_mld.after.eni: -------------------------------------------------------------------------------- 1 | auto br0 2 | iface br0 3 | bridge-vlan-aware yes 4 | bridge-ports swp_AA_ 5 | 6 | auto br1 7 | iface br1 8 | bridge-ports swp_BB_ 9 | -------------------------------------------------------------------------------- /debian/ifupdown2.links: -------------------------------------------------------------------------------- 1 | usr/share/ifupdown2/__main__.py usr/share/ifupdown2/ifupdown2 2 | usr/share/ifupdown2/ifupdown2 sbin/ifup 3 | usr/share/ifupdown2/ifupdown2 sbin/ifdown 4 | usr/share/ifupdown2/ifupdown2 sbin/ifquery 5 | usr/share/ifupdown2/ifupdown2 sbin/ifreload 6 | -------------------------------------------------------------------------------- /tests/scp/bridge_new_attribute_vlan_protocol_stats.after.eni: -------------------------------------------------------------------------------- 1 | auto br0 2 | iface br0 3 | bridge-vlan-aware yes 4 | bridge-ports swp_AA_ 5 | bridge-vlan-protocol 802.1ad 6 | 7 | auto br1 8 | iface br1 9 | bridge-ports swp_BB_ 10 | bridge-vlan-protocol 802.1ad 11 | -------------------------------------------------------------------------------- /docs/examples/batman_adv/interfaces_batman: -------------------------------------------------------------------------------- 1 | auto eth0 2 | iface eth0 inet dhcp 3 | 4 | auto lo 5 | iface lo inet 6 | 7 | auto bat0 8 | iface bat0 9 | batman-ifaces tap0 tap1 10 | batman-ifaces-ignore-regex .*_nodes 11 | batman-hop-penalty 23 12 | address 192.0.2.42/24 -------------------------------------------------------------------------------- /tests/eni/bridge_new_attribute.eni: -------------------------------------------------------------------------------- 1 | # The loopback network interface 2 | auto lo 3 | iface lo inet loopback 4 | 5 | # The primary network interface 6 | auto eth0 7 | iface eth0 inet dhcp 8 | vrf mgmt 9 | 10 | auto mgmt 11 | iface mgmt 12 | vrf-table auto 13 | 14 | source /etc/network/interfaces.d/*.eni 15 | -------------------------------------------------------------------------------- /tests/eni/interfaces_link_state.eni: -------------------------------------------------------------------------------- 1 | # The loopback network interface 2 | auto lo 3 | iface lo inet loopback 4 | 5 | # The primary network interface 6 | auto eth0 7 | iface eth0 inet dhcp 8 | vrf mgmt 9 | 10 | auto mgmt 11 | iface mgmt 12 | vrf-table auto 13 | 14 | source /etc/network/interfaces.d/*.eni 15 | -------------------------------------------------------------------------------- /tests/scp/bridge_new_attribute_igmp_mld.before.eni: -------------------------------------------------------------------------------- 1 | auto br0 2 | iface br0 3 | bridge-vlan-aware yes 4 | bridge-ports swp_AA_ 5 | bridge-igmp-version 3 6 | bridge-mld-version 2 7 | 8 | auto br1 9 | iface br1 10 | bridge-ports swp_BB_ 11 | bridge-igmp-version 3 12 | bridge-mld-version 2 13 | -------------------------------------------------------------------------------- /tests/eni/mac1.eni: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet loopback 3 | 4 | auto eth0 5 | iface eth0 inet dhcp 6 | vrf mgmt 7 | 8 | auto mgmt 9 | iface mgmt 10 | vrf-table auto 11 | 12 | auto swp_AA_ 13 | iface swp_AA_ 14 | hwaddress ether 90:e2:ba:2c:b1:96 15 | 16 | auto swp_BB_ 17 | iface swp_BB_ 18 | hwaddress 90:e2:ba:2c:b2:95 19 | -------------------------------------------------------------------------------- /tests/scp/bridge_new_attribute_vlan_protocol_stats.before.eni: -------------------------------------------------------------------------------- 1 | auto br0 2 | iface br0 3 | bridge-vlan-aware yes 4 | bridge-ports swp_AA_ 5 | bridge-vlan-protocol 802.1ad 6 | bridge-vlan-stats on 7 | 8 | auto br1 9 | iface br1 10 | bridge-ports swp_BB_ 11 | bridge-vlan-protocol 802.1ad 12 | bridge-vlan-stats off 13 | -------------------------------------------------------------------------------- /tests/scp/bridge_attr_back_to_default.after.eni: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet loopback 3 | 4 | auto eth0 5 | iface eth0 inet dhcp 6 | vrf mgmt 7 | 8 | auto mgmt 9 | iface mgmt 10 | vrf-table auto 11 | 12 | auto br0 13 | iface br0 14 | bridge-ports vx42 15 | 16 | auto vx42 17 | iface vx42 18 | vxlan-id 42 19 | bridge-access 42 20 | -------------------------------------------------------------------------------- /ifupdown2/nlmanager/README: -------------------------------------------------------------------------------- 1 | DO NOT EDIT NLMANAGER SOURCES. 2 | This is a mirror copy of python-nlmanager sources. 3 | It was extracted and directly included here to support some usecases where 4 | user don't have python-nlmanager already installed on their system. So we 5 | decided to have local copy and build with it. It is the mainter responsability 6 | to keep an updated version of nlmanager. -------------------------------------------------------------------------------- /docs/examples/mgmt-vrf: -------------------------------------------------------------------------------- 1 | 2 | # Example config for management VRF 3 | # - 'vrf-default-route no' tells ifupdown2 not to install 4 | # the default unreachable route (dhclient will add the 5 | # default route) 6 | 7 | auto eth0 8 | iface eth0 inet dhcp 9 | vrf mgmt 10 | 11 | auto mgmt 12 | iface mgmt 13 | address 127.0.0.1/8 14 | vrf-table auto 15 | vrf-default-route no 16 | 17 | -------------------------------------------------------------------------------- /tests/eni/bridge1.eni: -------------------------------------------------------------------------------- 1 | # The loopback network interface 2 | auto lo 3 | iface lo inet loopback 4 | 5 | # The primary network interface 6 | auto eth0 7 | iface eth0 inet dhcp 8 | vrf mgmt 9 | 10 | auto mgmt 11 | iface mgmt 12 | vrf-table auto 13 | 14 | auto bridge 15 | iface bridge 16 | bridge-vlan-aware yes 17 | bridge-ports swp_AA_ swp_BB_ 18 | bridge-trunk 1-20 19 | -------------------------------------------------------------------------------- /tests/scp/bridge_new_attribute_ucast_mcast_flood.after.eni: -------------------------------------------------------------------------------- 1 | auto swp_AA_ 2 | iface swp_AA_ 3 | bridge-unicast-flood off 4 | bridge-multicast-flood off 5 | 6 | auto br0 7 | iface br0 8 | bridge-vlan-aware yes 9 | bridge-ports swp_AA_ 10 | 11 | auto br1 12 | iface br1 13 | bridge-ports swp_BB_ 14 | bridge-unicast-flood swp_BB_=off 15 | bridge-multicast-flood swp_BB_=off 16 | -------------------------------------------------------------------------------- /tests/scp/bridge_new_attribute_ucast_mcast_flood.before.eni: -------------------------------------------------------------------------------- 1 | auto swp_AA_ 2 | iface swp_AA_ 3 | bridge-unicast-flood on 4 | bridge-multicast-flood on 5 | 6 | auto br0 7 | iface br0 8 | bridge-vlan-aware yes 9 | bridge-ports swp_AA_ 10 | 11 | auto br1 12 | iface br1 13 | bridge-ports swp_BB_ 14 | bridge-unicast-flood swp_BB_=on 15 | bridge-multicast-flood swp_BB_=on 16 | -------------------------------------------------------------------------------- /tests/eni/bridge6_multiple_bridge_ports_lines.eni: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet loopback 3 | 4 | # The primary network interface 5 | auto eth0 6 | iface eth0 inet dhcp 7 | vrf mgmt 8 | 9 | auto mgmt 10 | iface mgmt 11 | vrf-table auto 12 | 13 | auto bridge 14 | iface bridge 15 | bridge-vlan-aware yes 16 | bridge-stp on 17 | bridge-ports swp_AA_ swp_BB_ 18 | bridge-ports swp_CC_ swp_DD_ 19 | -------------------------------------------------------------------------------- /tests/eni/bridge8_reserved_vlans.eni: -------------------------------------------------------------------------------- 1 | # The loopback network interface 2 | auto lo 3 | iface lo inet loopback 4 | 5 | # The primary network interface 6 | auto eth0 7 | iface eth0 inet dhcp 8 | vrf mgmt 9 | 10 | auto mgmt 11 | iface mgmt 12 | vrf-table auto 13 | 14 | auto bridge 15 | iface bridge 16 | bridge-vlan-aware yes 17 | bridge-ports swp_AA_ swp_BB_ 18 | bridge-trunk 2999-4000 19 | -------------------------------------------------------------------------------- /ifupdown2/ifupdown/ifupdownconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Copyright 2015-2017 Cumulus Networks, Inc. All rights reserved. 4 | # 5 | # Author: Roopa Prabhu, roopa@cumulusnetworks.com 6 | # 7 | 8 | class ifupdownConfig(): 9 | 10 | def __init__(self): 11 | self.conf = {} 12 | 13 | config = ifupdownConfig() 14 | diff_mode = False 15 | 16 | def reset(): 17 | global config 18 | config = ifupdownConfig() 19 | -------------------------------------------------------------------------------- /tests/eni/bridge2.eni: -------------------------------------------------------------------------------- 1 | # The loopback network interface 2 | auto lo 3 | iface lo inet loopback 4 | 5 | # The primary network interface 6 | auto eth0 7 | iface eth0 inet dhcp 8 | vrf mgmt 9 | 10 | auto mgmt 11 | iface mgmt 12 | vrf-table auto 13 | 14 | auto bridge 15 | iface bridge 16 | bridge-vlan-aware yes 17 | bridge-ports swp_AA_ swp_BB_ 18 | bridge-pvid 2 19 | bridge-vids 1-20 20 | -------------------------------------------------------------------------------- /tests/scp/bridge_new_attribute_ipforward_vlan_protocol_mcstats.after.eni: -------------------------------------------------------------------------------- 1 | auto swp_AA_ 2 | iface swp_AA_ 3 | 4 | auto swp_BB_ 5 | iface swp_BB_ 6 | 7 | auto br2 8 | iface br2 9 | address 6.0.0.2/32 10 | bridge-ports swp_DD_ swp_EE_ 11 | ip-forward on 12 | 13 | auto vlan100 14 | iface vlan100 15 | vlan-raw-device swp_CC_ 16 | vlan-id 100 17 | 18 | auto br3 19 | iface br3 20 | bridge-ports swp_FF_ 21 | -------------------------------------------------------------------------------- /tests/eni/address.eni: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet loopback 3 | 4 | auto eth0 5 | iface eth0 inet dhcp 6 | vrf mgmt 7 | 8 | auto mgmt 9 | iface mgmt 10 | vrf-table auto 11 | 12 | auto swp_AA_ 13 | iface swp_AA_ 14 | address 2001:db8::1/128 15 | address 192.0.2.1/32 16 | address 2001:db8::42/128 17 | address 192.0.2.42/32 18 | address 2042:db8::1/128 19 | address 192.0.42.1/32 20 | address 192.42.2.42/32 21 | -------------------------------------------------------------------------------- /tests/eni/bridge5.eni: -------------------------------------------------------------------------------- 1 | # The loopback network interface 2 | auto lo 3 | iface lo inet loopback 4 | 5 | # The primary network interface 6 | auto eth0 7 | iface eth0 inet dhcp 8 | vrf mgmt 9 | 10 | auto mgmt 11 | iface mgmt 12 | vrf-table auto 13 | 14 | auto swp_AA_ 15 | iface swp_AA_ 16 | 17 | auto swp_BB_ 18 | iface swp_BB_ 19 | 20 | auto bridge 21 | iface bridge 22 | bridge-ports swp_AA_ swp_BB_ 23 | bridge-vids 1-200 24 | bridge-vlan-aware yes 25 | -------------------------------------------------------------------------------- /tests/eni/address_gateway.eni: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet loopback 3 | 4 | auto eth0 5 | iface eth0 inet dhcp 6 | vrf mgmt 7 | 8 | auto mgmt 9 | iface mgmt 10 | vrf-table auto 11 | 12 | auto swp_AA_ 13 | iface swp_AA_ 14 | address 10.0.14.3/14 15 | gateway 10.1.14.3 16 | link-down yes 17 | 18 | auto br1 19 | iface br1 20 | bridge-ports swp_AA_.3000 21 | address 10.8.22.2/23 22 | address-virtual 44:39:39:FF:30:00 10.8.22.1/23 2001:0388:6080:0340::1/64 23 | -------------------------------------------------------------------------------- /tests/scp/bridge_new_attribute_ipforward_vlan_protocol_mcstats.before.eni: -------------------------------------------------------------------------------- 1 | auto swp_AA_ 2 | iface swp_AA_ 3 | ip-forward off 4 | 5 | auto swp_BB_ 6 | iface swp_BB_ 7 | ip6-forward off 8 | 9 | auto br2 10 | iface br2 11 | bridge-ports swp_DD_ swp_EE_ 12 | ip-forward on 13 | bridge-mcstats off 14 | 15 | auto vlan100 16 | iface vlan100 17 | vlan-raw-device swp_CC_ 18 | vlan-id 100 19 | vlan-protocol 802.1ad 20 | 21 | auto br3 22 | iface br3 23 | bridge-ports swp_FF_ 24 | bridge-mcstats off 25 | -------------------------------------------------------------------------------- /tests/scp/bridge_new_attribute_learning_arp_nd_suppress.after.eni: -------------------------------------------------------------------------------- 1 | auto vxlan10101 2 | iface vxlan10101 3 | vxlan-id 10101 4 | vxlan-local-tunnelip 6.0.0.17 5 | bridge-access 101 6 | 7 | auto br1 8 | iface br1 9 | bridge-ports vxlan10101 10 | bridge-vlan-aware yes 11 | bridge-vids 101 12 | 13 | auto vxlan10102 14 | iface vxlan10102 15 | vxlan-id 10102 16 | vxlan-local-tunnelip 6.0.0.17 17 | bridge-access 102 18 | 19 | auto br2 20 | iface br2 21 | bridge-ports vxlan10102 22 | bridge-vids 101 23 | -------------------------------------------------------------------------------- /tests/eni/bridge3.eni: -------------------------------------------------------------------------------- 1 | # The loopback network interface 2 | auto lo 3 | iface lo inet loopback 4 | 5 | # The primary network interface 6 | auto eth0 7 | iface eth0 inet dhcp 8 | vrf mgmt 9 | 10 | auto mgmt 11 | iface mgmt 12 | vrf-table auto 13 | 14 | auto swp_AA_ 15 | iface swp_AA_ 16 | bridge-access 100 17 | 18 | auto swp_BB_ 19 | iface swp_BB_ 20 | bridge-vids 200 21 | 22 | auto bridge 23 | iface bridge 24 | bridge-vlan-aware yes 25 | bridge-ports swp_AA_ swp_BB_ 26 | bridge-pvid 2 27 | bridge-vids 1-20 28 | -------------------------------------------------------------------------------- /tests/eni/bridge_igmp_version.eni: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet loopback 3 | 4 | # The primary network interface 5 | auto eth0 6 | iface eth0 inet dhcp 7 | vrf mgmt 8 | 9 | auto mgmt 10 | iface mgmt 11 | vrf-table auto 12 | 13 | auto br0 14 | iface br0 15 | bridge-vlan-aware yes 16 | bridge-ports swp_AA_ 17 | bridge-igmp-version 3 18 | bridge-mld-version 2 19 | 20 | auto br1 21 | iface br1 22 | bridge-ports swp_BB_ 23 | bridge-igmp-version 3 24 | bridge-mld-version 2 25 | 26 | auto br2 27 | iface br2 28 | bridge-ports swp_CC_ 29 | -------------------------------------------------------------------------------- /tests/eni/bridge4.eni: -------------------------------------------------------------------------------- 1 | # The loopback network interface 2 | auto lo 3 | iface lo inet loopback 4 | 5 | # The primary network interface 6 | auto eth0 7 | iface eth0 inet dhcp 8 | vrf mgmt 9 | 10 | auto mgmt 11 | iface mgmt 12 | vrf-table auto 13 | 14 | auto swp_AA_ 15 | iface swp_AA_ 16 | bridge-pvid 4 17 | 18 | auto swp_BB_ 19 | iface swp_BB_ 20 | bridge-pvid 3 21 | bridge-trunk 40 22 | 23 | auto bridge 24 | iface bridge 25 | bridge-vlan-aware yes 26 | bridge-ports swp_AA_ swp_BB_ 27 | bridge-pvid 2 28 | bridge-trunk 1-20 29 | -------------------------------------------------------------------------------- /debian/ifup@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=ifup for %I 3 | After=local-fs.target network-pre.target networking.service systemd-sysctl.service 4 | Before=network.target shutdown.target network-online.target 5 | Conflicts=shutdown.target 6 | BindsTo=sys-subsystem-net-devices-%i.device 7 | After=sys-subsystem-net-devices-%i.device 8 | DefaultDependencies=no 9 | IgnoreOnIsolate=yes 10 | 11 | [Service] 12 | # avoid stopping on shutdown via stopping system-ifup.slice 13 | Slice=system.slice 14 | ExecStart=/sbin/ifup --allow=hotplug %I 15 | ExecStop=/sbin/ifdown %I 16 | RemainAfterExit=true 17 | TimeoutStartSec=2min 18 | -------------------------------------------------------------------------------- /docs/examples/interfaces_with_template: -------------------------------------------------------------------------------- 1 | # 2 | # Example interfaces file using mako templates 3 | # 4 | # The below section can be copied into 5 | # /etc/network/interfaces file 6 | # or 7 | # to a file under /etc/network/interfaces.d/ 8 | # and include in the interfaces file using the 9 | # 'source' command. 10 | # 11 | # see manpage interfaces(5) for details 12 | # 13 | # 14 | 15 | %for v in range(1000,1100): 16 | auto vlan-${v} 17 | iface vlan-${v} inet static 18 | bridge-ports glob swp1-6.${v} 19 | bridge-stp on 20 | bridge-ageing 200 21 | bridge-maxage 10 22 | bridge-fd 10 23 | %endfor 24 | 25 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. ifupdown2 documentation master file, created by 2 | sphinx-quickstart on Sun Jul 6 23:49:20 2014. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to ifupdown2's documentation! 7 | ===================================== 8 | 9 | Contents: 10 | 11 | .. toctree:: 12 | :maxdepth: 2 13 | 14 | intro.rst 15 | gettingstarted.rst 16 | userguide.rst 17 | developmentcorner.rst 18 | 19 | Indices and tables 20 | ================== 21 | 22 | * :ref:`genindex` 23 | * :ref:`modindex` 24 | * :ref:`search` 25 | 26 | -------------------------------------------------------------------------------- /docs/source/addonshelperapiref.rst: -------------------------------------------------------------------------------- 1 | Documentation for the ifupdownaddons package helper modules 2 | *********************************************************** 3 | 4 | This package contains modules that provide helper methods 5 | for ifupdown2 addon modules to interact directly with tools 6 | like iproute2, brctl etc. 7 | 8 | LinkUtils 9 | =========== 10 | 11 | Helper module to work with brctl, bonds, iproute2, mstpctl commands 12 | 13 | .. automodule:: LinkUtils 14 | 15 | .. autoclass:: LinkUtils 16 | 17 | dhclient 18 | ======== 19 | 20 | Helper module to interact with dhclient tools. 21 | 22 | .. automodule:: dhclient 23 | 24 | .. autoclass:: dhclient 25 | -------------------------------------------------------------------------------- /tests/test_ifupdown2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """Tests for `ifupdown2` package.""" 5 | 6 | import pytest 7 | 8 | 9 | @pytest.fixture 10 | def response(): 11 | """Sample pytest fixture. 12 | 13 | See more at: http://doc.pytest.org/en/latest/fixture.html 14 | """ 15 | # import requests 16 | # return requests.get('https://github.com/audreyr/cookiecutter-pypackage') 17 | 18 | 19 | def test_content(response): 20 | """Sample pytest test function with the pytest fixture as an argument.""" 21 | # from bs4 import BeautifulSoup 22 | # assert 'GitHub' in BeautifulSoup(response.content).title.string 23 | -------------------------------------------------------------------------------- /tests/scp/bond.default.eni: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet loopback 3 | 4 | auto eth0 5 | iface eth0 inet dhcp 6 | vrf mgmt 7 | 8 | auto mgmt 9 | iface mgmt 10 | vrf-table auto 11 | 12 | auto bond0 13 | iface bond0 14 | bond-slaves swp_AA_ 15 | 16 | auto bond1 17 | iface bond1 18 | bond-slaves swp_BB_ 19 | 20 | auto bond2 21 | iface bond2 22 | bond-slaves swp_CC_ 23 | 24 | auto bond3 25 | iface bond3 26 | bond-slaves swp_DD_ 27 | 28 | auto bond4 29 | iface bond4 30 | bond-slaves swp_EE_ 31 | 32 | auto bond5 33 | iface bond5 34 | bond-slaves swp_FF_ 35 | 36 | auto bond6 37 | iface bond6 38 | bond-slaves swp_GG_ 39 | -------------------------------------------------------------------------------- /tests/scp/bridge_new_attribute_learning_arp_nd_suppress.before.eni: -------------------------------------------------------------------------------- 1 | auto vxlan10101 2 | iface vxlan10101 3 | vxlan-id 10101 4 | vxlan-local-tunnelip 6.0.0.17 5 | bridge-learning off 6 | bridge-arp-nd-suppress on 7 | bridge-access 101 8 | 9 | auto br1 10 | iface br1 11 | bridge-ports vxlan10101 12 | bridge-vlan-aware yes 13 | bridge-vids 101 14 | 15 | auto vxlan10102 16 | iface vxlan10102 17 | vxlan-id 10102 18 | vxlan-local-tunnelip 6.0.0.17 19 | bridge-access 102 20 | 21 | auto br2 22 | iface br2 23 | bridge-ports vxlan10102 24 | bridge-vids 101 25 | bridge-learning vxlan10102=off 26 | bridge-arp-nd-suppress vxlan10102=on 27 | -------------------------------------------------------------------------------- /tests/output/bridge_access.vlan.show.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ifname": "vxlan1", 4 | "vlans": [ 5 | { 6 | "vlan": 1, 7 | "flags": [ 8 | "PVID", 9 | "Egress Untagged" 10 | ] 11 | } 12 | ] 13 | }, 14 | { 15 | "ifname": "vxlan500", 16 | "vlans": [ 17 | { 18 | "vlan": 500, 19 | "flags": [ 20 | "PVID", 21 | "Egress Untagged" 22 | ] 23 | } 24 | ] 25 | }, 26 | { 27 | "ifname": "br0", 28 | "vlans": [ 29 | { 30 | "vlan": 1, 31 | "flags": [ 32 | "PVID", 33 | "Egress Untagged" 34 | ] 35 | } 36 | ] 37 | } 38 | ] 39 | -------------------------------------------------------------------------------- /tests/eni/bridge_l2protocol_tunnel.eni: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet loopback 3 | 4 | auto eth0 5 | iface eth0 inet dhcp 6 | vrf mgmt 7 | 8 | auto mgmt 9 | iface mgmt 10 | vrf-table auto 11 | 12 | auto br_vlan_unaware 13 | iface br_vlan_unaware 14 | bridge-ports swp_AA_ swp_BB_ swp_CC_ swp_DD_ swp_EE_ 15 | bridge-l2protocol-tunnel swp_AA_=lacp,pvst swp_BB_=stp,cdp swp_CC_=all swp_DD_=lldp 16 | 17 | auto br_vlan_aware 18 | iface br_vlan_aware 19 | bridge-ports swp_FF_ swp_GG_ 20 | bridge-vlan-aware yes 21 | 22 | auto swp_GG_ 23 | iface swp_GG_ 24 | bridge-l2protocol-tunnel all 25 | 26 | auto swp_FF_ 27 | iface swp_FF_ 28 | bridge-l2protocol-tunnel stp lacp lldp,pvst cdp 29 | -------------------------------------------------------------------------------- /tests/eni/interfaces_vrr_vrf.eni: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet loopback 3 | 4 | auto eth0 5 | iface eth0 inet dhcp 6 | vrf mgmt 7 | 8 | auto mgmt 9 | iface mgmt 10 | vrf-table auto 11 | 12 | auto peerlink 13 | iface peerlink 14 | bond-slaves swp_AA_ swp_BB_ 15 | 16 | auto peerlink.4094 17 | iface peerlink.4094 18 | address 169.254.1.1/30 19 | 20 | auto myvrf 21 | iface myvrf 22 | vrf-table auto 23 | 24 | auto bridge 25 | iface bridge 26 | bridge-vlan-aware yes 27 | bridge-ports peerlink bond0 28 | bridge-stp on 29 | 30 | auto bridge.901 31 | iface bridge.901 32 | address 10.1.63.2/28 33 | address-virtual 00:00:5e:00:01:81 10.1.63.1/28 34 | vrf myvrf 35 | 36 | auto bond0 37 | iface bond0 38 | bond-slaves swp_CC_ 39 | -------------------------------------------------------------------------------- /etc/default/networking: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # Parameters for: 4 | # - /etc/init.d/networking script 5 | # - systemd networking service 6 | # 7 | # 8 | 9 | # Change the below to yes if you want verbose logging to be enabled 10 | VERBOSE="no" 11 | 12 | # Change the below to yes if you want debug logging to be enabled 13 | DEBUG="no" 14 | 15 | # Change the below to yes if you want logging to go to syslog 16 | SYSLOG="no" 17 | 18 | # Exclude interfaces 19 | EXCLUDE_INTERFACES= 20 | 21 | # Set to 'yes' if you want to skip ifdown during system reboot 22 | # and shutdown. This is of interest in large scale interface 23 | # deployments where you dont want to wait for interface 24 | # deconfiguration to speed up shutdown/reboot 25 | SKIP_DOWN_AT_SYSRESET="yes" 26 | -------------------------------------------------------------------------------- /tests/output/bridge3.vlan.show.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ifname": "swp_AA_", 4 | "vlans": [ 5 | { 6 | "vlan": 100, 7 | "flags": [ 8 | "PVID", 9 | "Egress Untagged" 10 | ] 11 | } 12 | ] 13 | }, 14 | { 15 | "ifname": "swp_BB_", 16 | "vlans": [ 17 | { 18 | "vlan": 2, 19 | "flags": [ 20 | "PVID", 21 | "Egress Untagged" 22 | ] 23 | }, 24 | { 25 | "vlan": 200 26 | } 27 | ] 28 | }, 29 | { 30 | "ifname": "bridge", 31 | "vlans": [ 32 | { 33 | "vlan": 1, 34 | "flags": [ 35 | "PVID", 36 | "Egress Untagged" 37 | ] 38 | } 39 | ] 40 | } 41 | ] 42 | -------------------------------------------------------------------------------- /ifupdown2/man/genmanpages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright 2013 Cumulus Networks, Inc. 4 | # All rights reserved. 5 | # 6 | 7 | # Install the man pages into the sysroot 8 | SRC_MAN_DIR=$1 9 | DST_MAN_DIR=$2 10 | 11 | echo -n "Generating man pages .." 12 | # Loop over all the man directories 13 | mkdir -p $DST_MAN_DIR 14 | for p in $(ls $SRC_MAN_DIR/*.rst) ; do 15 | # strip src man path 16 | src_file=$p 17 | dst_file=${p##.*\/} 18 | dst_file="${DST_MAN_DIR}/${dst_file%.rst}" 19 | # treat warnings as errors 20 | rst2man --halt=2 "$p" > $dst_file || { 21 | echo 22 | echo "Error: problems generating man page: $p" 23 | rm -f $dst_file &>/dev/null 24 | exit 1 25 | } 26 | echo -n "." 27 | done 28 | echo " done." 29 | -------------------------------------------------------------------------------- /tests/scp/interfaces_link_state.before.eni: -------------------------------------------------------------------------------- 1 | # this link should down 2 | auto swp_AA_ 3 | iface swp_AA_ inet manual 4 | 5 | # link should be up 6 | auto swp_BB_ 7 | iface swp_BB_ 8 | 9 | # link should be up 10 | # interface 11 | auto bridge1 12 | iface bridge1 13 | bridge-ports swp_CC_ 14 | 15 | # link should be up, since it is a logical 16 | # interface. manual is ignored. 17 | auto bridge2 18 | iface bridge2 inet manual 19 | bridge-ports swp_DD_ 20 | 21 | # link should be down, since 'down yes' is set. 22 | auto bridge3 23 | iface bridge3 inet manual 24 | bridge-ports swp_EE_ 25 | link-down yes 26 | 27 | # link should be up, since 'link-down no' is set. 28 | auto bridge4 29 | iface bridge4 inet manual 30 | bridge-ports swp_FF_ 31 | link-down no 32 | -------------------------------------------------------------------------------- /docs/source/gettingstarted.rst: -------------------------------------------------------------------------------- 1 | Getting Started 2 | =============== 3 | 4 | Prerequisites 5 | ------------- 6 | * python-ifupdown2 is currently only tested on debian wheezy 7 | * python-ifupdown2 needs python version 2.6 or greater 8 | * Depends on: python-stdeb (for deb builds), python-docutils 9 | (for rst2man), 'python-ipaddr' 10 | * Depends on python-gvgen package for printing interface graphs (this will be made optional in the future) 11 | * Optional dependency for template engine: python-mako 12 | 13 | 14 | Building 15 | -------- 16 | $git clone ifupdown2 17 | 18 | $cd ifupdown2/ifupdown2 19 | 20 | $./build.sh 21 | 22 | Installing 23 | ---------- 24 | install generated python-ifupdown2-.deb 25 | 26 | $dpkg -i .deb 27 | 28 | -------------------------------------------------------------------------------- /tests/eni/bridge_access.eni: -------------------------------------------------------------------------------- 1 | # This file describes the network interfaces available on your system 2 | # and how to activate them. For more information, see interfaces(5). 3 | 4 | source /etc/network/interfaces.d/*.intf 5 | 6 | # The loopback network interface 7 | auto lo 8 | iface lo inet loopback 9 | 10 | # The primary network interface 11 | auto eth0 12 | iface eth0 inet dhcp 13 | vrf mgmt 14 | 15 | auto mgmt 16 | iface mgmt 17 | vrf-table auto 18 | 19 | auto vxlan1 20 | iface vxlan1 21 | vxlan-id 1 22 | bridge-access 1 23 | vxlan-local-tunnelip 27.0.0.11 24 | 25 | auto vxlan500 26 | iface vxlan500 27 | vxlan-id 500 28 | bridge-access 500 29 | vxlan-local-tunnelip 27.0.0.11 30 | 31 | auto br0 32 | iface br0 33 | bridge-vlan-aware yes 34 | bridge-ports vxlan1 vxlan500 35 | -------------------------------------------------------------------------------- /debian/ifupdown2.networking.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Network initialization 3 | Documentation=man:interfaces(5) man:ifup(8) man:ifdown(8) 4 | DefaultDependencies=no 5 | After=local-fs.target network-pre.target 6 | Before=shutdown.target network.target network-online.target 7 | Conflicts=shutdown.target 8 | Wants=systemd-udev-settle.service 9 | After=systemd-udev-settle.service 10 | 11 | [Service] 12 | Type=oneshot 13 | RemainAfterExit=yes 14 | SyslogIdentifier=networking 15 | TimeoutStopSec=30s 16 | EnvironmentFile=/etc/default/networking 17 | ExecStart=/usr/share/ifupdown2/sbin/start-networking start 18 | ExecStop=/usr/share/ifupdown2/sbin/start-networking stop 19 | ExecReload=/usr/share/ifupdown2/sbin/start-networking reload 20 | 21 | [Install] 22 | WantedBy=basic.target network.target shutdown.target 23 | -------------------------------------------------------------------------------- /docs/examples/vlan_aware_bridges/interfaces.basic: -------------------------------------------------------------------------------- 1 | # 2 | # vlan-aware bridge simple example 3 | # 4 | # 'bridge' is a vlan aware bridge with all ports (swp1-52). 5 | # native vlan is by default 1 6 | # 7 | # 'bridge-vids' attribute is used to declare vlans. 8 | # 'bridge-pvid' attribute is used to specify native vlans if other than 1 9 | # 'bridge-access' attribute is used to declare access port 10 | # 11 | 12 | # 13 | # ports swp1-swp52 are trunk ports which inherit vlans from 'bridge' 14 | # ie vlans 310 700 707 712 850 910 15 | 16 | # 17 | # the following is a vlan aware bridge with ports swp1-swp52 18 | # It has stp on 19 | # 20 | auto bridge 21 | iface bridge 22 | bridge-vlan-aware yes 23 | bridge-ports glob swp1-52 24 | bridge-stp on 25 | bridge-vids 310 700 707 712 850 910 26 | -------------------------------------------------------------------------------- /tests/scp/interfaces_link_state.after.eni: -------------------------------------------------------------------------------- 1 | # this link should be down 2 | auto swp_AA_ 3 | iface swp_AA_ inet manual 4 | 5 | # link should be down 6 | auto swp_BB_ 7 | iface swp_BB_ 8 | link-down yes 9 | 10 | # link should be up 11 | # interface 12 | auto bridge1 13 | iface bridge1 14 | bridge-ports swp_CC_ 15 | 16 | # link should be up, since it is a logical 17 | # interface. manual is ignored. 18 | auto bridge2 19 | iface bridge2 inet manual 20 | bridge-ports swp_DD_ 21 | 22 | # link should be up, since 'link-down no' is set. 23 | auto bridge3 24 | iface bridge3 inet manual 25 | bridge-ports swp_EE_ 26 | link-down no 27 | 28 | # link should be down, since 'link-down yes' is set. 29 | auto bridge4 30 | iface bridge4 inet manual 31 | bridge-ports swp_FF_ 32 | link-down yes 33 | -------------------------------------------------------------------------------- /tests/eni/cm_11485_vlan_device_name_vlan.eni: -------------------------------------------------------------------------------- 1 | auto eth0 2 | iface eth0 inet dhcp 3 | vrf mgmt 4 | 5 | auto mgmt 6 | iface mgmt 7 | vrf-table auto 8 | 9 | auto lo 10 | iface lo inet loopback 11 | 12 | auto swp_AA_ 13 | iface swp_AA_ inet static 14 | address 172.30.1.3 15 | netmask 24 16 | 17 | auto swp_BB_.1005 18 | iface swp_BB_.1005 19 | address 10.132.253.11/31 20 | 21 | auto bond0 22 | iface bond0 inet manual 23 | bond-slaves swp_BB_ swp_CC_ 24 | bond-mode 802.3ad 25 | bond-min-links 1 26 | bond-xmit-hash-policy layer2+3 27 | 28 | auto vlan1007 29 | iface vlan1007 30 | vlan-raw-device bond0 31 | vlan-id 1007 32 | address 10.132.253.15/31 33 | 34 | auto dummy0 35 | iface dummy0 36 | link-type dummy 37 | address fdca:ffee:ff12:fe06::1/64 38 | -------------------------------------------------------------------------------- /tests/eni/bond_lacp.eni: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet loopback 3 | 4 | auto eth0 5 | iface eth0 inet dhcp 6 | vrf mgmt 7 | 8 | auto mgmt 9 | iface mgmt 10 | vrf-table auto 11 | 12 | auto bond4 13 | iface bond4 14 | bond-slaves swp_EE_ 15 | bond-mode 802.3ad 16 | bond-lacp-rate slow 17 | bond-lacp-bypass-allow yes 18 | 19 | auto bond7 20 | iface bond7 21 | bond-slaves swp_HH_ 22 | bond-mode 802.3ad 23 | bond-lacp-rate fast 24 | bond-lacp-bypass-allow no 25 | 26 | auto bond8 27 | iface bond8 28 | bond-slaves swp_II_ 29 | bond-mode 802.3ad 30 | bond-lacp-rate 0 31 | bond-lacp-bypass-allow 0 32 | 33 | auto bond9 34 | iface bond9 35 | bond-slaves swp_JJ_ 36 | bond-mode 802.3ad 37 | bond-lacp-rate 1 38 | bond-lacp-bypass-allow 1 39 | -------------------------------------------------------------------------------- /ifupdown2/ifupdown/ifupdownflags.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Copyright 2015-2017 Cumulus Networks, Inc. All rights reserved. 4 | # 5 | # Author: Roopa Prabhu, roopa@cumulusnetworks.com 6 | # 7 | 8 | class ifupdownFlags(): 9 | 10 | def __init__(self): 11 | self.ALL = False 12 | self.CLASS = False 13 | self.FORCE = False 14 | self.DRYRUN = False 15 | self.NOWAIT = False 16 | self.PERFMODE = False 17 | self.CACHE = False 18 | self.WITHDEFAULTS = False 19 | self.IGNORE_ERRORS = False 20 | 21 | # Flags 22 | self.CACHE_FLAGS = 0x0 23 | 24 | flags = ifupdownFlags() 25 | 26 | 27 | def reset(): 28 | global flags 29 | flags = ifupdownFlags() 30 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | #export DH_VERBOSE=1 4 | export PYBUILD_NAME=ifupdown2 5 | export PYBUILD_INSTALL_ARGS=--install-lib=/usr/share/ --install-scripts=/usr/share/ 6 | 7 | %: 8 | dh $@ --with=python3 --with systemd --buildsystem=pybuild 9 | 10 | override_dh_installman: 11 | ./ifupdown2/man/genmanpages.sh ./ifupdown2/man ./man 12 | dh_installman 13 | 14 | override_dh_install: 15 | dh_install 16 | mkdir -p debian/ifupdown2/lib/systemd/system/ 17 | install --mode=644 debian/ifup@.service debian/ifupdown2/lib/systemd/system/ 18 | 19 | override_dh_auto_test: 20 | @echo "Skipping tests during the build process." 21 | 22 | override_dh_systemd_start: 23 | dh_systemd_start --name=networking --no-start 24 | 25 | override_dh_systemd_enable: 26 | dh_systemd_enable --name=networking 27 | 28 | override_dh_compress: 29 | dh_compress -X.py 30 | -------------------------------------------------------------------------------- /docs/source/addonsapiref.rst: -------------------------------------------------------------------------------- 1 | Documentation for the ifupdownaddons default addons modules 2 | *********************************************************** 3 | 4 | address 5 | ======= 6 | 7 | .. automodule:: address 8 | 9 | .. autoclass:: address 10 | :members: run, get_ops 11 | 12 | 13 | bridge 14 | ====== 15 | 16 | .. automodule:: bridge 17 | 18 | .. autoclass:: bridge 19 | :members: run, get_ops 20 | 21 | dhcp 22 | ==== 23 | 24 | .. automodule:: dhcp 25 | 26 | .. autoclass:: dhcp 27 | 28 | ethtool 29 | ======= 30 | 31 | .. automodule:: ethtool 32 | 33 | .. autoclass:: ethtool 34 | 35 | bond 36 | ==== 37 | 38 | .. automodule:: bond 39 | 40 | .. autoclass:: bond 41 | 42 | mstpctl 43 | ======= 44 | 45 | .. automodule:: mstpctl 46 | 47 | .. autoclass:: mstpctl 48 | 49 | usercmds 50 | ======== 51 | 52 | .. automodule:: usercmds 53 | 54 | .. autoclass:: usercmds 55 | 56 | vlan 57 | ==== 58 | 59 | .. automodule:: vlan 60 | 61 | .. autoclass:: vlan 62 | -------------------------------------------------------------------------------- /etc/network/ifupdown2/addons.conf: -------------------------------------------------------------------------------- 1 | pre-up,openvswitch 2 | pre-up,openvswitch_port 3 | pre-up,xfrm 4 | pre-up,link 5 | pre-up,ppp 6 | pre-up,bond 7 | pre-up,batman_adv 8 | pre-up,vlan 9 | pre-up,vxlan 10 | pre-up,clagd 11 | pre-up,usercmds 12 | pre-up,bridge 13 | pre-up,bridgevlan 14 | pre-up,mstpctl 15 | pre-up,tunnel 16 | pre-up,vrf 17 | pre-up,ethtool 18 | pre-up,address 19 | up,dhcp 20 | up,address 21 | up,addressvirtual 22 | up,usercmds 23 | post-up,usercmds 24 | post-up,clagd 25 | post-up,vxrd 26 | pre-down,ethtool 27 | pre-down,usercmds 28 | pre-down,vxrd 29 | pre-down,dhcp 30 | down,ppp 31 | down,addressvirtual 32 | down,address 33 | down,usercmds 34 | post-down,vrf 35 | post-down,clagd 36 | post-down,mstpctl 37 | post-down,bridgevlan 38 | post-down,bridge 39 | post-down,vxlan 40 | post-down,vlan 41 | post-down,bond 42 | post-down,batman_adv 43 | post-down,usercmds 44 | post-down,link 45 | post-down,tunnel 46 | post-down,xfrm 47 | post-down,openvswitch_port 48 | post-down,openvswitch 49 | 50 | -------------------------------------------------------------------------------- /tests/output/bridge1.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "bridge", 37 | "auto": true, 38 | "config": { 39 | "bridge-vlan-aware": "yes", 40 | "bridge-ports": "swp_AA_ swp_BB_", 41 | "bridge-vids": "1-20" 42 | }, 43 | "config_status": { 44 | "bridge-vlan-aware": "pass", 45 | "bridge-ports": "pass", 46 | "bridge-vids": "" 47 | }, 48 | "status": "pass" 49 | } 50 | ] 51 | -------------------------------------------------------------------------------- /tests/output/bridge6_multiple_bridge_ports_lines.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "bridge", 37 | "auto": true, 38 | "config": { 39 | "bridge-vlan-aware": "yes", 40 | "bridge-ports": "swp_AA_ swp_BB_ swp_CC_ swp_DD_", 41 | "bridge-stp": "yes" 42 | }, 43 | "config_status": { 44 | "bridge-vlan-aware": "pass", 45 | "bridge-ports": "pass", 46 | "bridge-stp": "pass" 47 | }, 48 | "status": "pass" 49 | } 50 | ] 51 | -------------------------------------------------------------------------------- /docs/examples/interfaces_bridge_template_func: -------------------------------------------------------------------------------- 1 | # 2 | # mako template function to create a bridge 3 | # 4 | # mako defs provide the advantage of declaring predefined functions in 5 | # separate files. 6 | # 7 | # Below is an example that illustrates how to define such functions and use 8 | # them in the /etc/network/interfaces file to create bridges 9 | # 10 | # This file defines a function makebr to create a bridge. The arguments to the 11 | # function are vlan and ip address of the bridge. 12 | # 13 | # The default directory for template functions is 14 | # /etc/network/ifupdown2/templates/. Copy this file under the template 15 | # dir (create the directory if does not exist) 16 | # 17 | # To use this template function in /etc/network/interfaces, add the following 18 | # to the /etc/network/interfaces file: 19 | # 20 | # <%namespace name="bridge" file="/bridge_template"/> 21 | # 22 | # ${bridge.makebr(1096, "10.0.23.2/24")} 23 | # ${bridge.makebr(1097, "10.0.23.3/24")} 24 | # 25 | # 26 | 27 | <%def name="makebr(vlan, addr)"> 28 | auto br${vlan} 29 | iface br${vlan} inet static 30 | address ${addr} 31 | bridge-ports swp1.${vlan} swp2.${vlan} 32 | bridge-stp on 33 | 34 | -------------------------------------------------------------------------------- /tests/output/bridge2.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "bridge", 37 | "auto": true, 38 | "config": { 39 | "bridge-vlan-aware": "yes", 40 | "bridge-ports": "swp_AA_ swp_BB_", 41 | "bridge-pvid": "2", 42 | "bridge-vids": "1-20" 43 | }, 44 | "config_status": { 45 | "bridge-vlan-aware": "pass", 46 | "bridge-ports": "pass", 47 | "bridge-pvid": "", 48 | "bridge-vids": "" 49 | }, 50 | "status": "pass" 51 | } 52 | ] 53 | -------------------------------------------------------------------------------- /tests/output/mac1.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "swp_AA_", 37 | "auto": true, 38 | "config": { 39 | "hwaddress": "90:e2:ba:2c:b1:96" 40 | }, 41 | "config_status": { 42 | "hwaddress": "pass" 43 | }, 44 | "status": "pass" 45 | }, 46 | { 47 | "name": "swp_BB_", 48 | "auto": true, 49 | "config": { 50 | "hwaddress": "90:e2:ba:2c:b2:95" 51 | }, 52 | "config_status": { 53 | "hwaddress": "pass" 54 | }, 55 | "status": "pass" 56 | } 57 | ] 58 | -------------------------------------------------------------------------------- /tests/output/bridge_attr_back_to_default.after.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "br0", 37 | "auto": true, 38 | "config": { 39 | "bridge-ports": "vx42" 40 | }, 41 | "config_status": { 42 | "bridge-ports": "pass" 43 | }, 44 | "status": "pass" 45 | }, 46 | { 47 | "name": "vx42", 48 | "auto": true, 49 | "config": { 50 | "vxlan-id": "42" 51 | }, 52 | "config_status": { 53 | "vxlan-id": "pass" 54 | }, 55 | "status": "pass" 56 | } 57 | ] 58 | 59 | -------------------------------------------------------------------------------- /tests/eni/vxlandev_sanity.eni: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet loopback 3 | 4 | auto eth0 5 | iface eth0 inet dhcp 6 | vrf mgmt 7 | 8 | auto mgmt 9 | iface mgmt 10 | vrf-table auto 11 | 12 | auto bridge 13 | iface bridge 14 | bridge-vlan-aware yes 15 | bridge-ports swp_AA_ swp_BB_ vxlan1000 vxlan10200 16 | bridge-stp on 17 | bridge-vids 100 200 18 | bridge-pvid 1 19 | 20 | auto vxlan1000 21 | iface vxlan1000 22 | vxlan-id 1000 23 | bridge-access 100 24 | vxlan-local-tunnelip 27.0.0.11 25 | mstpctl-portbpdufilter yes 26 | mstpctl-bpduguard yes 27 | 28 | auto vxlan10200 29 | iface vxlan10200 30 | vxlan-id 10200 31 | vxlan-local-tunnelip 6.0.0.15 32 | vxlan-remoteip 6.0.0.16 33 | bridge-learning on 34 | bridge-access 200 35 | 36 | auto bridge.100 37 | iface bridge.100 38 | address 45.0.0.16/26 39 | 40 | auto bridge.200 41 | iface bridge.200 42 | 43 | auto vx0 44 | iface vx0 45 | vxlan-id 42 46 | vxlan-ageing 30 47 | vxlan-local-tunnelip 172.16.20.105 48 | vxlan-svcnodeip 172.16.22.126 49 | vxlan-remoteip 172.16.22.128 50 | vxlan-learning yes 51 | vxlan-purge-remotes yes 52 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: ifupdown2 3 | Upstream-Contact: Julien Fortin 4 | Source: https://github.com/cumulusnetworks/ifupdown2 5 | 6 | Files: * 7 | Copyright: 2014,2015,2016,2017,2018,2019,2020,2021,2022 Cumulus Networks, Inc. 8 | License: GPL-2 9 | 10 | Files: debian/* 11 | Copyright: 2014,2015,2016,2017,2018,2019,2020,2021,2022 Cumulus Networks, Inc. 12 | License: GPL-2 13 | 14 | License: GPL-2 15 | This package is free software; you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as published by 17 | the Free Software Foundation; version 2 of the License 18 | . 19 | This package is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | . 24 | You should have received a copy of the GNU General Public License 25 | along with this program. If not, see 26 | . 27 | On Debian systems, the complete text of the GNU General 28 | Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". 29 | -------------------------------------------------------------------------------- /debian/ifupdown2.postrm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | MYNAME="${0##*/}" 5 | 6 | report() { echo "${MYNAME}: $*" ; } 7 | report_warn() { report "Warning: $*" >&2 ; } 8 | report_err() { report "Error: $*" >&2 ; } 9 | 10 | process_state_file() 11 | { 12 | rm -f /run/network/ifstatenew 13 | } 14 | 15 | process_udev() 16 | { 17 | if [ -e /etc/udev/rules.d/80-networking.rules ]; then 18 | udevlink=$(readlink /etc/udev/rules.d/80-networking.rules 2>/dev/null || true) 19 | [ -n "$udevlink" -a "$udevlink" = "/dev/null" ] && rm -f /etc/udev/rules.d/80-networking.rules 20 | fi 21 | 22 | if [ -e /etc/udev/rules.d/60-bridge-network-interface.rules ]; then 23 | udevlink=$(readlink /etc/udev/rules.d/60-bridge-network-interface.rules 2>/dev/null || true) 24 | [ -n "$udevlink" -a "$udevlink" = "/dev/null" ] && rm -f /etc/udev/rules.d/60-bridge-network-interface.rules 25 | fi 26 | } 27 | 28 | case "$1" in 29 | purge|remove|abort-install|disappear) 30 | process_state_file 31 | process_udev 32 | ;; 33 | 34 | upgrade|failed-upgrade|abort-upgrade|disappear) 35 | ;; 36 | 37 | *) 38 | echo "postrm called with unknown argument \`$1'" >&2 39 | exit 1 40 | ;; 41 | esac 42 | 43 | 44 | #DEBHELPER# 45 | 46 | exit 0 47 | -------------------------------------------------------------------------------- /tests/output/bridge_new_attribute_igmp_mld.after.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "br0", 37 | "auto": true, 38 | "config": { 39 | "bridge-vlan-aware": "yes", 40 | "bridge-ports": "swp_AA_" 41 | }, 42 | "config_status": { 43 | "bridge-vlan-aware": "pass", 44 | "bridge-ports": "pass" 45 | }, 46 | "status": "pass" 47 | }, 48 | { 49 | "name": "br1", 50 | "auto": true, 51 | "config": { 52 | "bridge-ports": "swp_BB_" 53 | }, 54 | "config_status": { 55 | "bridge-ports": "pass" 56 | }, 57 | "status": "pass" 58 | } 59 | ] 60 | -------------------------------------------------------------------------------- /tests/output/address.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "swp_AA_", 37 | "auto": true, 38 | "config": { 39 | "address": [ 40 | "192.0.2.1/32", 41 | "192.0.2.42/32", 42 | "192.0.42.1/32", 43 | "192.42.2.42/32", 44 | "2001:db8::1/128", 45 | "2001:db8::42/128", 46 | "2042:db8::1/128" 47 | ] 48 | }, 49 | "config_status": { 50 | "address": [ 51 | "pass", 52 | "pass", 53 | "pass", 54 | "pass", 55 | "pass", 56 | "pass", 57 | "pass" 58 | ] 59 | }, 60 | "status": "pass" 61 | } 62 | ] 63 | -------------------------------------------------------------------------------- /tests/output/address_gateway.empty_addrs.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "swp_AA_", 37 | "auto": true, 38 | "config": { 39 | "link-down": "yes" 40 | }, 41 | "config_status": { 42 | "link-down": "pass" 43 | }, 44 | "status": "pass" 45 | }, 46 | { 47 | "name": "br1", 48 | "auto": true, 49 | "config": { 50 | "address-virtual": "44:39:39:FF:30:00 10.8.22.1/23 2001:0388:6080:0340::1/64", 51 | "bridge-ports": "swp_AA_.3000" 52 | }, 53 | "config_status": { 54 | "address-virtual": "pass", 55 | "bridge-ports": "pass" 56 | }, 57 | "status": "pass" 58 | } 59 | ] 60 | -------------------------------------------------------------------------------- /tests/eni/bridge_attr_back_to_default.eni: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet loopback 3 | 4 | auto eth0 5 | iface eth0 inet dhcp 6 | vrf mgmt 7 | 8 | auto mgmt 9 | iface mgmt 10 | vrf-table auto 11 | 12 | auto br0 13 | iface br0 14 | bridge-ports vx42 15 | bridge-vlan-aware yes 16 | bridge-stp off 17 | bridge-bridgeprio 42 18 | bridge-ageing 42 19 | bridge-fd 29 20 | bridge-hello 10 21 | bridge-maxage 10 22 | bridge-pathcosts vx42=42 23 | bridge-portprios vx42=10 24 | bridge-mclmc 42 25 | bridge-mcrouter no 26 | bridge-mcsnoop no 27 | bridge-mcsqc 42 28 | bridge-mcqifaddr yes 29 | bridge-mcquerier yes 30 | bridge-hashmax 1024 31 | bridge-mclmi 42 32 | bridge-mcmi 42 33 | bridge-mcqpi 42 34 | bridge-mcqi 42 35 | bridge-mcqri 42 36 | bridge-mcsqi 42 37 | bridge-portmcfl vx42=yes 38 | bridge-learning vx42=off 39 | bridge-igmp-version 3 40 | bridge-mld-version 2 41 | bridge-unicast-flood vx42=off 42 | bridge-multicast-flood vx42=off 43 | bridge-vlan-protocol 802.1ad 44 | bridge-vlan-stats off 45 | bridge-arp-nd-suppress vx42=on 46 | bridge-mcstats off 47 | bridge-l2protocol-tunnel all 48 | 49 | auto vx42 50 | iface vx42 51 | vxlan-id 42 52 | bridge-access 42 53 | -------------------------------------------------------------------------------- /ifupdown2/ifupdown/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved. 2 | # Authors: 3 | # Roopa Prabhu, roopa@cumulusnetworks.com 4 | # Julien Fortin, julien@cumulusnetworks.com 5 | # 6 | # ifupdown -- 7 | # exceptions 8 | # 9 | 10 | import logging 11 | 12 | log = logging.getLogger() 13 | 14 | 15 | class Error(Exception): 16 | """Base class for exceptions in ifupdown""" 17 | 18 | def log_error(self): 19 | log.error(self.message) 20 | 21 | def log_warning(self): 22 | log.warning(self.message) 23 | 24 | def log_info(self): 25 | log.info(self.message) 26 | 27 | def log_debug(self): 28 | log.debug(self.message) 29 | 30 | 31 | class ArgvParseError(Error): 32 | """ 33 | Exception coming from argv parsing 34 | """ 35 | pass 36 | 37 | 38 | class ArgvParseHelp(Error): 39 | """ 40 | When ifupdown2 is called with --help argparse raise SystemExit 41 | we need to catch this to properly print the help and exit 0 not 1 42 | """ 43 | pass 44 | 45 | 46 | class ifaceNotFoundError(Error): 47 | pass 48 | 49 | 50 | class invalidValueError(Error): 51 | pass 52 | 53 | 54 | class errorReadingStateError(Error): 55 | pass 56 | 57 | 58 | class moduleNotSupported(Error): 59 | pass 60 | 61 | 62 | class ReservedVlanException(Error): 63 | pass 64 | -------------------------------------------------------------------------------- /tests/output/bridge5.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "swp_AA_", 37 | "auto": true, 38 | "config": {}, 39 | "config_status": {}, 40 | "status": "pass" 41 | }, 42 | { 43 | "name": "swp_BB_", 44 | "auto": true, 45 | "config": {}, 46 | "config_status": {}, 47 | "status": "pass" 48 | }, 49 | { 50 | "name": "bridge", 51 | "auto": true, 52 | "config": { 53 | "bridge-vlan-aware": "yes", 54 | "bridge-ports": "swp_AA_ swp_BB_", 55 | "bridge-vids": "1-200" 56 | }, 57 | "config_status": { 58 | "bridge-vlan-aware": "pass", 59 | "bridge-ports": "pass", 60 | "bridge-vids": "" 61 | }, 62 | "status": "pass" 63 | } 64 | ] -------------------------------------------------------------------------------- /tests/output/address_gateway.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "swp_AA_", 37 | "auto": true, 38 | "config": { 39 | "link-down": "yes", 40 | "address": "10.0.14.3/14" 41 | }, 42 | "config_status": { 43 | "link-down": "pass", 44 | "address": "pass" 45 | }, 46 | "status": "pass" 47 | }, 48 | { 49 | "name": "br1", 50 | "auto": true, 51 | "config": { 52 | "address-virtual": "44:39:39:FF:30:00 10.8.22.1/23 2001:0388:6080:0340::1/64", 53 | "bridge-ports": "swp_AA_.3000", 54 | "address": "10.8.22.2/23" 55 | }, 56 | "config_status": { 57 | "address-virtual": "pass", 58 | "bridge-ports": "pass", 59 | "address": "pass" 60 | }, 61 | "status": "pass" 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /tests/output/bridge_new_attribute_vlan_protocol_stats.after.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "br0", 37 | "auto": true, 38 | "config": { 39 | "bridge-vlan-protocol": "802.1ad", 40 | "bridge-vlan-aware": "yes", 41 | "bridge-ports": "swp_AA_" 42 | }, 43 | "config_status": { 44 | "bridge-vlan-protocol": "pass", 45 | "bridge-vlan-aware": "pass", 46 | "bridge-ports": "pass" 47 | }, 48 | "status": "pass" 49 | }, 50 | { 51 | "name": "br1", 52 | "auto": true, 53 | "config": { 54 | "bridge-vlan-protocol": "802.1ad", 55 | "bridge-ports": "swp_BB_" 56 | }, 57 | "config_status": { 58 | "bridge-vlan-protocol": "pass", 59 | "bridge-ports": "pass" 60 | }, 61 | "status": "pass" 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /docs/source/apiref.rst: -------------------------------------------------------------------------------- 1 | Documentation for the Code 2 | ************************** 3 | 4 | 5 | ifupdownmain 6 | ============ 7 | 8 | ifupdownmain is the main ifupdown module. 9 | 10 | .. automodule:: ifupdownmain 11 | 12 | .. autoclass:: ifupdownMain 13 | :members: up, down, reload, query 14 | 15 | iface 16 | ===== 17 | 18 | .. automodule:: iface 19 | 20 | .. autoclass:: iface 21 | :members: state, status, flags, priv_flags, refcnt, lowerifaces, upperifaces, add_to_upperifaces, get_attr_value, get_attr_value_first, get_attr_value_n, update_config, update_config_with_status, get_config_attr_status, compare, dump_raw, dump, dump_pretty 22 | 23 | .. autoclass:: ifaceState 24 | 25 | .. autoclass:: ifaceStatus 26 | 27 | .. autoclass:: ifaceJsonEncoder 28 | 29 | scheduler 30 | ========= 31 | 32 | .. automodule:: scheduler 33 | 34 | .. autoclass:: ifaceScheduler 35 | :members: sched_ifaces 36 | 37 | .. autoclass:: ifaceSchedulerFlags 38 | 39 | 40 | networkinterfaces 41 | ================= 42 | 43 | .. automodule:: networkinterfaces 44 | 45 | .. autoclass:: networkInterfaces 46 | :members: load, subscribe 47 | 48 | statemanager 49 | ============ 50 | 51 | .. automodule:: statemanager 52 | 53 | .. autoclass:: pickling 54 | :members: save, save_obj, load 55 | 56 | .. autoclass:: stateManager 57 | :members: read_saved_state, save_state 58 | 59 | graph 60 | ===== 61 | 62 | .. automodule:: graph 63 | 64 | .. autoclass:: graph 65 | :members: topological_sort_graphs_all, generate_dots 66 | -------------------------------------------------------------------------------- /tests/eni/bond.eni: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet loopback 3 | 4 | auto eth0 5 | iface eth0 inet dhcp 6 | vrf mgmt 7 | 8 | auto mgmt 9 | iface mgmt 10 | vrf-table auto 11 | 12 | auto bond0 13 | iface bond0 14 | bond-slaves swp_AA_ 15 | bond-use-carrier yes 16 | bond-num-grat-arp 0 17 | bond-num-unsol-na 0 18 | bond-xmit-hash-policy layer2 19 | bond-miimon 0 20 | bond-min-links 0 21 | bond-mode balance-rr 22 | bond-updelay 0 23 | 24 | auto bond1 25 | iface bond1 26 | bond-slaves swp_BB_ 27 | bond-use-carrier no 28 | bond-num-grat-arp 255 29 | bond-num-unsol-na 255 30 | bond-xmit-hash-policy layer3+4 31 | bond-miimon 255 32 | bond-min-links 255 33 | bond-mode active-backup 34 | bond-updelay 65535 35 | 36 | auto bond2 37 | iface bond2 38 | bond-slaves swp_CC_ 39 | bond-use-carrier 0 40 | bond-num-grat-arp 1 41 | bond-num-unsol-na 1 42 | bond-xmit-hash-policy layer2+3 43 | bond-miimon 1 44 | bond-min-links 1 45 | bond-mode balance-xor 46 | bond-updelay 1 47 | 48 | auto bond3 49 | iface bond3 50 | bond-slaves swp_DD_ 51 | bond-use-carrier 1 52 | bond-num-grat-arp 42 53 | bond-num-unsol-na 42 54 | bond-miimon 42 55 | bond-min-links 42 56 | bond-mode broadcast 57 | bond-updelay 42 58 | 59 | auto bond5 60 | iface bond5 61 | bond-slaves swp_FF_ 62 | bond-mode balance-tlb 63 | 64 | auto bond6 65 | iface bond6 66 | bond-slaves swp_GG_ 67 | bond-mode balance-alb 68 | -------------------------------------------------------------------------------- /ifupdown2/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | __version__ = '3.9.0' 5 | 6 | # Copyright (C) 2014,2015,2016,2017,2018,2019,2020 Cumulus Networks, Inc. All rights reserved 7 | # 8 | # This program is free software; you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License as 10 | # published by the Free Software Foundation; version 2. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | # General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | # 02110-1301, USA. 21 | # 22 | # https://www.gnu.org/licenses/gpl-2.0-standalone.html 23 | # 24 | # Authors: 25 | # Roopa Prabhu, roopa@cumulusnetworks.com 26 | # Julien Fortin, julien@cumulusnetworks.com 27 | 28 | __license__ = 'GPL-2' 29 | __status__ = 'Production' 30 | __copyright__ = 'Copyright (C) 2014,2015,2016,2017,2018,2019,2020 Cumulus Networks, Inc.' 31 | 32 | 33 | __authors__ = [ 34 | 'Roopa Prabhu', 35 | 'Julien Fortin' 36 | ] 37 | __credits__ = [ 38 | 'Roopa Prabhu', 39 | 'Julien Fortin' 40 | ] 41 | __emails__ = [ 42 | 'roopa@cumulusnetworks.com', 43 | 'julien@cumulusnetworks.com' 44 | ] 45 | __maintainer__ = 'Julien Fortin' 46 | __email__ = 'julien@cumulusnetworks.com' 47 | -------------------------------------------------------------------------------- /tests/output/bridge_new_attribute_igmp_mld.before.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "br0", 37 | "auto": true, 38 | "config": { 39 | "bridge-igmp-version": "3", 40 | "bridge-ports": "swp_AA_", 41 | "bridge-vlan-aware": "yes", 42 | "bridge-mld-version": "2" 43 | }, 44 | "config_status": { 45 | "bridge-igmp-version": "pass", 46 | "bridge-ports": "pass", 47 | "bridge-vlan-aware": "pass", 48 | "bridge-mld-version": "pass" 49 | }, 50 | "status": "pass" 51 | }, 52 | { 53 | "name": "br1", 54 | "auto": true, 55 | "config": { 56 | "bridge-mld-version": "2", 57 | "bridge-igmp-version": "3", 58 | "bridge-ports": "swp_BB_" 59 | }, 60 | "config_status": { 61 | "bridge-mld-version": "pass", 62 | "bridge-igmp-version": "pass", 63 | "bridge-ports": "pass" 64 | }, 65 | "status": "pass" 66 | } 67 | ] 68 | -------------------------------------------------------------------------------- /tests/output/bridge3.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "swp_AA_", 37 | "auto": true, 38 | "config": { 39 | "bridge-access": "100" 40 | }, 41 | "config_status": { 42 | "bridge-access": "pass" 43 | }, 44 | "status": "pass" 45 | }, 46 | { 47 | "name": "swp_BB_", 48 | "auto": true, 49 | "config": { 50 | "bridge-vids": "200" 51 | }, 52 | "config_status": { 53 | "bridge-vids": "pass" 54 | }, 55 | "status": "pass" 56 | }, 57 | { 58 | "name": "bridge", 59 | "auto": true, 60 | "config": { 61 | "bridge-vlan-aware": "yes", 62 | "bridge-ports": "swp_AA_ swp_BB_", 63 | "bridge-pvid": "2", 64 | "bridge-vids": "1-20" 65 | }, 66 | "config_status": { 67 | "bridge-vlan-aware": "pass", 68 | "bridge-ports": "pass", 69 | "bridge-pvid": "", 70 | "bridge-vids": "" 71 | }, 72 | "status": "pass" 73 | } 74 | ] 75 | -------------------------------------------------------------------------------- /ifupdown2/lib/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2017, 2018, 2019 Cumulus Networks, Inc. all rights reserved 2 | # 3 | # This program is free software; you can redistribute it and/or 4 | # modify it under the terms of the GNU General Public License as 5 | # published by the Free Software Foundation; version 2. 6 | # 7 | # This program is distributed in the hope that it will be useful, 8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | # General Public License for more details. 11 | # 12 | # You should have received a copy of the GNU General Public License 13 | # along with this program; if not, write to the Free Software 14 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 | # 02110-1301, USA. 16 | # 17 | # https://www.gnu.org/licenses/gpl-2.0-standalone.html 18 | # 19 | # Author: 20 | # Julien Fortin, julien@cumulusnetworks.com 21 | # 22 | # ifupdown2 custom exceptions 23 | # 24 | 25 | 26 | class Ifupdown2Exception(Exception): 27 | pass 28 | 29 | 30 | class ExitWithStatus(Ifupdown2Exception): 31 | 32 | def __init__(self, status): 33 | Ifupdown2Exception.__init__(self) 34 | self.status = status 35 | 36 | def get_status(self): 37 | return self.status 38 | 39 | 40 | class ExitWithStatusAndError(ExitWithStatus): 41 | def __init__(self, status, message): 42 | ExitWithStatus.__init__(self, status) 43 | self.message = message 44 | 45 | 46 | class RetryCMD(Ifupdown2Exception): 47 | def __init__(self, cmd): 48 | Ifupdown2Exception.__init__(self) 49 | self.cmd = cmd 50 | -------------------------------------------------------------------------------- /tests/output/bridge_new_attribute_vlan_protocol_stats.before.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "br0", 37 | "auto": true, 38 | "config": { 39 | "bridge-vlan-protocol": "802.1ad", 40 | "bridge-vlan-stats": "on", 41 | "bridge-vlan-aware": "yes", 42 | "bridge-ports": "swp_AA_" 43 | }, 44 | "config_status": { 45 | "bridge-vlan-protocol": "pass", 46 | "bridge-vlan-stats": "pass", 47 | "bridge-vlan-aware": "pass", 48 | "bridge-ports": "pass" 49 | }, 50 | "status": "pass" 51 | }, 52 | { 53 | "name": "br1", 54 | "auto": true, 55 | "config": { 56 | "bridge-vlan-protocol": "802.1ad", 57 | "bridge-vlan-stats": "off", 58 | "bridge-ports": "swp_BB_" 59 | }, 60 | "config_status": { 61 | "bridge-vlan-protocol": "pass", 62 | "bridge-vlan-stats": "pass", 63 | "bridge-ports": "pass" 64 | }, 65 | "status": "pass" 66 | } 67 | ] 68 | -------------------------------------------------------------------------------- /docs/examples/batman_adv/configure_batman_adv.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Installing batman-adv module on debian/ubuntu" 4 | echo "" 5 | echo "Batman is a Layer2-Mesh protocol which uses Ethernet devices (like eth*, 6 | vlans, etc.) to communicate with peers and provides access to the L2-mesh via 7 | a batX interface. You can only create a batman instance if at least one batman- 8 | -iface (read: an interface where the mesh protocol is spoken on) is present and 9 | added to the batman-mesh-instance." 10 | echo "More info: https://en.wikipedia.org/wiki/B.A.T.M.A.N." 11 | echo "" 12 | 13 | echo "installing batctl: apt-get install batctl" 14 | apt-get install batctl 15 | echo "" 16 | echo "" 17 | 18 | echo "loading batman-adv module: modprobe batman-adv" 19 | modprobe batman-adv 20 | echo "" 21 | 22 | echo "usefull commands: 23 | $ batctl if add \$IFACE 24 | $ batctl -m bat0 if add \$IFACE" 25 | echo "please read: man batctl" 26 | echo "" 27 | echo "" 28 | 29 | echo "configuration example: 30 | $ cat /etc/network/interfaces 31 | 32 | auto bat0 33 | iface bat0 34 | batman-ifaces \$IFACE [\$IFACES...] 35 | batman-ifaces-ignore-regex .*_nodes 36 | batman-hop-penalty 23 37 | address 192.0.2.42/24 38 | $ 39 | $ 40 | $ ifreload -a 41 | $ ifquery -a -c 42 | auto bat0 43 | iface bat0 [pass] 44 | batman-ifaces tap0 tap1 [pass] 45 | batman-ifaces-ignore-regex .*_nodes [pass] 46 | batman-hop-penalty 23 [pass] 47 | address 192.0.2.42/24 [pass] 48 | 49 | $" 50 | -------------------------------------------------------------------------------- /tests/output/bridge4.vlan.show.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ifname": "swp_AA_", 4 | "vlans": [ 5 | { 6 | "vlan": 1 7 | }, 8 | { 9 | "vlan": 2 10 | }, 11 | { 12 | "vlan": 3 13 | }, 14 | { 15 | "vlan": 4, 16 | "flags": [ 17 | "PVID", 18 | "Egress Untagged" 19 | ] 20 | }, 21 | { 22 | "vlan": 5 23 | }, 24 | { 25 | "vlan": 6 26 | }, 27 | { 28 | "vlan": 7 29 | }, 30 | { 31 | "vlan": 8 32 | }, 33 | { 34 | "vlan": 9 35 | }, 36 | { 37 | "vlan": 10 38 | }, 39 | { 40 | "vlan": 11 41 | }, 42 | { 43 | "vlan": 12 44 | }, 45 | { 46 | "vlan": 13 47 | }, 48 | { 49 | "vlan": 14 50 | }, 51 | { 52 | "vlan": 15 53 | }, 54 | { 55 | "vlan": 16 56 | }, 57 | { 58 | "vlan": 17 59 | }, 60 | { 61 | "vlan": 18 62 | }, 63 | { 64 | "vlan": 19 65 | }, 66 | { 67 | "vlan": 20 68 | } 69 | ] 70 | }, 71 | { 72 | "ifname": "swp_BB_", 73 | "vlans": [ 74 | { 75 | "vlan": 3, 76 | "flags": [ 77 | "PVID", 78 | "Egress Untagged" 79 | ] 80 | }, 81 | { 82 | "vlan": 40 83 | } 84 | ] 85 | }, 86 | { 87 | "ifname": "bridge", 88 | "vlans": [ 89 | { 90 | "vlan": 1, 91 | "flags": [ 92 | "PVID", 93 | "Egress Untagged" 94 | ] 95 | } 96 | ] 97 | } 98 | ] 99 | -------------------------------------------------------------------------------- /docs/source/intro.rst: -------------------------------------------------------------------------------- 1 | python-ifupdown2 2 | ---------------- 3 | 4 | The python-ifupdown2 package provides the infrastructure for 5 | parsing /etc/network/interfaces file, loading, scheduling, template parsing, 6 | state management and interface dependency generation of interfaces. 7 | It dynamically loads python addon modules from /usr/share/ifupdownmodules. 8 | To remain compatible with other packages that depend on ifupdown, it also 9 | executes scripts under /etc/network/. To make the transition smoother, a 10 | python module under /usr/share/ifupdownmodules will override a script by 11 | the same name under /etc/network/. ifupdown2 publishes an interface object which 12 | is passed to all loadble python addon modules. All lodable modules are 13 | called for every interface declared in the /etc/network/interfaces file. 14 | 15 | Addon modules are responsible for applying interface configuration. 16 | python-ifupdown2 ships with a set of default addon modules. Each module can 17 | declare its own set of supported attributes. Each module is passed the iface 18 | object (which is a representation of /etc/network/interfaces 19 | iface entry). Each module is also passed the operation to be performed. 20 | 21 | Example modules are /usr/share/ifupdownmodules/address.py, 22 | /usr/share/ifupdownmodules/bridge.py etc 23 | 24 | The order in which these modules are invoked is listed in 25 | /var/lib/ifupdownaddons/addons.conf. There is an ifaddon utility in the works 26 | to better manage the module ordering. 27 | 28 | For more details on adding an addon module, see the section on adding python 29 | modules. For details on how to write a module, see the api reference and 30 | development documentation. 31 | 32 | -------------------------------------------------------------------------------- /tests/output/bridge4.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "swp_AA_", 37 | "auto": true, 38 | "config": { 39 | "bridge-pvid": "4" 40 | }, 41 | "config_status": { 42 | "bridge-pvid": "pass" 43 | }, 44 | "status": "pass" 45 | }, 46 | { 47 | "name": "swp_BB_", 48 | "auto": true, 49 | "config": { 50 | "bridge-vids": "40", 51 | "bridge-pvid": "3" 52 | }, 53 | "config_status": { 54 | "bridge-vids": "pass", 55 | "bridge-pvid": "pass" 56 | }, 57 | "status": "pass" 58 | }, 59 | { 60 | "name": "bridge", 61 | "auto": true, 62 | "config": { 63 | "bridge-vlan-aware": "yes", 64 | "bridge-ports": "swp_AA_ swp_BB_", 65 | "bridge-vids": "1-20", 66 | "bridge-pvid": "2" 67 | }, 68 | "config_status": { 69 | "bridge-vlan-aware": "pass", 70 | "bridge-ports": "pass", 71 | "bridge-vids": "", 72 | "bridge-pvid": "" 73 | }, 74 | "status": "pass" 75 | } 76 | ] 77 | -------------------------------------------------------------------------------- /tests/eni/evpn_vab_clag_riot_flood_sup_off_config_tors2.eni: -------------------------------------------------------------------------------- 1 | auto eth0 2 | iface eth0 inet dhcp 3 | vrf mgmt 4 | 5 | auto mgmt 6 | iface mgmt 7 | vrf-table auto 8 | 9 | auto lo 10 | iface lo 11 | address 27.0.0.16/32 12 | alias BGP un-numbered Use for Vxlan Src Tunnel 13 | 14 | auto uplink 15 | iface uplink 16 | bond-slaves swp_AA_ swp_BB_ 17 | bond-mode 802.3ad 18 | bond-min-links 1 19 | bond-lacp-rate 1 20 | mtu 9202 21 | 22 | auto hostbond3 23 | iface hostbond3 24 | bond-slaves swp_CC_ swp_DD_ 25 | bond-mode 802.3ad 26 | bond-min-links 1 27 | bond-lacp-rate 1 28 | mtu 9152 29 | bridge-pvid 1000 30 | 31 | 32 | auto vx-1000 33 | iface vx-1000 34 | vxlan-id 1000 35 | bridge-access 1000 36 | vxlan-local-tunnelip 27.0.0.16 37 | bridge-learning off 38 | mstpctl-portbpdufilter yes 39 | mstpctl-bpduguard yes 40 | mtu 9152 41 | 42 | auto vx-1001 43 | iface vx-1001 44 | vxlan-id 1001 45 | bridge-access 1001 46 | vxlan-local-tunnelip 27.0.0.16 47 | bridge-learning off 48 | mstpctl-portbpdufilter yes 49 | mstpctl-bpduguard yes 50 | mtu 9152 51 | 52 | auto bridge 53 | iface bridge 54 | bridge-vlan-aware yes 55 | bridge-ports vx-1000 vx-1001 hostbond3 56 | bridge-stp on 57 | bridge-vids 1000-1004 58 | bridge-pvid 1 59 | 60 | auto vlan1000 61 | iface vlan1000 62 | address 45.0.0.2/24 63 | vlan-id 1000 64 | vlan-raw-device bridge 65 | address-virtual 00:00:5e:00:01:01 45.0.0.1/24 2001:fee1::1/64 66 | 67 | auto vlan1001 68 | iface vlan1001 69 | address 45.0.1.2/24 70 | vlan-id 1001 71 | vlan-raw-device bridge 72 | address-virtual 00:00:5e:00:01:01 45.0.1.1/24 2001:fee1:0:1::1/64 73 | -------------------------------------------------------------------------------- /tests/output/bridge_access.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "vxlan1", 37 | "auto": true, 38 | "config": { 39 | "vxlan-id": "1", 40 | "bridge-access": "1", 41 | "vxlan-local-tunnelip": "27.0.0.11" 42 | }, 43 | "config_status": { 44 | "vxlan-id": "pass", 45 | "bridge-access": "pass", 46 | "vxlan-local-tunnelip": "pass" 47 | }, 48 | "status": "pass" 49 | }, 50 | { 51 | "name": "vxlan500", 52 | "auto": true, 53 | "config": { 54 | "vxlan-id": "500", 55 | "bridge-access": "500", 56 | "vxlan-local-tunnelip": "27.0.0.11" 57 | }, 58 | "config_status": { 59 | "vxlan-id": "pass", 60 | "bridge-access": "pass", 61 | "vxlan-local-tunnelip": "pass" 62 | }, 63 | "status": "pass" 64 | }, 65 | { 66 | "name": "br0", 67 | "auto": true, 68 | "config": { 69 | "bridge-vlan-aware": "yes", 70 | "bridge-ports": "vxlan1 vxlan500" 71 | }, 72 | "config_status": { 73 | "bridge-vlan-aware": "pass", 74 | "bridge-ports": "pass" 75 | }, 76 | "status": "pass" 77 | } 78 | ] 79 | -------------------------------------------------------------------------------- /docs/examples/interfaces: -------------------------------------------------------------------------------- 1 | # This file describes the network interfaces available on your system 2 | # and how to activate them. For more information, see interfaces(5). 3 | 4 | # The loopback network interface 5 | auto lo 6 | iface lo inet loopback 7 | 8 | # The primary network interface 9 | auto eth0 10 | iface eth0 inet dhcp 11 | 12 | #source /etc/network/interfaces.d/template.bridges 13 | 14 | # swp interface 15 | auto swp30 16 | iface swp30 17 | address 12.0.0.4/24 18 | address 12.0.0.6/24 19 | address 2000:1000:1000:1000:3::5/128 20 | mtu 1600 21 | alias "test network" 22 | link-duplex full 23 | link-speed 1000 24 | link-autoneg no 25 | 26 | # bond interface 27 | auto bond3 28 | iface bond3 inet static 29 | bond-slaves swp1 swp2 30 | bond-mode 802.3ad 31 | bond-miimon 100 32 | bond-use-carrier yes 33 | bond-lacp-rate 1 34 | bond-min-links 1 35 | bond-xmit_hash_policy layer3+4 36 | 37 | # bond interface 38 | auto bond4 39 | iface bond4 inet static 40 | bond-slaves swp3 swp4 41 | bond-mode 802.3ad 42 | bond-miimon 100 43 | bond-use-carrier yes 44 | bond-lacp-rate 1 45 | bond-min-links 1 46 | bond-xmit_hash_policy layer3+4 47 | 48 | # bridge interface 49 | auto br0 50 | iface br0 51 | address 12.0.0.4/24 52 | address 12.0.0.6/24 53 | address 2000:1000:1000:1000:3::5/128 54 | bridge-ports bond3 bond4 swp5 swp8 55 | bridge-stp on 56 | 57 | # vlan interface on bond 58 | auto bond3.2000 59 | iface bond3.2000 inet static 60 | 61 | auto bond4.2000 62 | iface bond4.2000 inet static 63 | 64 | auto br2000 65 | iface br2000 inet6 static 66 | address 2001:dad:beef::4/64 67 | bridge-ports bond3.2000 bond4.2000 swp5.2000 68 | bridge-stp on 69 | mstpctl-treeprio 61440 70 | mstpctl-portp2p bond3.2000=yes bond4.2000=yes 71 | -------------------------------------------------------------------------------- /tests/output/bridge_new_attribute_ucast_mcast_flood.before.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "swp_AA_", 37 | "auto": true, 38 | "config": { 39 | "bridge-unicast-flood": "on", 40 | "bridge-multicast-flood": "on" 41 | }, 42 | "config_status": { 43 | "bridge-unicast-flood": "pass", 44 | "bridge-multicast-flood": "pass" 45 | }, 46 | "status": "pass" 47 | }, 48 | { 49 | "name": "br0", 50 | "auto": true, 51 | "config": { 52 | "bridge-vlan-aware": "yes", 53 | "bridge-ports": "swp_AA_" 54 | }, 55 | "config_status": { 56 | "bridge-vlan-aware": "pass", 57 | "bridge-ports": "pass" 58 | }, 59 | "status": "pass" 60 | }, 61 | { 62 | "name": "br1", 63 | "auto": true, 64 | "config": { 65 | "bridge-unicast-flood": "swp_BB_=on", 66 | "bridge-multicast-flood": "swp_BB_=on", 67 | "bridge-ports": "swp_BB_" 68 | }, 69 | "config_status": { 70 | "bridge-unicast-flood": "pass", 71 | "bridge-multicast-flood": "pass", 72 | "bridge-ports": "pass" 73 | }, 74 | "status": "pass" 75 | } 76 | ] 77 | -------------------------------------------------------------------------------- /tests/output/bridge_igmp_version.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "br0", 37 | "auto": true, 38 | "config": { 39 | "bridge-igmp-version": "3", 40 | "bridge-ports": "swp_AA_", 41 | "bridge-vlan-aware": "yes", 42 | "bridge-mld-version": "2" 43 | }, 44 | "config_status": { 45 | "bridge-igmp-version": "pass", 46 | "bridge-ports": "pass", 47 | "bridge-vlan-aware": "pass", 48 | "bridge-mld-version": "pass" 49 | }, 50 | "status": "pass" 51 | }, 52 | { 53 | "name": "br1", 54 | "auto": true, 55 | "config": { 56 | "bridge-mld-version": "2", 57 | "bridge-igmp-version": "3", 58 | "bridge-ports": "swp_BB_" 59 | }, 60 | "config_status": { 61 | "bridge-mld-version": "pass", 62 | "bridge-igmp-version": "pass", 63 | "bridge-ports": "pass" 64 | }, 65 | "status": "pass" 66 | }, 67 | { 68 | "name": "br2", 69 | "auto": true, 70 | "config": { 71 | "bridge-ports": "swp_CC_" 72 | }, 73 | "config_status": { 74 | "bridge-ports": "pass" 75 | }, 76 | "status": "pass" 77 | } 78 | ] 79 | -------------------------------------------------------------------------------- /tests/output/bridge_new_attribute_ucast_mcast_flood.after.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "swp_AA_", 37 | "auto": true, 38 | "config": { 39 | "bridge-unicast-flood": "off", 40 | "bridge-multicast-flood": "off" 41 | }, 42 | "config_status": { 43 | "bridge-unicast-flood": "pass", 44 | "bridge-multicast-flood": "pass" 45 | }, 46 | "status": "pass" 47 | }, 48 | { 49 | "name": "br0", 50 | "auto": true, 51 | "config": { 52 | "bridge-vlan-aware": "yes", 53 | "bridge-ports": "swp_AA_" 54 | }, 55 | "config_status": { 56 | "bridge-vlan-aware": "pass", 57 | "bridge-ports": "pass" 58 | }, 59 | "status": "pass" 60 | }, 61 | { 62 | "name": "br1", 63 | "auto": true, 64 | "config": { 65 | "bridge-unicast-flood": "swp_BB_=off", 66 | "bridge-multicast-flood": "swp_BB_=off", 67 | "bridge-ports": "swp_BB_" 68 | }, 69 | "config_status": { 70 | "bridge-unicast-flood": "pass", 71 | "bridge-multicast-flood": "pass", 72 | "bridge-ports": "pass" 73 | }, 74 | "status": "pass" 75 | } 76 | ] 77 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: ifupdown2 2 | Section: admin 3 | Priority: optional 4 | Maintainer: Julien Fortin 5 | Build-Depends: debhelper (>= 10), 6 | dh-python, 7 | python3, 8 | python3-all, 9 | python3-setuptools, 10 | python3-docutils 11 | Standards-Version: 4.5.0.2 12 | Homepage: https://github.com/cumulusnetworks/ifupdown2 13 | X-Python-Version: >= 3.7 14 | 15 | Package: ifupdown2 16 | Architecture: all 17 | Provides: ifupdown 18 | Conflicts: ifupdown 19 | Replaces: ifupdown 20 | Depends: ${python3:Depends}, ${misc:Depends}, iproute2, python3-six, python3-setuptools, python3-systemd 21 | Suggests: isc-dhcp-client, bridge-utils, ethtool, python3-gvgen, python3-mako 22 | Description: Network Interface Management tool similar to ifupdown 23 | ifupdown2 is ifupdown re-written in Python. It replaces ifupdown and provides 24 | the same user interface as ifupdown for network interface configuration. 25 | Like ifupdown, ifupdown2 is a high level tool to configure (or, respectively 26 | deconfigure) network interfaces based on interface definitions in 27 | /etc/network/interfaces. It is capable of detecting network interface 28 | dependencies and comes with several new features which are available as 29 | new command options to ifup/ifdown/ifquery commands. It also comes with a new 30 | command ifreload to reload interface configuration with minimum 31 | disruption. Most commands are also capable of input and output in JSON format. 32 | It is backward compatible with ifupdown /etc/network/interfaces format and 33 | supports newer simplified format. It also supports interface templates with 34 | python-mako for large scale interface deployments. See 35 | /usr/share/doc/ifupdown2/README.rst for details about ifupdown2. Examples 36 | are available under /usr/share/doc/ifupdown2/examples. 37 | -------------------------------------------------------------------------------- /docs/examples/vlan_aware_bridges/interfaces.vlan_prune_and_access_ports: -------------------------------------------------------------------------------- 1 | # 2 | # vlan-aware bridge access ports and pruned vlan example 3 | # 4 | # 'bridge' is a vlan aware bridge with all ports (swp1-52). 5 | # native vlan is by default 1 6 | # 7 | # 'bridge-vids' attribute is used to declare vlans. 8 | # 'bridge-pvid' attribute is used to specify native vlans if other than 1 9 | # 'bridge-access' attribute is used to declare access port 10 | # 11 | # 12 | 13 | # The following is an access port to vlan 310, no trunking 14 | auto swp1 15 | iface swp1 16 | bridge-access 310 17 | mstpctl-portadminedge yes 18 | mstpctl-bpduguard yes 19 | 20 | # The following is a truk port that is "pruned". 21 | # native vlan is 1, but only .1q tags of 707, 712, 850 are 22 | # sent and received 23 | # 24 | auto swp2 25 | iface swp2 26 | bridge-vids 707 712 850 27 | mstpctl-portadminedge yes 28 | mstpctl-bpduguard yes 29 | 30 | # The following port is the trunk uplink and inherits all vlans 31 | # from 'bridge' 32 | auto swp49 33 | iface swp49 34 | mstpctl-portpathcost 10 35 | # Enable bridge assurance on uplink port using 'portnetwork' attribute 36 | mstpctl-portnetwork yes 37 | 38 | # The following port is the trunk uplink and inherits all vlans 39 | # from 'bridge' 40 | auto swp50 41 | iface swp50 42 | mstpctl-portpathcost 0 43 | # Enable bridge assurance on uplink port using 'portnetwork' attribute 44 | mstpctl-portnetwork yes 45 | 46 | # 47 | # ports swp3-swp48 are trunk ports which inherit vlans from the 'bridge' 48 | # ie vlans 310,700,707,712,850,910 49 | 50 | # 51 | # the following is a vlan aware bridge with ports swp1-swp52 52 | # It has stp on 53 | # 54 | auto bridge 55 | iface bridge 56 | bridge-vlan-aware yes 57 | bridge-ports glob swp1-52 58 | bridge-stp on 59 | bridge-vids 310 700 707 712 850 910 60 | -------------------------------------------------------------------------------- /tests/output/bridge_new_attribute_ipforward_vlan_protocol_mcstats.after.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "swp_AA_", 37 | "auto": true, 38 | "config": {}, 39 | "config_status": {}, 40 | "status": "pass" 41 | }, 42 | { 43 | "name": "swp_BB_", 44 | "auto": true, 45 | "config": {}, 46 | "config_status": {}, 47 | "status": "pass" 48 | }, 49 | { 50 | "name": "br2", 51 | "auto": true, 52 | "config": { 53 | "ip-forward": "on", 54 | "bridge-ports": "swp_DD_ swp_EE_", 55 | "address": "6.0.0.2/32" 56 | }, 57 | "config_status": { 58 | "ip-forward": "pass", 59 | "bridge-ports": "pass", 60 | "address": "pass" 61 | }, 62 | "status": "pass" 63 | }, 64 | { 65 | "name": "vlan100", 66 | "auto": true, 67 | "config": { 68 | "vlan-id": "100", 69 | "vlan-raw-device": "swp_CC_" 70 | }, 71 | "config_status": { 72 | "vlan-id": "pass", 73 | "vlan-raw-device": "pass" 74 | }, 75 | "status": "pass" 76 | }, 77 | { 78 | "name": "br3", 79 | "auto": true, 80 | "config": { 81 | "bridge-ports": "swp_FF_" 82 | }, 83 | "config_status": { 84 | "bridge-ports": "pass" 85 | }, 86 | "status": "pass" 87 | } 88 | ] 89 | -------------------------------------------------------------------------------- /tests/output/interfaces.vrr_vrf.ifquery.ac.6.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "peerlink", 37 | "auto": true, 38 | "config": { 39 | "bond-slaves": "swp_AA_ swp_BB_" 40 | }, 41 | "config_status": { 42 | "bond-slaves": "pass" 43 | }, 44 | "status": "pass" 45 | }, 46 | { 47 | "name": "peerlink.4094", 48 | "auto": true, 49 | "config": { 50 | "address": "169.254.1.1/30" 51 | }, 52 | "config_status": { 53 | "address": "pass" 54 | }, 55 | "status": "pass" 56 | }, 57 | { 58 | "name": "myvrf", 59 | "auto": true, 60 | "config": { 61 | "vrf-table": "1002" 62 | }, 63 | "config_status": { 64 | "vrf-table": "pass" 65 | }, 66 | "status": "pass" 67 | }, 68 | { 69 | "name": "bridge", 70 | "auto": true, 71 | "config": {}, 72 | "config_status": {}, 73 | "status": "fail" 74 | }, 75 | { 76 | "name": "bridge.901", 77 | "auto": true, 78 | "config": {}, 79 | "config_status": {}, 80 | "status": "fail" 81 | }, 82 | { 83 | "name": "bond0", 84 | "auto": true, 85 | "config": { 86 | "bond-slaves": "swp_CC_" 87 | }, 88 | "config_status": { 89 | "bond-slaves": "pass" 90 | }, 91 | "status": "pass" 92 | } 93 | ] 94 | -------------------------------------------------------------------------------- /ifupdown2/ifupdown/config.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Copyright 2017 Cumulus Networks, Inc. All rights reserved. 4 | # Authors: 5 | # Julien Fortin, julien@cumulusnetworks.com 6 | # 7 | # ifupdown2 -- 8 | # tool to configure network interfaces 9 | # 10 | 11 | import os 12 | import resource 13 | 14 | IFUPDOWN2_ADDON_DROPIN_FOLDER = '/usr/share/ifupdown2/addons' 15 | 16 | try: 17 | # ifupdown2/ifupdown/config.py -> we need to use dirname twice. 18 | ADDON_MODULES_DIR = ['%s/addons' % (os.path.dirname(os.path.dirname(os.path.realpath(__file__))))] 19 | 20 | if ADDON_MODULES_DIR[0] != IFUPDOWN2_ADDON_DROPIN_FOLDER: 21 | ADDON_MODULES_DIR.append(IFUPDOWN2_ADDON_DROPIN_FOLDER) 22 | except Exception as e: 23 | print("debug: error resolving ifupdown2 addons module directory: %s" % str(e)) 24 | ADDON_MODULES_DIR = [IFUPDOWN2_ADDON_DROPIN_FOLDER] 25 | 26 | __version__ = '' 27 | 28 | 29 | def get_configuration_file_real_path(path_to_file): 30 | """ 31 | When install via pypi or `pip install .` ifupdown2 is install in a virtualenv 32 | config file that should be installed in /etc/network/ifupdown2 end-up being 33 | installed in /usr/local/lib/python2.7/dist-packages/etc/network/ifupdown2/ 34 | """ 35 | if not os.path.exists(path_to_file): 36 | # we will try to resolve the location of our conf file 37 | # otherwise default to the input argument 38 | package_dir = os.path.dirname(os.path.realpath(__file__)) 39 | parent_dir = os.path.dirname(package_dir) 40 | resolved_path = '%s%s' % (parent_dir, path_to_file) 41 | 42 | if os.path.exists(resolved_path): 43 | return resolved_path 44 | 45 | return path_to_file 46 | 47 | 48 | IFUPDOWN2_CONF_PATH = get_configuration_file_real_path('/etc/network/ifupdown2/ifupdown2.conf') 49 | ADDONS_CONF_PATH = get_configuration_file_real_path('/etc/network/ifupdown2/addons.conf') 50 | 51 | resource.setrlimit(resource.RLIMIT_CORE, (0, 0)) 52 | -------------------------------------------------------------------------------- /ifupdown2/lib/status.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Cumulus Networks, Inc. all rights reserved 2 | # 3 | # This program is free software; you can redistribute it and/or 4 | # modify it under the terms of the GNU General Public License as 5 | # published by the Free Software Foundation; version 2. 6 | # 7 | # This program is distributed in the hope that it will be useful, 8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | # General Public License for more details. 11 | # 12 | # You should have received a copy of the GNU General Public License 13 | # along with this program; if not, write to the Free Software 14 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 | # 02110-1301, USA. 16 | # 17 | # https://www.gnu.org/licenses/gpl-2.0-standalone.html 18 | # 19 | # Author: 20 | # Julien Fortin, julien@cumulusnetworks.com 21 | # 22 | 23 | 24 | class Status(object): 25 | """ 26 | Defining client and daemon exit status to better identify 27 | client and daemon issue and exceptions. 28 | 80 > unknown > 90 > client status > 100 > daemon status 29 | """ 30 | 31 | class Client(object): 32 | STATUS_SUCCESS = 0 33 | STATUS_INIT = 91 34 | STATUS_COULD_NOT_CONNECT = 92 35 | STATUS_NO_PID = 93 36 | STATUS_EMPTY = 94 37 | STATUS_KEYBOARD_INTERRUPT = 95 38 | STATUS_NLERROR = 96 39 | STATUS_EXCEPTION_MAIN = 99 40 | 41 | STATUS_ARGV_ERROR = 90 42 | STATUS_ALREADY_RUNNING = 89 43 | 44 | class Daemon(object): 45 | STATUS_SUCCESS = 0 46 | STATUS_INIT = 101 47 | STATUS_UNKNOWN = 102 48 | STATUS_SOCKET_ERROR = 103 49 | STATUS_PROCESS_REQUEST = 104 50 | STATUS_KEYBOARD_INTERRUPT = 105 51 | STATUS_NLERROR = 106 52 | 53 | STATUS_REQUEST_PARSE_ERROR = 106 54 | STATUS_REQUEST_EXCEPTION = 107 55 | STATUS_REQUEST_BASE_EXCEPTION = 108 56 | -------------------------------------------------------------------------------- /docs/examples/interfaces_bridge_igmp_mstp: -------------------------------------------------------------------------------- 1 | 2 | # 3 | # This example lists all attributes for bridge configuration. 4 | # The attributes with mstpctl- prefix indicate mstp settings on a bridge. 5 | # The attributes with bridge- prefix indicate bridge stp and igmp attributes. 6 | # Except bridge-ports, none of the other attributes are required. Default 7 | # values are documented in the ifupdown-addons-interfaces(5) man page. 8 | # 9 | # The bridge in the example below is a vlan unaware bridge (classic linux 10 | # bridge) 11 | # 12 | auto br-300 13 | iface br-300 inet static 14 | address 12.0.0.3/24 15 | bridge-ports swp13.300 swp14.300 16 | bridge-stp on 17 | mstpctl-maxage 20 18 | mstpctl-fdelay 15 19 | mstpctl-maxhops 20 20 | mstpctl-txholdcount 6 21 | mstpctl-forcevers rstp 22 | mstpctl-portpathcost swp13.300=0 swp14.300=0 23 | mstpctl-portadminedge swp13.300=no swp14.300=no 24 | mstpctl-portautoedge swp13.300=yes swp14.300=yes 25 | mstpctl-portp2p swp13.300=no swp13.300=no 26 | mstpctl-portrestrrole swp13.300=no swp14.300=no 27 | mstpctl-bpduguard swp13.300=no swp14.300=no 28 | mstpctl-portrestrtcn swp13.300=no swp14.300=no 29 | mstpctl-treeprio 32768 30 | mstpctl-treeportprio swp13.300=128 31 | mstpctl-hello 2 32 | mstpctl-portnetwork swp13.300=no 33 | bridge-mclmc 3 34 | bridge-mcrouter no 35 | bridge-mcsnoop yes 36 | bridge-mcsqc 3 37 | bridge-mcqifaddr yes 38 | bridge-mcquerier yes 39 | bridge-hashel 3 40 | bridge-hashmax 4 41 | bridge-mclmi 3 42 | bridge-mcmi 200 43 | bridge-mcqpi 200 44 | bridge-mcqi 100 45 | bridge-mcqri 20 46 | bridge-mcsqi 50 47 | bridge-portmcrouter swp13.300=0 48 | bridge-portmcfl swp13.300=1 49 | -------------------------------------------------------------------------------- /tests/output/bridge_l2protocol_tunnel.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "br_vlan_unaware", 37 | "auto": true, 38 | "config": { 39 | "bridge-ports": "swp_AA_ swp_BB_ swp_CC_ swp_DD_ swp_EE_", 40 | "bridge-l2protocol-tunnel": "swp_AA_=lacp,pvst swp_BB_=stp,cdp swp_CC_=all swp_DD_=lldp" 41 | }, 42 | "config_status": { 43 | "bridge-ports": "pass", 44 | "bridge-l2protocol-tunnel": "pass" 45 | }, 46 | "status": "pass" 47 | }, 48 | { 49 | "name": "br_vlan_aware", 50 | "auto": true, 51 | "config": { 52 | "bridge-vlan-aware": "yes", 53 | "bridge-ports": "swp_FF_ swp_GG_" 54 | }, 55 | "config_status": { 56 | "bridge-vlan-aware": "pass", 57 | "bridge-ports": "pass" 58 | }, 59 | "status": "pass" 60 | }, 61 | { 62 | "name": "swp_GG_", 63 | "auto": true, 64 | "config": { 65 | "bridge-l2protocol-tunnel": "all" 66 | }, 67 | "config_status": { 68 | "bridge-l2protocol-tunnel": "pass" 69 | }, 70 | "status": "pass" 71 | }, 72 | { 73 | "name": "swp_FF_", 74 | "auto": true, 75 | "config": { 76 | "bridge-l2protocol-tunnel": "stp lacp lldp,pvst cdp" 77 | }, 78 | "config_status": { 79 | "bridge-l2protocol-tunnel": "pass" 80 | }, 81 | "status": "pass" 82 | } 83 | ] 84 | -------------------------------------------------------------------------------- /ifupdown2/ifupdownaddons/systemutils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Copyright 2015-2017 Cumulus Networks, Inc. All rights reserved. 4 | # Author: Roopa Prabhu, roopa@cumulusnetworks.com 5 | # 6 | 7 | import os 8 | 9 | try: 10 | from ifupdown2.ifupdown.utils import utils 11 | from ifupdown2.ifupdownaddons.utilsbase import * 12 | except ImportError: 13 | from ifupdown.utils import utils 14 | from ifupdownaddons.utilsbase import * 15 | 16 | 17 | class systemUtils(): 18 | @classmethod 19 | def is_service_running(cls, procname=None, pidfile=None): 20 | utilsobj = utilsBase() 21 | if pidfile: 22 | if os.path.exists(pidfile): 23 | pid = utilsobj.read_file_oneline(pidfile) 24 | if not os.path.exists('/proc/%s' %pid): 25 | return False 26 | else: 27 | return False 28 | return True 29 | 30 | if procname: 31 | try: 32 | utils.exec_command('%s %s' % 33 | (utils.pidof_cmd, procname)) 34 | except Exception: 35 | return False 36 | else: 37 | return True 38 | 39 | return False 40 | 41 | @classmethod 42 | def check_service_status(cls, servicename=None): 43 | if not servicename: 44 | return False 45 | try: 46 | utils.exec_commandl([utils.service_cmd, 47 | servicename, 'status']) 48 | except Exception: 49 | # XXX: check for subprocess errors vs os error 50 | return False 51 | return True 52 | 53 | @staticmethod 54 | def is_process_running(processname): 55 | if not processname: 56 | return False 57 | try: 58 | utils.exec_command('%s %s' % 59 | (utils.pidof_cmd, processname)) 60 | except Exception: 61 | return False 62 | else: 63 | return True 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Python template 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | /lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | .hypothesis/ 50 | .pytest_cache/ 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | local_settings.py 59 | db.sqlite3 60 | 61 | # Flask stuff: 62 | instance/ 63 | .webassets-cache 64 | 65 | # Scrapy stuff: 66 | .scrapy 67 | 68 | # Sphinx documentation 69 | docs/_build/ 70 | 71 | # PyBuilder 72 | target/ 73 | 74 | # Jupyter Notebook 75 | .ipynb_checkpoints 76 | 77 | # pyenv 78 | .python-version 79 | 80 | # celery beat schedule file 81 | celerybeat-schedule 82 | 83 | # SageMath parsed files 84 | *.sage.py 85 | 86 | # Environments 87 | .env 88 | .venv 89 | env/ 90 | venv/ 91 | ENV/ 92 | env.bak/ 93 | venv.bak/ 94 | 95 | # Spyder project settings 96 | .spyderproject 97 | .spyproject 98 | 99 | # Rope project settings 100 | .ropeproject 101 | 102 | # mkdocs documentation 103 | /site 104 | 105 | # mypy 106 | .mypy_cache/ 107 | 108 | # macOS 109 | .DS_Store 110 | 111 | # pycharm IDE 112 | .idea/ 113 | 114 | ifupdown2/ifdown 115 | ifupdown2/ifquery 116 | ifupdown2/ifreload 117 | ifupdown2/ifup 118 | 119 | tests/results 120 | -------------------------------------------------------------------------------- /tests/output/interfaces.vrr_vrf.ifquery.ac.8.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "peerlink", 37 | "auto": true, 38 | "config": { 39 | "bond-slaves": "swp_AA_ swp_BB_" 40 | }, 41 | "config_status": { 42 | "bond-slaves": "pass" 43 | }, 44 | "status": "pass" 45 | }, 46 | { 47 | "name": "peerlink.4094", 48 | "auto": true, 49 | "config": { 50 | "address": "169.254.1.1/30" 51 | }, 52 | "config_status": { 53 | "address": "pass" 54 | }, 55 | "status": "pass" 56 | }, 57 | { 58 | "name": "myvrf", 59 | "auto": true, 60 | "config": { 61 | "vrf-table": "1002" 62 | }, 63 | "config_status": { 64 | "vrf-table": "pass" 65 | }, 66 | "status": "pass" 67 | }, 68 | { 69 | "name": "bridge", 70 | "auto": true, 71 | "config": { 72 | "bridge-vlan-aware": "yes", 73 | "bridge-ports": "peerlink", 74 | "bridge-stp": "yes" 75 | }, 76 | "config_status": { 77 | "bridge-vlan-aware": "pass", 78 | "bridge-ports": "fail", 79 | "bridge-stp": "pass" 80 | }, 81 | "status": "fail" 82 | }, 83 | { 84 | "name": "bridge.901", 85 | "auto": true, 86 | "config": {}, 87 | "config_status": {}, 88 | "status": "fail" 89 | }, 90 | { 91 | "name": "bond0", 92 | "auto": true, 93 | "config": {}, 94 | "config_status": {}, 95 | "status": "fail" 96 | } 97 | ] 98 | -------------------------------------------------------------------------------- /tests/output/bridge_new_attribute_learning_arp_nd_suppress.after.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "vxlan10101", 37 | "auto": true, 38 | "config": { 39 | "vxlan-id": "10101", 40 | "bridge-access": "101", 41 | "vxlan-local-tunnelip": "6.0.0.17" 42 | }, 43 | "config_status": { 44 | "vxlan-id": "pass", 45 | "bridge-access": "pass", 46 | "vxlan-local-tunnelip": "pass" 47 | }, 48 | "status": "pass" 49 | }, 50 | { 51 | "name": "br1", 52 | "auto": true, 53 | "config": { 54 | "bridge-vlan-aware": "yes", 55 | "bridge-ports": "vxlan10101", 56 | "bridge-vids": "101" 57 | }, 58 | "config_status": { 59 | "bridge-vlan-aware": "pass", 60 | "bridge-ports": "pass", 61 | "bridge-vids": "" 62 | }, 63 | "status": "pass" 64 | }, 65 | { 66 | "name": "vxlan10102", 67 | "auto": true, 68 | "config": { 69 | "vxlan-id": "10102", 70 | "vxlan-local-tunnelip": "6.0.0.17" 71 | }, 72 | "config_status": { 73 | "vxlan-id": "pass", 74 | "vxlan-local-tunnelip": "pass" 75 | }, 76 | "status": "pass" 77 | }, 78 | { 79 | "name": "br2", 80 | "auto": true, 81 | "config": { 82 | "bridge-ports": "vxlan10102", 83 | "bridge-vids": "101" 84 | }, 85 | "config_status": { 86 | "bridge-ports": "pass", 87 | "bridge-vids": "" 88 | }, 89 | "status": "pass" 90 | } 91 | ] 92 | -------------------------------------------------------------------------------- /docs/examples/interfaces_bridge_vlan_bond_vxlan_vrf: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet 3 | 4 | auto eth0 5 | iface eth0 inet dhcp 6 | 7 | <% 8 | id = 5 9 | access = 2 10 | %> 11 | %for i in range(0,2): 12 | auto swp${id} 13 | iface swp${id} 14 | bridge-access ${access} 15 | mtu 9000 16 | <% 17 | id += 1 18 | access -= 1 19 | %> 20 | %endfor 21 | 22 | auto swp7 23 | iface swp7 24 | bridge-vids 5 9-10 25 | hwaddress 44:38:39:00:27:b8 26 | mtu 9000 27 | 28 | auto v0 29 | iface v0 30 | vlan-raw-device swp22 31 | vlan-id 42 32 | 33 | auto bond0 34 | iface bond0 35 | bond-slaves swp1 swp2 36 | bond-mode 802.3ad 37 | bond-min-links 1 38 | bridge-access 2 39 | 40 | auto bond1 41 | iface bond1 42 | bond-slaves swp3 swp4 43 | bond-mode 802.3ad 44 | mtu 9000 45 | bond-min-links 1 46 | bridge-vids 5 8-12 47 | 48 | auto br0 49 | iface br0 50 | bridge-stp on 51 | bridge-mcsnoop 0 52 | bridge-vids 8 11-12 53 | bridge-vlan-aware yes 54 | bridge-ports bond0 bond1 swp5 swp6 swp7 swp8 55 | mstpctl-treeprio 4096 56 | 57 | auto br0.1 58 | iface br0.1 59 | address 11.0.1.1/24 60 | address 2001:470:1f05:1::1/64 61 | address-virtual 00:00:5e:00:01:1 11.0.1.2/24 62 | 63 | auto bond2 64 | iface bond2 65 | bond-slaves swp42 66 | bond-mode 802.3ad 67 | bond-miimon 100 68 | bond-min-links 1 69 | bond-xmit_hash_policy layer3+4 70 | bond-lacp-rate 1 71 | mtu 1500 72 | 73 | auto vx42 74 | iface vx42 75 | vxlan-id 42 76 | vxlan-local-tunnelip 27.0.0.11 77 | mtu 1500 78 | 79 | auto br1-untag 80 | iface br1-untag 81 | bridge-ports bond2 vx42 82 | bridge-stp on 83 | mstpctl-portbpdufilter vx42=yes 84 | mstpctl-bpduguard vx42=yes 85 | mstpctl-portadminedge bond2=yes 86 | 87 | auto bond3 88 | iface bond3 89 | bond-slaves swp15.100 swp16.100 90 | 91 | auto br3 92 | iface br3 93 | bridge-ports bond3 swp21 94 | 95 | auto swp10.100 96 | iface swp10.100 97 | vrf red 98 | 99 | auto red 100 | iface red 101 | address 127.0.0.1/8 102 | vrf-table auto 103 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | 6 | from setuptools import setup 7 | from setuptools import find_packages 8 | 9 | INSTALL_REQUIRES = [ 10 | 'daemon' 11 | ] 12 | 13 | DATA_FILES = [ 14 | ('/etc/default/', ['etc/default/networking']), 15 | ('/etc/network/ifupdown2/', ['etc/network/ifupdown2/addons.conf']), 16 | ('/etc/network/ifupdown2/', ['etc/network/ifupdown2/ifupdown2.conf']), 17 | ] 18 | 19 | SCRIPTS = [] 20 | 21 | ENTRY_POINTS = {} 22 | 23 | 24 | def build_deb_package(): 25 | try: 26 | return sys.argv[sys.argv.index('--root') + 1].endswith('/debian/ifupdown2') 27 | except Exception: 28 | pass 29 | return False 30 | 31 | 32 | if build_deb_package(): 33 | DATA_FILES.append(('/usr/share/ifupdown2/sbin/', ['ifupdown2/sbin/start-networking'])) 34 | else: 35 | ENTRY_POINTS = { 36 | 'console_scripts': [ 37 | 'ifup = ifupdown2.__main__:main', 38 | 'ifdown = ifupdown2.__main__:main', 39 | 'ifquery = ifupdown2.__main__:main', 40 | 'ifreload = ifupdown2.__main__:main', 41 | ], 42 | } 43 | 44 | setup( 45 | author='Julien Fortin', 46 | author_email='jfortin@nvidia.com', 47 | maintainer='Julien Fortin', 48 | maintainer_email='jfortin@nvidia.com', 49 | classifiers=[ 50 | 'Development Status :: 5 - Production/Stable', 51 | 'Environment :: Console', 52 | 'Intended Audience :: System Administrators', 53 | 'License :: OSI Approved :: GNU General Public License v2 (GPLv2)', 54 | 'Natural Language :: English', 55 | 'Operating System :: POSIX :: Linux', 56 | 'Programming Language :: Python :: 3', 57 | 'Topic :: System :: Networking', 58 | 'Topic :: System :: Systems Administration' 59 | ], 60 | description='interface network manager', 61 | install_requires=INSTALL_REQUIRES, 62 | license='GNU General Public License v2', 63 | keywords='ifupdown2', 64 | name='ifupdown2', 65 | packages=find_packages(), 66 | url='https://github.com/CumulusNetworks/ifupdown2', 67 | version='3.9.0', 68 | data_files=DATA_FILES, 69 | setup_requires=['setuptools'], 70 | scripts=SCRIPTS, 71 | entry_points=ENTRY_POINTS 72 | ) 73 | -------------------------------------------------------------------------------- /tests/output/interfaces.vrr_vrf.ifquery.ac.7.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "peerlink", 37 | "auto": true, 38 | "config": { 39 | "bond-slaves": "swp_AA_ swp_BB_" 40 | }, 41 | "config_status": { 42 | "bond-slaves": "pass" 43 | }, 44 | "status": "pass" 45 | }, 46 | { 47 | "name": "peerlink.4094", 48 | "auto": true, 49 | "config": { 50 | "address": "169.254.1.1/30" 51 | }, 52 | "config_status": { 53 | "address": "pass" 54 | }, 55 | "status": "pass" 56 | }, 57 | { 58 | "name": "myvrf", 59 | "auto": true, 60 | "config": { 61 | "vrf-table": "1002" 62 | }, 63 | "config_status": { 64 | "vrf-table": "pass" 65 | }, 66 | "status": "pass" 67 | }, 68 | { 69 | "name": "bridge", 70 | "auto": true, 71 | "config": { 72 | "bridge-vlan-aware": "yes", 73 | "bridge-ports": "peerlink bond0", 74 | "bridge-stp": "yes" 75 | }, 76 | "config_status": { 77 | "bridge-vlan-aware": "pass", 78 | "bridge-ports": "pass", 79 | "bridge-stp": "pass" 80 | }, 81 | "status": "pass" 82 | }, 83 | { 84 | "name": "bridge.901", 85 | "auto": true, 86 | "config": {}, 87 | "config_status": {}, 88 | "status": "fail" 89 | }, 90 | { 91 | "name": "bond0", 92 | "auto": true, 93 | "config": { 94 | "bond-slaves": "swp_CC_" 95 | }, 96 | "config_status": { 97 | "bond-slaves": "pass" 98 | }, 99 | "status": "pass" 100 | } 101 | ] 102 | -------------------------------------------------------------------------------- /tests/output/interfaces.vrr_vrf.ifquery.ac.5.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "peerlink", 37 | "auto": true, 38 | "config": { 39 | "bond-slaves": "swp_AA_ swp_BB_" 40 | }, 41 | "config_status": { 42 | "bond-slaves": "pass" 43 | }, 44 | "status": "pass" 45 | }, 46 | { 47 | "name": "peerlink.4094", 48 | "auto": true, 49 | "config": { 50 | "address": "169.254.1.1/30" 51 | }, 52 | "config_status": { 53 | "address": "pass" 54 | }, 55 | "status": "pass" 56 | }, 57 | { 58 | "name": "myvrf", 59 | "auto": true, 60 | "config": {}, 61 | "config_status": {}, 62 | "status": "fail" 63 | }, 64 | { 65 | "name": "bridge", 66 | "auto": true, 67 | "config": { 68 | "bridge-vlan-aware": "yes", 69 | "bridge-ports": "peerlink", 70 | "bridge-stp": "yes" 71 | }, 72 | "config_status": { 73 | "bridge-vlan-aware": "pass", 74 | "bridge-ports": "fail", 75 | "bridge-stp": "pass" 76 | }, 77 | "status": "fail" 78 | }, 79 | { 80 | "name": "bridge.901", 81 | "auto": true, 82 | "config": { 83 | "address-virtual": "00:00:5e:00:01:81", 84 | "vrf": "None", 85 | "address": "10.1.63.2/28" 86 | }, 87 | "config_status": { 88 | "address-virtual": "fail", 89 | "vrf": "fail", 90 | "address": "fail" 91 | }, 92 | "status": "fail" 93 | }, 94 | { 95 | "name": "bond0", 96 | "auto": true, 97 | "config": {}, 98 | "config_status": {}, 99 | "status": "fail" 100 | } 101 | ] 102 | -------------------------------------------------------------------------------- /docs/examples/vlan_aware_bridges/interfaces.with_bonds: -------------------------------------------------------------------------------- 1 | # 2 | # vlan-aware bridge with bonds example 3 | # 4 | # uplink1, peerlink and downlink are bond interfaces. 5 | # 'bridge' is a vlan aware bridge with ports uplink1, peerlink 6 | # and downlink (swp2-20). 7 | # 8 | # native vlan is by default 1 9 | # 10 | # 'bridge-vids' attribute is used to declare vlans. 11 | # 'bridge-pvid' attribute is used to specify native vlans if other than 1 12 | # 'bridge-access' attribute is used to declare access port 13 | # 14 | auto lo 15 | iface lo 16 | 17 | auto eth0 18 | iface eth0 inet dhcp 19 | 20 | # bond interface 21 | auto uplink1 22 | iface uplink1 23 | bond-slaves swp32 24 | bond-mode 802.3ad 25 | bond-miimon 100 26 | bond-use-carrier yes 27 | bond-lacp-rate 1 28 | bond-min-links 1 29 | bond-xmit-hash-policy layer2 30 | bridge-vids 2000-2079 31 | 32 | # bond interface 33 | auto peerlink 34 | iface peerlink 35 | bond-slaves swp30 swp31 36 | bond-mode 802.3ad 37 | bond-miimon 100 38 | bond-use-carrier yes 39 | bond-lacp-rate 1 40 | bond-min-links 1 41 | bond-xmit-hash-policy layer3+4 42 | bridge-vids 2000-2079 4094 43 | 44 | # bond interface 45 | auto downlink 46 | iface downlink 47 | bond-slaves swp1 48 | bond-mode 802.3ad 49 | bond-miimon 100 50 | bond-use-carrier yes 51 | bond-lacp-rate 1 52 | bond-min-links 1 53 | bond-xmit-hash-policy layer3+4 54 | bridge-vids 2000-2079 55 | 56 | # 57 | # Declare vlans for all swp ports 58 | # swp2-20 get vlans from 2004 to 2022. 59 | # The below uses mako templates to generate iface sections 60 | # with vlans for swp ports 61 | # 62 | %for port, vlanid in zip(range(2, 20), range(2004, 2022)) : 63 | auto swp${port} 64 | iface swp${port} 65 | bridge-vids ${vlanid} 66 | 67 | %endfor 68 | 69 | # svi vlan 4094 70 | auto bridge.4094 71 | iface bridge.4094 72 | address 11.100.1.252/24 73 | 74 | # l2 attributes for vlan 4094 75 | auto bridge.4094 76 | vlan bridge.4094 77 | bridge-igmp-querier-src 172.16.101.1 78 | 79 | # 80 | # vlan aware bridge 81 | # 82 | auto bridge 83 | iface bridge 84 | bridge-vlan-aware yes 85 | bridge-ports uplink1 peerlink downlink glob swp2-20 86 | bridge-stp on 87 | 88 | # svi peerlink vlan 89 | auto peerlink.4094 90 | iface peerlink.4094 91 | address 192.168.10.1/30 92 | broadcast 192.168.10.3 93 | -------------------------------------------------------------------------------- /tests/output/bridge_new_attribute_ipforward_vlan_protocol_mcstats.before.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "swp_AA_", 37 | "auto": true, 38 | "config": { 39 | "ip-forward": "off" 40 | }, 41 | "config_status": { 42 | "ip-forward": "pass" 43 | }, 44 | "status": "pass" 45 | }, 46 | { 47 | "name": "swp_BB_", 48 | "auto": true, 49 | "config": { 50 | "ip6-forward": "off" 51 | }, 52 | "config_status": { 53 | "ip6-forward": "pass" 54 | }, 55 | "status": "pass" 56 | }, 57 | { 58 | "name": "br2", 59 | "auto": true, 60 | "config": { 61 | "bridge-ports": "swp_DD_ swp_EE_", 62 | "bridge-mcstats": "off", 63 | "ip-forward": "on" 64 | }, 65 | "config_status": { 66 | "bridge-ports": "pass", 67 | "bridge-mcstats": "pass", 68 | "ip-forward": "pass" 69 | }, 70 | "status": "pass" 71 | }, 72 | { 73 | "name": "vlan100", 74 | "auto": true, 75 | "config": { 76 | "vlan-raw-device": "swp_CC_", 77 | "vlan-id": "100", 78 | "vlan-protocol": "802.1ad" 79 | }, 80 | "config_status": { 81 | "vlan-raw-device": "pass", 82 | "vlan-id": "pass", 83 | "vlan-protocol": "pass" 84 | }, 85 | "status": "pass" 86 | }, 87 | { 88 | "name": "br3", 89 | "auto": true, 90 | "config": { 91 | "bridge-ports": "swp_FF_", 92 | "bridge-mcstats": "off" 93 | }, 94 | "config_status": { 95 | "bridge-ports": "pass", 96 | "bridge-mcstats": "pass" 97 | }, 98 | "status": "pass" 99 | } 100 | ] 101 | -------------------------------------------------------------------------------- /tests/output/interfaces.vrr_vrf.ifquery.ac.2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "peerlink", 37 | "auto": true, 38 | "config": { 39 | "bond-slaves": "swp_AA_ swp_BB_" 40 | }, 41 | "config_status": { 42 | "bond-slaves": "pass" 43 | }, 44 | "status": "pass" 45 | }, 46 | { 47 | "name": "peerlink.4094", 48 | "auto": true, 49 | "config": { 50 | "address": "169.254.1.1/30" 51 | }, 52 | "config_status": { 53 | "address": "pass" 54 | }, 55 | "status": "pass" 56 | }, 57 | { 58 | "name": "myvrf", 59 | "auto": true, 60 | "config": { 61 | "vrf-table": "1002" 62 | }, 63 | "config_status": { 64 | "vrf-table": "pass" 65 | }, 66 | "status": "pass" 67 | }, 68 | { 69 | "name": "bridge", 70 | "auto": true, 71 | "config": { 72 | "bridge-vlan-aware": "yes", 73 | "bridge-ports": "peerlink", 74 | "bridge-stp": "yes" 75 | }, 76 | "config_status": { 77 | "bridge-vlan-aware": "pass", 78 | "bridge-ports": "fail", 79 | "bridge-stp": "pass" 80 | }, 81 | "status": "fail" 82 | }, 83 | { 84 | "name": "bridge.901", 85 | "auto": true, 86 | "config": { 87 | "address-virtual": "00:00:5e:00:01:81 10.1.63.1/28", 88 | "vrf": "myvrf", 89 | "address": "10.1.63.2/28" 90 | }, 91 | "config_status": { 92 | "address-virtual": "pass", 93 | "vrf": "pass", 94 | "address": "pass" 95 | }, 96 | "status": "pass" 97 | }, 98 | { 99 | "name": "bond0", 100 | "auto": true, 101 | "config": {}, 102 | "config_status": {}, 103 | "status": "fail" 104 | } 105 | ] 106 | -------------------------------------------------------------------------------- /tests/output/interfaces.vrr_vrf.ifquery.ac.4.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "peerlink", 37 | "auto": true, 38 | "config": { 39 | "bond-slaves": "swp_AA_ swp_BB_" 40 | }, 41 | "config_status": { 42 | "bond-slaves": "pass" 43 | }, 44 | "status": "pass" 45 | }, 46 | { 47 | "name": "peerlink.4094", 48 | "auto": true, 49 | "config": { 50 | "address": "169.254.1.1/30" 51 | }, 52 | "config_status": { 53 | "address": "pass" 54 | }, 55 | "status": "pass" 56 | }, 57 | { 58 | "name": "myvrf", 59 | "auto": true, 60 | "config": {}, 61 | "config_status": {}, 62 | "status": "fail" 63 | }, 64 | { 65 | "name": "bridge", 66 | "auto": true, 67 | "config": { 68 | "bridge-vlan-aware": "yes", 69 | "bridge-ports": "peerlink bond0", 70 | "bridge-stp": "yes" 71 | }, 72 | "config_status": { 73 | "bridge-vlan-aware": "pass", 74 | "bridge-ports": "pass", 75 | "bridge-stp": "pass" 76 | }, 77 | "status": "pass" 78 | }, 79 | { 80 | "name": "bridge.901", 81 | "auto": true, 82 | "config": { 83 | "address-virtual": "00:00:5e:00:01:81", 84 | "vrf": "None", 85 | "address": "10.1.63.2/28" 86 | }, 87 | "config_status": { 88 | "address-virtual": "fail", 89 | "vrf": "fail", 90 | "address": "fail" 91 | }, 92 | "status": "fail" 93 | }, 94 | { 95 | "name": "bond0", 96 | "auto": true, 97 | "config": { 98 | "bond-slaves": "swp_CC_" 99 | }, 100 | "config_status": { 101 | "bond-slaves": "pass" 102 | }, 103 | "status": "pass" 104 | } 105 | ] 106 | -------------------------------------------------------------------------------- /tests/output/interfaces_link_state.before.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "swp_AA_", 37 | "addr_method": "manual", 38 | "addr_family": "inet", 39 | "auto": true, 40 | "config": {}, 41 | "config_status": {}, 42 | "status": "pass" 43 | }, 44 | { 45 | "name": "swp_BB_", 46 | "auto": true, 47 | "config": {}, 48 | "config_status": {}, 49 | "status": "pass" 50 | }, 51 | { 52 | "name": "bridge1", 53 | "auto": true, 54 | "config": { 55 | "bridge-ports": "swp_CC_" 56 | }, 57 | "config_status": { 58 | "bridge-ports": "pass" 59 | }, 60 | "status": "pass" 61 | }, 62 | { 63 | "name": "bridge2", 64 | "addr_method": "manual", 65 | "addr_family": "inet", 66 | "auto": true, 67 | "config": { 68 | "bridge-ports": "swp_DD_" 69 | }, 70 | "config_status": { 71 | "bridge-ports": "pass" 72 | }, 73 | "status": "pass" 74 | }, 75 | { 76 | "name": "bridge3", 77 | "addr_method": "manual", 78 | "addr_family": "inet", 79 | "auto": true, 80 | "config": { 81 | "link-down": "yes", 82 | "bridge-ports": "swp_EE_" 83 | }, 84 | "config_status": { 85 | "link-down": "pass", 86 | "bridge-ports": "pass" 87 | }, 88 | "status": "pass" 89 | }, 90 | { 91 | "name": "bridge4", 92 | "addr_method": "manual", 93 | "addr_family": "inet", 94 | "auto": true, 95 | "config": { 96 | "link-down": "no", 97 | "bridge-ports": "swp_FF_" 98 | }, 99 | "config_status": { 100 | "link-down": "pass", 101 | "bridge-ports": "pass" 102 | }, 103 | "status": "pass" 104 | } 105 | ] 106 | -------------------------------------------------------------------------------- /ifupdown2/lib/base_objects.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2017, 2018 Cumulus Networks, Inc. all rights reserved 2 | # 3 | # This program is free software; you can redistribute it and/or 4 | # modify it under the terms of the GNU General Public License as 5 | # published by the Free Software Foundation; version 2. 6 | # 7 | # This program is distributed in the hope that it will be useful, 8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 | # General Public License for more details. 11 | # 12 | # You should have received a copy of the GNU General Public License 13 | # along with this program; if not, write to the Free Software 14 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 15 | # 02110-1301, USA. 16 | # 17 | # https://www.gnu.org/licenses/gpl-2.0-standalone.html 18 | # 19 | # Author: 20 | # Julien Fortin, julien@cumulusnetworks.com 21 | # 22 | # base_objects -- Base classes used by higher level classes 23 | # 24 | 25 | import os 26 | import logging 27 | 28 | try: 29 | from ifupdown2.lib.dry_run import DryRun 30 | from ifupdown2.ifupdown.utils import utils 31 | except ImportError: 32 | from lib.dry_run import DryRun 33 | from ifupdown.utils import utils 34 | 35 | 36 | class BaseObject(DryRun): 37 | """ 38 | BaseObject should be the parent of any ifupdown2 object that wishes to 39 | implement any "dry run" specific code and have a default logger. 40 | More classes can inherit BaseObject and add features like Addon, FileIO or Sysfs... 41 | """ 42 | 43 | def __init__(self): 44 | DryRun.__init__(self) 45 | self.logger = logging.getLogger("ifupdown2.%s" % self.__class__.__name__) 46 | 47 | 48 | def _import_NetlinkListenerWithCache(): 49 | try: 50 | from ifupdown2.lib.nlcache import NetlinkListenerWithCache 51 | except ImportError: 52 | from lib.nlcache import NetlinkListenerWithCache 53 | return NetlinkListenerWithCache 54 | 55 | 56 | class Cache(BaseObject): 57 | def __init__(self): 58 | BaseObject.__init__(self) 59 | self.cache = _import_NetlinkListenerWithCache().get_instance().cache 60 | 61 | 62 | class Netlink(BaseObject): 63 | def __init__(self): 64 | BaseObject.__init__(self) 65 | self.netlink = _import_NetlinkListenerWithCache().get_instance() 66 | 67 | 68 | class Requirements(BaseObject): 69 | bridge_utils_is_installed = os.path.exists(utils.brctl_cmd) 70 | -------------------------------------------------------------------------------- /tests/output/interfaces.vrr_vrf.ifquery.ac.3.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "peerlink", 37 | "auto": true, 38 | "config": {}, 39 | "config_status": {}, 40 | "status": "fail" 41 | }, 42 | { 43 | "name": "peerlink", 44 | "auto": true, 45 | "config": {}, 46 | "config_status": {}, 47 | "status": "fail" 48 | }, 49 | { 50 | "name": "peerlink.4094", 51 | "auto": true, 52 | "config": {}, 53 | "config_status": {}, 54 | "status": "fail" 55 | }, 56 | { 57 | "name": "myvrf", 58 | "auto": true, 59 | "config": { 60 | "vrf-table": "1002" 61 | }, 62 | "config_status": { 63 | "vrf-table": "pass" 64 | }, 65 | "status": "pass" 66 | }, 67 | { 68 | "name": "bridge", 69 | "auto": true, 70 | "config": { 71 | "bridge-vlan-aware": "yes", 72 | "bridge-ports": "bond0", 73 | "bridge-stp": "yes" 74 | }, 75 | "config_status": { 76 | "bridge-vlan-aware": "pass", 77 | "bridge-ports": "fail", 78 | "bridge-stp": "pass" 79 | }, 80 | "status": "fail" 81 | }, 82 | { 83 | "name": "bridge.901", 84 | "auto": true, 85 | "config": { 86 | "address-virtual": "00:00:5e:00:01:81 10.1.63.1/28", 87 | "vrf": "myvrf", 88 | "address": "10.1.63.2/28" 89 | }, 90 | "config_status": { 91 | "address-virtual": "pass", 92 | "vrf": "pass", 93 | "address": "pass" 94 | }, 95 | "status": "pass" 96 | }, 97 | { 98 | "name": "bond0", 99 | "auto": true, 100 | "config": { 101 | "bond-slaves": "swp_CC_" 102 | }, 103 | "config_status": { 104 | "bond-slaves": "pass" 105 | }, 106 | "status": "pass" 107 | } 108 | ] 109 | -------------------------------------------------------------------------------- /docs/examples/vlan_aware_bridges/interfaces.with_clag: -------------------------------------------------------------------------------- 1 | # 2 | # vlan-aware bridge with clag example 3 | # 4 | # 5 | # 'bridge' is a vlan aware bridge with ports: 6 | # 'peer-bond spine-bond glob host-bond-0[1-2]' 7 | # 8 | # All ports inherit 'vlans 10 20-23' from the 'bridge-vids' attribute 9 | # under the bridge 10 | # 11 | # native vlan is by default 1 12 | # 13 | # 'bridge-vids' attribute is used to declare vlans. 14 | # 'bridge-pvid' attribute is used to specify native vlans if other than 1 15 | # 'bridge-access' attribute is used to declare access port 16 | # 17 | # 'spine-bond host-bond-0[1-2]' are clag bonds and will be considered by 18 | # clagd for dual connection. clag-id has to be a non-zero and has to match 19 | # across the peer switches for the bonds to become dual connected. 20 | 21 | # spine bond 22 | # 23 | auto spine-bond 24 | iface spine-bond 25 | bond-slaves glob swp19-22 26 | bond-mode 802.3ad 27 | bond-miimon 100 28 | bond-use-carrier yes 29 | bond-lacp-rate 1 30 | bond-min-links 1 31 | bond-xmit-hash-policy layer3+4 32 | clag-id 100 33 | 34 | # mlag bond and peer interface 35 | # 36 | auto peer-bond 37 | iface peer-bond 38 | bond-slaves glob swp23-24 39 | bond-mode 802.3ad 40 | bond-miimon 100 41 | bond-use-carrier yes 42 | bond-lacp-rate 1 43 | bond-min-links 1 44 | bond-xmit-hash-policy layer3+4 45 | 46 | # sub-interface for clagd communication 47 | # 48 | auto peer-bond.4094 49 | iface peer-bond.4094 50 | address 169.254.0.1/30 51 | clagd-peer-ip 169.254.0.2 52 | clagd-sys-mac 44:38:39:ff:00:01 53 | #clagd-priority 4096 54 | # Please see man clagd for more options 55 | # clagd-args --peerTimeout 30 56 | 57 | # host ports 58 | # 59 | auto host-bond-01 60 | iface host-bond-01 61 | bond-slaves swp1 62 | bond-mode 802.3ad 63 | bond-miimon 100 64 | bond-use-carrier yes 65 | bond-lacp-rate 1 66 | bond-min-links 1 67 | bond-xmit-hash-policy layer3+4 68 | clag-id 1 69 | 70 | auto host-bond-02 71 | iface host-bond-02 72 | bond-slaves swp2 73 | bond-mode 802.3ad 74 | bond-miimon 100 75 | bond-use-carrier yes 76 | bond-lacp-rate 1 77 | bond-min-links 1 78 | bond-xmit-hash-policy layer3+4 79 | clag-id 2 80 | 81 | # the bridge 82 | auto bridge 83 | iface bridge 84 | bridge-vlan-aware yes 85 | bridge-ports peer-bond spine-bond glob host-bond-0[1-2] 86 | bridge-stp on 87 | bridge-vids 10 20-23 88 | -------------------------------------------------------------------------------- /tests/output/interfaces_link_state.after.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "swp_AA_", 37 | "addr_method": "manual", 38 | "addr_family": "inet", 39 | "auto": true, 40 | "config": {}, 41 | "config_status": {}, 42 | "status": "pass" 43 | }, 44 | { 45 | "name": "swp_BB_", 46 | "auto": true, 47 | "config": { 48 | "link-down": "yes" 49 | }, 50 | "config_status": { 51 | "link-down": "pass" 52 | }, 53 | "status": "pass" 54 | }, 55 | { 56 | "name": "bridge1", 57 | "auto": true, 58 | "config": { 59 | "bridge-ports": "swp_CC_" 60 | }, 61 | "config_status": { 62 | "bridge-ports": "pass" 63 | }, 64 | "status": "pass" 65 | }, 66 | { 67 | "name": "bridge2", 68 | "addr_method": "manual", 69 | "addr_family": "inet", 70 | "auto": true, 71 | "config": { 72 | "bridge-ports": "swp_DD_" 73 | }, 74 | "config_status": { 75 | "bridge-ports": "pass" 76 | }, 77 | "status": "pass" 78 | }, 79 | { 80 | "name": "bridge3", 81 | "addr_method": "manual", 82 | "addr_family": "inet", 83 | "auto": true, 84 | "config": { 85 | "link-down": "no", 86 | "bridge-ports": "swp_EE_" 87 | }, 88 | "config_status": { 89 | "link-down": "pass", 90 | "bridge-ports": "pass" 91 | }, 92 | "status": "pass" 93 | }, 94 | { 95 | "name": "bridge4", 96 | "addr_method": "manual", 97 | "addr_family": "inet", 98 | "auto": true, 99 | "config": { 100 | "link-down": "yes", 101 | "bridge-ports": "swp_FF_" 102 | }, 103 | "config_status": { 104 | "link-down": "pass", 105 | "bridge-ports": "pass" 106 | }, 107 | "status": "pass" 108 | } 109 | ] 110 | -------------------------------------------------------------------------------- /tests/output/interfaces.vrr_vrf.ifquery.ac.1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "peerlink", 37 | "auto": true, 38 | "config": { 39 | "bond-slaves": "swp_AA_ swp_BB_" 40 | }, 41 | "config_status": { 42 | "bond-slaves": "pass" 43 | }, 44 | "status": "pass" 45 | }, 46 | { 47 | "name": "peerlink.4094", 48 | "auto": true, 49 | "config": { 50 | "address": "169.254.1.1/30" 51 | }, 52 | "config_status": { 53 | "address": "pass" 54 | }, 55 | "status": "pass" 56 | }, 57 | { 58 | "name": "myvrf", 59 | "auto": true, 60 | "config": { 61 | "vrf-table": "1002" 62 | }, 63 | "config_status": { 64 | "vrf-table": "pass" 65 | }, 66 | "status": "pass" 67 | }, 68 | { 69 | "name": "bridge", 70 | "auto": true, 71 | "config": { 72 | "bridge-vlan-aware": "yes", 73 | "bridge-ports": "peerlink bond0", 74 | "bridge-stp": "yes" 75 | }, 76 | "config_status": { 77 | "bridge-vlan-aware": "pass", 78 | "bridge-ports": "pass", 79 | "bridge-stp": "pass" 80 | }, 81 | "status": "pass" 82 | }, 83 | { 84 | "name": "bridge.901", 85 | "auto": true, 86 | "config": { 87 | "address-virtual": "00:00:5e:00:01:81 10.1.63.1/28", 88 | "vrf": "myvrf", 89 | "address": "10.1.63.2/28" 90 | }, 91 | "config_status": { 92 | "address-virtual": "pass", 93 | "vrf": "pass", 94 | "address": "pass" 95 | }, 96 | "status": "pass" 97 | }, 98 | { 99 | "name": "bond0", 100 | "auto": true, 101 | "config": { 102 | "bond-slaves": "swp_CC_" 103 | }, 104 | "config_status": { 105 | "bond-slaves": "pass" 106 | }, 107 | "status": "pass" 108 | } 109 | ] 110 | -------------------------------------------------------------------------------- /tests/output/bridge_new_attribute_learning_arp_nd_suppress.before.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "vxlan10101", 37 | "auto": true, 38 | "config": { 39 | "bridge-arp-nd-suppress": "on", 40 | "bridge-learning": "off", 41 | "vxlan-id": "10101", 42 | "bridge-access": "101", 43 | "vxlan-local-tunnelip": "6.0.0.17" 44 | }, 45 | "config_status": { 46 | "bridge-arp-nd-suppress": "pass", 47 | "bridge-learning": "pass", 48 | "vxlan-id": "pass", 49 | "bridge-access": "pass", 50 | "vxlan-local-tunnelip": "pass" 51 | }, 52 | "status": "pass" 53 | }, 54 | { 55 | "name": "br1", 56 | "auto": true, 57 | "config": { 58 | "bridge-vlan-aware": "yes", 59 | "bridge-ports": "vxlan10101", 60 | "bridge-vids": "101" 61 | }, 62 | "config_status": { 63 | "bridge-vlan-aware": "pass", 64 | "bridge-ports": "pass", 65 | "bridge-vids": "" 66 | }, 67 | "status": "pass" 68 | }, 69 | { 70 | "name": "vxlan10102", 71 | "auto": true, 72 | "config": { 73 | "vxlan-id": "10102", 74 | "vxlan-local-tunnelip": "6.0.0.17" 75 | }, 76 | "config_status": { 77 | "vxlan-id": "pass", 78 | "vxlan-local-tunnelip": "pass" 79 | }, 80 | "status": "pass" 81 | }, 82 | { 83 | "name": "br2", 84 | "auto": true, 85 | "config": { 86 | "bridge-arp-nd-suppress": "vxlan10102=on", 87 | "bridge-learning": "vxlan10102=off", 88 | "bridge-ports": "vxlan10102", 89 | "bridge-vids": "101" 90 | }, 91 | "config_status": { 92 | "bridge-arp-nd-suppress": "pass", 93 | "bridge-learning": "pass", 94 | "bridge-ports": "pass", 95 | "bridge-vids": "" 96 | }, 97 | "status": "pass" 98 | } 99 | ] 100 | -------------------------------------------------------------------------------- /tests/output/cm_11485_vlan_device_name_vlan.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "eth0", 4 | "addr_method": "dhcp", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": { 8 | "vrf": "mgmt" 9 | }, 10 | "config_status": { 11 | "vrf": "pass" 12 | }, 13 | "status": "pass" 14 | }, 15 | { 16 | "name": "mgmt", 17 | "auto": true, 18 | "config": { 19 | "vrf-table": "1001" 20 | }, 21 | "config_status": { 22 | "vrf-table": "pass" 23 | }, 24 | "status": "pass" 25 | }, 26 | { 27 | "name": "lo", 28 | "addr_method": "loopback", 29 | "addr_family": "inet", 30 | "auto": true, 31 | "config": {}, 32 | "config_status": {}, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "swp_AA_", 37 | "addr_method": "static", 38 | "addr_family": "inet", 39 | "auto": true, 40 | "config": { 41 | "address": "172.30.1.3/24" 42 | }, 43 | "config_status": { 44 | "address": "pass" 45 | }, 46 | "status": "pass" 47 | }, 48 | { 49 | "name": "swp_BB_.1005", 50 | "auto": true, 51 | "config": { 52 | "address": "10.132.253.11/31" 53 | }, 54 | "config_status": { 55 | "address": "pass" 56 | }, 57 | "status": "pass" 58 | }, 59 | { 60 | "name": "bond0", 61 | "addr_method": "manual", 62 | "addr_family": "inet", 63 | "auto": true, 64 | "config": { 65 | "bond-slaves": "None", 66 | "bond-mode": "802.3ad", 67 | "bond-min-links": "1", 68 | "bond-xmit-hash-policy": "layer2+3" 69 | }, 70 | "config_status": { 71 | "bond-slaves": "fail", 72 | "bond-mode": "pass", 73 | "bond-min-links": "pass", 74 | "bond-xmit-hash-policy": "pass" 75 | }, 76 | "status": "fail" 77 | }, 78 | { 79 | "name": "vlan1007", 80 | "auto": true, 81 | "config": { 82 | "vlan-raw-device": "bond0", 83 | "vlan-id": "1007", 84 | "address": "10.132.253.15/31" 85 | }, 86 | "config_status": { 87 | "vlan-raw-device": "pass", 88 | "vlan-id": "pass", 89 | "address": "pass" 90 | }, 91 | "status": "pass" 92 | }, 93 | { 94 | "name": "dummy0", 95 | "auto": true, 96 | "config": { 97 | "link-type": "dummy", 98 | "address": "fdca:ffee:ff12:fe06::1/64" 99 | }, 100 | "config_status": { 101 | "link-type": "pass", 102 | "address": "pass" 103 | }, 104 | "status": "pass" 105 | } 106 | ] 107 | -------------------------------------------------------------------------------- /ifupdown2/ifupdownaddons/utilsbase.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved. 4 | # Author: Roopa Prabhu, roopa@cumulusnetworks.com 5 | # 6 | 7 | import time 8 | import logging 9 | 10 | try: 11 | from ifupdown2.ifupdown.iface import * 12 | from ifupdown2.ifupdown.utils import utils 13 | 14 | import ifupdown2.ifupdown.ifupdownflags as ifupdownflags 15 | except ImportError: 16 | from ifupdown.iface import * 17 | from ifupdown.utils import utils 18 | 19 | import ifupdown.ifupdownflags as ifupdownflags 20 | 21 | 22 | def profile(func): 23 | def wrap(*args, **kwargs): 24 | started_at = time.time() 25 | result = func(*args, **kwargs) 26 | print(str(func)) 27 | print((time.time() - started_at)) 28 | return result 29 | return wrap 30 | 31 | class utilsBase(object): 32 | """ Base class for ifupdown addon utilities """ 33 | 34 | def __init__(self, *args, **kargs): 35 | modulename = self.__class__.__name__ 36 | self.logger = logging.getLogger('ifupdown.' + modulename) 37 | 38 | def write_file(self, filename, strexpr): 39 | try: 40 | self.logger.info('writing \'%s\'' %strexpr + 41 | ' to file %s' %filename) 42 | if ifupdownflags.flags.DRYRUN: 43 | return 0 44 | with open(filename, 'w') as f: 45 | f.write(strexpr) 46 | except IOError as e: 47 | self.logger.warning('error writing to file %s' 48 | %filename + '(' + str(e) + ')') 49 | return -1 50 | return 0 51 | 52 | def read_file(self, filename): 53 | try: 54 | self.logger.debug('reading \'%s\'' %filename) 55 | with open(filename, 'r') as f: 56 | return f.readlines() 57 | except Exception: 58 | return None 59 | return None 60 | 61 | def read_file_oneline(self, filename): 62 | try: 63 | self.logger.debug('reading \'%s\'' %filename) 64 | with open(filename, 'r') as f: 65 | return f.readline().strip('\n') 66 | except Exception: 67 | return None 68 | return None 69 | 70 | def sysctl_set(self, variable, value): 71 | utils.exec_command('%s %s=%s' % 72 | (utils.sysctl_cmd, variable, value)) 73 | 74 | def sysctl_get(self, variable): 75 | return utils.exec_command('%s %s' % 76 | (utils.sysctl_cmd, 77 | variable)).split('=')[1].strip() 78 | -------------------------------------------------------------------------------- /tests/output/bond_lacp.flipped.values.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "bond4", 37 | "auto": true, 38 | "config": { 39 | "bond-lacp-rate": "slow", 40 | "bond-lacp-bypass-allow": "no", 41 | "bond-mode": "4", 42 | "bond-slaves": "swp_EE_" 43 | }, 44 | "config_status": { 45 | "bond-lacp-rate": "pass", 46 | "bond-lacp-bypass-allow": "pass", 47 | "bond-mode": "pass", 48 | "bond-slaves": "pass" 49 | }, 50 | "status": "pass" 51 | }, 52 | { 53 | "name": "bond7", 54 | "auto": true, 55 | "config": { 56 | "bond-lacp-rate": "fast", 57 | "bond-lacp-bypass-allow": "yes", 58 | "bond-mode": "4", 59 | "bond-slaves": "swp_HH_" 60 | }, 61 | "config_status": { 62 | "bond-lacp-rate": "pass", 63 | "bond-lacp-bypass-allow": "pass", 64 | "bond-mode": "pass", 65 | "bond-slaves": "pass" 66 | }, 67 | "status": "pass" 68 | }, 69 | { 70 | "name": "bond8", 71 | "auto": true, 72 | "config": { 73 | "bond-lacp-rate": "1", 74 | "bond-lacp-bypass-allow": "1", 75 | "bond-mode": "4", 76 | "bond-slaves": "swp_II_" 77 | }, 78 | "config_status": { 79 | "bond-lacp-rate": "pass", 80 | "bond-lacp-bypass-allow": "pass", 81 | "bond-mode": "pass", 82 | "bond-slaves": "pass" 83 | }, 84 | "status": "pass" 85 | }, 86 | { 87 | "name": "bond9", 88 | "auto": true, 89 | "config": { 90 | "bond-lacp-rate": "0", 91 | "bond-lacp-bypass-allow": "0", 92 | "bond-mode": "4", 93 | "bond-slaves": "swp_JJ_" 94 | }, 95 | "config_status": { 96 | "bond-lacp-rate": "pass", 97 | "bond-lacp-bypass-allow": "pass", 98 | "bond-mode": "pass", 99 | "bond-slaves": "pass" 100 | }, 101 | "status": "pass" 102 | } 103 | ] 104 | -------------------------------------------------------------------------------- /ifupdown2/ifupdown/template.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved. 4 | # Author: Roopa Prabhu, roopa@cumulusnetworks.com 5 | # 6 | # template -- 7 | # helper class to render templates 8 | # 9 | 10 | try: 11 | from ifupdown2.ifupdown.utils import * 12 | except ImportError: 13 | from ifupdown.utils import * 14 | 15 | 16 | class templateEngine(): 17 | """ provides template rendering methods """ 18 | 19 | def __init__(self, template_engine, template_enable='0', 20 | template_lookuppath=None): 21 | self.logger = logging.getLogger('ifupdown.' + 22 | self.__class__.__name__) 23 | self.tclass = None 24 | self.tclassargs = {} 25 | self.render = self._render_default 26 | if template_enable == '0': 27 | return 28 | if template_engine == 'mako': 29 | try: 30 | self.tclass = utils.importName('mako.template', 'Template') 31 | except Exception as e: 32 | self.logger.warning('unable to load template engine %s (%s)' 33 | %(template_engine, str(e))) 34 | if template_lookuppath: 35 | try: 36 | self.logger.debug('setting template lookuppath to %s' 37 | %template_lookuppath) 38 | lc = utils.importName('mako.lookup', 'TemplateLookup') 39 | self.tclassargs['lookup'] = lc( 40 | directories=template_lookuppath.split(':')) 41 | except Exception as e: 42 | self.logger.warning('unable to set template lookup path' 43 | ' %s (%s): are you sure \'python3-mako\'' 44 | 'is installed?' 45 | % (template_lookuppath, str(e))) 46 | self.render = self._render_mako 47 | else: 48 | self.logger.info('skip template processing.., ' + 49 | 'template engine not found') 50 | 51 | def _render_default(self, textdata): 52 | return textdata 53 | 54 | def _render_mako(self, textdata): 55 | """ render textdata passed as argument using mako 56 | 57 | Returns rendered textdata """ 58 | 59 | if not self.tclass: 60 | return textdata 61 | self.logger.info('template processing on interfaces file ...') 62 | t = self.tclass(text=textdata, output_encoding='utf-8', 63 | lookup=self.tclassargs.get('lookup')) 64 | return t.render() 65 | -------------------------------------------------------------------------------- /tests/output/bond_lacp.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "bond4", 37 | "auto": true, 38 | "config": { 39 | "bond-lacp-rate": "slow", 40 | "bond-lacp-bypass-allow": "yes", 41 | "bond-mode": "802.3ad", 42 | "bond-slaves": "swp_EE_" 43 | }, 44 | "config_status": { 45 | "bond-lacp-rate": "pass", 46 | "bond-lacp-bypass-allow": "pass", 47 | "bond-mode": "pass", 48 | "bond-slaves": "pass" 49 | }, 50 | "status": "pass" 51 | }, 52 | { 53 | "name": "bond7", 54 | "auto": true, 55 | "config": { 56 | "bond-lacp-rate": "fast", 57 | "bond-lacp-bypass-allow": "no", 58 | "bond-mode": "802.3ad", 59 | "bond-slaves": "swp_HH_" 60 | }, 61 | "config_status": { 62 | "bond-lacp-rate": "pass", 63 | "bond-lacp-bypass-allow": "pass", 64 | "bond-mode": "pass", 65 | "bond-slaves": "pass" 66 | }, 67 | "status": "pass" 68 | }, 69 | { 70 | "name": "bond8", 71 | "auto": true, 72 | "config": { 73 | "bond-lacp-rate": "0", 74 | "bond-lacp-bypass-allow": "0", 75 | "bond-mode": "802.3ad", 76 | "bond-slaves": "swp_II_" 77 | }, 78 | "config_status": { 79 | "bond-lacp-rate": "pass", 80 | "bond-lacp-bypass-allow": "pass", 81 | "bond-mode": "pass", 82 | "bond-slaves": "pass" 83 | }, 84 | "status": "pass" 85 | }, 86 | { 87 | "name": "bond9", 88 | "auto": true, 89 | "config": { 90 | "bond-lacp-rate": "1", 91 | "bond-lacp-bypass-allow": "1", 92 | "bond-mode": "802.3ad", 93 | "bond-slaves": "swp_JJ_" 94 | }, 95 | "config_status": { 96 | "bond-lacp-rate": "pass", 97 | "bond-lacp-bypass-allow": "pass", 98 | "bond-mode": "pass", 99 | "bond-slaves": "pass" 100 | }, 101 | "status": "pass" 102 | } 103 | ] 104 | -------------------------------------------------------------------------------- /tests/output/bridge1.vlan.show.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ifname": "swp_AA_", 4 | "vlans": [ 5 | { 6 | "vlan": 1, 7 | "flags": [ 8 | "PVID", 9 | "Egress Untagged" 10 | ] 11 | }, 12 | { 13 | "vlan": 2 14 | }, 15 | { 16 | "vlan": 3 17 | }, 18 | { 19 | "vlan": 4 20 | }, 21 | { 22 | "vlan": 5 23 | }, 24 | { 25 | "vlan": 6 26 | }, 27 | { 28 | "vlan": 7 29 | }, 30 | { 31 | "vlan": 8 32 | }, 33 | { 34 | "vlan": 9 35 | }, 36 | { 37 | "vlan": 10 38 | }, 39 | { 40 | "vlan": 11 41 | }, 42 | { 43 | "vlan": 12 44 | }, 45 | { 46 | "vlan": 13 47 | }, 48 | { 49 | "vlan": 14 50 | }, 51 | { 52 | "vlan": 15 53 | }, 54 | { 55 | "vlan": 16 56 | }, 57 | { 58 | "vlan": 17 59 | }, 60 | { 61 | "vlan": 18 62 | }, 63 | { 64 | "vlan": 19 65 | }, 66 | { 67 | "vlan": 20 68 | } 69 | ] 70 | }, 71 | { 72 | "ifname": "swp_BB_", 73 | "vlans": [ 74 | { 75 | "vlan": 1, 76 | "flags": [ 77 | "PVID", 78 | "Egress Untagged" 79 | ] 80 | }, 81 | { 82 | "vlan": 2 83 | }, 84 | { 85 | "vlan": 3 86 | }, 87 | { 88 | "vlan": 4 89 | }, 90 | { 91 | "vlan": 5 92 | }, 93 | { 94 | "vlan": 6 95 | }, 96 | { 97 | "vlan": 7 98 | }, 99 | { 100 | "vlan": 8 101 | }, 102 | { 103 | "vlan": 9 104 | }, 105 | { 106 | "vlan": 10 107 | }, 108 | { 109 | "vlan": 11 110 | }, 111 | { 112 | "vlan": 12 113 | }, 114 | { 115 | "vlan": 13 116 | }, 117 | { 118 | "vlan": 14 119 | }, 120 | { 121 | "vlan": 15 122 | }, 123 | { 124 | "vlan": 16 125 | }, 126 | { 127 | "vlan": 17 128 | }, 129 | { 130 | "vlan": 18 131 | }, 132 | { 133 | "vlan": 19 134 | }, 135 | { 136 | "vlan": 20 137 | } 138 | ] 139 | }, 140 | { 141 | "ifname": "bridge", 142 | "vlans": [ 143 | { 144 | "vlan": 1, 145 | "flags": [ 146 | "PVID", 147 | "Egress Untagged" 148 | ] 149 | } 150 | ] 151 | } 152 | ] 153 | -------------------------------------------------------------------------------- /tests/output/bridge2.vlan.show.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "ifname": "swp_AA_", 4 | "vlans": [ 5 | { 6 | "vlan": 1 7 | }, 8 | { 9 | "vlan": 2, 10 | "flags": [ 11 | "PVID", 12 | "Egress Untagged" 13 | ] 14 | }, 15 | { 16 | "vlan": 3 17 | }, 18 | { 19 | "vlan": 4 20 | }, 21 | { 22 | "vlan": 5 23 | }, 24 | { 25 | "vlan": 6 26 | }, 27 | { 28 | "vlan": 7 29 | }, 30 | { 31 | "vlan": 8 32 | }, 33 | { 34 | "vlan": 9 35 | }, 36 | { 37 | "vlan": 10 38 | }, 39 | { 40 | "vlan": 11 41 | }, 42 | { 43 | "vlan": 12 44 | }, 45 | { 46 | "vlan": 13 47 | }, 48 | { 49 | "vlan": 14 50 | }, 51 | { 52 | "vlan": 15 53 | }, 54 | { 55 | "vlan": 16 56 | }, 57 | { 58 | "vlan": 17 59 | }, 60 | { 61 | "vlan": 18 62 | }, 63 | { 64 | "vlan": 19 65 | }, 66 | { 67 | "vlan": 20 68 | } 69 | ] 70 | }, 71 | { 72 | "ifname": "swp_BB_", 73 | "vlans": [ 74 | { 75 | "vlan": 1 76 | }, 77 | { 78 | "vlan": 2, 79 | "flags": [ 80 | "PVID", 81 | "Egress Untagged" 82 | ] 83 | }, 84 | { 85 | "vlan": 3 86 | }, 87 | { 88 | "vlan": 4 89 | }, 90 | { 91 | "vlan": 5 92 | }, 93 | { 94 | "vlan": 6 95 | }, 96 | { 97 | "vlan": 7 98 | }, 99 | { 100 | "vlan": 8 101 | }, 102 | { 103 | "vlan": 9 104 | }, 105 | { 106 | "vlan": 10 107 | }, 108 | { 109 | "vlan": 11 110 | }, 111 | { 112 | "vlan": 12 113 | }, 114 | { 115 | "vlan": 13 116 | }, 117 | { 118 | "vlan": 14 119 | }, 120 | { 121 | "vlan": 15 122 | }, 123 | { 124 | "vlan": 16 125 | }, 126 | { 127 | "vlan": 17 128 | }, 129 | { 130 | "vlan": 18 131 | }, 132 | { 133 | "vlan": 19 134 | }, 135 | { 136 | "vlan": 20 137 | } 138 | ] 139 | }, 140 | { 141 | "ifname": "bridge", 142 | "vlans": [ 143 | { 144 | "vlan": 1, 145 | "flags": [ 146 | "PVID", 147 | "Egress Untagged" 148 | ] 149 | } 150 | ] 151 | } 152 | ] 153 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: clean clean-test clean-pyc clean-build docs help 2 | .DEFAULT_GOAL := help 3 | 4 | define BROWSER_PYSCRIPT 5 | import os, webbrowser, sys 6 | 7 | try: 8 | from urllib import pathname2url 9 | except Exception: 10 | from urllib.request import pathname2url 11 | 12 | webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1]))) 13 | endef 14 | export BROWSER_PYSCRIPT 15 | 16 | define PRINT_HELP_PYSCRIPT 17 | import re, sys 18 | 19 | for line in sys.stdin: 20 | match = re.match(r'^([a-zA-Z_-]+):.*?## (.*)$$', line) 21 | if match: 22 | target, help = match.groups() 23 | print("%-20s %s" % (target, help)) 24 | endef 25 | export PRINT_HELP_PYSCRIPT 26 | 27 | BROWSER := python -c "$$BROWSER_PYSCRIPT" 28 | 29 | help: 30 | @python -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) 31 | 32 | clean: clean-build clean-pyc clean-test ## remove all build, test, coverage and Python artifacts 33 | 34 | clean-build: ## remove build artifacts 35 | rm -fr build/ 36 | rm -fr dist/ 37 | rm -fr .eggs/ 38 | find . -name '*.egg-info' -exec rm -fr {} + 39 | find . -name '*.egg' -exec rm -f {} + 40 | 41 | clean-pyc: ## remove Python file artifacts 42 | find . -name '*.pyc' -exec rm -f {} + 43 | find . -name '*.pyo' -exec rm -f {} + 44 | find . -name '*~' -exec rm -f {} + 45 | find . -name '__pycache__' -exec rm -fr {} + 46 | 47 | clean-test: ## remove test and coverage artifacts 48 | rm -fr .tox/ 49 | rm -f .coverage 50 | rm -fr htmlcov/ 51 | rm -fr .pytest_cache 52 | 53 | lint: ## check style with flake8 54 | flake8 ifupdown2 tests 55 | 56 | test: ## run tests quickly with the default Python 57 | py.test 58 | 59 | test-all: ## run tests on every Python version with tox 60 | tox 61 | 62 | coverage: ## check code coverage quickly with the default Python 63 | coverage run --source ifupdown2 -m pytest 64 | coverage report -m 65 | coverage html 66 | $(BROWSER) htmlcov/index.html 67 | 68 | docs: ## generate Sphinx HTML documentation, including API docs 69 | rm -f docs/ifupdown2.rst 70 | rm -f docs/modules.rst 71 | sphinx-apidoc -o docs/ ifupdown2 72 | $(MAKE) -C docs clean 73 | $(MAKE) -C docs html 74 | $(BROWSER) docs/_build/html/index.html 75 | 76 | servedocs: docs ## compile the docs watching for changes 77 | watchmedo shell-command -p '*.rst' -c '$(MAKE) -C docs html' -R -D . 78 | 79 | testpy: ## package and upload to testpy 80 | python setup.py sdist bdist_wheel 81 | twine upload --repository-url https://test.pypi.org/legacy/ dist/* 82 | @echo "Install ifupdown2 from testpy 'pip install --index-url https://test.pypi.org/simple/ ifupdown2'" 83 | 84 | release: dist ## package and upload a release 85 | twine upload dist/* 86 | 87 | dist: clean ## builds source and wheel package 88 | python setup.py sdist 89 | python setup.py bdist_wheel 90 | ls -l dist 91 | 92 | install: clean ## install the package to the active Python's site-packages 93 | python setup.py install 94 | 95 | deb: clean ## create a debian package (.deb) 96 | debuild -b -rfakeroot -us -uc 97 | -------------------------------------------------------------------------------- /docs/README.rst: -------------------------------------------------------------------------------- 1 | python-ifupdown2 2 | ================ 3 | 4 | This package is a replacement for the debian ifupdown package. 5 | It is ifupdown re-written in python. It maintains the original ifupdown 6 | pluggable architecture and extends it further. 7 | 8 | The python-ifupdown2 package provides the infrastructure for 9 | parsing /etc/network/interfaces file, loading, scheduling and state 10 | management of interfaces. 11 | 12 | It dynamically loads python modules from /usr/share/ifupdownmodules (provided 13 | by the python-ifupdown2-addons package). To remain compatible with other 14 | packages that depend on ifupdown, it also executes scripts under /etc/network/. 15 | To make the transition smoother, a python module under 16 | /usr/share/ifupdownmodules will override a script by the same name under 17 | /etc/network/. 18 | 19 | It publishes an interface object which is passed to all loadble python 20 | modules. For more details on adding a addon module, see the section on 21 | adding python modules. 22 | 23 | 24 | pluggable python modules: 25 | ========================= 26 | Unlike original ifupdown, all interface configuration is moved to external 27 | python modules. That includes inet, inet6 and dhcp configurations. 28 | 29 | A set of default modules are provided by the python-ifupdown2-addons deb. 30 | 31 | python-ifupdown2 expects a few things from the pluggable modules: 32 | - the module should implement a class by the same name 33 | - the interface object (class iface) and the operation to be performed is 34 | passed to the modules 35 | - the python addon class should provide a few methods: 36 | - run() : method to configure the interface. 37 | - get_ops() : must return a list of operations it supports. 38 | eg: 'pre-up', 'post-down' 39 | - get_dependent_ifacenames() : must return a list of interfaces the 40 | interface is dependent on. This is used to build the dependency list 41 | for sorting and executing interfaces in dependency order. 42 | - if the module supports -r option to ifquery, ie ability to construct the 43 | ifaceobj from running state, it can optionally implement the 44 | get_dependent_ifacenames_running() method, to return the list of 45 | dependent interfaces derived from running state of the interface. 46 | This is different from get_dependent_ifacenames() where the dependent 47 | interfaces are derived from the interfaces config file (provided by the 48 | user). 49 | 50 | Example: Address handling module /usr/share/ifupdownaddons/address.py 51 | 52 | 53 | build 54 | ===== 55 | - get source 56 | 57 | - install build dependencies: 58 | apt-get install python-stdeb 59 | apt-get install python-docutils 60 | 61 | - cd && ./build.sh 62 | 63 | (generates python-ifupdown2-.deb) 64 | 65 | install 66 | ======= 67 | 68 | - remove existing ifupdown package 69 | dpkg -r ifupdown 70 | 71 | - install python-ifupdown2 using `dpkg -i` 72 | 73 | - or install from deb 74 | dpkg -i python-ifupdown2-.deb 75 | 76 | - note that python-ifupdown2 requires python-ifupdown2-addons package to 77 | function. And python-ifupdown2-addons deb has an install dependency on 78 | python-ifupdown2 79 | -------------------------------------------------------------------------------- /ifupdown2/ifupdown/graph.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved. 4 | # Author: Roopa Prabhu, roopa@cumulusnetworks.com 5 | # 6 | # graph -- 7 | # graph helper module for ifupdown 8 | # 9 | 10 | import copy 11 | import logging 12 | 13 | from collections import deque 14 | 15 | 16 | try: 17 | from ifupdown2.lib.gvgen import GvGen 18 | except ImportError: 19 | from lib.gvgen import GvGen 20 | 21 | 22 | class GraphException(Exception): 23 | pass 24 | 25 | 26 | class graph(): 27 | """ graph functions to sort and print interface graph """ 28 | 29 | logger = logging.getLogger('ifupdown.graph') 30 | 31 | @classmethod 32 | def topological_sort_graphs_all(cls, dependency_graphs, indegrees_arg): 33 | """ runs topological sort on interface list passed as dependency graph 34 | 35 | Args: 36 | **dependency_graphs** (dict): dependency graph with dependency 37 | lists for interfaces 38 | 39 | **indegrees_arg** (dict): indegrees array for all interfaces 40 | """ 41 | S = [] 42 | Q = deque() 43 | 44 | indegrees = copy.deepcopy(indegrees_arg) 45 | for ifname,indegree in list(indegrees.items()): 46 | if indegree == 0: 47 | Q.append(ifname) 48 | 49 | while len(Q): 50 | # initialize queue 51 | x = Q.popleft() 52 | 53 | # Get dependents of x 54 | dlist = dependency_graphs.get(x) 55 | if not dlist: 56 | S.append(x) 57 | continue 58 | 59 | for y in dlist: 60 | try: 61 | indegrees[y] = indegrees.get(y) - 1 62 | except Exception: 63 | cls.logger.debug('topological_sort_graphs_all: did not find %s' %y) 64 | indegrees[y] = 0 65 | if indegrees.get(y) == 0: 66 | Q.append(y) 67 | 68 | S.append(x) 69 | 70 | for ifname,indegree in list(indegrees.items()): 71 | if indegree != 0: 72 | raise GraphException('cycle found involving iface %s' %ifname + 73 | ' (indegree %d)' %indegree) 74 | 75 | return S 76 | 77 | @classmethod 78 | def generate_dots(cls, dependency_graph, indegrees): 79 | """ spits out interface dependency graph in dot format 80 | 81 | Args: 82 | **dependency_graphs** (dict): dependency graph with dependency 83 | lists for interfaces 84 | 85 | **indegrees_arg** (dict): indegrees array for all interfaces 86 | """ 87 | 88 | gvgraph = GvGen() 89 | graphnodes = {} 90 | for v in list(dependency_graph.keys()): 91 | graphnodes[v] = gvgraph.newItem(v) 92 | 93 | for i, v in list(graphnodes.items()): 94 | dlist = dependency_graph.get(i, []) 95 | if not dlist: 96 | continue 97 | for d in dlist: 98 | gvgraph.newLink(v, graphnodes.get(d)) 99 | gvgraph.dot() 100 | -------------------------------------------------------------------------------- /tests/output/vxlan_sanity.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "bridge", 37 | "auto": true, 38 | "config": { 39 | "bridge-vlan-aware": "yes", 40 | "bridge-ports": "swp_AA_ swp_BB_ vxlan1000 vxlan10200", 41 | "bridge-stp": "yes", 42 | "bridge-pvid": "1", 43 | "bridge-vids": "100 200" 44 | }, 45 | "config_status": { 46 | "bridge-vlan-aware": "pass", 47 | "bridge-ports": "pass", 48 | "bridge-stp": "pass", 49 | "bridge-pvid": "", 50 | "bridge-vids": "" 51 | }, 52 | "status": "pass" 53 | }, 54 | { 55 | "name": "vxlan1000", 56 | "auto": true, 57 | "config": { 58 | "vxlan-id": "1000", 59 | "bridge-access": "100", 60 | "vxlan-local-tunnelip": "27.0.0.11" 61 | }, 62 | "config_status": { 63 | "vxlan-id": "pass", 64 | "bridge-access": "pass", 65 | "vxlan-local-tunnelip": "pass" 66 | }, 67 | "status": "pass" 68 | }, 69 | { 70 | "name": "vxlan10200", 71 | "auto": true, 72 | "config": { 73 | "bridge-learning": "on", 74 | "vxlan-id": "10200", 75 | "vxlan-remoteip": "6.0.0.16", 76 | "bridge-access": "200", 77 | "vxlan-local-tunnelip": "6.0.0.15" 78 | }, 79 | "config_status": { 80 | "bridge-learning": "pass", 81 | "vxlan-id": "pass", 82 | "vxlan-remoteip": "pass", 83 | "bridge-access": "pass", 84 | "vxlan-local-tunnelip": "pass" 85 | }, 86 | "status": "pass" 87 | }, 88 | { 89 | "name": "bridge.100", 90 | "auto": true, 91 | "config": { 92 | "address": "45.0.0.16/26" 93 | }, 94 | "config_status": { 95 | "address": "pass" 96 | }, 97 | "status": "pass" 98 | }, 99 | { 100 | "name": "bridge.200", 101 | "auto": true, 102 | "config": {}, 103 | "config_status": {}, 104 | "status": "pass" 105 | }, 106 | { 107 | "name": "vx0", 108 | "auto": true, 109 | "config": { 110 | "vxlan-ageing": "30", 111 | "vxlan-local-tunnelip": "172.16.20.105", 112 | "vxlan-svcnodeip": "172.16.22.126", 113 | "vxlan-id": "42", 114 | "vxlan-learning": "yes", 115 | "vxlan-remoteip": "172.16.22.128" 116 | }, 117 | "config_status": { 118 | "vxlan-ageing": "pass", 119 | "vxlan-local-tunnelip": "pass", 120 | "vxlan-svcnodeip": "pass", 121 | "vxlan-id": "pass", 122 | "vxlan-learning": "pass", 123 | "vxlan-remoteip": "pass" 124 | }, 125 | "status": "pass" 126 | } 127 | ] 128 | -------------------------------------------------------------------------------- /tests/test_coverage.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from pathlib import Path 3 | 4 | import pytest 5 | import logging 6 | import tarfile 7 | import coverage 8 | import subprocess 9 | 10 | from .conftest import registered_files 11 | 12 | logging.basicConfig(level=logging.INFO) 13 | logger = logging.getLogger(__name__) 14 | 15 | 16 | def __doesnt_start_with(file_path: Path, exclude_list: List[str]) -> bool: 17 | for exclude in exclude_list: 18 | if str(file_path).startswith(f"tests/{exclude}"): 19 | return False 20 | return True 21 | 22 | 23 | @pytest.mark.order(-2) 24 | def test_orphan_files(skip_if_any_test_failed): 25 | """ 26 | Check if we have orphaned files in tests/ 27 | Orphaned files might have been used by older test but not used anymore 28 | This test ensure that all files are used and not stale 29 | """ 30 | exclude_list = [ 31 | "__pycache__", 32 | "results", 33 | "conftest.py", 34 | "test_l2.py", 35 | "test_l3.py", 36 | "test_coverage.py", 37 | "__init__.py" 38 | ] 39 | files = set(str(path) for path in Path("tests/").rglob("*") if path.is_file() and __doesnt_start_with(path, exclude_list)) 40 | 41 | if orphan_files := files - registered_files: 42 | pytest.fail(f"Found orphan files: {orphan_files}") 43 | 44 | 45 | def extract_tar_gz(archive_path, extract_path): 46 | """ 47 | Extracts a .tar.gz archive to the specified directory. 48 | """ 49 | with tarfile.open(archive_path, "r:gz") as archive: 50 | archive.extractall(path=extract_path) 51 | logger.info(f"Archive '{archive_path}' successfully extracted to '{extract_path}'.") 52 | 53 | 54 | @pytest.mark.order(-1) 55 | def test_coverage(ssh): 56 | if ssh.coverage_enabled: 57 | # todo move some of those things to a fixture? 58 | ssh.download_coverage() 59 | extract_tar_gz("tests/results/coverage_data.tar.gz", "tests/results/") 60 | cov = coverage.Coverage(data_file="tests/results/coverage_data/.coverage") 61 | cov.load() 62 | total_coverage = cov.report(ignore_errors=True) 63 | assert total_coverage >= 75, f"Coverage less than 75% - total coverage: {total_coverage} - details in ./tests/results/coverage_data.tar.gz" 64 | else: 65 | pytest.skip("coverage is disabled") 66 | 67 | 68 | @pytest.mark.skip(reason="This test is currently disabled because flake8 is currently reporting 3638 errors and polluting the output") 69 | def test_flake8(): 70 | result = subprocess.run(["flake8", "."], text=True, capture_output=True) 71 | 72 | if result.returncode != 0: 73 | error_count = len(result.stdout.strip().split("\n")) 74 | pytest.fail( 75 | f"flake8 reported {error_count} error{'s' if error_count > 1 else ''} (see logs)\n" 76 | f"{result.stdout}\n" 77 | f"{result.stderr}\n" 78 | ) 79 | 80 | 81 | @pytest.mark.skip(reason="This test is currently disabled due to import-not-found errors") 82 | def test_mypy(): 83 | result = subprocess.run(["mypy", "."], text=True, capture_output=True) 84 | 85 | if result.returncode != 0: 86 | msg = result.stdout.strip().split("\n")[-1] 87 | pytest.fail( 88 | f"Mypy {msg}\n" 89 | f"{result.stdout}\n" 90 | f"{result.stderr}\n" 91 | ) 92 | -------------------------------------------------------------------------------- /docs/source/developmentcorner.rst: -------------------------------------------------------------------------------- 1 | Development Corner 2 | ================== 3 | 4 | Getting started 5 | --------------- 6 | Unlike original ifupdown, all interface configuration is moved to external 7 | python modules. That includes inet, inet6 and dhcp configurations. 8 | 9 | * if you are looking at fixing bugs or adding new features to the ifupdown2 10 | infrastructure package, pls look at the apiref, documentation and code 11 | for python-ifupdown2 12 | 13 | 14 | Writing a ifupdown2 addon module 15 | -------------------------------- 16 | Addon modules are a nice way to add additional functionality to ifupdown2. 17 | Typically a new addon module will include support for a new network interface 18 | configuration which is not already supported by existing ifupdown2 addon 19 | modules. 20 | 21 | ifupdown2 addon modules are written in python. python-ifupdown2 package 22 | comes with default addon modules. All addon modules are installed under 23 | /usr/share/ifupdownaddons directory. 24 | 25 | The center of the universe for an addon module is the 'class iface' object 26 | exported by the python-ifupdown2 package. 27 | 28 | The iface object is modeled after an iface entry in the user provided network 29 | configuration file (eg. /etc/network/interfaces). For more details see 30 | the api reference for the iface class. 31 | 32 | ifupdown2 dynamically loads a python addon module. It expects the addon module 33 | to implement a few methods. 34 | 35 | * all addon modules must inherit from moduleBase class 36 | * the module must implement a class by the same name 37 | * the network interface object (class iface) and the operation to be performed 38 | is passed to the modules. Operation can be any of 'pre-up', 'up', 'post-up', 39 | 'pre-down', 'down', 'post-down', 'query-check', 'query-running'. 40 | The module can choose to support a subset or all operations. 41 | In cases when the operation is query-check, the module must compare between 42 | the given and running state and return the checked state of the object in 43 | queryobjcur passed as argument to the run menthod. 44 | * the python addon class must provide a few methods: 45 | * run() : method to configure the interface. 46 | * get_ops() : must return a list of operations it supports. 47 | eg: 'pre-up', 'post-down' 48 | * get_dependent_ifacenames() : must return a list of interfaces the 49 | supported interface is dependent on. This is used to build the 50 | dependency list for sorting and executing interfaces in dependency order. 51 | * if the module supports -r option to ifquery, ie ability to construct the 52 | ifaceobj from running state, it can optionally implement the 53 | get_dependent_ifacenames_running() method, to return the list of 54 | dependent interfaces derived from running state of the interface. 55 | This is different from get_dependent_ifacenames() where the dependent 56 | interfaces are derived from the interfaces config file (provided by the 57 | user). 58 | * provide a dictionary of all supported attributes in the _modinfo 59 | attribute. This is useful for syntax help and man page generation. 60 | 61 | python-ifupdown2 package also installs ifupdownaddons python package 62 | that contains helper modules for all addon modules. 63 | 64 | see example address handling module /usr/share/ifupdownaddons/address.py 65 | 66 | API reference 67 | ------------- 68 | .. toctree:: 69 | :maxdepth: 2 70 | 71 | addonsapiref.rst 72 | addonshelperapiref.rst 73 | -------------------------------------------------------------------------------- /ifupdown2/man/ifreload.8.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | ifreload 3 | ======== 4 | 5 | -------------------------------------- 6 | reload network interface configuration 7 | -------------------------------------- 8 | 9 | :Author: Roopa Prabhu 10 | :Date: 2014-02-05 11 | :Copyright: Copyright 2014 Cumulus Networks, Inc. All rights reserved. 12 | :Version: 0.1 13 | :Manual section: 8 14 | 15 | SYNOPSIS 16 | ======== 17 | ifreload [-h] (-a|-c) [-v] [-d] [-f] [-n] [-s] 18 | 19 | DESCRIPTION 20 | =========== 21 | reloads network **interfaces(5)** file **/etc/network/interfaces** 22 | or config file defined in ifupdown2.conf file. 23 | 24 | Runs **ifdown** on interfaces that were removed from the file and 25 | subsequently runs **ifup** on all interfaces. 26 | 27 | ifreload is non-disruptive. It will fix running config to match what 28 | is configured in the interfaces file without bringing the interface 29 | down. There are some cases where on linux an interface config cannot 30 | be applied unless the interface is brought down...eg: change of mac 31 | address and a few bond attributes. For such attribute changes, it may 32 | flap the interface only if the linux kernel requires it to. 33 | 34 | When removing an interface (iface section) from the interfaces file 35 | please make sure all its references are removed as well. Similarly 36 | when renaming an interface, please make sure all references to the 37 | interface are changed to the new name. Renaming an interface 38 | in the interfaces file results in ifdown of the old and ifup 39 | of the interface with the new name. 40 | 41 | If you do not wish to execute **down** on any interfaces, but only **up** on 42 | interfaces that were already **up**, please see the **--currently-up** 43 | option below. 44 | 45 | OPTIONS 46 | ======= 47 | -h, --help show this help message and exit 48 | 49 | -a, --all process all interfaces marked "auto" 50 | 51 | -v, --verbose verbose 52 | 53 | -d, --debug output debug info 54 | 55 | -f, --force force run all operations 56 | 57 | -c, --currently-up Reload the configuration for all interfaces which 58 | are currently up regardless of whether an interface 59 | has "auto " configuration within the 60 | /etc/network/interfaces file. 61 | 62 | -X EXCLUDEPATS, --exclude EXCLUDEPATS 63 | Exclude interfaces from the list of interfaces to 64 | operate on. Can be specified multiple times 65 | If the excluded interface has dependent interfaces, 66 | (e.g. a bridge or a bond with multiple enslaved interfaces) 67 | then each dependent interface must be specified in order 68 | to be excluded. 69 | 70 | -s, --syntax-check Only run the interfaces file parser 71 | 72 | 73 | EXAMPLES 74 | ======== 75 | # reload all auto interfaces in **interfaces(5)** file 76 | 77 | **ifreload -a** 78 | 79 | # reload all interfaces using service command 80 | 81 | **service networking reload** 82 | 83 | # reload all currently up interfaces without bringing any interfaces down 84 | 85 | **service networking reload-currently-up** 86 | 87 | SEE ALSO 88 | ======== 89 | ifup(8), 90 | ifdown(8), 91 | ifquery(8), 92 | interfaces(5), 93 | ifupdown-addons-interfaces(5) 94 | -------------------------------------------------------------------------------- /etc/network/ifupdown2/ifupdown2.conf: -------------------------------------------------------------------------------- 1 | # 2 | # ifupdown2 configuration file 3 | # 4 | # This file contains default settings for ifupdown 5 | # 6 | 7 | # enable persistent ifupdown2 debug logs 8 | # ifupdown2 will keep debug logs in /etc/network/ifupdown2/logs 9 | # by default the last 42 configurations logs will be kept. 10 | # yes - (default) enable persistent logging (42 configs) 11 | # no - disable persistent logging 12 | # [2-9]+ - specify how many configuration logs should be stored 13 | enable_persistent_debug_logging=yes 14 | 15 | # use ifupdown2d 16 | use_daemon=no 17 | 18 | # enable templates 19 | template_enable=1 20 | 21 | # default template engine (only mako is currently supported) 22 | template_engine=mako 23 | 24 | # default template lookup path during template rendering 25 | template_lookuppath=/etc/network/ifupdown2/templates 26 | 27 | # default network configuration filepath 28 | default_interfaces_configfile=/etc/network/interfaces 29 | 30 | # The -i interfacefile option is allowed by default but 31 | # can be disabled by setting the below option to 1 to 32 | # reduce security issues (due to the pre- and post- commands) 33 | disable_cli_interfacesfile=0 34 | 35 | 36 | # enable addon module syntax check: 37 | # Python addon modules register dictionary of supported attributes. 38 | # The syntax checker in ifupdown2 uses this dictionary for syntax 39 | # checks in the interfaces file. This works well, when only python modules 40 | # are used. But when a mix of scripts and modules are used (which is the 41 | # default case), you may get false warnings for attributes supported 42 | # by scripts 43 | addon_syntax_check=0 44 | 45 | # Support executing of ifupdown style scripts. 46 | # Note that by default python addon modules override scripts with the same 47 | # name 48 | addon_scripts_support=1 49 | 50 | # enable python addons 51 | addon_python_modules_support=1 52 | 53 | # By default ifupdown2 only supports a single vlan filtering bridge 54 | # on the system. Set this flag to 1 to support multiple vlan 55 | # filtering bridges 56 | multiple_vlan_aware_bridge_support=0 57 | 58 | # ifquery check status strings. 59 | # By default `ifquery --check` prints the check and 60 | # cross marks against interface attributes. 61 | # Use the below strings to modify the default behaviour. 62 | # 63 | ifquery_check_success_str=pass 64 | ifquery_check_error_str=fail 65 | ifquery_check_unknown_str= 66 | # 67 | 68 | # This attribute controls iface/vlan range expansions 69 | # in ifquery default output. 70 | ifquery_ifacename_expand_range=0 71 | 72 | # Let link master (bridges, bonds) own the link state of slaves 73 | link_master_slave=1 74 | 75 | # Delay admin state change till the end 76 | delay_admin_state_change=0 77 | 78 | # ifreload by default downs: 'all interfaces for which config changed' + 79 | # 'interfaces that were deleted'. With the below variable set to '0' 80 | # ifreload will only down 'interfaces that were deleted' 81 | ifreload_down_changed=0 82 | 83 | # squash all addr config when you process the first interface 84 | addr_config_squash=0 85 | 86 | # squash iface config into one when you have multiple 87 | # ifaces stanzas for an interface 88 | ifaceobj_squash=0 89 | 90 | # By default ifupdown2 will adjust logical devices MTU 91 | # based on the physical interface they are running on top of. 92 | # set this flag to 0 to disable this behaviour 93 | adjust_logical_dev_mtu=1 94 | 95 | # directory where the state file is stored 96 | # if this directory doesn't exists ifupdown2 will create it 97 | # if directory creation fails or state_dir variable is empty 98 | # state_dir will default to /var/tmp/network/ 99 | state_dir=/var/tmp/network/ 100 | -------------------------------------------------------------------------------- /tests/eni/bridge7_macvlans.eni: -------------------------------------------------------------------------------- 1 | auto lo 2 | iface lo inet loopback 3 | 4 | auto eth0 5 | iface eth0 inet dhcp 6 | vrf mgmt 7 | 8 | auto mgmt 9 | iface mgmt 10 | vrf-table auto 11 | 12 | auto bridge 13 | iface bridge 14 | bridge-vlan-aware yes 15 | bridge-ports swp_AA_ 16 | bridge-stp on 17 | bridge-vids 1-33 18 | bridge-pvid 192 19 | 20 | auto bridge.1 21 | iface bridge.1 22 | address-virtual 42:38:39:FF:00:1 10.7.192.1/1 23 | 24 | auto bridge.2 25 | iface bridge.2 26 | address-virtual 42:38:39:ff:00:2 10.7.192.2/2 27 | 28 | auto bridge.3 29 | iface bridge.3 30 | address-virtual 42:38:39:ff:00:3 10.7.192.3/3 31 | 32 | auto bridge.4 33 | iface bridge.4 34 | address-virtual 42:38:39:ff:00:4 10.7.192.4/4 35 | 36 | auto bridge.5 37 | iface bridge.5 38 | address-virtual 42:38:39:ff:00:5 10.7.192.5/5 39 | 40 | auto bridge.6 41 | iface bridge.6 42 | address-virtual 42:38:39:ff:00:6 10.7.192.6/6 43 | 44 | auto bridge.7 45 | iface bridge.7 46 | address-virtual 42:38:39:ff:00:7 10.7.192.7/7 47 | 48 | auto bridge.8 49 | iface bridge.8 50 | address-virtual 42:38:39:ff:00:8 10.7.192.8/8 51 | 52 | auto bridge.9 53 | iface bridge.9 54 | address-virtual 42:38:39:ff:00:9 10.7.192.9/9 55 | 56 | auto bridge.10 57 | iface bridge.10 58 | address-virtual 42:38:39:ff:00:10 10.7.192.10/10 59 | 60 | auto bridge.11 61 | iface bridge.11 62 | address-virtual 42:38:39:ff:00:11 10.7.192.11/11 63 | 64 | auto bridge.12 65 | iface bridge.12 66 | address-virtual 42:38:39:ff:00:12 10.7.192.12/12 67 | 68 | auto bridge.13 69 | iface bridge.13 70 | address-virtual 42:38:39:ff:00:13 10.7.192.13/13 71 | 72 | auto bridge.14 73 | iface bridge.14 74 | address-virtual 42:38:39:ff:00:14 10.7.192.14/14 75 | 76 | auto bridge.15 77 | iface bridge.15 78 | address-virtual 42:38:39:ff:00:15 10.7.192.15/15 79 | 80 | auto bridge.16 81 | iface bridge.16 82 | address-virtual 42:38:39:ff:00:16 10.7.192.16/16 83 | 84 | auto bridge.17 85 | iface bridge.17 86 | address-virtual 42:38:39:ff:00:17 10.7.192.17/17 87 | 88 | auto bridge.18 89 | iface bridge.18 90 | address-virtual 42:38:39:ff:00:18 10.7.192.18/18 91 | 92 | auto bridge.19 93 | iface bridge.19 94 | address-virtual 42:38:39:ff:00:19 10.7.192.19/19 95 | 96 | auto bridge.20 97 | iface bridge.20 98 | address-virtual 42:38:39:ff:00:20 10.7.192.20/20 99 | 100 | auto bridge.21 101 | iface bridge.21 102 | address-virtual 42:38:39:ff:00:21 10.7.192.21/21 103 | 104 | auto bridge.22 105 | iface bridge.22 106 | address-virtual 42:38:39:ff:00:22 10.7.192.22/22 107 | 108 | auto bridge.23 109 | iface bridge.23 110 | address-virtual 42:38:39:ff:00:23 10.7.192.23/23 111 | 112 | auto bridge.24 113 | iface bridge.24 114 | address-virtual 42:38:39:ff:00:24 10.7.192.24/24 115 | 116 | auto bridge.25 117 | iface bridge.25 118 | address-virtual 42:38:39:ff:00:25 10.7.192.25/25 119 | 120 | auto bridge.26 121 | iface bridge.26 122 | address-virtual 42:38:39:ff:00:26 10.7.192.26/26 123 | 124 | auto bridge.27 125 | iface bridge.27 126 | address-virtual 42:38:39:ff:00:27 10.7.192.27/27 127 | 128 | auto bridge.28 129 | iface bridge.28 130 | address-virtual 42:38:39:ff:00:28 10.7.192.28/28 131 | 132 | auto bridge.29 133 | iface bridge.29 134 | address-virtual 42:38:39:ff:00:29 10.7.192.29/29 135 | 136 | auto bridge.30 137 | iface bridge.30 138 | address-virtual 42:38:39:ff:00:30 10.7.192.30/30 139 | 140 | auto bridge.31 141 | iface bridge.31 142 | address-virtual 42:38:39:ff:00:31 10.7.192.31/31 143 | 144 | auto bridge.32 145 | iface bridge.32 146 | address-virtual 42:38:39:ff:00:32 10.7.192.32/32 147 | -------------------------------------------------------------------------------- /tests/output/bridge_attr_back_to_default.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "br0", 37 | "auto": true, 38 | "config": { 39 | "bridge-mcqifaddr": "yes", 40 | "bridge-vlan-protocol": "802.1ad", 41 | "bridge-mcsqc": "42", 42 | "bridge-stp": "no", 43 | "bridge-mcsqi": "42", 44 | "bridge-arp-nd-suppress": "vx42=on", 45 | "bridge-mcmi": "42", 46 | "bridge-ports": "vx42", 47 | "bridge-l2protocol-tunnel": "all", 48 | "bridge-unicast-flood": "vx42=off", 49 | "bridge-mcsnoop": "no", 50 | "bridge-vlan-aware": "yes", 51 | "bridge-pathcosts": "vx42=42", 52 | "bridge-portprios": "vx42=10", 53 | "bridge-fd": "29", 54 | "bridge-ageing": "42", 55 | "bridge-multicast-flood": "vx42=off", 56 | "bridge-hello": "10", 57 | "bridge-mcquerier": "yes", 58 | "bridge-mclmc": "42", 59 | "bridge-mcrouter": "no", 60 | "bridge-vlan-stats": "off", 61 | "bridge-mclmi": "42", 62 | "bridge-hashmax": "1024", 63 | "bridge-mcqri": "42", 64 | "bridge-mcqpi": "42", 65 | "bridge-bridgeprio": "42", 66 | "bridge-maxage": "10", 67 | "bridge-igmp-version": "3", 68 | "bridge-mld-version": "2", 69 | "bridge-learning": "vx42=off", 70 | "bridge-mcstats": "off", 71 | "bridge-portmcfl": "vx42=yes", 72 | "bridge-mcqi": "42" 73 | }, 74 | "config_status": { 75 | "bridge-mcqifaddr": "pass", 76 | "bridge-vlan-protocol": "pass", 77 | "bridge-mcsqc": "pass", 78 | "bridge-stp": "pass", 79 | "bridge-mcsqi": "pass", 80 | "bridge-arp-nd-suppress": "pass", 81 | "bridge-mcmi": "pass", 82 | "bridge-ports": "pass", 83 | "bridge-l2protocol-tunnel": "pass", 84 | "bridge-unicast-flood": "pass", 85 | "bridge-mcsnoop": "pass", 86 | "bridge-vlan-aware": "pass", 87 | "bridge-pathcosts": "pass", 88 | "bridge-portprios": "pass", 89 | "bridge-fd": "pass", 90 | "bridge-ageing": "pass", 91 | "bridge-multicast-flood": "pass", 92 | "bridge-hello": "pass", 93 | "bridge-mcquerier": "pass", 94 | "bridge-mclmc": "pass", 95 | "bridge-mcrouter": "pass", 96 | "bridge-vlan-stats": "pass", 97 | "bridge-mclmi": "pass", 98 | "bridge-hashmax": "pass", 99 | "bridge-mcqri": "pass", 100 | "bridge-mcqpi": "pass", 101 | "bridge-bridgeprio": "pass", 102 | "bridge-maxage": "pass", 103 | "bridge-igmp-version": "pass", 104 | "bridge-mld-version": "pass", 105 | "bridge-learning": "pass", 106 | "bridge-mcstats": "pass", 107 | "bridge-portmcfl": "pass", 108 | "bridge-mcqi": "pass" 109 | }, 110 | "status": "pass" 111 | }, 112 | { 113 | "name": "vx42", 114 | "auto": true, 115 | "config": { 116 | "vxlan-id": "42", 117 | "bridge-access": "42" 118 | }, 119 | "config_status": { 120 | "vxlan-id": "pass", 121 | "bridge-access": "pass" 122 | }, 123 | "status": "pass" 124 | } 125 | ] 126 | -------------------------------------------------------------------------------- /debian/ifupdown2.postinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | MYNAME="${0##*/}" 5 | 6 | report() { echo "${MYNAME}: $*" ; } 7 | report_warn() { report "Warning: $*" >&2 ; } 8 | report_err() { report "Error: $*" >&2 ; } 9 | 10 | fix_dhclient_file_with_space() 11 | { 12 | # because of a typo an older ifupdown2 version was creating lease file 13 | # with trailing space. In case we still have users with such files we 14 | # need to strip that trailing whitespace. 15 | for filename in `find /var/lib/dhcp/ -name "dhclient.*.leases "` 16 | do 17 | if [ -f "$filename " ]; 18 | then 19 | interface_name=`echo $filename | cut -d'.' -f2,3,4,5` 20 | mv "$filename " /var/lib/dhcp/dhclient6.$interface_name 21 | fi 22 | done 23 | } 24 | 25 | process_etc_network_interfaces() 26 | { 27 | # Generic stuff done on all configurations 28 | if [ -f /etc/network/interfaces ] ; then 29 | if ! grep -q -E "^[[:space:]]*iface[[:space:]]+l[o0]([[:space:]]+inet([[:space:]]+loopback)?)?[[:space:]]*$" /etc/network/interfaces ; then 30 | report_warn "No 'iface lo' definition found in /etc/network/interfaces" 31 | fi 32 | 33 | if ! grep -q "^[[:space:]]*\(allow-\|\)auto[[:space:]]\+\(.*[[:space:]]\+\|\)lo0\?\([[:space:]]\+\|$\)" /etc/network/interfaces ; then 34 | report_warn "No 'auto lo' statement found in /etc/network/interfaces" 35 | fi 36 | else # ! -f /etc/network/interfaces 37 | if [ -z "$2" ]; then 38 | echo "Creating /etc/network/interfaces." 39 | echo "# interfaces(5) file used by ifup(8) and ifdown(8)" > /etc/network/interfaces 40 | echo "source /etc/network/interfaces.d/*" >> /etc/network/interfaces 41 | echo "auto lo" >> /etc/network/interfaces 42 | echo "iface lo inet loopback" >> /etc/network/interfaces 43 | else 44 | report_warn "/etc/network/interfaces does not exist" 45 | fi 46 | fi 47 | } 48 | 49 | process_udev() 50 | { 51 | # override default udev bridge and hotplug rules because they interfere with 52 | # networking init script 53 | udev_user_rulesdir=/etc/udev/rules.d/ 54 | udev_sys_rulesdir=/lib/udev/rules.d/ 55 | if [ -e $udev_user_rulesdir ]; then 56 | udev_ifupdown2_overrides="80-networking.rules 57 | 60-bridge-network-interface.rules" 58 | for u in ${udev_ifupdown2_overrides} 59 | do 60 | if [ -e ${udev_sys_rulesdir}/$u -a ! -e ${udev_user_rulesdir}/$u ]; then 61 | (cd ${udev_user_rulesdir} && ln -sf /dev/null $u) 62 | fi 63 | done 64 | fi 65 | } 66 | 67 | # restore file if we diverted it on install/upgrade 68 | _postinst_remove_diverts() 69 | { 70 | diversions=$(LC_ALL=C.UTF-8 dpkg-divert --list | grep "^diversion of $1 .* by ifupdown2$" | wc -l 2> /dev/null) 71 | if [ $diversions -gt 0 ]; 72 | then 73 | dpkg-divert --remove --package ifupdown2 --rename $1 74 | fi 75 | } 76 | 77 | postinst_remove_diverts() 78 | { 79 | for filename in ifup ifdown ifquery ifreload 80 | do 81 | _postinst_remove_diverts "/sbin/$filename" 82 | _postinst_remove_diverts "/usr/share/bash-completion/completions/$filename" 83 | _postinst_remove_diverts "/etc/bash_completion.d/$filename" 84 | _postinst_remove_diverts "/usr/share/man/man8/$filename.8.gz" 85 | done 86 | _postinst_remove_diverts "/usr/share/man/man5/interfaces.5.gz" 87 | } 88 | 89 | case "$1" in 90 | configure) 91 | fix_dhclient_file_with_space 92 | process_etc_network_interfaces 93 | process_udev 94 | chmod +x /usr/share/ifupdown2/__main__.py 95 | postinst_remove_diverts 96 | ;; 97 | 98 | abort-upgrade|abort-remove|abort-deconfigure) 99 | ;; 100 | 101 | *) 102 | echo "postinst called with unknown argument \`$1'" >&2 103 | exit 1 104 | ;; 105 | esac 106 | 107 | 108 | #DEBHELPER# 109 | 110 | exit 0 111 | -------------------------------------------------------------------------------- /tests/output/bond.flipped.values.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "lo", 4 | "addr_method": "loopback", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": {}, 8 | "config_status": {}, 9 | "status": "pass" 10 | }, 11 | { 12 | "name": "eth0", 13 | "addr_method": "dhcp", 14 | "addr_family": "inet", 15 | "auto": true, 16 | "config": { 17 | "vrf": "mgmt" 18 | }, 19 | "config_status": { 20 | "vrf": "pass" 21 | }, 22 | "status": "pass" 23 | }, 24 | { 25 | "name": "mgmt", 26 | "auto": true, 27 | "config": { 28 | "vrf-table": "1001" 29 | }, 30 | "config_status": { 31 | "vrf-table": "pass" 32 | }, 33 | "status": "pass" 34 | }, 35 | { 36 | "name": "bond0", 37 | "auto": true, 38 | "config": { 39 | "bond-use-carrier": "no", 40 | "bond-miimon": "1", 41 | "bond-min-links": "1", 42 | "bond-slaves": "swp_AA_", 43 | "bond-mode": "0", 44 | "bond-num-unsol-na": "1", 45 | "bond-updelay": "1", 46 | "bond-xmit-hash-policy": "layer3+4", 47 | "bond-num-grat-arp": "1" 48 | }, 49 | "config_status": { 50 | "bond-use-carrier": "pass", 51 | "bond-miimon": "pass", 52 | "bond-min-links": "pass", 53 | "bond-slaves": "pass", 54 | "bond-mode": "pass", 55 | "bond-num-unsol-na": "pass", 56 | "bond-updelay": "pass", 57 | "bond-xmit-hash-policy": "pass", 58 | "bond-num-grat-arp": "pass" 59 | }, 60 | "status": "pass" 61 | }, 62 | { 63 | "name": "bond1", 64 | "auto": true, 65 | "config": { 66 | "bond-use-carrier": "yes", 67 | "bond-miimon": "0", 68 | "bond-min-links": "0", 69 | "bond-slaves": "swp_BB_", 70 | "bond-mode": "1", 71 | "bond-num-unsol-na": "0", 72 | "bond-xmit-hash-policy": "layer2", 73 | "bond-num-grat-arp": "0" 74 | }, 75 | "config_status": { 76 | "bond-use-carrier": "pass", 77 | "bond-miimon": "pass", 78 | "bond-min-links": "pass", 79 | "bond-slaves": "pass", 80 | "bond-mode": "pass", 81 | "bond-num-unsol-na": "pass", 82 | "bond-xmit-hash-policy": "pass", 83 | "bond-num-grat-arp": "pass" 84 | }, 85 | "status": "pass" 86 | }, 87 | { 88 | "name": "bond2", 89 | "auto": true, 90 | "config": { 91 | "bond-use-carrier": "1", 92 | "bond-miimon": "0", 93 | "bond-min-links": "0", 94 | "bond-slaves": "swp_CC_", 95 | "bond-mode": "2", 96 | "bond-num-unsol-na": "0", 97 | "bond-updelay": "0", 98 | "bond-xmit-hash-policy": "layer2+3", 99 | "bond-num-grat-arp": "0" 100 | }, 101 | "config_status": { 102 | "bond-use-carrier": "pass", 103 | "bond-miimon": "pass", 104 | "bond-min-links": "pass", 105 | "bond-slaves": "pass", 106 | "bond-mode": "pass", 107 | "bond-num-unsol-na": "pass", 108 | "bond-updelay": "pass", 109 | "bond-xmit-hash-policy": "pass", 110 | "bond-num-grat-arp": "pass" 111 | }, 112 | "status": "pass" 113 | }, 114 | { 115 | "name": "bond3", 116 | "auto": true, 117 | "config": { 118 | "bond-use-carrier": "0", 119 | "bond-miimon": "42", 120 | "bond-min-links": "42", 121 | "bond-slaves": "swp_DD_", 122 | "bond-mode": "3", 123 | "bond-num-unsol-na": "42", 124 | "bond-updelay": "42", 125 | "bond-num-grat-arp": "42" 126 | }, 127 | "config_status": { 128 | "bond-use-carrier": "pass", 129 | "bond-miimon": "pass", 130 | "bond-min-links": "pass", 131 | "bond-slaves": "pass", 132 | "bond-mode": "pass", 133 | "bond-num-unsol-na": "pass", 134 | "bond-updelay": "pass", 135 | "bond-num-grat-arp": "pass" 136 | }, 137 | "status": "pass" 138 | }, 139 | { 140 | "name": "bond5", 141 | "auto": true, 142 | "config": { 143 | "bond-mode": "5", 144 | "bond-slaves": "swp_FF_" 145 | }, 146 | "config_status": { 147 | "bond-mode": "pass", 148 | "bond-slaves": "pass" 149 | }, 150 | "status": "pass" 151 | }, 152 | { 153 | "name": "bond6", 154 | "auto": true, 155 | "config": { 156 | "bond-mode": "6", 157 | "bond-slaves": "swp_GG_" 158 | }, 159 | "config_status": { 160 | "bond-mode": "pass", 161 | "bond-slaves": "pass" 162 | }, 163 | "status": "pass" 164 | } 165 | ] 166 | -------------------------------------------------------------------------------- /tests/output/EvpnVabClagRiotFloodSupOffConfig.ifquery.ac.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "eth0", 4 | "addr_method": "dhcp", 5 | "addr_family": "inet", 6 | "auto": true, 7 | "config": { 8 | "vrf": "mgmt" 9 | }, 10 | "config_status": { 11 | "vrf": "pass" 12 | }, 13 | "status": "pass" 14 | }, 15 | { 16 | "name": "mgmt", 17 | "auto": true, 18 | "config": { 19 | "vrf-table": "1001" 20 | }, 21 | "config_status": { 22 | "vrf-table": "pass" 23 | }, 24 | "status": "pass" 25 | }, 26 | { 27 | "name": "lo", 28 | "auto": true, 29 | "config": { 30 | "alias": "BGP un-numbered Use for Vxlan Src Tunnel", 31 | "address": "27.0.0.16/32" 32 | }, 33 | "config_status": { 34 | "alias": "pass", 35 | "address": "pass" 36 | }, 37 | "status": "pass" 38 | }, 39 | { 40 | "name": "uplink", 41 | "auto": true, 42 | "config": { 43 | "bond-lacp-rate": "1", 44 | "mtu": "9202", 45 | "bond-mode": "802.3ad", 46 | "bond-min-links": "1", 47 | "bond-slaves": "swp_AA_ swp_BB_" 48 | }, 49 | "config_status": { 50 | "bond-lacp-rate": "pass", 51 | "mtu": "pass", 52 | "bond-mode": "pass", 53 | "bond-min-links": "pass", 54 | "bond-slaves": "pass" 55 | }, 56 | "status": "pass" 57 | }, 58 | { 59 | "name": "hostbond3", 60 | "auto": true, 61 | "config": { 62 | "bond-lacp-rate": "1", 63 | "bond-min-links": "1", 64 | "mtu": "9152", 65 | "bond-mode": "802.3ad", 66 | "bridge-pvid": "1000", 67 | "bond-slaves": "swp_CC_ swp_DD_" 68 | }, 69 | "config_status": { 70 | "bond-lacp-rate": "pass", 71 | "bond-min-links": "pass", 72 | "mtu": "pass", 73 | "bond-mode": "pass", 74 | "bridge-pvid": "pass", 75 | "bond-slaves": "pass" 76 | }, 77 | "status": "pass" 78 | }, 79 | { 80 | "name": "vx-1000", 81 | "auto": true, 82 | "config": { 83 | "bridge-learning": "off", 84 | "vxlan-id": "1000", 85 | "bridge-access": "1000", 86 | "mtu": "9152", 87 | "vxlan-local-tunnelip": "27.0.0.16" 88 | }, 89 | "config_status": { 90 | "bridge-learning": "pass", 91 | "vxlan-id": "pass", 92 | "bridge-access": "pass", 93 | "mtu": "pass", 94 | "vxlan-local-tunnelip": "pass" 95 | }, 96 | "status": "pass" 97 | }, 98 | { 99 | "name": "vx-1001", 100 | "auto": true, 101 | "config": { 102 | "bridge-learning": "off", 103 | "vxlan-id": "1001", 104 | "bridge-access": "1001", 105 | "mtu": "9152", 106 | "vxlan-local-tunnelip": "27.0.0.16" 107 | }, 108 | "config_status": { 109 | "bridge-learning": "pass", 110 | "vxlan-id": "pass", 111 | "bridge-access": "pass", 112 | "mtu": "pass", 113 | "vxlan-local-tunnelip": "pass" 114 | }, 115 | "status": "pass" 116 | }, 117 | { 118 | "name": "bridge", 119 | "auto": true, 120 | "config": { 121 | "bridge-vlan-aware": "yes", 122 | "bridge-ports": "vx-1000 vx-1001 hostbond3", 123 | "bridge-stp": "yes", 124 | "bridge-pvid": "1", 125 | "bridge-vids": "1000-1004" 126 | }, 127 | "config_status": { 128 | "bridge-vlan-aware": "pass", 129 | "bridge-ports": "pass", 130 | "bridge-stp": "pass", 131 | "bridge-pvid": "", 132 | "bridge-vids": "" 133 | }, 134 | "status": "pass" 135 | }, 136 | { 137 | "name": "vlan1000", 138 | "auto": true, 139 | "config": { 140 | "vlan-id": "1000", 141 | "address-virtual": "00:00:5e:00:01:01 45.0.0.1/24 2001:fee1::1/64", 142 | "vlan-raw-device": "bridge", 143 | "address": "45.0.0.2/24" 144 | }, 145 | "config_status": { 146 | "vlan-id": "pass", 147 | "address-virtual": "pass", 148 | "vlan-raw-device": "pass", 149 | "address": "pass" 150 | }, 151 | "status": "pass" 152 | }, 153 | { 154 | "name": "vlan1001", 155 | "auto": true, 156 | "config": { 157 | "vlan-id": "1001", 158 | "address-virtual": "00:00:5e:00:01:01 45.0.1.1/24 2001:fee1:0:1::1/64", 159 | "vlan-raw-device": "bridge", 160 | "address": "45.0.1.2/24" 161 | }, 162 | "config_status": { 163 | "vlan-id": "pass", 164 | "address-virtual": "pass", 165 | "vlan-raw-device": "pass", 166 | "address": "pass" 167 | }, 168 | "status": "pass" 169 | } 170 | ] 171 | -------------------------------------------------------------------------------- /ifupdown2/addons/usercmds.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Copyright 2014-2017 Cumulus Networks, Inc. All rights reserved. 4 | # Author: Roopa Prabhu, roopa@cumulusnetworks.com 5 | # 6 | 7 | import os 8 | 9 | try: 10 | from ifupdown2.ifupdown.utils import utils 11 | 12 | from ifupdown2.ifupdownaddons.modulebase import moduleBase 13 | except ImportError: 14 | from ifupdown.utils import utils 15 | 16 | from ifupdownaddons.modulebase import moduleBase 17 | 18 | 19 | class usercmds(moduleBase): 20 | """ ifupdown2 addon module to configure user specified commands """ 21 | 22 | _modinfo = {'mhelp' : 'user commands for interfaces', 23 | 'attrs' : { 24 | 'pre-up' : 25 | {'help' : 'run command before bringing the interface up', 26 | 'multiline' : True}, 27 | 'up' : 28 | {'help' : 'run command at interface bring up', 29 | 'multiline' : True}, 30 | 'post-up' : 31 | {'help' : 'run command after interface bring up', 32 | 'multiline' : True}, 33 | 'pre-down' : 34 | {'help' : 'run command before bringing the interface down', 35 | 'multiline' : True}, 36 | 'down' : 37 | {'help' : 'run command at interface down', 38 | 'multiline' : True}, 39 | 'post-down' : 40 | {'help' : 'run command after bringing interface down', 41 | 'multiline' : True}}} 42 | 43 | def _run_command(self, ifaceobj, op): 44 | cmd_list = ifaceobj.get_attr_value(op) 45 | if cmd_list: 46 | env = dict(os.environ) 47 | env.update({ 48 | 'LOGICAL': ifaceobj.name if ifaceobj.name else '', 49 | 'METHOD': ifaceobj.addr_method if ifaceobj.addr_method else '', 50 | 'ADDRFAM': ','.join(ifaceobj.addr_family) if ifaceobj.addr_family else '' 51 | }) 52 | env.update(ifaceobj.get_env()) 53 | for cmd in cmd_list: 54 | try: 55 | utils.exec_user_command(cmd, env=env) 56 | except Exception as e: 57 | if not self.ignore_error(str(e)): 58 | self.logger.warning('%s: %s %s' % (ifaceobj.name, op, 59 | str(e).strip('\n'))) 60 | 61 | def _query_check(self, ifaceobj, ifaceobjcurr): 62 | if ifaceobj.config: 63 | for ops in ['pre-up', 64 | 'up', 65 | 'post-up', 66 | 'pre-down', 67 | 'down', 68 | 'post-down']: 69 | for cmd in ifaceobj.config.get(ops, []): 70 | ifaceobjcurr.update_config_with_status(ops, cmd, -1) 71 | 72 | _run_ops = {'pre-up' : _run_command, 73 | 'pre-down' : _run_command, 74 | 'up' : _run_command, 75 | 'post-up' : _run_command, 76 | 'down' : _run_command, 77 | 'post-down' : _run_command, 78 | 'query-checkcurr': _query_check} 79 | 80 | def get_ops(self): 81 | """ returns list of ops supported by this module """ 82 | return list(self._run_ops.keys()) 83 | 84 | def run(self, ifaceobj, operation, query_ifaceobj=None, **extra_args): 85 | """ run user commands 86 | 87 | Args: 88 | **ifaceobj** (object): iface object 89 | 90 | **operation** (str): list of ops 91 | 92 | Kwargs: 93 | **query_ifaceobj** (object): query check ifaceobject. This is only 94 | valid when op is 'query-checkcurr'. It is an object same as 95 | ifaceobj, but contains running attribute values and its config 96 | status. The modules can use it to return queried running state 97 | of interfaces. status is success if the running state is same 98 | as user required state in ifaceobj. error otherwise. 99 | """ 100 | op_handler = self._run_ops.get(operation) 101 | if not op_handler: 102 | return 103 | if operation == 'query-checkcurr': 104 | op_handler(self, ifaceobj, query_ifaceobj) 105 | else: 106 | op_handler(self, ifaceobj, operation) 107 | --------------------------------------------------------------------------------