Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No longer able to rename interface after update to any version later than 0.7.6: "could not setup alt ifnames" #1178

Open
spike77453 opened this issue Feb 16, 2024 · 12 comments
Labels

Comments

@spike77453
Copy link

After updating pyroute2 to any version newer that 0.7.6 I'm no longer able to run the following snippet ("Hello world" example from https://docs.pyroute2.org/general.html#ndb-high-level-rtnl-api):

from pyroute2 import NDB

with NDB() as ndb:
    with ndb.interfaces['enp7s0'] as interface:
        interface.set(state='down')
        interface.commit()
        interface.set(ifname='test', state='up')
        interface.commit()
# virtualenv /root/pyroute2_venv
# source /root/pyroute2_venv/bin/activate
# pip install pyroute2
# python mve.py 
Traceback (most recent call last):
  File "/root/pyroute2_test/mve.py", line 8, in <module>
    interface.commit()
  File "/root/pyroute2_venv/lib/python3.11/site-packages/pyroute2/ndb/auth_manager.py", line 67, in guard
    return f(obj, *argv, **kwarg)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/root/pyroute2_venv/lib/python3.11/site-packages/pyroute2/ndb/objects/__init__.py", line 736, in commit
    self.apply(mode='commit')
  File "/root/pyroute2_venv/lib/python3.11/site-packages/pyroute2/ndb/auth_manager.py", line 67, in guard
    return f(obj, *argv, **kwarg)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/root/pyroute2_venv/lib/python3.11/site-packages/pyroute2/ndb/objects/interface.py", line 1016, in apply
    self.apply_altnames(alt_ifname_setup)
  File "/root/pyroute2_venv/lib/python3.11/site-packages/pyroute2/ndb/auth_manager.py", line 67, in guard
    return f(obj, *argv, **kwarg)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/root/pyroute2_venv/lib/python3.11/site-packages/pyroute2/ndb/objects/interface.py", line 994, in apply_altnames
    raise Exception('could not setup alt ifnames')
Exception: could not setup alt ifnames

After downgrading pyroute2 to version 0.7.6 renaming the interface works again as expected:

# pip install pyroute2==0.7.6
Collecting pyroute2==0.7.6
  Using cached pyroute2-0.7.6-py3-none-any.whl (454 kB)
Installing collected packages: pyroute2
  Attempting uninstall: pyroute2
    Found existing installation: pyroute2 0.7.12
    Uninstalling pyroute2-0.7.12:
      Successfully uninstalled pyroute2-0.7.12
Successfully installed pyroute2-0.7.6
# python mve.py

OS is Debian 12.5. Interface is unconfigured, i.e. /etc/network/interfaces does not contain anything about the device. Neither NetworkManager nor systemd-networkd is installed.
I've checked a all versions between 0.7.6 and 0.7.12 as well, all with the same result (i.e. Exception: could not setup alt ifnames).

@svinota svinota added the bug label Feb 17, 2024
@svinota
Copy link
Owner

svinota commented Feb 18, 2024

Strange enough I can not reproduce it on the master branch, but obviously there is some issue.

If you have a VM (an image or a deployed instance) to reproduce and you could give a chance to debug there — I would be very grateful.

@spike77453
Copy link
Author

It's reproducible for me with the stock Debian images (e.g. debian-12-nocloud-amd64 on qemu), and pyroute2 from the master branch:

# wget https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-nocloud-amd64.qcow2
# qemu-img create -f qcow2 -o preallocation=metadata debian12-pyroute-mve.qcow2 10G
# virt-resize --resize /dev/sda1=5G debian-12-nocloud-amd64.qcow2 debian12-pyroute-mve.qcow2
# virt-install --import --boot uefi --name debian12-pyroute-mve --memory 2048 --vcpus 2 --cpu host --disk /absolute/path/to/debian12-pyroute-mve.qcow2 --network bridge=br0,model=virtio --network bridge=br0,model=virtio --os-variant=debian12 --graphics spice --noautoconsole
# virsh console debian12-pyroute-mve
Connected to domain 'debian12-pyroute-mve'
Escape character is ^] (Ctrl + ])
root
Linux localhost 6.1.0-18-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.76-1 (2024-02-01) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Feb 20 13:53:01 UTC 2024 on ttyS0
root@localhost:~# apt update
...
root@localhost:~# apt install python3-virtualenv git -y
...
root@localhost:~# virtualenv pyroute2
root@localhost:~# source pyroute2/bin/activate

(pyroute2) root@localhost:~# pip3 install git+https://github.com/svinota/pyroute2
Collecting git+https://github.com/svinota/pyroute2s://github.com/svinota/pyroute2
  Cloning https://github.com/svinota/pyroute2 to /tmp/pip-req-build-y8wh_cb9
  Running command git clone --filter=blob:none --quiet https://github.com/svinota/pyroute2 /tmp/pip-req-build-y8wh_cb9
  Resolved https://github.com/svinota/pyroute2 to commit 34d0768f89fd232126c49e2f7c94e6da6582795b
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
  Preparing metadata (pyproject.toml) ... done
Building wheels for collected packages: pyroute2
  Building wheel for pyroute2 (pyproject.toml) ... done
  Created wheel for pyroute2: filename=pyroute2-0.7.12-py3-none-any.whl size=463056 sha256=c45617a459663ab6622abe48e8cec6e3be64ecd616a7b933eb617c3da78809a3
  Stored in directory: /tmp/pip-ephem-wheel-cache-ogmw86_5/wheels/29/74/0a/96ccb56939438993da9c1eb456d4b46928e293695020098a58
Successfully built pyroute2
Installing collected packages: pyroute2
Successfully installed pyroute2-0.7.12

(pyroute2) root@localhost:~# cat <<EOF >mve.py
from pyroute2 import NDB

with NDB() as ndb:
    with ndb.interfaces['enp2s0'] as interface:
        interface.set(state='down')
        interface.commit()
        interface.set(ifname='test', state='up')
        interface.commit()
EOF

(pyroute2) root@localhost:~# systemctl disable systemd-networkd.socket
(pyroute2) root@localhost:~# systemctl disable systemd-networkd.service
(pyroute2) root@localhost:~# systemctl stop systemd-networkd.socket
(pyroute2) root@localhost:~# systemctl stop systemd-networkd.service
(pyroute2) root@localhost:~# python mve.py 
[  831.727359] virtio_net virtio2 test: renamed from enp2s0
Traceback (most recent call last):
  File "/root/mve.py", line 8, in <module>
    interface.commit()
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/ndb/auth_manager.py", line 67, in guard
    return f(obj, *argv, **kwarg)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/ndb/objects/__init__.py", line 736, in commit
    self.apply(mode='commit')
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/ndb/auth_manager.py", line 67, in guard
    return f(obj, *argv, **kwarg)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/ndb/objects/interface.py", line 1016, in apply
    self.apply_altnames(alt_ifname_setup)
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/ndb/auth_manager.py", line 67, in guard
    return f(obj, *argv, **kwarg)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/ndb/objects/interface.py", line 994, in apply_altnames
    raise Exception('could not setup alt ifnames')
Exception: could not setup alt ifnames

With systemd-networkd running I run into pyroute2.netlink.exceptions.NetlinkError: (16, 'Device or resource busy'). A workaround could be

from pyroute2 import NDB

with NDB() as ndb:
    with ndb.interfaces['enp2s0'] as interface:
        interface.set(state='down')
        interface.commit()
        interface.set(ifname='test')
        interface.commit()
    with ndb.interface['test'] as interface:
        interface.set(state='up')
        interface.commit()

Which leads me back to Exception: could not setup alt ifnames again.

I originally stumbled upon this on a Debian host with the "traditional" networking.service (minimal installation from iso, no further changes) without systemd-networkd or NetworkManager.

@svinota
Copy link
Owner

svinota commented Feb 20, 2024

Thanks a lot! Investigating

@svinota
Copy link
Owner

svinota commented Feb 20, 2024

Reproduced, thanks! This week the issue will be fixed.

@svinota
Copy link
Owner

svinota commented Feb 20, 2024

Before 0.7.7 NDB simply ignored altnames, thus the latest working version for you is 0.7.6.

But with 0.7.7 NDB started to track altnames too. Renaming some types of interfaces on some kernels causes the old name to become an altname, and NDB rejects it, expecting no altnames change. Dummy interfaces don't cause this issue, so CI didn't catch it.

  1. Looks fixable, so this week it should be ready.
  2. Maybe I have to rethink the CI so it will use ephemeral VMs and try to work with more "real" interfaces than dummy and veth.

@spike77453
Copy link
Author

Awesome. Thanks a bunch!

svinota added a commit that referenced this issue Feb 21, 2024
Control `alt_ifname_list` after rename. Ignore the old interface
name in `alt_ifname_list`.

