svinota / pyroute2

Python Netlink and PF_ROUTE library — network configuration and monitoring
https://pyroute2.org/
Other
951 stars 244 forks source link

Unable to move interface to network NS #1181

Open daghaian opened 7 months ago

daghaian commented 7 months ago

Currently, when attempting the code below, the interface is moved into the network namespace but an exception is thrown

>>> ndb = NDB()
>>> ndb.interfaces.create(
...             ifname="net1.311",
...             kind="vlan",
...             link="net1",
...             state="up",
...             vlan_id=311,
...       ).commit()
{'alt_ifname_list': [], 'state': 'up', 'ifname': 'net1.311', 'kind': 'vlan', 'link': 4, 'vlan_id': 311, 'target': 'localhost', 'tflags': 0, 'family': 0, 'ifi_type': 1, 'index': 6, 'flags': 69699, 'change': 0, 'address': 'aa:93:41:2e:5f:d0', 'broadcast': 'ff:ff:ff:ff:ff:ff', 'mtu': 1500, 'qdisc': 'noqueue', 'master': None, 'txqlen': 1000, 'operstate': 'UP', 'linkmode': 0, 'net_ns_pid': None, 'ifalias': None, 'num_vf': None, 'group': 0, 'ext_mask': None, 'promiscuity': 0, 'num_tx_queues': 1, 'num_rx_queues': 1, 'carrier': 1, 'carrier_changes': 0, 'link_netnsid': None, 'phys_port_name': None, 'proto_down': 0, 'gso_max_segs': 65535, 'gso_max_size': 65536, 'event': None, 'new_netnsid': None, 'if_netnsid': None, 'carrier_up_count': 0, 'carrier_down_count': 0, 'new_ifindex': None, 'min_mtu': 0, 'max_mtu': 65535, 'alt_ifname': None, 'parent_dev_name': None, 'parent_dev_bus_name': None, 'gro_max_size': None, 'tso_max_size': None, 'tso_max_segs': None, 'slave_kind': None, 'xdp_attached': None, 'xdp_flags': None, 'xdp_prog_id': None, 'xdp_drv_prog_id': None, 'xdp_skb_prog_id': None, 'xdp_hw_prog_id': None, 'vlan_protocol': 33024}
>>>
>>>
>>> with ndb.interfaces['net1.311'] as dev:
...     dev['net_ns_fd'] = 'ns337'
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.11/site-packages/pyroute2/ndb/objects/__init__.py", line 416, in __exit__
    self.commit()
  File "/usr/lib/python3.11/site-packages/pyroute2/ndb/auth_manager.py", line 67, in guard
    return f(obj, *argv, **kwarg)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/pyroute2/ndb/objects/__init__.py", line 736, in commit
    self.apply(mode='commit')
  File "/usr/lib/python3.11/site-packages/pyroute2/ndb/auth_manager.py", line 67, in guard
    return f(obj, *argv, **kwarg)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/pyroute2/ndb/objects/interface.py", line 1016, in apply
    self.apply_altnames(alt_ifname_setup)
  File "/usr/lib/python3.11/site-packages/pyroute2/ndb/auth_manager.py", line 67, in guard
    return f(obj, *argv, **kwarg)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.11/site-packages/pyroute2/ndb/objects/interface.py", line 991, in apply_altnames
    self.load_from_system()
  File "/usr/lib/python3.11/site-packages/pyroute2/ndb/objects/interface.py", line 1106, in load_from_system
    self.sources[self['target']].api(
  File "/usr/lib/python3.11/site-packages/pyroute2/ndb/source.py", line 126, in api
    self.ndb.messenger.emit(
    ^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'emit'

Do I need to register some messenger prior to making these calls? Any information would be appreciated. Thanks

svinota commented 7 months ago

Thanks for the feedback, investigating

Shaun-3adesign commented 3 months ago

I'm also seeing this issue is there any update on a fix?

tomkcook commented 2 months ago

Likewise, almost any attempt to move an interface to a namespace results in this error:

ndb.interfaces.create(ifname="veth0", kind="veth", target="test-ns").commit()
ndb.interfaces.create(ifname="veth0", kind="veth", net_ns_fd="test-ns").commit()
ndb.interfaces.create(ifname="veth0", kind="veth").set("target", "test-ns").commit()
ndb.interfaces.create(ifname="veth0", kind="veth").set("net_ns_fd", "test-ns").commit()

ndb.interfaces.create(ifname="veth0", kind="veth").commit()

with ndb.interfaces["veth0"] as dev:
    dev["target"] = "test-ns"

All give the same error.

tomkcook commented 2 months ago

A quick bit of bisecting gives this working in pyroute2 0.7.6 but failing in 0.7.7.

tomkcook commented 2 months ago

And a git bisect points to 8c6421b63a93b1eea8b9df29e76516107c099929 as the offending commit. For reference, the result was produced like this:

$ cat > test.py <<EOM
import pyroute2

try:
    ndb = pyroute2.NDB()
    ctx = ndb.begin()
    ctx.push(
        ns := ndb.netns.create("test-2"),
    )

    ctx.push(
        eth0 := ndb.interfaces.create(ifname="eth0", kind="veth", peer="eth0-1").set("target", "test-2")
    )
    ctx.commit()

    ctx = ndb.begin()
    ctx.push(ns.remove())
    ctx.commit()
except:
    exit(10)

exit(0)
EOM
$ python3 -m venv venv/
$ venv/bin/pip install -e .
$ git bisect start HEAD 0.7.6
$ git bisect run sudo venv/bin/python3 test.py