Skip to content

ifupdown not able to reconfigure interfaces #75

@metalwanderer

Description

@metalwanderer

Hi! I really appreciate the debops project! :-) I've done my best to exclude errors on my part, but as best as I can tell, the ifupdown-reconfigure-interfaces can never successfully reconfigure interfaces on my Debian Buster system.

The scenario: A baremetal server with some LXC containers running on it, interfaces are configured statically. The ifupdown role will generate the interface configs in /etc/network/interface.config.d/ but the task to apply the new configs always fails.

From looking at the script, it seems the issue revolves around the assumption that systemd-based systems always have ifup@${if}.service units to control their network interfaces... my system is systemd-based, but has no such units, either on host or in containers.

For the sake of sparing the baremetal host a lot of mucking around with the network, I've done most of my testing with a test container, but the behavior is the same when applied against the host:

(.ansible_venv) ansible@mgmt1:~/midgard/prod$ debops -l test1 --tags "role::ifupdown"                                  Running Ansible playbooks:
/opt/ansible/midgard/prod/ansible/playbooks/site.yml

...

PLAY [Manage network configuration using ifupdown] ********************************************************************

TASK [Gathering Facts] ************************************************************************************************
ok: [test1]

TASK [ifupdown : Prepare configuration of dependent Ansible roles] ****************************************************
ok: [test1]

TASK [sysctl : Pre hooks] *********************************************************************************************

TASK [sysctl : Post hooks] ********************************************************************************************

TASK [ifupdown : Make sure that Ansible local facts directory exists] *************************************************
ok: [test1]

TASK [ifupdown : Save ifupdown local facts] ***************************************************************************
ok: [test1]

TASK [ifupdown : Install required packages] ***************************************************************************
ok: [test1]

TASK [ifupdown : Purge conflicting packages] **************************************************************************
ok: [test1]

TASK [ifupdown : Check systemd version] *******************************************************************************
ok: [test1]

TASK [ifupdown : Install custom ifupdown services] ********************************************************************
ok: [test1] => (item=iface@.service)
ok: [test1] => (item=ifup-wait-all-auto.service)
ok: [test1] => (item=ifup-allow-boot.service)

TASK [ifupdown : Test if Ansible is running in check mode] ************************************************************
ok: [test1]

TASK [ifupdown : Enable custom ifupdown services] *********************************************************************
ok: [test1] => (item=ifup-wait-all-auto)
ok: [test1] => (item=ifup-allow-boot)

TASK [ifupdown : Create configuration directories] ********************************************************************
ok: [test1] => (item=/etc/network/interfaces.d)
ok: [test1] => (item=/etc/network/interfaces.config.d)

TASK [ifupdown : Divert original /etc/network/interfaces] *************************************************************
ok: [test1]

TASK [ifupdown : Create /etc/network/interfaces] **********************************************************************
changed: [test1]

TASK [ifupdown : Ensure that runtime directory exists] ****************************************************************
ok: [test1]

TASK [ifupdown : Request entire network reconfiguration] **************************************************************
changed: [test1]

TASK [ifupdown : Generate network interface configuration] ************************************************************
changed: [test1] => (item={'key': 'eth0', 'value': {'address': '10.100.201.201/16', 'allow': 'hotplug', 'auto': True, 'dns_nameservers': ['10.100.0.2', '10.100.0.1'], 'dns_search': ['midgard.metalwanderer.net'], 'gateway': '10.100.254.254', 'iface': 'eth0', 'inet': 'static', 'inet6': 'auto', 'type': 'ether'}})

TASK [ifupdown : Remove unknown interface configuration] **************************************************************
changed: [test1] => (item={'diff': [], 'dest': '/etc/network/interfaces.config.d/020_iface_eth0', 'src': '/opt/ansible/.ansible/tmp/ansible-tmp-1630618748.460853-1555-254863054817577/source', 'md5sum': '8b79c694c47bae5507c79247f6867de8', 'checksum': '4274a513ad2e2092b86e06428ec96f5a4d2f7d49', 'changed': True, 'uid': 0, 'gid': 0, 'owner': 'root', 'group': 'root', 'mode': '0644', 'state': 'file', 'size': 330, 'invocation': {'module_args': {'src': '/opt/ansible/.ansible/tmp/ansible-tmp-1630618748.460853-1555-254863054817577/source', 'dest': '/etc/network/interfaces.config.d/020_iface_eth0', 'owner': 'root', 'group': 'root', 'mode': '0644', 'follow': False, '_original_basename': 'iface.j2', 'checksum': '4274a513ad2e2092b86e06428ec96f5a4d2f7d49', 'backup': False, 'force': True, 'unsafe_writes': False, 'content': None, 'validate': None, 'directory_mode': None, 'remote_src': None, 'local_follow': None, 'seuser': None, 'serole': None, 'selevel': None, 'setype': None, 'attributes': None}}, 'failed': False, 'item': {'key': 'eth0', 'value': {'address': '10.100.201.201/16', 'allow': 'hotplug', 'auto': True, 'dns_nameservers': ['10.100.0.2', '10.100.0.1'], 'dns_search': ['midgard.metalwanderer.net'], 'gateway': '10.100.254.254', 'iface': 'eth0', 'inet': 'static', 'inet6': 'auto', 'type': 'ether'}}, 'ansible_loop_var': 'item'})