Bug-Url: #1178
svinota added a commit that referenced this issue Feb 21, 2024
Control `alt_ifname_list` after rename. Ignore the old interface
name in `alt_ifname_list`.

Bug-Url: #1178
svinota added a commit that referenced this issue Feb 21, 2024
Control `alt_ifname_list` after rename. Ignore the old interface
name in `alt_ifname_list`.

Bug-Url: #1178
svinota added a commit that referenced this issue Feb 21, 2024
Control `alt_ifname_list` after rename. Ignore the old interface
name in `alt_ifname_list`.

Bug-Url: #1178
svinota added a commit that referenced this issue Feb 21, 2024
Control `alt_ifname_list` after rename. Ignore the old interface
name in `alt_ifname_list`.

Bug-Url: #1178
@svinota
Copy link
Owner

svinota commented Feb 21, 2024

Pls try if this will work: #1180

(It works for me, but I could miss something)

@spike77453
Copy link
Author

Pls try if this will work: #1180

Works for my use cases. Thanks! ❤️

I don't know if it's intended, but changing the name and then reverting to the original doesn't work since the original name becomes an altname on the interface, i.e. running

from pyroute2 import NDB

with NDB() as ndb:
    with ndb.interfaces['enp2s0'] as interface:
        interface.set(state='down')
        interface.commit()
        interface.set(ifname='test', state='up')
        interface.commit()
# ip addr show dev test
3: test: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:82:09:f9 brd ff:ff:ff:ff:ff:ff
    altname enp2s0
    inet6 fe80::5054:ff:fe82:9f9/64 scope link 
       valid_lft forever preferred_lft forever

followed by

from pyroute2 import NDB

with NDB() as ndb:
    with ndb.interfaces['test'] as interface:
        interface.set(state='down')
        interface.commit()
        interface.set(ifname='enp2s0', state='up')
        interface.commit()

results in

Traceback (most recent call last):
  File "/root/mve.py", line 4, in <module>
    with ndb.interfaces['test'] as interface:
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/ndb/objects/__init__.py", line 416, in __exit__
    self.commit()
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/ndb/auth_manager.py", line 67, in guard
    return f(obj, *argv, **kwarg)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/ndb/objects/__init__.py", line 736, in commit
    self.apply(mode='commit')
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/ndb/auth_manager.py", line 67, in guard
    return f(obj, *argv, **kwarg)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/ndb/objects/interface.py", line 1018, in apply
    super(Interface, self).apply(rollback, req_filter, mode)
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/ndb/auth_manager.py", line 67, in guard
    return f(obj, *argv, **kwarg)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/ndb/objects/__init__.py", line 903, in apply
    (self.sources[self['target']].api(self.api, method, **req))
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/ndb/source.py", line 292, in api
    return getattr(self.nl, name)(*argv, **kwarg)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/iproute/linux.py", line 1776, in link
    ret = tuple(ret)
          ^^^^^^^^^^
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/netlink/nlsocket.py", line 1214, in nlm_request
    for msg in self.get(
  File "/root/pyroute2/lib/python3.11/site-packages/pyroute2/netlink/nlsocket.py", line 550, in get
    raise msg['header']['error']
pyroute2.netlink.exceptions.NetlinkError: (17, 'File exists')

I have no need for this but maybe this should be mentioned in the documentation somewhere?

@svinota
Copy link
Owner

svinota commented Feb 22, 2024

It's not intended, it's how the kernel works in this case. Let me add a workaround for that.

svinota added a commit that referenced this issue Feb 26, 2024
If the new name is in altnames, remove it from there first.

Bug-Url: #1178
svinota added a commit that referenced this issue Feb 26, 2024
If the new name is in altnames, remove it from there first.

Bug-Url: #1178
@svinota
Copy link
Owner

svinota commented Feb 26, 2024

Ok, now I believe it should work better in any direction, including rollbacks. I don't like too much the way I had to do it, since the commit logic becomes too fuzzy, but it should work for now. May I ask you to check? Thanks a lot for the help!

svinota added a commit that referenced this issue Feb 27, 2024
ndb link rename vs. altnames

Bug-Url: #1178
Bug-Url: #1180
@svinota
Copy link
Owner

svinota commented Feb 27, 2024

Merged to the master branch in order not to block the next PR.

@spike77453
Copy link
Author

May I ask you to check? Thanks a lot for the help!

No worries, thanks a bunch for fixing this! Really appreciated. ❤️
Tried the latest commit from the master branch. Seems to do the trick.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants