Closed
Description
Hi and thanks for the great library!
I have been experimenting with the NDB interface and network namespaces, and I'm currently struggling to make the network interface inside a netns to go up.
As similar procedure works fine with the "IPDB-way", I think it is a bug, but I couldn't figure out where should I start looking to fix it.
P.S. A quick side-question, is it safe to use multiple context managers, ala with ndb.interfaces[peer_dict] as peer_veth, nbd.interfaces[root_ns_if] as root_veth:
?
NDB
interface on main namespace
1272: prcf30af0d-r@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether a6:6f:4e:64:dd:36 brd ff:ff:ff:ff:ff:ff link-netns prcf30af0d
inet 192.168.233.0/31 scope global prcf30af0d-r
valid_lft forever preferred_lft forever
inet6 fe80::a46f:4eff:fe64:dd36/64 scope link
valid_lft forever preferred_lft forever
Interface inside the NS
- Note the smallish index number, potentially related as IPDB assigns a sequantial index?
- On the main namespace that index is reserved for the ethernet adapter.
2: prcf30af0d-p@if1272: <BROADCAST,MULTICAST> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether 36:65:27:22:ae:76 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.233.1/31 scope global prcf30af0d-p
valid_lft forever preferred_lft forever
Debug log
DEBUG:pyroute2.ndb.139946316556880.view.interfaces:cache del (('target', 'localhost'), ('tflags', 0), ('index', 1272))
DEBUG:pyroute2.ndb.139946316556880.view.interfaces:cache add (('target', 'prcf30af0d'), ('tflags', 0), ('index', 2))
INFO:__main__:setting peer iface prcf30af0d-p up with 192.168.233.1/31
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:commit: [(1565646783.800148, 'invalid'), (1565646783.8018253, 'system')]
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:init
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:complete key OrderedDict([('target', 'prcf30af0d'), ('tflags', 0), ('index', 2)]) from table interfaces_139946275317232
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:got OrderedDict([('target', 'prcf30af0d'), ('tflags', 0), ('index', 2)])
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_sql: ('prcf30af0d', 0, 0, 1, 2, 4098, 0, '36:65:27:22:ae:76', 'ff:ff:ff:ff:ff:ff', 'prcf30af0d-p', 1500, 1272, 'noop', None, 1000, 0, None, None, None, 0, None, 0, 1, 1, 0, 1, 0, None, 0, 65535, 65536, 0, 1, 'down', 'veth', None)
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot interfaces_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot addresses_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot neighbours_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot routes_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot nh_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot rules_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot netns_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot p2p_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot ifinfo_bridge_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot ifinfo_bond_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot ifinfo_vlan_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot ifinfo_vxlan_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot ifinfo_gre_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot ifinfo_vrf_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot ifinfo_vti_139946275317232
DEBUG:pyroute2.ndb.139946316556880.schema:create snapshot ifinfo_vti6_139946275317232
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:apply: [(1565646783.800148, 'invalid'), (1565646783.8018253, 'system')]
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_sql: ('prcf30af0d', 0, 0, 1, 2, 4098, 0, '36:65:27:22:ae:76', 'ff:ff:ff:ff:ff:ff', 'prcf30af0d-p', 1500, 1272, 'noop', None, 1000, 0, None, None, None, 0, None, 0, 1, 1, 0, 1, 0, None, 0, 65535, 65536, 0, 1, 'down', 'veth', None)
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:apply req: {'target': 'prcf30af0d', 'tflags': 0, 'index': 2, 'state': 'up', 'master': None}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:apply idx_req: {'target': 'prcf30af0d', 'tflags': 0, 'index': 2}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:apply state: system
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:run set ({'target': 'prcf30af0d', 'tflags': 0, 'index': 2, 'state': 'up', 'master': None})
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:stats: apply set {objid 139946275317232, wtime 0.4, mqsize 4, nqsize 0}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_rtnl: {'length': 1360, 'type': 16, 'flags': 0, 'sequence_number': 0, 'pid': 0, 'error': None, 'stats': Stats(qsize=0, delta=0, delay=0)}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_sql: ('prcf30af0d', 0, 0, 1, 2, 69635, 1, '36:65:27:22:ae:76', 'ff:ff:ff:ff:ff:ff', 'prcf30af0d-p', 1500, 1272, 'noqueue', None, 1000, 0, None, None, None, 0, None, 0, 1, 1, 1, 2, 0, None, 0, 65535, 65536, 1, 1, 'up', 'veth', None)
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_sql: ('prcf30af0d', 0, 0, 1, 2, 69635, 1, '36:65:27:22:ae:76', 'ff:ff:ff:ff:ff:ff', 'prcf30af0d-p', 1500, 1272, 'noqueue', None, 1000, 0, None, None, None, 0, None, 0, 1, 1, 1, 2, 0, None, 0, 65535, 65536, 1, 1, 'up', 'veth', None)
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:check: [(1565646783.800148, 'invalid'), (1565646783.844721, 'system')]
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:check: True
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:checked
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:stats: 139946275317232 pass
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:init
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:complete key {'target': 'localhost', 'address': '192.168.233.1', 'prefixlen': 31} from table addresses
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_rtnl: {'length': 1360, 'type': 16, 'flags': 0, 'sequence_number': 0, 'pid': 0, 'error': None, 'stats': Stats(qsize=0, delta=0, delay=0)}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_sql: ('localhost', 0, 0, 1, 1272, 69699, 0, 'a6:6f:4e:64:dd:36', 'ff:ff:ff:ff:ff:ff', 'prcf30af0d-r', 1500, 2, 'noqueue', None, 1000, 0, None, None, None, 0, None, 0, 1, 1, 1, 2, 0, None, 0, 65535, 65536, 1, 1, 'up', 'veth', None)
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_rtnl: {'length': 1360, 'type': 16, 'flags': 0, 'sequence_number': 0, 'pid': 0, 'error': None, 'stats': Stats(qsize=0, delta=0, delay=0)}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_sql: ('prcf30af0d', 0, 0, 1, 2, 69699, 0, '36:65:27:22:ae:76', 'ff:ff:ff:ff:ff:ff', 'prcf30af0d-p', 1500, 1272, 'noqueue', None, 1000, 0, None, None, None, 0, None, 0, 1, 1, 1, 2, 0, None, 0, 65535, 65536, 1, 1, 'up', 'veth', None)
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:got none
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:apply: [(1565646783.8450475, 'invalid')]
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_sql: None
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:apply req: {'target': 'prcf30af0d', 'prefixlen': 31, 'IFA_ADDRESS': '192.168.233.1', 'address': '192.168.233.1'}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:apply idx_req: {'target': 'prcf30af0d', 'prefixlen': 31, 'IFA_ADDRESS': '192.168.233.1'}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:apply state: invalid
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:run add ({'target': 'prcf30af0d', 'address': '192.168.233.1', 'prefixlen': 31, 'index': 2})
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:stats: apply add {objid 139946275357616, wtime 0.0, mqsize 0, nqsize 0}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_sql: ('prcf30af0d', 0, 2, 31, 128, 0, 2, '192.168.233.1', '192.168.233.1', 'prcf30af0d-p', None, None, None, 128)
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:check: [(1565646783.8450475, 'invalid'), (1565646783.854934, 'system')]
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:check changed: {'target'}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:check failed
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:run add ({'target': 'prcf30af0d', 'address': '192.168.233.1', 'prefixlen': 31, 'index': 2})
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:error: (17, 'File exists')
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:ignore error 17 for {'target': 'localhost', 'address': '192.168.233.1', 'prefixlen': 31, 'tflags': 0, 'family': 2, 'flags': 128, 'scope': 0, 'index': 2, 'local': '192.168.233.1', 'label': 'prcf30af0d-p', 'broadcast': None, 'anycast': None, 'multicast': None}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:run fallback set ({'target': 'prcf30af0d', 'address': '192.168.233.1', 'prefixlen': 31, 'index': 2})
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:stats: apply add {objid 139946275357616, wtime 0.1, mqsize 1, nqsize 0}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_sql: ('prcf30af0d', 0, 2, 31, 128, 0, 2, '192.168.233.1', '192.168.233.1', 'prcf30af0d-p', None, None, None, 128)
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:check: [(1565646783.8450475, 'invalid'), (1565646783.8588128, 'system')]
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:check changed: {'target'}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:check failed
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:run add ({'target': 'prcf30af0d', 'address': '192.168.233.1', 'prefixlen': 31, 'index': 2})
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:error: (17, 'File exists')
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:ignore error 17 for {'target': 'localhost', 'address': '192.168.233.1', 'prefixlen': 31, 'tflags': 0, 'family': 2, 'flags': 128, 'scope': 0, 'index': 2, 'local': '192.168.233.1', 'label': 'prcf30af0d-p', 'broadcast': None, 'anycast': None, 'multicast': None}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:run fallback set ({'target': 'prcf30af0d', 'address': '192.168.233.1', 'prefixlen': 31, 'index': 2})
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:stats: apply add {objid 139946275357616, wtime 0.2, mqsize 0, nqsize 0}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_sql: ('prcf30af0d', 0, 2, 31, 128, 0, 2, '192.168.233.1', '192.168.233.1', 'prcf30af0d-p', None, None, None, 128)
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:check: [(1565646783.8450475, 'invalid'), (1565646783.9650478, 'system')]
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:check changed: {'target'}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:check failed
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:run add ({'target': 'prcf30af0d', 'address': '192.168.233.1', 'prefixlen': 31, 'index': 2})
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:error: (17, 'File exists')
<I snipped off some more tries from here>
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:run set ({'target': 'prcf30af0d', 'tflags': 0, 'index': 2, 'state': 'down', 'master': None})
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:stats: apply set {objid 139946275002032, wtime 0.4, mqsize 4, nqsize 0}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_rtnl: {'length': 1360, 'type': 16, 'flags': 0, 'sequence_number': 0, 'pid': 0, 'error': None, 'stats': Stats(qsize=0, delta=0, delay=0)}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_sql: ('prcf30af0d', 0, 0, 1, 2, 4098, 1, '36:65:27:22:ae:76', 'ff:ff:ff:ff:ff:ff', 'prcf30af0d-p', 1500, 1272, 'noqueue', None, 1000, 0, None, None, None, 0, None, 0, 1, 1, 0, 3, 0, None, 0, 65535, 65536, 1, 2, 'down', 'veth', None)
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_sql: ('prcf30af0d', 0, 0, 1, 2, 4098, 0, '36:65:27:22:ae:76', 'ff:ff:ff:ff:ff:ff', 'prcf30af0d-p', 1500, 1272, 'noop', None, 1000, 0, None, None, None, 0, None, 0, 1, 1, 0, 1, 0, None, 0, 65535, 65536, 0, 1, 'down', 'veth', None)
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:check: [(1565646783.808394, 'invalid'), (1565646798.4870124, 'system')]
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:check: True
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:checked
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:stats: 139946275002032 pass
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_rtnl: {'length': 1360, 'type': 16, 'flags': 0, 'sequence_number': 0, 'pid': 0, 'error': None, 'stats': Stats(qsize=0, delta=-1, delay=0)}
DEBUG:pyroute2.ndb.139946316556880.rtnl_object:load_sql: ('localhost', 0, 0, 1, 1272, 4099, 0, 'a6:6f:4e:64:dd:36', 'ff:ff:ff:ff:ff:ff', 'prcf30af0d-r', 1500, 2, 'noqueue', None, 1000, 0, None, None, None, 0, None, 0, 1, 1, 0, 3, 0, None, 0, 65535, 65536, 1, 2, 'up', 'veth', None)
Traceback (most recent call last):
File "test_ndb.py", line 65, in <module>
create_namespace_nbd()
File "test_ndb.py", line 39, in create_namespace_nbd
_LOGGER.info(f"setting peer iface {peer_ns_if} up with {peer_ip_w_cidr}")
File "/code/path/lib/pyroute2/pyroute2/ndb/objects/__init__.py", line 261, in __exit__
self.commit()
File "/code/path/lib/pyroute2/pyroute2/ndb/objects/__init__.py", line 496, in commit
self.apply()
File "/code/path/lib/pyroute2/pyroute2/ndb/objects/interface.py", line 315, in apply
super(Interface, self).apply(rollback)
File "/code/path/lib/pyroute2/pyroute2/ndb/objects/__init__.py", line 715, in apply
raise ret
File "/code/path/lib/pyroute2/pyroute2/ndb/objects/interface.py", line 211, in do_add_ip
self.ipaddr.create(spec).apply()
File "/code/path/lib/pyroute2/pyroute2/ndb/objects/__init__.py", line 672, in apply
raise Exception('lost sync in apply()')
Exception: lost sync in apply()
IPDB variant
- Running the IPDB version works as expected.
- The interface numbers are sequential here.
Main namespace
1274: pr5ddf7a81-r@if1273: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 62:f4:1a:e1:10:23 brd ff:ff:ff:ff:ff:ff link-netns pr5ddf7a81
inet 192.168.233.0/31 scope global pr5ddf7a81-r
valid_lft forever preferred_lft forever
inet6 fe80::60f4:1aff:fee1:1023/64 scope link
valid_lft forever preferred_lft forever
Inside the namespace
1273: pr5ddf7a81-p@if1274: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether d6:80:b2:5a:a0:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.233.1/31 scope global pr5ddf7a81-p
valid_lft forever preferred_lft forever
inet6 fe80::d480:b2ff:fe5a:a004/64 scope link
valid_lft forever preferred_lft forever
Test script
- Note, this does not clean the interfaces nor the namespace afterwards, for testing I simple used
ip -all netns delete
.
from pyroute2 import IPRoute, netns, NetNS, NDB, IPDB
from pyroute2.common import uifname
import logging
logging.basicConfig(level=logging.DEBUG)
_LOGGER = logging.getLogger(__name__)
root_ip, peer_ip = "192.168.233.0", "192.168.233.1"
root_ip_w_cidr = f"{root_ip}/31"
peer_ip_w_cidr = f"{peer_ip}/31"
nsname = uifname()
root_ns_if = f"{nsname}-r"
peer_ns_if = f"{nsname}-p"
def create_namespace_nbd():
ndb = NDB(debug=True)
ndb.sources.add(netns=nsname)
ndb.interfaces.create(
ifname=root_ns_if, kind="veth", peer={"ifname": peer_ns_if, "net_ns_fd": nsname}
).commit()
with ndb.interfaces[root_ns_if] as root_veth:
root_veth.add_ip(root_ip_w_cidr)
root_veth["state"] = "up"
_LOGGER.info(f"setting root iface {root_ns_if} up with {root_ip_w_cidr}")
# need to use net_ns_fd to locate the peer interface
peer_dict = {"net_ns_fd": nsname, "ifname": peer_ns_if}
with ndb.interfaces[peer_dict] as peer_veth:
peer_veth.add_ip(peer_ip_w_cidr)
peer_veth["state"] = "up"
_LOGGER.info(f"setting peer iface {peer_ns_if} up with {peer_ip_w_cidr}")
def create_namespace_ipr():
ipdb = IPDB()
ns = NetNS(nsname)
ipdb.create(ifname=root_ns_if, kind="veth", peer=peer_ns_if).commit()
with ipdb.interfaces[peer_ns_if] as i:
i.net_ns_fd = nsname
with ipdb.interfaces[root_ns_if] as root_veth:
root_veth.add_ip(root_ip_w_cidr)
root_veth.up()
ipdb_ns = IPDB(nl=ns)
with ipdb_ns.interfaces[peer_ns_if] as peer_veth:
peer_veth.add_ip(peer_ip_w_cidr)
peer_veth.up()
_LOGGER.info(f"created successfully.")
ipdb_ns.release()
ns.close()
# create_namespace_nbd()
create_namespace_ipr()
Activity