TASK [ifupdown : Mark modified interfaces for processing] *************************************************************
changed: [test1] => (item={'diff': [], 'dest': '/etc/network/interfaces.config.d/020_iface_eth0', 'src': '/opt/ansible/.ansible/tmp/ansible-tmp-1630618748.460853-1555-254863054817577/source', 'md5sum': '8b79c694c47bae5507c79247f6867de8', 'checksum': '4274a513ad2e2092b86e06428ec96f5a4d2f7d49', 'changed': True, 'uid': 0, 'gid': 0, 'owner': 'root', 'group': 'root', 'mode': '0644', 'state': 'file', 'size': 330, 'invocation': {'module_args': {'src': '/opt/ansible/.ansible/tmp/ansible-tmp-1630618748.460853-1555-254863054817577/source', 'dest': '/etc/network/interfaces.config.d/020_iface_eth0', 'owner': 'root', 'group': 'root', 'mode': '0644', 'follow': False, '_original_basename': 'iface.j2', 'checksum': '4274a513ad2e2092b86e06428ec96f5a4d2f7d49', 'backup': False, 'force': True, 'unsafe_writes': False, 'content': None, 'validate': None, 'directory_mode': None, 'remote_src': None, 'local_follow': None, 'seuser': None, 'serole': None, 'selevel': None, 'setype': None, 'attributes': None}}, 'failed': False, 'item': {'key': 'eth0', 'value': {'address': '10.100.201.201/16', 'allow': 'hotplug', 'auto': True, 'dns_nameservers': ['10.100.0.2', '10.100.0.1'], 'dns_search': ['midgard.metalwanderer.net'], 'gateway': '10.100.254.254', 'iface': 'eth0', 'inet': 'static', 'inet6': 'auto', 'type': 'ether'}}, 'ansible_loop_var': 'item'})

TASK [ifupdown : Install custom ifupdown hooks] ***********************************************************************
ok: [test1] => (item={'name': 'filter-dhcp-options', 'hook': 'etc/dhcp/dhclient-enter-hooks.d/filter-dhcp-options', 'mode': '0644', 'state': 'present'})

TASK [ifupdown : Save role version information] ***********************************************************************
ok: [test1]

RUNNING HANDLER [ifupdown : Apply ifupdown configuration] *************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: NoneType: None
fatal: [test1]: FAILED! => changed=true 
  msg: non-zero return code
  rc: 1
  stderr: |-
    Shared connection to test1.midgard.metalwanderer.net closed.
  stderr_lines: <omitted>
  stdout: |-
    Detected interfaces to reconfigure: eth0
    Bringing down 'eth0' interface
    Error: Script was working on 'eth0' network interface when it lost knowledge about the network interface state. The '/etc/network/interfaces.d/' might be desynchronized. Exiting to avoid loss of connectivity, investigate the issue.
  stdout_lines: <omitted>

NO MORE HOSTS LEFT ****************************************************************************************************

PLAY RECAP ************************************************************************************************************
test1                      : ok=25   changed=5    unreachable=0    failed=1    skipped=9    rescued=0    ignored=0

Purge conflicting packages ---------------------------------------------- 4.21s
Prepare configuration of dependent Ansible roles ------------------------ 4.04s
Install custom ifupdown services ---------------------------------------- 2.56s
Gathering Facts --------------------------------------------------------- 2.52s
Generate network interface configuration -------------------------------- 2.16s
Install required packages ----------------------------------------------- 2.11s
Install custom ifupdown hooks ------------------------------------------- 1.95s
Enable custom ifupdown services ----------------------------------------- 1.68s
Remove network interface configuration ---------------------------------- 1.17s
Save ifupdown local facts ----------------------------------------------- 1.15s

Relevant hostvars:

---
ifupdown__interface_layout: static
ifupdown__host_interfaces:
  "eth0":
    inet: static
    allow: hotplug
    address: >
      {{ [ ansible_facts.eth0.ipv4.address, ansible_facts.eth0.ipv4.netmask ] |
      join('/') | ansible.netcommon.ipv4 }}
    gateway: "{{ gateways_prod[0] }}"
    dns_nameservers: "{{ nameservers_prod }}"
    dns_search: "{{ ( [netbase__domain] + [site_domain] ) | unique }}"
    auto: True

Filesystem state after run:

root@test1:~# find /etc/network
/etc/network
/etc/network/interfaces
/etc/network/interfaces.dpkg-divert
/etc/network/if-up.d
/etc/network/if-up.d/000resolvconf
/etc/network/if-up.d/chrony
/etc/network/interfaces.d
/etc/network/if-post-down.d
/etc/network/if-post-down.d/chrony
/etc/network/interfaces.config.d
/etc/network/interfaces.config.d/020_iface_eth0
/etc/network/if-pre-up.d
/etc/network/if-down.d
/etc/network/if-down.d/resolvconf

To attempt to manually apply, I restore the /etc/network/interfaces file, and run with: debops -l test1 --tags "role::ifupdown" --extra-vars "ifupdown__reconfigure_auto=False"

After the run, on the container:

root@test1:~# find /run/network
/run/network
/run/network/debops-ifupdown-reconfigure,020,eth0
/run/network/debops-ifupdown-reconfigure.networking
/run/network/ifstate
/run/network/ifstate.eth0
/run/network/.ifstate.lock
/run/network/ifstate.lo

# I've added 'set -x' at the beginning of the script to get debug output
root@test1:~# /usr/local/lib/ifupdown-reconfigure-interfaces
+ set -o nounset -o pipefail -o errexit
+ pid=10696
++ basename /usr/local/lib/ifupdown-reconfigure-interfaces
+ script=ifupdown-reconfigure-interfaces
+ interface_request_path=/run/network
+ interface_request_prefix=debops-ifupdown-reconfigure
+ interface_reconfigure_all=networking
+ trap on_exit EXIT
+ '[' -d /run/network ']'
+ declare -a changed_interfaces
+ declare -a changed_interface_names
+ declare -a created_interfaces
+ declare -a removed_interfaces
+ mapfile -t changed_interfaces
++ find /run/network -type f -name 'debops-ifupdown-reconfigure,*'
++ sed -e 's#^/run/network/debops-ifupdown-reconfigure,##'
++ sort -n
+ mapfile -t changed_interface_names
++ find /run/network -type f -name 'debops-ifupdown-reconfigure,*'
++ sed -e 's#^/run/network/debops-ifupdown-reconfigure,##'
++ sort -n
++ sed -e 's/^.*\,//'
+ '[' 1 -gt 0 ']'
++ join_by , eth0
++ local IFS=,
++ shift
++ echo eth0
+ log_message -m 'Detected interfaces to reconfigure: eth0'
+ local -A args
+ local OPTIND optchar
+ local optspec=:mflth-:
+ getopts :mflth-: optchar
+ case "${optchar}" in
+ args["message"]='Detected interfaces to reconfigure: eth0'
+ OPTIND=3
+ getopts :mflth-: optchar
+ key_exists args message
+ eval '[ ${args[$2]+test_of_existence} ]'
++ '[' test_of_existence ']'
+ tty -s
+ echo 'Detected interfaces to reconfigure: eth0'
Detected interfaces to reconfigure: eth0
+ type logger
+ logger -t 'ifupdown-reconfigure-interfaces[10696]' 'Detected interfaces to reconfigure: eth0'
+ declare -a systemd_ifup_instances
+ declare -a systemd_iface_instances
+ declare -a systemd_interface_instances
+ is_systemd
+ '[' -d /run/systemd/system ']'
+ return 0
+ mapfile -t systemd_ifup_instances
++ systemctl list-units --no-legend --state=active 'ifup@*.service'
++ awk '{print $1}'
++ sed -e 's/^ifup\@//' -e 's/\.service$//'
+ mapfile -t systemd_iface_instances
++ systemctl list-units --no-legend --state=active 'iface@*.service'
++ awk '{print $1}'
++ sed -e 's/^iface\@//' -e 's/\.service$//'
+ '[' 0 -gt 0 ']'
+ '[' 0 -gt 0 ']'
+ systemd_interface_instances=("${systemd_ifup_instances[@]:-}" "${systemd_iface_instances[@]:-}")
+ containsElement networking eth0
+ local e
+ for e in "${@:2}"
+ [[ eth0 == \n\e\t\w\o\r\k\i\n\g ]]
+ return 1
+ (( i=1-1 )) 
+ (( i>=0 ))  
+ iface=020,eth0
++ echo 020,eth0
++ sed -e 's/^.*\,//'
+ iface_name=eth0
+ '[' 020,eth0 '!=' networking ']'
+ '[' changed '!=' created ']'
+ ifquery --state eth0
+ log_message -m 'Bringing down '\''eth0'\'' interface'
+ local -A args
+ local OPTIND optchar
+ local optspec=:mflth-:
+ getopts :mflth-: optchar
+ case "${optchar}" in
+ args["message"]='Bringing down '\''eth0'\'' interface'
+ OPTIND=3
+ getopts :mflth-: optchar
+ key_exists args message
+ eval '[ ${args[$2]+test_of_existence} ]'
++ '[' test_of_existence ']'
+ tty -s
+ echo 'Bringing down '\''eth0'\'' interface'
Bringing down 'eth0' interface
+ type logger 
+ logger -t 'ifupdown-reconfigure-interfaces[10696]' 'Bringing down '\''eth0'\'' interface'
+ interface_down eth0
+ is_systemd  
+ '[' -d /run/systemd/system ']'
+ return 0
+ local -a if_hotplug_interfaces
+ local -a if_boot_interfaces
+ local -a systemd_ifup_instances
+ mapfile -t if_hotplug_interfaces
++ ifquery --list --allow=hotplug
+ mapfile -t if_boot_interfaces
++ ifquery --list --allow=boot
+ mapfile -t systemd_ifup_instances
++ systemctl list-units --no-legend --state=active 'ifup@*.service'
++ awk '{print $1}'
++ sed -e 's/^ifup\@//' -e 's/\.service$//'
+ '[' 0 -gt 0 ']'
+ '[' 0 -gt 0 ']'
+ ifquery --state eth0
+ containsElement eth0 '' ''
+ local e
+ for e in "${@:2}"
+ [[ '' == \e\t\h\0 ]]
+ for e in "${@:2}"
+ [[ '' == \e\t\h\0 ]]
+ return 1
+ log_message -m 'Error: Script was working on '\''eth0'\'' network interface when it lost knowledge about the network interface state. The '\''/etc/network/interfaces.d/'\'' might be desynchronized. Exiting to avoid loss of connectivity, investigate the issue.'
+ local -A args
+ local OPTIND optchar
+ local optspec=:mflth-:
+ getopts :mflth-: optchar
+ case "${optchar}" in
+ args["message"]='Error: Script was working on '\''eth0'\'' network interface when it lost knowledge about the network interface state. The '\''/etc/network/interfaces.d/'\'' might be desynchronized. Exiting to avoid loss of connectivity, investigate the issue.'
+ OPTIND=3
+ getopts :mflth-: optchar
+ key_exists args message
+ eval '[ ${args[$2]+test_of_existence} ]'
++ '[' test_of_existence ']'
+ tty -s
+ echo 'Error: Script was working on '\''eth0'\'' network interface when it lost knowledge about the network interface state. The '\''/etc/network/interfaces.d/'\'' might be desynchronized. Exiting to avoid loss of connectivity, investigate the issue.'
Error: Script was working on 'eth0' network interface when it lost knowledge about the network interface state. The '/etc/network/interfaces.d/' might be desynchronized. Exiting to avoid loss of connectivity, investigate the issue.
+ type logger 
+ logger -t 'ifupdown-reconfigure-interfaces[10696]' 'Error: Script was working on '\''eth0'\'' network interface when it lost knowledge about the network interface state. The '\''/etc/network/interfaces.d/'\'' might be desynchronized. Exiting to avoid loss of connectivity, investigate the issue.'
+ exit 1
+ on_exit
+ rm -f /run/network/debops-ifupdown-reconfigure,020,eth0

This is a systemd-based system:

root@test1:~# ls -d /run/systemd/system
/run/systemd/system
root@test1:~# dpkg -s systemd | grep Version:
Version: 241-7~deb10u8

But there are no ifup@${if}.service units:

root@test1:~# systemctl list-units --no-legend --state=active 'ifup@*.service'
root@test1:~# echo $?
0

So it seems to me that interface_down() will always fail to stop any interfaces.

There is nothing particularly unusual about my install that I can think of which make networking behave radically different. Am I missing something obvious?

Here's some output from the baremetal host:

root@thor:~# ifdown br_mgmt
root@thor:~# systemctl start ifup@br_mgmt.service
A dependency job for ifup@br_mgmt.service failed. See 'journalctl -xe' for details.
root@thor:~# journalctl -xe
Sep 02 22:34:05 thor audit[10842]: AVC apparmor="ALLOWED" operation="open" profile="/usr/sbin/sssd" name="/sys/devices/
Sep 02 22:34:05 thor kernel: audit: type=1400 audit(1630614845.624:24283): apparmor="ALLOWED" operation="open" profile=
Sep 02 22:35:58 thor systemd[1]: sys-subsystem-net-devices-br_mgmt.device: Job sys-subsystem-net-devices-br_mgmt.device
Sep 02 22:35:58 thor systemd[1]: Timed out waiting for device /sys/subsystem/net/devices/br_mgmt.
-- Subject: A start job for unit sys-subsystem-net-devices-br_mgmt.device has failed
-- Defined-By: systemd
-- Support: https://www.debian.org/support
--
-- A start job for unit sys-subsystem-net-devices-br_mgmt.device has finished with a failure.
--
-- The job identifier is 13458 and the job result is timeout.
Sep 02 22:35:58 thor systemd[1]: Dependency failed for ifup for br_mgmt.
-- Subject: A start job for unit ifup@br_mgmt.service has failed
-- Defined-By: systemd
-- Support: https://www.debian.org/support
--
-- A start job for unit ifup@br_mgmt.service has finished with a failure.
--
-- The job identifier is 13455 and the job result is dependency.
Sep 02 22:35:58 thor systemd[1]: ifup@br_mgmt.service: Job ifup@br_mgmt.service/start failed with result 'dependency'.
Sep 02 22:35:58 thor systemd[1]: sys-subsystem-net-devices-br_mgmt.device: Job sys-subsystem-net-devices-br_mgmt.device
Sep 02 22:36:01 thor CRON[23138]: pam_unix(cron:session): session opened for user root by (uid=0)
Sep 02 22:36:01 thor CRON[23139]: (root) CMD (cd / && run-parts --report /etc/cron.hourly)
Sep 02 22:36:01 thor CRON[23138]: pam_unix(cron:session): session closed for user root
root@thor:~# systemctl list-units --no-legend --state=active 'ifup@*.service'
root@thor:~# ifup br_mgmt

Waiting for br_mgmt to get ready (MAXWAIT is 32 seconds).
root@thor:~# ip a show dev br_mgmt
138: br_mgmt: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 2c:ea:7f:f9:c1:64 brd ff:ff:ff:ff:ff:ff
    inet 10.254.10.10/16 brd 10.254.255.255 scope global br_mgmt
       valid_lft forever preferred_lft forever
    inet6 fe80::2eea:7fff:fef9:c164/64 scope link
       valid_lft forever preferred_lft forever
root@thor:~# find /etc/network
/etc/network
/etc/network/if-up.d
/etc/network/if-up.d/chrony
/etc/network/if-up.d/ip
/etc/network/if-up.d/ifenslave
/etc/network/if-up.d/000resolvconf
/etc/network/interfaces
/etc/network/interfaces.config.d
/etc/network/interfaces.d
/etc/network/interfaces.d/020_iface_eno2
/etc/network/interfaces.d/010_iface_bond0
/etc/network/interfaces.d/060_iface_br_local
/etc/network/interfaces.d/060_iface_br_guest
/etc/network/interfaces.d/020_iface_eno1
/etc/network/interfaces.d/020_iface_ens1f1
/etc/network/interfaces.d/020_iface_ens1f0
/etc/network/interfaces.d/060_iface_br_mgmt
/etc/network/interfaces.d/015_iface_bond0.1
/etc/network/interfaces.d/015_iface_bond0.1200
/etc/network/if-down.d
/etc/network/if-down.d/resolvconf
/etc/network/interfaces.dpkg-divert
/etc/network/interfaces.old
/etc/network/if-post-down.d
/etc/network/if-post-down.d/chrony
/etc/network/if-post-down.d/bridge
/etc/network/if-post-down.d/ifenslave
/etc/network/if-post-down.d/vlan
/etc/network/if-pre-up.d
/etc/network/if-pre-up.d/bridge
/etc/network/if-pre-up.d/ifenslave
/etc/network/if-pre-up.d/vlan

Note: I have manually moved the interface configs from interfaces.config.d/ to interfaces.d/ to activate them.

What's so strange about my setup that it breaks the script assumptions?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions