def run(self): logging.info('Started LinkNeg...') iface = self.get_mopt('iface') state = bool_it(self.get_mopt('state')) admin_speed = self.get_opt('speed', default=0) timeout = self.get_opt('timeout', default=10) ip = IPDB() self.oper_state = ip.interfaces[iface]['operstate'] wd = ip.watchdog(ifname=iface) cuid = ip.register_callback(self._cb) wd.wait(timeout=timeout) ip.unregister_callback(cuid) ip.release() admin_state = 'UP' if state else 'DOWN' oper_state = self.oper_state if admin_state == oper_state and admin_speed: oper_speed = self.get_speed(iface) else: oper_speed = 0 res_data = {'admin_state': admin_state, 'oper_state': oper_state} if admin_speed: res_data['admin_speed'] = "%s Mb/s" % admin_speed res_data['oper_speed'] = "%s Mb/s" % oper_speed if admin_state == oper_state and admin_speed == oper_speed: self.set_pass(res_data) else: self.set_fail(res_data)
def run(self): logging.info('Started LinkNeg...') iface = self.get_mopt('iface') state = bool_it(self.get_mopt('state')) timeout = self.get_opt('timeout', default=10) ip = IPDB() self.oper_state = ip.interfaces[iface]['operstate'] wd = ip.watchdog(ifname=iface) cuid = ip.register_callback(self._cb) wd.wait(timeout=timeout) ip.unregister_callback(cuid) ip.release() admin_state = 'UP' if state else 'DOWN' oper_state = self.oper_state res_data = {'admin_state': admin_state, 'oper_state': oper_state} if admin_state == oper_state: self.set_pass(res_data) else: self.set_fail(res_data)
class TestExplicit(object): ip = None mode = "explicit" def setup(self): self.ifaces = [] self.ifd = self.get_ifname() create_link(self.ifd, kind="dummy") self.ip = IPDB(mode=self.mode) def get_ifname(self): ifname = uifname() self.ifaces.append(ifname) return ifname def teardown(self): for name in self.ifaces: try: # just a hardcore removal self.ip.nl.link_remove(self.ip.interfaces[name].index) except Exception: pass self.ip.release() self.ifaces = [] def test_simple(self): assert len(list(self.ip.interfaces.keys())) > 0 def test_empty_transaction(self): assert "lo" in self.ip.interfaces with self.ip.interfaces.lo as i: assert isinstance(i.mtu, int) def test_idx_len(self): assert len(self.ip.by_name.keys()) == len(self.ip.by_index.keys()) def test_idx_set(self): assert set(self.ip.by_name.values()) == set(self.ip.by_index.values()) def test_idx_types(self): assert all(isinstance(i, int) for i in self.ip.by_index.keys()) assert all(isinstance(i, basestring) for i in self.ip.by_name.keys()) def test_addr_attributes(self): require_user("root") if1 = self.get_ifname() if2 = self.get_ifname() with self.ip.create(ifname=if1, kind="dummy") as i: # +scope host (=> broadcast == None) i.add_ip("172.16.102.1/24", scope=254) with self.ip.create(ifname=if2, kind="dummy") as i: # +broadcast (default scope == 0) i.add_ip("172.16.103.1/24", broadcast="172.16.103.128") index = self.ip.interfaces[if1]["index"] addr = self.ip.nl.get_addr(index=index)[0] assert addr["scope"] == 254 assert addr.get_attr("IFA_BROADCAST") is None index = self.ip.interfaces[if2]["index"] addr = self.ip.nl.get_addr(index=index)[0] assert addr["scope"] == 0 assert addr.get_attr("IFA_BROADCAST") == "172.16.103.128" def test_addr_loaded(self): for name in self.ip.by_name: assert len(self.ip.interfaces[name]["ipaddr"]) == len(get_ip_addr(name)) def test_reprs(self): assert isinstance(repr(self.ip.interfaces.lo.ipaddr), basestring) assert isinstance(repr(self.ip.interfaces.lo), basestring) def test_dotkeys(self): # self.ip.lo hint for ipython assert "lo" in dir(self.ip.interfaces) assert "lo" in self.ip.interfaces assert self.ip.interfaces.lo == self.ip.interfaces["lo"] # create attribute self.ip.interfaces["newitem"] = True self.ip.interfaces.newattr = True self.ip.interfaces.newitem = None assert self.ip.interfaces.newitem == self.ip.interfaces["newitem"] assert self.ip.interfaces.newitem is None # delete attribute del self.ip.interfaces.newitem del self.ip.interfaces.newattr assert "newattr" not in dir(self.ip.interfaces) # test hasattr protocol assert hasattr(self.ip.interfaces, "nonexistinginterface") is False @skip_if_not_supported def test_vlan_slave_bridge(self): # https://github.com/svinota/pyroute2/issues/58 # based on the code by Petr Horáček dXname = self.get_ifname() vXname = self.get_ifname() vYname = self.get_ifname() brname = self.get_ifname() require_user("root") dX = self.ip.create(ifname=dXname, kind="dummy").commit() vX = self.ip.create(ifname=vXname, kind="vlan", link=dX, vlan_id=101).commit() vY = self.ip.create(ifname=vYname, kind="vlan", link=dX, vlan_id=102).commit() with self.ip.create(ifname=brname, kind="bridge") as i: i.add_port(vX) i.add_port(vY["index"]) assert vX["index"] in self.ip.interfaces[brname]["ports"] assert vY["index"] in self.ip.interfaces[brname].ports assert vX["link"] == dX["index"] assert vY["link"] == dX["index"] assert vX["master"] == self.ip.interfaces[brname]["index"] assert vY["master"] == self.ip.interfaces[brname].index def _test_commit_hook_positive(self): require_user("root") # test callback, that adds an address by itself -- # just to check the possibility def cb(interface, snapshot, transaction): self.ip.nl.addr("add", self.ip.interfaces[self.ifd].index, address="172.16.22.1", mask=24) # register callback and check CB chain length self.ip.interfaces[self.ifd].register_commit_hook(cb) assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1 # create a transaction and commit it if self.ip.interfaces[self.ifd]._mode == "explicit": self.ip.interfaces[self.ifd].begin() self.ip.interfaces[self.ifd].add_ip("172.16.21.1/24") self.ip.interfaces[self.ifd].commit() # added address should be there assert ("172.16.21.1", 24) in self.ip.interfaces[self.ifd].ipaddr # and the one, added by the callback, too assert ("172.16.22.1", 24) in self.ip.interfaces[self.ifd].ipaddr # unregister callback self.ip.interfaces[self.ifd].unregister_commit_hook(cb) assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0 def _test_commit_hook_negative(self): require_user("root") # test exception to differentiate class CBException(Exception): pass # test callback, that always fail def cb(interface, snapshot, transaction): raise CBException() # register callback and check CB chain length self.ip.interfaces[self.ifd].register_commit_hook(cb) assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1 # create a transaction and commit it; should fail # 'cause of the callback if self.ip.interfaces[self.ifd]._mode == "explicit": self.ip.interfaces[self.ifd].begin() self.ip.interfaces[self.ifd].add_ip("172.16.21.1/24") try: self.ip.interfaces[self.ifd].commit() except CBException: pass # added address should be removed assert ("172.16.21.1", 24) not in self.ip.interfaces[self.ifd].ipaddr # unregister callback self.ip.interfaces[self.ifd].unregister_commit_hook(cb) assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0 def test_review(self): assert len(self.ip.interfaces.lo._tids) == 0 if self.ip.interfaces.lo._mode == "explicit": self.ip.interfaces.lo.begin() self.ip.interfaces.lo.add_ip("172.16.21.1/24") r = self.ip.interfaces.lo.review() assert len(r["+ipaddr"]) == 1 assert len(r["-ipaddr"]) == 0 assert len(r["+ports"]) == 0 assert len(r["-ports"]) == 0 # +/-ipaddr, +/-ports assert len([i for i in r if r[i] is not None]) == 4 self.ip.interfaces.lo.drop() def test_rename(self): require_user("root") ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, kind="dummy").commit() if self.ip.interfaces[ifA]._mode == "explicit": self.ip.interfaces[ifA].begin() self.ip.interfaces[ifA].ifname = ifB self.ip.interfaces[ifA].commit() assert ifB in self.ip.interfaces assert ifA not in self.ip.interfaces if self.ip.interfaces[ifB]._mode == "explicit": self.ip.interfaces[ifB].begin() self.ip.interfaces[ifB].ifname = ifA self.ip.interfaces[ifB].commit() assert ifB not in self.ip.interfaces assert ifA in self.ip.interfaces def test_routes_keys(self): assert "172.16.0.0/24" not in self.ip.routes # create but not commit self.ip.routes.add(dst="172.16.0.0/24", gateway="127.0.0.1") # checks assert "172.16.0.0/24" in self.ip.routes assert "172.16.0.0/24" in list(self.ip.routes.keys()) def test_routes(self): require_user("root") assert "172.16.0.0/24" not in self.ip.routes # create a route with self.ip.routes.add({"dst": "172.16.0.0/24", "gateway": "127.0.0.1"}) as r: pass assert "172.16.0.0/24" in self.ip.routes.keys() assert grep("ip ro", pattern="172.16.0.0/24.*127.0.0.1") # change the route with self.ip.routes["172.16.0.0/24"] as r: r.gateway = "127.0.0.2" assert self.ip.routes["172.16.0.0/24"].gateway == "127.0.0.2" assert grep("ip ro", pattern="172.16.0.0/24.*127.0.0.2") # delete the route with self.ip.routes["172.16.0.0/24"] as r: r.remove() assert "172.16.0.0/24" not in self.ip.routes.keys() assert not grep("ip ro", pattern="172.16.0.0/24") def test_routes_multipath_gateway(self): require_user("root") ifR = self.get_ifname() with self.ip.create(ifname=ifR, kind="dummy") as i: i.add_ip("172.16.231.1/24") i.up() r = self.ip.routes.add( { "dst": "172.16.232.0/24", "multipath": [ {"gateway": "172.16.231.2", "hops": 20}, {"gateway": "172.16.231.3", "hops": 30}, {"gateway": "172.16.231.4"}, ], } ) r.commit() assert grep("ip ro", pattern="172.16.232.0/24") assert grep("ip ro", pattern="nexthop.*172.16.231.2.*weight.*21") assert grep("ip ro", pattern="nexthop.*172.16.231.3.*weight.*31") assert grep("ip ro", pattern="nexthop.*172.16.231.4.*weight.*1") with self.ip.routes["172.16.232.0/24"] as r: r.add_nh({"gateway": "172.16.231.5", "hops": 50}) r.del_nh({"gateway": "172.16.231.2"}) assert grep("ip ro", pattern="172.16.232.0/24") assert grep("ip ro", pattern="nexthop.*172.16.231.5.*weight.*51") assert grep("ip ro", pattern="nexthop.*172.16.231.3.*weight.*31") assert grep("ip ro", pattern="nexthop.*172.16.231.4.*weight.*1") def test_routes_metrics(self): require_user("root") assert "172.16.0.0/24" not in self.ip.routes.keys() # create a route self.ip.routes.add({"dst": "172.16.0.0/24", "gateway": "127.0.0.1", "metrics": {"mtu": 1360}}).commit() assert grep("ip ro", pattern="172.16.0.0/24.*mtu 1360") # change metrics with self.ip.routes["172.16.0.0/24"] as r: r.metrics.mtu = 1400 assert self.ip.routes["172.16.0.0/24"]["metrics"]["mtu"] == 1400 assert grep("ip ro", pattern="172.16.0.0/24.*mtu 1400") # delete the route with self.ip.routes["172.16.0.0/24"] as r: r.remove() assert "172.16.0.0/24" not in self.ip.routes.keys() assert not grep("ip ro", pattern="172.16.0.0/24") def test_wait_ip_exact(self): ts = time.time() ret = self.ip.interfaces.lo.wait_ip("127.0.0.1", timeout=2) assert (time.time() - ts) < 2 assert ret def test_wait_ip_net(self): ts = time.time() ret = self.ip.interfaces.lo.ipaddr.wait_ip("127.0.0.0", 8, timeout=2) assert (time.time() - ts) < 2 assert ret def test_wait_ip_exact_fail(self): ts = time.time() ret = self.ip.interfaces.lo.wait_ip("1.1.1.1", timeout=2) assert (time.time() - ts) >= 2 assert not ret def test_wait_ip_net_fail(self): ts = time.time() ret = self.ip.interfaces.lo.ipaddr.wait_ip("172.6.0.0", 24, timeout=2) assert (time.time() - ts) >= 2 assert not ret @skip_if_not_supported def _test_shadow(self, kind): ifA = self.get_ifname() a = self.ip.create(ifname=ifA, kind=kind).commit() if a._mode == "explicit": a.begin() a.shadow().commit() assert ifA in self.ip.interfaces assert not grep("ip link", pattern=ifA) time.sleep(0.5) b = self.ip.create(ifname=ifA, kind=kind).commit() assert a == b assert grep("ip link", pattern=ifA) def test_shadow_bond(self): require_user("root") self._test_shadow("bond") def test_shadow_bridge(self): require_user("root") self._test_shadow("bridge") def test_shadow_dummy(self): require_user("root") self._test_shadow("dummy") def test_updown(self): require_user("root") if self.ip.interfaces[self.ifd]._mode == "explicit": self.ip.interfaces[self.ifd].begin() self.ip.interfaces[self.ifd].up() self.ip.interfaces[self.ifd].commit() assert self.ip.interfaces[self.ifd].flags & 1 if self.ip.interfaces[self.ifd]._mode == "explicit": self.ip.interfaces[self.ifd].begin() self.ip.interfaces[self.ifd].down() self.ip.interfaces[self.ifd].commit() assert not (self.ip.interfaces[self.ifd].flags & 1) def test_slave_data(self): require_user("root") ifBR = self.get_ifname() ifP = self.get_ifname() self.ip.debug = True bridge = self.ip.create(ifname=ifBR, kind="bridge").commit() port = self.ip.create(ifname=ifP, kind="dummy").commit() if self.ip.mode == "explicit": bridge.begin() bridge.add_port(port) bridge.up() bridge.commit() li = port.nlmsg.get_attr("IFLA_LINKINFO") skind = li.get_attr("IFLA_INFO_SLAVE_KIND") sdata = li.get_attr("IFLA_INFO_SLAVE_DATA") self.ip.debug = False if skind is None or sdata is None: raise SkipTest("slave data not provided") assert sdata.get_attr("IFLA_BRPORT_STATE") is not None assert sdata.get_attr("IFLA_BRPORT_MODE") is not None def test_fail_ipaddr(self): require_user("root") ifA = self.get_ifname() i = self.ip.create(ifname=ifA, kind="dummy").commit() assert not len(i.ipaddr) if i._mode == "explicit": i.begin() i.add_ip("123.456.789.1024/153") try: i.commit() except socket.error as e: if not e.args[0].startswith("illegal IP"): raise assert not len(i.ipaddr) if i._mode == "explicit": i.begin() i.remove().commit() assert ifA not in self.ip.interfaces def test_multiple_ips_one_transaction(self): require_user("root") ifA = self.get_ifname() with self.ip.create(kind="dummy", ifname=ifA) as i: for x in range(1, 255): i.add_ip("172.16.0.%i/24" % x) i.up() idx = self.ip.interfaces[ifA].index assert len(self.ip.nl.get_addr(index=idx, family=2)) == 254 def test_json_dump(self): require_user("root") ifA = self.get_ifname() ifB = self.get_ifname() # set up the interface with self.ip.create(kind="dummy", ifname=ifA) as i: i.add_ip("172.16.0.1/24") i.up() # imitate some runtime time.sleep(2) # make a backup backup = self.ip.interfaces[ifA].dump() assert isinstance(backup, dict) # remove index and protinfo -- make it portable del backup["index"] if "protinfo" in backup: del backup["protinfo"] # serialize backup = json.dumps(backup) # remove the interface with self.ip.interfaces[ifA] as i: i.remove() # create again, but with different name self.ip.create(kind="dummy", ifname=ifB).commit() # load the backup # 1. prepare to the restore: bring it down with self.ip.interfaces[ifB] as i: i.down() # 2. please notice, the interface will be renamed after the backup with self.ip.interfaces[ifB] as i: i.load(json.loads(backup)) # check :) assert ifA in self.ip.interfaces assert ifB not in self.ip.interfaces for ipaddr in json.loads(backup)["ipaddr"]: assert tuple(ipaddr) in self.ip.interfaces[ifA].ipaddr assert self.ip.interfaces[ifA].flags & 1 def test_freeze_del(self): require_user("root") interface = self.ip.interfaces[self.ifd] # set up the interface with interface as i: i.add_ip("172.16.0.1/24") i.add_ip("172.16.1.1/24") i.up() # check assert ("172.16.0.1", 24) in interface.ipaddr assert ("172.16.1.1", 24) in interface.ipaddr assert interface.flags & 1 interface.freeze() # delete interface with an external routine remove_link(interface.ifname) # wait for a second time.sleep(1) # check if it is back ipdb = IPDB() try: ifc = ipdb.interfaces[self.ifd] assert ("172.16.0.1", 24) in ifc.ipaddr assert ("172.16.1.1", 24) in ifc.ipaddr assert ifc.flags & 1 except: raise finally: interface.unfreeze() ipdb.release() def test_freeze(self): require_user("root") interface = self.ip.interfaces[self.ifd] # set up the interface with interface as i: i.add_ip("172.16.0.1/24") i.add_ip("172.16.1.1/24") i.up() # check assert ("172.16.0.1", 24) in interface.ipaddr assert ("172.16.1.1", 24) in interface.ipaddr assert interface.flags & 1 # assert routine def probe(): # The freeze results are dynamic: it is not a real freeze, # it is a restore routine. So it takes time for results # to stabilize err = None for _ in range(3): err = None interface.ipaddr.set_target((("172.16.0.1", 24), ("172.16.1.1", 24))) interface.ipaddr.target.wait() try: assert ("172.16.0.1", 24) in interface.ipaddr assert ("172.16.1.1", 24) in interface.ipaddr assert interface.flags & 1 break except AssertionError as e: err = e continue except Exception as e: err = e break if err is not None: interface.unfreeze() i2.close() raise err # freeze interface.freeze() # change the interface somehow i2 = IPRoute() i2.addr("delete", interface.index, "172.16.0.1", 24) i2.addr("delete", interface.index, "172.16.1.1", 24) probe() # unfreeze self.ip.interfaces[self.ifd].unfreeze() try: i2.addr("delete", interface.index, "172.16.0.1", 24) i2.addr("delete", interface.index, "172.16.1.1", 24) except: pass finally: i2.close() # should be up, but w/o addresses interface.ipaddr.set_target(set()) interface.ipaddr.target.wait(3) assert ("172.16.0.1", 24) not in self.ip.interfaces[self.ifd].ipaddr assert ("172.16.1.1", 24) not in self.ip.interfaces[self.ifd].ipaddr assert self.ip.interfaces[self.ifd].flags & 1 def test_snapshots(self): require_user("root") ifB = self.get_ifname() # set up the interface with self.ip.interfaces[self.ifd] as i: i.add_ip("172.16.0.1/24") i.up() # check it assert ("172.16.0.1", 24) in self.ip.interfaces[self.ifd].ipaddr assert self.ip.interfaces[self.ifd].flags & 1 # make a snapshot s = self.ip.interfaces[self.ifd].snapshot() i = self.ip.interfaces[self.ifd] # check it assert i.last_snapshot_id() == s # unset the interface with self.ip.interfaces[self.ifd] as i: i.del_ip("172.16.0.1/24") i.down() # we can not rename the interface while it is up, # so do it in two turns with self.ip.interfaces[self.ifd] as i: i.ifname = ifB # check it assert ifB in self.ip.interfaces assert self.ifd not in self.ip.interfaces y = self.ip.interfaces[ifB] assert i == y assert ("172.16.0.1", 24) not in y.ipaddr assert not (y.flags & 1) # revert snapshot y.revert(s).commit() # check it assert ifB not in self.ip.interfaces assert self.ifd in self.ip.interfaces assert ("172.16.0.1", 24) in self.ip.interfaces[self.ifd].ipaddr assert self.ip.interfaces[self.ifd].flags & 1 @skip_if_not_supported def _test_ipv(self, ipv, kind): require_user("root") ifA = self.get_ifname() i = self.ip.create(kind=kind, ifname=ifA).commit() if self.ip.interfaces[ifA]._mode == "explicit": self.ip.interfaces[ifA].begin() if ipv == 4: addr = "172.16.0.1/24" elif ipv == 6: addr = "fdb3:84e5:4ff4:55e4::1/64" else: raise Exception("bad IP version") i.add_ip(addr).commit() pre_target = addr.split("/") target = (pre_target[0], int(pre_target[1])) assert target in i["ipaddr"] def test_ipv4_dummy(self): self._test_ipv(4, "dummy") def test_ipv4_bond(self): self._test_ipv(4, "bond") def test_ipv4_bridge(self): self._test_ipv(4, "bridge") def test_ipv6_dummy(self): self._test_ipv(6, "dummy") def test_ipv6_bond(self): self._test_ipv(6, "bond") def test_ipv6_bridge(self): self._test_ipv(6, "bridge") @skip_if_not_supported def test_create_tuntap_fail(self): try: self.ip.create(ifname="fAiL", kind="tuntap", mode="fail").commit() except: assert not grep("ip link", pattern="fAiL") return raise Exception("tuntap create succeded") @skip_if_not_supported def test_create_tuntap(self): require_user("root") ifA = self.get_ifname() self.ip.create(ifname=ifA, kind="tuntap", mode="tap", uid=1, gid=1).commit() assert ifA in self.ip.interfaces assert grep("ip link", pattern=ifA) def test_global_create(self): require_user("root") ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, kind="dummy") self.ip.create(ifname=ifB, kind="dummy") self.ip.commit() assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces assert grep("ip link", pattern=ifA) assert grep("ip link", pattern=ifB) def test_global_priorities(self): require_user("root") ifA = self.get_ifname() ifB = self.get_ifname() ifC = self.get_ifname() a = self.ip.create(ifname=ifA, kind="dummy").commit() # if a._mode == "explicit": a.begin() # prepare transaction: two interface creations # and one failure on an existing interface a.set_address("11:22:33:44:55:66") b = self.ip.create(ifname=ifB, kind="dummy") c = self.ip.create(ifname=ifC, kind="dummy") # now assign priorities b.ipdb_priority = 15 # will be execute first a.ipdb_priority = 10 # second -- and fail c.ipdb_priority = 5 # should not be executed # prepare watchdogs wdb = self.ip.watchdog(ifname=ifB) wdc = self.ip.watchdog(ifname=ifC) # run the transaction try: self.ip.commit() except NetlinkError: pass # control system state assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces assert ifC in self.ip.interfaces assert a.ipdb_scope == "system" assert b.ipdb_scope == "create" assert c.ipdb_scope == "create" assert a.address != "11:22:33:44:55:66" assert grep("ip link", pattern=ifA) assert not grep("ip link", pattern=ifB) assert not grep("ip link", pattern=ifC) wdb.wait(1) wdc.wait(1) assert wdb.is_set assert not wdc.is_set def test_global_rollback(self): require_user("root") ifA = self.get_ifname() ifB = self.get_ifname() a = self.ip.create(ifname=ifA, kind="dummy").commit() # if a._mode == "explicit": a.begin() a.remove() b = self.ip.create(ifname=ifB, kind="dummy") b.set_mtu(1500).set_address("11:22:33:44:55:66") try: self.ip.commit() except NetlinkError: pass assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces assert b.ipdb_scope == "create" assert grep("ip link", pattern=ifA) assert not grep("ip link", pattern=ifB) def test_global_netns(self): require_user("root") ifA = self.get_ifname() ifB = self.get_ifname() ns = str(uuid.uuid4()) with IPDB(nl=NetNS(ns)) as nsdb: v1 = self.ip.create(ifname="x" + ifA, kind="veth", peer=ifA) v2 = self.ip.create(ifname="x" + ifB, kind="veth", peer=ifB) if v1._mode == "explicit": v1.begin() v2.begin() v1.net_ns_fd = ns v2.net_ns_fd = ns self.ip.commit() nsdb.interfaces["x" + ifA].ifname = "eth0" nsdb.interfaces["x" + ifB].ifname = "eth1" nsdb.commit() if self.ip.interfaces[ifA]._mode == "explicit": self.ip.interfaces[ifA].begin() self.ip.interfaces[ifB].begin() self.ip.interfaces[ifA].up() self.ip.interfaces[ifB].up() self.ip.commit() assert "x" + ifA not in self.ip.interfaces assert "x" + ifB not in self.ip.interfaces assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces assert self.ip.interfaces[ifA].flags & 1 assert self.ip.interfaces[ifB].flags & 1 if self.ip.interfaces[ifA]._mode == "explicit": self.ip.interfaces[ifA].begin() self.ip.interfaces[ifB].begin() self.ip.interfaces[ifA].remove() self.ip.interfaces[ifB].remove() self.ip.commit() netns.remove(ns) @skip_if_not_supported def test_create_veth(self): require_user("root") ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, kind="veth", peer=ifB).commit() assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces def test_create_fail(self): require_user("root") ifA = self.get_ifname() # create with mac 11:22:33:44:55:66 should fail i = self.ip.create(kind="dummy", ifname=ifA, address="11:22:33:44:55:66") try: i.commit() except NetlinkError: pass assert i._mode == "invalid" assert ifA not in self.ip.interfaces def test_create_dqn(self): require_user("root") ifA = self.get_ifname() i = self.ip.create(kind="dummy", ifname=ifA) i.add_ip("172.16.0.1/255.255.255.0") i.commit() assert ("172.16.0.1", 24) in self.ip.interfaces[ifA].ipaddr assert "172.16.0.1/24" in get_ip_addr(interface=ifA) def test_create_double_reuse(self): require_user("root") ifA = self.get_ifname() # create an interface i1 = self.ip.create(kind="dummy", ifname=ifA).commit() try: # this call should fail on the very first step: # `bala` interface already exists self.ip.create(kind="dummy", ifname=ifA) except CreateException: pass # add `reuse` keyword -- now should pass i2 = self.ip.create(kind="dummy", ifname=ifA, reuse=True).commit() # assert that we have got references to the same interface assert i1 == i2 @skip_if_not_supported def _create_double(self, kind): require_user("root") ifA = self.get_ifname() self.ip.create(kind=kind, ifname=ifA).commit() try: self.ip.create(kind=kind, ifname=ifA).commit() except CreateException: pass def test_create_double_dummy(self): self._create_double("dummy") def test_create_double_bridge(self): self._create_double("bridge") def test_create_double_bond(self): self._create_double("bond") def test_create_plain(self): require_user("root") ifA = self.get_ifname() i = self.ip.create(kind="dummy", ifname=ifA) i.add_ip("172.16.0.1/24") i.commit() assert ("172.16.0.1", 24) in self.ip.interfaces[ifA].ipaddr assert "172.16.0.1/24" in get_ip_addr(interface=ifA) def test_create_and_remove(self): require_user("root") ifA = self.get_ifname() with self.ip.create(kind="dummy", ifname=ifA) as i: i.add_ip("172.16.0.1/24") assert ("172.16.0.1", 24) in self.ip.interfaces[ifA].ipaddr assert "172.16.0.1/24" in get_ip_addr(interface=ifA) with self.ip.interfaces[ifA] as i: i.remove() assert ifA not in self.ip.interfaces def test_dqn_mask(self): require_user("root") iface = self.ip.interfaces[self.ifd] with iface as i: i.add_ip("172.16.0.1/24") i.add_ip("172.16.0.2", mask=24) i.add_ip("172.16.0.3/255.255.255.0") i.add_ip("172.16.0.4", mask="255.255.255.0") assert ("172.16.0.1", 24) in iface.ipaddr assert ("172.16.0.2", 24) in iface.ipaddr assert ("172.16.0.3", 24) in iface.ipaddr assert ("172.16.0.4", 24) in iface.ipaddr @skip_if_not_supported def test_master_cleanup_del_port(self): require_user("root") ifMname = self.get_ifname() ifPname = self.get_ifname() ifM = self.ip.create(ifname=ifMname, kind="bridge").commit() ifP = self.ip.create(ifname=ifPname, kind="dummy").commit() if self.ip.mode == "explicit": ifM.begin() ifM.add_port(ifP).commit() assert ifP.index in ifM.ports assert ifP.master == ifM.index if self.ip.mode == "explicit": ifM.begin() ifM.del_port(ifP).commit() assert ifPname in self.ip.interfaces assert ifP.index not in ifM.ports assert ifP.master is None @skip_if_not_supported def _create_master(self, kind, **kwarg): ifM = self.get_ifname() ifP1 = self.get_ifname() ifP2 = self.get_ifname() self.ip.create(kind="dummy", ifname=ifP1).commit() self.ip.create(kind="dummy", ifname=ifP2).commit() with self.ip.create(kind=kind, ifname=ifM, **kwarg) as i: i.add_port(self.ip.interfaces[ifP1]) i.add_ip("172.16.0.1/24") with self.ip.interfaces[ifM] as i: i.add_port(self.ip.interfaces[ifP2]) i.add_ip("172.16.0.2/24") assert ("172.16.0.1", 24) in self.ip.interfaces[ifM].ipaddr assert ("172.16.0.2", 24) in self.ip.interfaces[ifM].ipaddr assert "172.16.0.1/24" in get_ip_addr(interface=ifM) assert "172.16.0.2/24" in get_ip_addr(interface=ifM) assert self.ip.interfaces[ifP1].if_master == self.ip.interfaces[ifM].index assert self.ip.interfaces[ifP2].if_master == self.ip.interfaces[ifM].index with self.ip.interfaces[ifM] as i: i.del_port(self.ip.interfaces[ifP1]) i.del_port(self.ip.interfaces[ifP2]) i.del_ip("172.16.0.1/24") i.del_ip("172.16.0.2/24") assert ("172.16.0.1", 24) not in self.ip.interfaces[ifM].ipaddr assert ("172.16.0.2", 24) not in self.ip.interfaces[ifM].ipaddr assert "172.16.0.1/24" not in get_ip_addr(interface=ifM) assert "172.16.0.2/24" not in get_ip_addr(interface=ifM) assert self.ip.interfaces[ifP1].if_master is None assert self.ip.interfaces[ifP2].if_master is None def test_create_bridge(self): require_user("root") self._create_master("bridge") def test_create_bond(self): require_user("root") self._create_master("bond") def test_create_team(self): require_user("root") self._create_master("team") def test_create_bond2(self): require_user("root") self._create_master("bond", bond_mode=2) @skip_if_not_supported def _create_macvx_mode(self, kind, mode): require_user("root") ifL = self.get_ifname() ifV = self.get_ifname() ifdb = self.ip.interfaces self.ip.create(kind="dummy", ifname=ifL).commit() self.ip.create(**{"kind": kind, "link": ifdb[ifL], "ifname": ifV, "%s_mode" % kind: mode}).commit() ip2 = IPDB() ifdb = ip2.interfaces try: assert ifdb[ifV].link == ifdb[ifL].index assert ifdb[ifV]["%s_mode" % kind] == mode except Exception: raise finally: ip2.release() def test_create_macvtap_vepa(self): return self._create_macvx_mode("macvtap", "vepa") def test_create_macvtap_bridge(self): return self._create_macvx_mode("macvtap", "bridge") def test_create_macvlan_vepa(self): return self._create_macvx_mode("macvlan", "vepa") def test_create_macvlan_bridge(self): return self._create_macvx_mode("macvlan", "bridge") def test_create_utf_name(self): require_user("root") ifO = "ༀ" self.ip.create(kind="dummy", ifname=ifO).commit() assert ifO in self.ip.interfaces assert self.ip.nl.link_lookup(ifname=ifO) if self.ip.interfaces[ifO]._mode == "explicit": self.ip.interfaces[ifO].begin() self.ip.interfaces[ifO].remove().commit() @skip_if_not_supported def test_create_gre(self): require_user("root") ifL = self.get_ifname() ifV = self.get_ifname() with self.ip.create(kind="dummy", ifname=ifL) as i: i.add_ip("172.16.0.1/24") i.up() self.ip.create(kind="gre", ifname=ifV, gre_local="172.16.0.1", gre_remote="172.16.0.2", gre_ttl=16).commit() ip2 = IPDB() ifdb = ip2.interfaces try: assert ifdb[ifV].gre_local == "172.16.0.1" assert ifdb[ifV].gre_remote == "172.16.0.2" assert ifdb[ifV].gre_ttl == 16 except Exception: raise finally: ip2.release() @skip_if_not_supported def test_create_gretap(self): require_user("root") ifL = self.get_ifname() ifV = self.get_ifname() with self.ip.create(kind="dummy", ifname=ifL) as i: i.add_ip("172.16.0.1/24") i.up() self.ip.create( kind="gretap", ifname=ifV, gre_local="172.16.0.1", gre_ikey=1, gre_okey=2, gre_iflags=0x0020, gre_oflags=0x0020, gre_collect_metadata=True, gre_ttl=16, ).commit() ip2 = IPDB() ifdb = ip2.interfaces try: assert ifdb[ifV].gre_local == "172.16.0.1" assert ifdb[ifV].gre_ikey == 1 assert ifdb[ifV].gre_okey == 2 assert ifdb[ifV].gre_iflags == 0x0020 assert ifdb[ifV].gre_oflags == 0x0020 if kernel_version_ge(4, 3): assert ifdb[ifV].gre_collect_metadata assert ifdb[ifV].gre_ttl == 16 except Exception: raise finally: ip2.release() @skip_if_not_supported def test_create_vxlan(self): require_user("root") ifL = self.get_ifname() ifV = self.get_ifname() ifdb = self.ip.interfaces self.ip.create(kind="dummy", ifname=ifL).commit() self.ip.create(kind="vxlan", ifname=ifV, vxlan_link=ifdb[ifL], vxlan_id=101, vxlan_group="239.1.1.1").commit() ip2 = IPDB() ifdb = ip2.interfaces try: assert ifdb[ifV].vxlan_link == ifdb[ifL].index assert ifdb[ifV].vxlan_group == "239.1.1.1" assert ifdb[ifV].vxlan_id == 101 except Exception: raise finally: ip2.release() def test_create_vlan_by_interface(self): require_user("root") require_8021q() ifL = self.get_ifname() ifV = self.get_ifname() self.ip.create(kind="dummy", ifname=ifL).commit() self.ip.create(kind="vlan", ifname=ifV, link=self.ip.interfaces[ifL], vlan_id=101).commit() assert self.ip.interfaces[ifV].link == self.ip.interfaces[ifL].index def test_create_vlan_by_index(self): require_user("root") require_8021q() ifL = self.get_ifname() ifV = self.get_ifname() self.ip.create(kind="dummy", ifname=ifL).commit() self.ip.create(kind="vlan", ifname=ifV, link=self.ip.interfaces[ifL].index, vlan_id=101).commit() assert self.ip.interfaces[ifV].link == self.ip.interfaces[ifL].index def test_remove_secondaries(self): require_user("root") ifA = self.get_ifname() with self.ip.create(kind="dummy", ifname=ifA) as i: i.add_ip("172.16.0.1", 24) i.add_ip("172.16.0.2", 24) assert ifA in self.ip.interfaces assert ("172.16.0.1", 24) in self.ip.interfaces[ifA].ipaddr assert ("172.16.0.2", 24) in self.ip.interfaces[ifA].ipaddr assert "172.16.0.1/24" in get_ip_addr(interface=ifA) assert "172.16.0.2/24" in get_ip_addr(interface=ifA) if i._mode == "explicit": i.begin() i.del_ip("172.16.0.1", 24) i.del_ip("172.16.0.2", 24) i.commit() assert ("172.16.0.1", 24) not in self.ip.interfaces[ifA].ipaddr assert ("172.16.0.2", 24) not in self.ip.interfaces[ifA].ipaddr assert "172.16.0.1/24" not in get_ip_addr(interface=ifA) assert "172.16.0.2/24" not in get_ip_addr(interface=ifA)
class TestExplicit(object): ip = None mode = 'explicit' def setup(self): self.ifaces = [] self.ifd = self.get_ifname() create_link(self.ifd, kind='dummy') self.ip = IPDB(mode=self.mode) def get_ifname(self): ifname = uifname() self.ifaces.append(ifname) return ifname def teardown(self): for name in self.ifaces: try: # just a hardcore removal self.ip.nl.link_remove(self.ip.interfaces[name].index) except Exception: pass self.ip.release() self.ifaces = [] def test_simple(self): assert len(list(self.ip.interfaces.keys())) > 0 def test_empty_transaction(self): assert 'lo' in self.ip.interfaces with self.ip.interfaces.lo as i: assert isinstance(i.mtu, int) def test_idx_len(self): assert len(self.ip.by_name.keys()) == len(self.ip.by_index.keys()) def test_idx_set(self): assert set(self.ip.by_name.values()) == set(self.ip.by_index.values()) def test_idx_types(self): assert all(isinstance(i, int) for i in self.ip.by_index.keys()) assert all(isinstance(i, basestring) for i in self.ip.by_name.keys()) def test_addr_attributes(self): require_user('root') if1 = self.get_ifname() if2 = self.get_ifname() with self.ip.create(ifname=if1, kind='dummy') as i: # +scope host (=> broadcast == None) i.add_ip('172.16.102.1/24', scope=254) with self.ip.create(ifname=if2, kind='dummy') as i: # +broadcast (default scope == 0) i.add_ip('172.16.103.1/24', broadcast='172.16.103.128') index = self.ip.interfaces[if1]['index'] addr = self.ip.nl.get_addr(index=index)[0] assert addr['scope'] == 254 assert addr.get_attr('IFA_BROADCAST') is None index = self.ip.interfaces[if2]['index'] addr = self.ip.nl.get_addr(index=index)[0] assert addr['scope'] == 0 assert addr.get_attr('IFA_BROADCAST') == '172.16.103.128' def test_addr_loaded(self): for name in self.ip.by_name: assert len(self.ip.interfaces[name]['ipaddr']) == \ len(get_ip_addr(name)) def test_reprs(self): assert isinstance(repr(self.ip.interfaces.lo.ipaddr), basestring) assert isinstance(repr(self.ip.interfaces.lo), basestring) def test_dotkeys(self): # self.ip.lo hint for ipython assert 'lo' in dir(self.ip.interfaces) assert 'lo' in self.ip.interfaces assert self.ip.interfaces.lo == self.ip.interfaces['lo'] # create attribute self.ip.interfaces['newitem'] = True self.ip.interfaces.newattr = True self.ip.interfaces.newitem = None assert self.ip.interfaces.newitem == self.ip.interfaces['newitem'] assert self.ip.interfaces.newitem is None # delete attribute del self.ip.interfaces.newitem del self.ip.interfaces.newattr assert 'newattr' not in dir(self.ip.interfaces) @skip_if_not_supported def test_vlan_slave_bridge(self): # https://github.com/svinota/pyroute2/issues/58 # based on the code by Petr Horáček dXname = self.get_ifname() vXname = self.get_ifname() vYname = self.get_ifname() brname = self.get_ifname() require_user('root') dX = self.ip.create(ifname=dXname, kind='dummy').commit() vX = self.ip.create(ifname=vXname, kind='vlan', link=dX, vlan_id=101).commit() vY = self.ip.create(ifname=vYname, kind='vlan', link=dX, vlan_id=102).commit() with self.ip.create(ifname=brname, kind='bridge') as i: i.add_port(vX) i.add_port(vY['index']) assert vX['index'] in self.ip.interfaces[brname]['ports'] assert vY['index'] in self.ip.interfaces[brname].ports assert vX['link'] == dX['index'] assert vY['link'] == dX['index'] assert vX['master'] == self.ip.interfaces[brname]['index'] assert vY['master'] == self.ip.interfaces[brname].index def _test_commit_hook_positive(self): require_user('root') # test callback, that adds an address by itself -- # just to check the possibility def cb(interface, snapshot, transaction): self.ip.nl.addr('add', self.ip.interfaces[self.ifd].index, address='172.16.22.1', mask=24) # register callback and check CB chain length self.ip.interfaces[self.ifd].register_commit_hook(cb) assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1 # create a transaction and commit it if self.ip.interfaces[self.ifd]._mode == 'explicit': self.ip.interfaces[self.ifd].begin() self.ip.interfaces[self.ifd].add_ip('172.16.21.1/24') self.ip.interfaces[self.ifd].commit() # added address should be there assert ('172.16.21.1', 24) in \ self.ip.interfaces[self.ifd].ipaddr # and the one, added by the callback, too assert ('172.16.22.1', 24) in \ self.ip.interfaces[self.ifd].ipaddr # unregister callback self.ip.interfaces[self.ifd].unregister_commit_hook(cb) assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0 def _test_commit_hook_negative(self): require_user('root') # test exception to differentiate class CBException(Exception): pass # test callback, that always fail def cb(interface, snapshot, transaction): raise CBException() # register callback and check CB chain length self.ip.interfaces[self.ifd].register_commit_hook(cb) assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1 # create a transaction and commit it; should fail # 'cause of the callback if self.ip.interfaces[self.ifd]._mode == 'explicit': self.ip.interfaces[self.ifd].begin() self.ip.interfaces[self.ifd].add_ip('172.16.21.1/24') try: self.ip.interfaces[self.ifd].commit() except CBException: pass # added address should be removed assert ('172.16.21.1', 24) not in \ self.ip.interfaces[self.ifd].ipaddr # unregister callback self.ip.interfaces[self.ifd].unregister_commit_hook(cb) assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0 def test_review(self): assert len(self.ip.interfaces.lo._tids) == 0 if self.ip.interfaces.lo._mode == 'explicit': self.ip.interfaces.lo.begin() self.ip.interfaces.lo.add_ip('172.16.21.1/24') r = self.ip.interfaces.lo.review() assert len(r['+ipaddr']) == 1 assert len(r['-ipaddr']) == 0 assert len(r['+ports']) == 0 assert len(r['-ports']) == 0 # +/-ipaddr, +/-ports assert len([i for i in r if r[i] is not None]) == 4 self.ip.interfaces.lo.drop() def test_rename(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, kind='dummy').commit() if self.ip.interfaces[ifA]._mode == 'explicit': self.ip.interfaces[ifA].begin() self.ip.interfaces[ifA].ifname = ifB self.ip.interfaces[ifA].commit() assert ifB in self.ip.interfaces assert ifA not in self.ip.interfaces if self.ip.interfaces[ifB]._mode == 'explicit': self.ip.interfaces[ifB].begin() self.ip.interfaces[ifB].ifname = ifA self.ip.interfaces[ifB].commit() assert ifB not in self.ip.interfaces assert ifA in self.ip.interfaces def test_routes_keys(self): assert '172.16.0.0/24' not in self.ip.routes # create but not commit self.ip.routes.add(dst='172.16.0.0/24', gateway='127.0.0.1') # checks assert '172.16.0.0/24' in self.ip.routes assert '172.16.0.0/24' in list(self.ip.routes.keys()) def test_routes(self): require_user('root') assert '172.16.0.0/24' not in self.ip.routes # create a route with self.ip.routes.add({ 'dst': '172.16.0.0/24', 'gateway': '127.0.0.1' }) as r: pass assert '172.16.0.0/24' in self.ip.routes.keys() assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.1') # change the route with self.ip.routes['172.16.0.0/24'] as r: r.gateway = '127.0.0.2' assert self.ip.routes['172.16.0.0/24'].gateway == '127.0.0.2' assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.2') # delete the route with self.ip.routes['172.16.0.0/24'] as r: r.remove() assert '172.16.0.0/24' not in self.ip.routes.keys() assert not grep('ip ro', pattern='172.16.0.0/24') def test_routes_multipath_gateway(self): require_user('root') ifR = self.get_ifname() with self.ip.create(ifname=ifR, kind='dummy') as i: i.add_ip('172.16.231.1/24') i.up() r = self.ip.routes.add({ 'dst': '172.16.232.0/24', 'multipath': [{ 'gateway': '172.16.231.2', 'hops': 20 }, { 'gateway': '172.16.231.3', 'hops': 30 }, { 'gateway': '172.16.231.4' }] }) r.commit() assert grep('ip ro', pattern='172.16.232.0/24') assert grep('ip ro', pattern='nexthop.*172.16.231.2.*weight.*21') assert grep('ip ro', pattern='nexthop.*172.16.231.3.*weight.*31') assert grep('ip ro', pattern='nexthop.*172.16.231.4.*weight.*1') with self.ip.routes['172.16.232.0/24'] as r: r.add_nh({'gateway': '172.16.231.5', 'hops': 50}) r.del_nh({'gateway': '172.16.231.2'}) assert grep('ip ro', pattern='172.16.232.0/24') assert grep('ip ro', pattern='nexthop.*172.16.231.5.*weight.*51') assert grep('ip ro', pattern='nexthop.*172.16.231.3.*weight.*31') assert grep('ip ro', pattern='nexthop.*172.16.231.4.*weight.*1') def test_routes_metrics(self): require_user('root') assert '172.16.0.0/24' not in self.ip.routes.keys() # create a route self.ip.routes.add({ 'dst': '172.16.0.0/24', 'gateway': '127.0.0.1', 'metrics': { 'mtu': 1360 } }).commit() assert grep('ip ro', pattern='172.16.0.0/24.*mtu 1360') # change metrics with self.ip.routes['172.16.0.0/24'] as r: r.metrics.mtu = 1400 assert self.ip.routes['172.16.0.0/24']['metrics']['mtu'] == 1400 assert grep('ip ro', pattern='172.16.0.0/24.*mtu 1400') # delete the route with self.ip.routes['172.16.0.0/24'] as r: r.remove() assert '172.16.0.0/24' not in self.ip.routes.keys() assert not grep('ip ro', pattern='172.16.0.0/24') @skip_if_not_supported def _test_shadow(self, kind): ifA = self.get_ifname() a = self.ip.create(ifname=ifA, kind=kind).commit() if a._mode == 'explicit': a.begin() a.shadow().commit() assert ifA in self.ip.interfaces assert not grep('ip link', pattern=ifA) time.sleep(0.5) b = self.ip.create(ifname=ifA, kind=kind).commit() assert a == b assert grep('ip link', pattern=ifA) def test_shadow_bond(self): require_user('root') self._test_shadow('bond') def test_shadow_bridge(self): require_user('root') self._test_shadow('bridge') def test_shadow_dummy(self): require_user('root') self._test_shadow('dummy') def test_updown(self): require_user('root') if self.ip.interfaces[self.ifd]._mode == 'explicit': self.ip.interfaces[self.ifd].begin() self.ip.interfaces[self.ifd].up() self.ip.interfaces[self.ifd].commit() assert self.ip.interfaces[self.ifd].flags & 1 if self.ip.interfaces[self.ifd]._mode == 'explicit': self.ip.interfaces[self.ifd].begin() self.ip.interfaces[self.ifd].down() self.ip.interfaces[self.ifd].commit() assert not (self.ip.interfaces[self.ifd].flags & 1) def test_slave_data(self): require_user('root') ifBR = self.get_ifname() ifP = self.get_ifname() self.ip.debug = True bridge = self.ip.create(ifname=ifBR, kind='bridge').commit() port = self.ip.create(ifname=ifP, kind='dummy').commit() if self.ip.mode == 'explicit': bridge.begin() bridge.add_port(port) bridge.up() bridge.commit() li = port.nlmsg.get_attr('IFLA_LINKINFO') skind = li.get_attr('IFLA_INFO_SLAVE_KIND') sdata = li.get_attr('IFLA_INFO_SLAVE_DATA') self.ip.debug = False if skind is None or sdata is None: raise SkipTest('slave data not provided') assert sdata.get_attr('IFLA_BRPORT_STATE') is not None assert sdata.get_attr('IFLA_BRPORT_MODE') is not None def test_fail_ipaddr(self): require_user('root') ifA = self.get_ifname() i = self.ip.create(ifname=ifA, kind='dummy').commit() assert not len(i.ipaddr) if i._mode == 'explicit': i.begin() i.add_ip('123.456.789.1024/153') try: i.commit() except socket.error as e: if not e.args[0].startswith('illegal IP'): raise assert not len(i.ipaddr) if i._mode == 'explicit': i.begin() i.remove().commit() assert ifA not in self.ip.interfaces def test_json_dump(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() # set up the interface with self.ip.create(kind='dummy', ifname=ifA) as i: i.add_ip('172.16.0.1/24') i.add_ip('172.16.0.2/24') i.up() # make a backup backup = self.ip.interfaces[ifA].dump() assert isinstance(backup, dict) # remove index and protinfo -- make it portable del backup['index'] if 'protinfo' in backup: del backup['protinfo'] # serialize backup = json.dumps(backup) # remove the interface with self.ip.interfaces[ifA] as i: i.remove() # create again, but with different name self.ip.create(kind='dummy', ifname=ifB).commit() # load the backup # 1. prepare to the restore: bring it down with self.ip.interfaces[ifB] as i: i.down() # 2. please notice, the interface will be renamed after the backup with self.ip.interfaces[ifB] as i: i.load(json.loads(backup)) # check :) assert ifA in self.ip.interfaces assert ifB not in self.ip.interfaces assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr assert ('172.16.0.2', 24) in self.ip.interfaces[ifA].ipaddr assert self.ip.interfaces[ifA].flags & 1 def test_freeze_del(self): require_user('root') interface = self.ip.interfaces[self.ifd] # set up the interface with interface as i: i.add_ip('172.16.0.1/24') i.add_ip('172.16.1.1/24') i.up() # check assert ('172.16.0.1', 24) in interface.ipaddr assert ('172.16.1.1', 24) in interface.ipaddr assert interface.flags & 1 interface.freeze() # delete interface with an external routine remove_link(interface.ifname) # wait for a second time.sleep(1) # check if it is back ipdb = IPDB() try: ifc = ipdb.interfaces[self.ifd] assert ('172.16.0.1', 24) in ifc.ipaddr assert ('172.16.1.1', 24) in ifc.ipaddr assert ifc.flags & 1 except: raise finally: interface.unfreeze() ipdb.release() def test_freeze(self): require_user('root') interface = self.ip.interfaces[self.ifd] # set up the interface with interface as i: i.add_ip('172.16.0.1/24') i.add_ip('172.16.1.1/24') i.up() # check assert ('172.16.0.1', 24) in interface.ipaddr assert ('172.16.1.1', 24) in interface.ipaddr assert interface.flags & 1 # assert routine def probe(): # The freeze results are dynamic: it is not a real freeze, # it is a restore routine. So it takes time for results # to stabilize err = None for _ in range(3): err = None interface.ipaddr.set_target( (('172.16.0.1', 24), ('172.16.1.1', 24))) interface.ipaddr.target.wait() try: assert ('172.16.0.1', 24) in interface.ipaddr assert ('172.16.1.1', 24) in interface.ipaddr assert interface.flags & 1 break except AssertionError as e: err = e continue except Exception as e: err = e break if err is not None: interface.unfreeze() i2.close() raise err # freeze interface.freeze() # change the interface somehow i2 = IPRoute() i2.addr('delete', interface.index, '172.16.0.1', 24) i2.addr('delete', interface.index, '172.16.1.1', 24) probe() # unfreeze self.ip.interfaces[self.ifd].unfreeze() try: i2.addr('delete', interface.index, '172.16.0.1', 24) i2.addr('delete', interface.index, '172.16.1.1', 24) except: pass finally: i2.close() # should be up, but w/o addresses interface.ipaddr.set_target(set()) interface.ipaddr.target.wait(3) assert ('172.16.0.1', 24) not in self.ip.interfaces[self.ifd].ipaddr assert ('172.16.1.1', 24) not in self.ip.interfaces[self.ifd].ipaddr assert self.ip.interfaces[self.ifd].flags & 1 def test_snapshots(self): require_user('root') ifB = self.get_ifname() # set up the interface with self.ip.interfaces[self.ifd] as i: i.add_ip('172.16.0.1/24') i.up() # check it assert ('172.16.0.1', 24) in self.ip.interfaces[self.ifd].ipaddr assert self.ip.interfaces[self.ifd].flags & 1 # make a snapshot s = self.ip.interfaces[self.ifd].snapshot() i = self.ip.interfaces[self.ifd] # check it assert i.last_snapshot_id() == s # unset the interface with self.ip.interfaces[self.ifd] as i: i.del_ip('172.16.0.1/24') i.down() # we can not rename the interface while it is up, # so do it in two turns with self.ip.interfaces[self.ifd] as i: i.ifname = ifB # check it assert ifB in self.ip.interfaces assert self.ifd not in self.ip.interfaces y = self.ip.interfaces[ifB] assert i == y assert ('172.16.0.1', 24) not in y.ipaddr assert not (y.flags & 1) # revert snapshot y.revert(s).commit() # check it assert ifB not in self.ip.interfaces assert self.ifd in self.ip.interfaces assert ('172.16.0.1', 24) in self.ip.interfaces[self.ifd].ipaddr assert self.ip.interfaces[self.ifd].flags & 1 @skip_if_not_supported def _test_ipv(self, ipv, kind): require_user('root') ifA = self.get_ifname() i = self.ip.create(kind=kind, ifname=ifA).commit() if self.ip.interfaces[ifA]._mode == 'explicit': self.ip.interfaces[ifA].begin() if ipv == 4: addr = '172.16.0.1/24' elif ipv == 6: addr = 'fdb3:84e5:4ff4:55e4::1/64' else: raise Exception('bad IP version') i.add_ip(addr).commit() pre_target = addr.split('/') target = (pre_target[0], int(pre_target[1])) assert target in i['ipaddr'] def test_ipv4_dummy(self): self._test_ipv(4, 'dummy') def test_ipv4_bond(self): self._test_ipv(4, 'bond') def test_ipv4_bridge(self): self._test_ipv(4, 'bridge') def test_ipv6_dummy(self): self._test_ipv(6, 'dummy') def test_ipv6_bond(self): self._test_ipv(6, 'bond') def test_ipv6_bridge(self): self._test_ipv(6, 'bridge') @skip_if_not_supported def test_create_tuntap_fail(self): try: self.ip.create(ifname='fAiL', kind='tuntap', mode='fail').commit() except: assert not grep('ip link', pattern='fAiL') return raise Exception('tuntap create succeded') @skip_if_not_supported def test_create_tuntap(self): require_user('root') ifA = self.get_ifname() self.ip.create(ifname=ifA, kind='tuntap', mode='tap', uid=1, gid=1).commit() assert ifA in self.ip.interfaces assert grep('ip link', pattern=ifA) @skip_if_not_supported def test_ovs_kind_aliases(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, kind='ovs-bridge').commit() self.ip.create(ifname=ifB, kind='openvswitch').commit() assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces assert grep('ip link', pattern=ifA) assert grep('ip link', pattern=ifB) @skip_if_not_supported def test_ovs_add_remove_port(self): require_user('root') ifOVS = self.get_ifname() self.ip.create(ifname=ifOVS, kind='ovs-bridge').commit() ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, kind='dummy') self.ip.create(ifname=ifB, peer='x' + ifB, kind='veth') self.ip.commit() # add ports if self.ip.mode == 'explicit': self.ip.interfaces[ifOVS].begin() self.ip.interfaces[ifOVS].\ add_port(self.ip.interfaces[ifA]).\ add_port(self.ip.interfaces[ifB]).\ commit() # assert self.ip.interfaces[ifA].master == \ self.ip.interfaces[ifOVS].index assert self.ip.interfaces[ifB].master == \ self.ip.interfaces[ifOVS].index assert self.ip.interfaces[ifA].index in \ self.ip.interfaces[ifOVS].ports assert self.ip.interfaces[ifB].index in \ self.ip.interfaces[ifOVS].ports # remove ports if self.ip.mode == 'explicit': self.ip.interfaces[ifOVS].begin() self.ip.interfaces[ifOVS].\ del_port(self.ip.interfaces[ifA]).\ del_port(self.ip.interfaces[ifB]).\ commit() # assert self.ip.interfaces[ifA].get('master') is None assert self.ip.interfaces[ifB].get('master') is None assert not self.ip.interfaces[ifOVS].ports def test_global_create(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, kind='dummy') self.ip.create(ifname=ifB, kind='dummy') self.ip.commit() assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces assert grep('ip link', pattern=ifA) assert grep('ip link', pattern=ifB) def test_global_priorities(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() ifC = self.get_ifname() a = self.ip.create(ifname=ifA, kind='dummy').commit() # if a._mode == 'explicit': a.begin() # prepare transaction: two interface creations # and one failure on an existing interface a.set_address('11:22:33:44:55:66') b = self.ip.create(ifname=ifB, kind='dummy') c = self.ip.create(ifname=ifC, kind='dummy') # now assign priorities b.ipdb_priority = 15 # will be execute first a.ipdb_priority = 10 # second -- and fail c.ipdb_priority = 5 # should not be executed # prepare watchdogs wdb = self.ip.watchdog(ifname=ifB) wdc = self.ip.watchdog(ifname=ifC) # run the transaction try: self.ip.commit() except NetlinkError: pass # control system state assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces assert ifC in self.ip.interfaces assert a.ipdb_scope == 'system' assert b.ipdb_scope == 'create' assert c.ipdb_scope == 'create' assert a.address != '11:22:33:44:55:66' assert grep('ip link', pattern=ifA) assert not grep('ip link', pattern=ifB) assert not grep('ip link', pattern=ifC) wdb.wait(1) wdc.wait(1) assert wdb.is_set assert not wdc.is_set def test_global_veth(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, peer=ifB, kind='veth') self.ip.commit() assert self.ip.interfaces[ifA]['ipdb_scope'] == 'system' assert self.ip.interfaces[ifB]['ipdb_scope'] == 'system' if self.ip.mode == 'explicit': self.ip.interfaces[ifA].begin() self.ip.interfaces[ifB].begin() self.ip.interfaces[ifA].remove() self.ip.interfaces[ifB].remove() self.ip.commit() assert ifA not in self.ip.interfaces assert ifB not in self.ip.interfaces def test_global_rollback(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() a = self.ip.create(ifname=ifA, kind='dummy').commit() # if a._mode == 'explicit': a.begin() a.remove() b = self.ip.create(ifname=ifB, kind='dummy') b.set_mtu(1500).set_address('11:22:33:44:55:66') try: self.ip.commit() except NetlinkError: pass assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces assert b.ipdb_scope == 'create' assert grep('ip link', pattern=ifA) assert not grep('ip link', pattern=ifB) def test_global_netns(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() ns = str(uuid.uuid4()) with IPDB(nl=NetNS(ns)) as nsdb: v1 = self.ip.create(ifname='x' + ifA, kind='veth', peer=ifA) v2 = self.ip.create(ifname='x' + ifB, kind='veth', peer=ifB) if v1._mode == 'explicit': v1.begin() v2.begin() v1.net_ns_fd = ns v2.net_ns_fd = ns self.ip.commit() nsdb.interfaces['x' + ifA].ifname = 'eth0' nsdb.interfaces['x' + ifB].ifname = 'eth1' nsdb.commit() if self.ip.interfaces[ifA]._mode == 'explicit': self.ip.interfaces[ifA].begin() self.ip.interfaces[ifB].begin() self.ip.interfaces[ifA].up() self.ip.interfaces[ifB].up() self.ip.commit() assert 'x' + ifA not in self.ip.interfaces assert 'x' + ifB not in self.ip.interfaces assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces assert self.ip.interfaces[ifA].flags & 1 assert self.ip.interfaces[ifB].flags & 1 if self.ip.interfaces[ifA]._mode == 'explicit': self.ip.interfaces[ifA].begin() self.ip.interfaces[ifB].begin() self.ip.interfaces[ifA].remove() self.ip.interfaces[ifB].remove() self.ip.commit() netns.remove(ns) @skip_if_not_supported def test_create_veth(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, kind='veth', peer=ifB).commit() assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces def test_create_fail(self): require_user('root') ifA = self.get_ifname() # create with mac 11:22:33:44:55:66 should fail i = self.ip.create(kind='dummy', ifname=ifA, address='11:22:33:44:55:66') try: i.commit() except NetlinkError: pass assert i._mode == 'invalid' assert ifA not in self.ip.interfaces def test_create_dqn(self): require_user('root') ifA = self.get_ifname() i = self.ip.create(kind='dummy', ifname=ifA) i.add_ip('172.16.0.1/255.255.255.0') i.commit() assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr assert '172.16.0.1/24' in get_ip_addr(interface=ifA) def test_create_double_reuse(self): require_user('root') ifA = self.get_ifname() # create an interface i1 = self.ip.create(kind='dummy', ifname=ifA).commit() try: # this call should fail on the very first step: # `bala` interface already exists self.ip.create(kind='dummy', ifname=ifA) except CreateException: pass # add `reuse` keyword -- now should pass i2 = self.ip.create(kind='dummy', ifname=ifA, reuse=True).commit() # assert that we have got references to the same interface assert i1 == i2 @skip_if_not_supported def _create_double(self, kind): require_user('root') ifA = self.get_ifname() self.ip.create(kind=kind, ifname=ifA).commit() try: self.ip.create(kind=kind, ifname=ifA).commit() except CreateException: pass def test_create_double_dummy(self): self._create_double('dummy') def test_create_double_bridge(self): self._create_double('bridge') def test_create_double_bond(self): self._create_double('bond') def test_create_plain(self): require_user('root') ifA = self.get_ifname() i = self.ip.create(kind='dummy', ifname=ifA) i.add_ip('172.16.0.1/24') i.commit() assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr assert '172.16.0.1/24' in get_ip_addr(interface=ifA) def test_create_and_remove(self): require_user('root') ifA = self.get_ifname() with self.ip.create(kind='dummy', ifname=ifA) as i: i.add_ip('172.16.0.1/24') assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr assert '172.16.0.1/24' in get_ip_addr(interface=ifA) with self.ip.interfaces[ifA] as i: i.remove() assert ifA not in self.ip.interfaces def test_dqn_mask(self): require_user('root') iface = self.ip.interfaces[self.ifd] with iface as i: i.add_ip('172.16.0.1/24') i.add_ip('172.16.0.2', mask=24) i.add_ip('172.16.0.3/255.255.255.0') i.add_ip('172.16.0.4', mask='255.255.255.0') assert ('172.16.0.1', 24) in iface.ipaddr assert ('172.16.0.2', 24) in iface.ipaddr assert ('172.16.0.3', 24) in iface.ipaddr assert ('172.16.0.4', 24) in iface.ipaddr @skip_if_not_supported def _create_master(self, kind, **kwarg): ifM = self.get_ifname() ifP1 = self.get_ifname() ifP2 = self.get_ifname() self.ip.create(kind='dummy', ifname=ifP1).commit() self.ip.create(kind='dummy', ifname=ifP2).commit() with self.ip.create(kind=kind, ifname=ifM, **kwarg) as i: i.add_port(self.ip.interfaces[ifP1]) i.add_ip('172.16.0.1/24') with self.ip.interfaces[ifM] as i: i.add_port(self.ip.interfaces[ifP2]) i.add_ip('172.16.0.2/24') assert ('172.16.0.1', 24) in self.ip.interfaces[ifM].ipaddr assert ('172.16.0.2', 24) in self.ip.interfaces[ifM].ipaddr assert '172.16.0.1/24' in get_ip_addr(interface=ifM) assert '172.16.0.2/24' in get_ip_addr(interface=ifM) assert self.ip.interfaces[ifP1].if_master == \ self.ip.interfaces[ifM].index assert self.ip.interfaces[ifP2].if_master == \ self.ip.interfaces[ifM].index with self.ip.interfaces[ifM] as i: i.del_port(self.ip.interfaces[ifP1]) i.del_port(self.ip.interfaces[ifP2]) i.del_ip('172.16.0.1/24') i.del_ip('172.16.0.2/24') assert ('172.16.0.1', 24) not in self.ip.interfaces[ifM].ipaddr assert ('172.16.0.2', 24) not in self.ip.interfaces[ifM].ipaddr assert '172.16.0.1/24' not in get_ip_addr(interface=ifM) assert '172.16.0.2/24' not in get_ip_addr(interface=ifM) assert self.ip.interfaces[ifP1].if_master is None assert self.ip.interfaces[ifP2].if_master is None def test_create_bridge(self): require_user('root') self._create_master('bridge') def test_create_bond(self): require_user('root') self._create_master('bond') def test_create_team(self): require_user('root') self._create_master('team') def test_create_ovs(self): require_user('root') self._create_master('openvswitch') def test_create_bond2(self): require_user('root') self._create_master('bond', bond_mode=2) @skip_if_not_supported def _create_macvx_mode(self, kind, mode): require_user('root') ifL = self.get_ifname() ifV = self.get_ifname() ifdb = self.ip.interfaces self.ip.create(kind='dummy', ifname=ifL).commit() self.ip.create(**{ 'kind': kind, 'link': ifdb[ifL], 'ifname': ifV, '%s_mode' % kind: mode }).commit() ip2 = IPDB() ifdb = ip2.interfaces try: assert ifdb[ifV].link == ifdb[ifL].index assert ifdb[ifV]['%s_mode' % kind] == mode except Exception: raise finally: ip2.release() def test_create_macvtap_vepa(self): return self._create_macvx_mode('macvtap', 'vepa') def test_create_macvtap_bridge(self): return self._create_macvx_mode('macvtap', 'bridge') def test_create_macvlan_vepa(self): return self._create_macvx_mode('macvlan', 'vepa') def test_create_macvlan_bridge(self): return self._create_macvx_mode('macvlan', 'bridge') def test_create_utf_name(self): require_user('root') ifO = 'ༀ' self.ip.create(kind='dummy', ifname=ifO).commit() assert ifO in self.ip.interfaces assert self.ip.nl.link_lookup(ifname=ifO) if self.ip.interfaces[ifO]._mode == 'explicit': self.ip.interfaces[ifO].begin() self.ip.interfaces[ifO].remove().commit() @skip_if_not_supported def test_create_gre(self): require_user('root') ifL = self.get_ifname() ifV = self.get_ifname() with self.ip.create(kind='dummy', ifname=ifL) as i: i.add_ip('172.16.0.1/24') i.up() self.ip.create(kind='gre', ifname=ifV, gre_local='172.16.0.1', gre_remote='172.16.0.2', gre_ttl=16).commit() ip2 = IPDB() ifdb = ip2.interfaces try: assert ifdb[ifV].gre_local == '172.16.0.1' assert ifdb[ifV].gre_remote == '172.16.0.2' assert ifdb[ifV].gre_ttl == 16 except Exception: raise finally: ip2.release() @skip_if_not_supported def test_create_vxlan(self): require_user('root') ifL = self.get_ifname() ifV = self.get_ifname() ifdb = self.ip.interfaces self.ip.create(kind='dummy', ifname=ifL).commit() self.ip.create(kind='vxlan', ifname=ifV, vxlan_link=ifdb[ifL], vxlan_id=101, vxlan_group='239.1.1.1').commit() ip2 = IPDB() ifdb = ip2.interfaces try: assert ifdb[ifV].vxlan_link == ifdb[ifL].index assert ifdb[ifV].vxlan_group == '239.1.1.1' assert ifdb[ifV].vxlan_id == 101 except Exception: raise finally: ip2.release() def test_create_vlan_by_interface(self): require_user('root') require_8021q() ifL = self.get_ifname() ifV = self.get_ifname() self.ip.create(kind='dummy', ifname=ifL).commit() self.ip.create(kind='vlan', ifname=ifV, link=self.ip.interfaces[ifL], vlan_id=101).commit() assert self.ip.interfaces[ifV].link == \ self.ip.interfaces[ifL].index def test_create_vlan_by_index(self): require_user('root') require_8021q() ifL = self.get_ifname() ifV = self.get_ifname() self.ip.create(kind='dummy', ifname=ifL).commit() self.ip.create(kind='vlan', ifname=ifV, link=self.ip.interfaces[ifL].index, vlan_id=101).commit() assert self.ip.interfaces[ifV].link == \ self.ip.interfaces[ifL].index def test_remove_secondaries(self): require_user('root') ifA = self.get_ifname() with self.ip.create(kind='dummy', ifname=ifA) as i: i.add_ip('172.16.0.1', 24) i.add_ip('172.16.0.2', 24) assert ifA in self.ip.interfaces assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr assert ('172.16.0.2', 24) in self.ip.interfaces[ifA].ipaddr assert '172.16.0.1/24' in get_ip_addr(interface=ifA) assert '172.16.0.2/24' in get_ip_addr(interface=ifA) if i._mode == 'explicit': i.begin() i.del_ip('172.16.0.1', 24) i.del_ip('172.16.0.2', 24) i.commit() assert ('172.16.0.1', 24) not in self.ip.interfaces[ifA].ipaddr assert ('172.16.0.2', 24) not in self.ip.interfaces[ifA].ipaddr assert '172.16.0.1/24' not in get_ip_addr(interface=ifA) assert '172.16.0.2/24' not in get_ip_addr(interface=ifA)
if action == 'RTM_NEWLINK' and \ msg.get_attr('IFLA_IFNAME', '').startswith('bala_port'): # get corresponding interface -- in the case of # post-callbacks it is created already interface = ipdb.interfaces[msg['index']] # add it as a port to the bridge ipdb.interfaces.br0.add_port(interface) try: ipdb.interfaces.br0.commit() except Exception: pass # create IPDB instance ip = IPDB() # create watchdogs wd0 = ip.watchdog(ifname='br0') wd1 = ip.watchdog(ifname='bala_port0') wd2 = ip.watchdog(ifname='bala_port1') # create bridge ip.create(kind='bridge', ifname='br0').commit() # wait the bridge to be created wd0.wait() # register callback ip.register_callback(cb) # create ports ip.create(kind='dummy', ifname='bala_port0').commit() ip.create(kind='dummy', ifname='bala_port1').commit() # sleep for interfaces wd1.wait() wd2.wait()
class TestExplicit(object): ip = None mode = 'explicit' def setup(self): self.ifaces = [] self.ifd = self.get_ifname() create_link(self.ifd, kind='dummy') self.ip = IPDB(mode=self.mode) def get_ifname(self): ifname = uifname() self.ifaces.append(ifname) return ifname def teardown(self): for name in self.ifaces: try: # just a hardcore removal self.ip.nl.link_remove(self.ip.interfaces[name].index) except Exception: pass self.ip.release() self.ifaces = [] def test_simple(self): assert len(list(self.ip.interfaces.keys())) > 0 def test_empty_transaction(self): assert 'lo' in self.ip.interfaces with self.ip.interfaces.lo as i: assert isinstance(i.mtu, int) def test_idx_len(self): assert len(self.ip.by_name.keys()) == len(self.ip.by_index.keys()) def test_idx_set(self): assert set(self.ip.by_name.values()) == set(self.ip.by_index.values()) def test_idx_types(self): assert all(isinstance(i, int) for i in self.ip.by_index.keys()) assert all(isinstance(i, basestring) for i in self.ip.by_name.keys()) def test_addr_attributes(self): require_user('root') if1 = self.get_ifname() if2 = self.get_ifname() with self.ip.create(ifname=if1, kind='dummy') as i: # +scope host (=> broadcast == None) i.add_ip('172.16.102.1/24', scope=254) with self.ip.create(ifname=if2, kind='dummy') as i: # +broadcast (default scope == 0) i.add_ip('172.16.103.1/24', broadcast='172.16.103.128') index = self.ip.interfaces[if1]['index'] addr = self.ip.nl.get_addr(index=index)[0] assert addr['scope'] == 254 assert addr.get_attr('IFA_BROADCAST') is None index = self.ip.interfaces[if2]['index'] addr = self.ip.nl.get_addr(index=index)[0] assert addr['scope'] == 0 assert addr.get_attr('IFA_BROADCAST') == '172.16.103.128' def test_addr_loaded(self): for name in self.ip.by_name: assert len(self.ip.interfaces[name]['ipaddr']) == \ len(get_ip_addr(name)) def test_reprs(self): assert isinstance(repr(self.ip.interfaces.lo.ipaddr), basestring) assert isinstance(repr(self.ip.interfaces.lo), basestring) def test_dotkeys(self): # self.ip.lo hint for ipython assert 'lo' in dir(self.ip.interfaces) assert 'lo' in self.ip.interfaces assert self.ip.interfaces.lo == self.ip.interfaces['lo'] # create attribute self.ip.interfaces['newitem'] = True self.ip.interfaces.newattr = True self.ip.interfaces.newitem = None assert self.ip.interfaces.newitem == self.ip.interfaces['newitem'] assert self.ip.interfaces.newitem is None # delete attribute del self.ip.interfaces.newitem del self.ip.interfaces.newattr assert 'newattr' not in dir(self.ip.interfaces) @skip_if_not_supported def test_vlan_slave_bridge(self): # https://github.com/svinota/pyroute2/issues/58 # based on the code by Petr Horáček dXname = self.get_ifname() vXname = self.get_ifname() vYname = self.get_ifname() brname = self.get_ifname() require_user('root') dX = self.ip.create(ifname=dXname, kind='dummy').commit() vX = self.ip.create(ifname=vXname, kind='vlan', link=dX, vlan_id=101).commit() vY = self.ip.create(ifname=vYname, kind='vlan', link=dX, vlan_id=102).commit() with self.ip.create(ifname=brname, kind='bridge') as i: i.add_port(vX) i.add_port(vY['index']) assert vX['index'] in self.ip.interfaces[brname]['ports'] assert vY['index'] in self.ip.interfaces[brname].ports assert vX['link'] == dX['index'] assert vY['link'] == dX['index'] assert vX['master'] == self.ip.interfaces[brname]['index'] assert vY['master'] == self.ip.interfaces[brname].index def _test_commit_hook_positive(self): require_user('root') # test callback, that adds an address by itself -- # just to check the possibility def cb(interface, snapshot, transaction): self.ip.nl.addr('add', self.ip.interfaces[self.ifd].index, address='172.16.22.1', mask=24) # register callback and check CB chain length self.ip.interfaces[self.ifd].register_commit_hook(cb) assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1 # create a transaction and commit it if self.ip.interfaces[self.ifd]._mode == 'explicit': self.ip.interfaces[self.ifd].begin() self.ip.interfaces[self.ifd].add_ip('172.16.21.1/24') self.ip.interfaces[self.ifd].commit() # added address should be there assert ('172.16.21.1', 24) in \ self.ip.interfaces[self.ifd].ipaddr # and the one, added by the callback, too assert ('172.16.22.1', 24) in \ self.ip.interfaces[self.ifd].ipaddr # unregister callback self.ip.interfaces[self.ifd].unregister_commit_hook(cb) assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0 def _test_commit_hook_negative(self): require_user('root') # test exception to differentiate class CBException(Exception): pass # test callback, that always fail def cb(interface, snapshot, transaction): raise CBException() # register callback and check CB chain length self.ip.interfaces[self.ifd].register_commit_hook(cb) assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 1 # create a transaction and commit it; should fail # 'cause of the callback if self.ip.interfaces[self.ifd]._mode == 'explicit': self.ip.interfaces[self.ifd].begin() self.ip.interfaces[self.ifd].add_ip('172.16.21.1/24') try: self.ip.interfaces[self.ifd].commit() except CBException: pass # added address should be removed assert ('172.16.21.1', 24) not in \ self.ip.interfaces[self.ifd].ipaddr # unregister callback self.ip.interfaces[self.ifd].unregister_commit_hook(cb) assert len(self.ip.interfaces[self.ifd]._commit_hooks) == 0 def test_review(self): assert len(self.ip.interfaces.lo._tids) == 0 if self.ip.interfaces.lo._mode == 'explicit': self.ip.interfaces.lo.begin() self.ip.interfaces.lo.add_ip('172.16.21.1/24') r = self.ip.interfaces.lo.review() assert len(r['+ipaddr']) == 1 assert len(r['-ipaddr']) == 0 assert len(r['+ports']) == 0 assert len(r['-ports']) == 0 # +/-ipaddr, +/-ports assert len([i for i in r if r[i] is not None]) == 4 self.ip.interfaces.lo.drop() def test_rename(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, kind='dummy').commit() if self.ip.interfaces[ifA]._mode == 'explicit': self.ip.interfaces[ifA].begin() self.ip.interfaces[ifA].ifname = ifB self.ip.interfaces[ifA].commit() assert ifB in self.ip.interfaces assert ifA not in self.ip.interfaces if self.ip.interfaces[ifB]._mode == 'explicit': self.ip.interfaces[ifB].begin() self.ip.interfaces[ifB].ifname = ifA self.ip.interfaces[ifB].commit() assert ifB not in self.ip.interfaces assert ifA in self.ip.interfaces def test_routes_keys(self): assert '172.16.0.0/24' not in self.ip.routes # create but not commit self.ip.routes.add(dst='172.16.0.0/24', gateway='127.0.0.1') # checks assert '172.16.0.0/24' in self.ip.routes assert '172.16.0.0/24' in list(self.ip.routes.keys()) def test_routes(self): require_user('root') assert '172.16.0.0/24' not in self.ip.routes # create a route with self.ip.routes.add({'dst': '172.16.0.0/24', 'gateway': '127.0.0.1'}) as r: pass assert '172.16.0.0/24' in self.ip.routes.keys() assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.1') # change the route with self.ip.routes['172.16.0.0/24'] as r: r.gateway = '127.0.0.2' assert self.ip.routes['172.16.0.0/24'].gateway == '127.0.0.2' assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.2') # delete the route with self.ip.routes['172.16.0.0/24'] as r: r.remove() assert '172.16.0.0/24' not in self.ip.routes.keys() assert not grep('ip ro', pattern='172.16.0.0/24') def test_routes_multipath_gateway(self): require_user('root') ifR = self.get_ifname() with self.ip.create(ifname=ifR, kind='dummy') as i: i.add_ip('172.16.231.1/24') i.up() r = self.ip.routes.add({'dst': '172.16.232.0/24', 'multipath': [{'gateway': '172.16.231.2', 'hops': 20}, {'gateway': '172.16.231.3', 'hops': 30}, {'gateway': '172.16.231.4'}]}) r.commit() assert grep('ip ro', pattern='172.16.232.0/24') assert grep('ip ro', pattern='nexthop.*172.16.231.2.*weight.*21') assert grep('ip ro', pattern='nexthop.*172.16.231.3.*weight.*31') assert grep('ip ro', pattern='nexthop.*172.16.231.4.*weight.*1') with self.ip.routes['172.16.232.0/24'] as r: r.add_nh({'gateway': '172.16.231.5', 'hops': 50}) r.del_nh({'gateway': '172.16.231.2'}) assert grep('ip ro', pattern='172.16.232.0/24') assert grep('ip ro', pattern='nexthop.*172.16.231.5.*weight.*51') assert grep('ip ro', pattern='nexthop.*172.16.231.3.*weight.*31') assert grep('ip ro', pattern='nexthop.*172.16.231.4.*weight.*1') def test_routes_metrics(self): require_user('root') assert '172.16.0.0/24' not in self.ip.routes.keys() # create a route self.ip.routes.add({'dst': '172.16.0.0/24', 'gateway': '127.0.0.1', 'metrics': {'mtu': 1360}}).commit() assert grep('ip ro', pattern='172.16.0.0/24.*mtu 1360') # change metrics with self.ip.routes['172.16.0.0/24'] as r: r.metrics.mtu = 1400 assert self.ip.routes['172.16.0.0/24']['metrics']['mtu'] == 1400 assert grep('ip ro', pattern='172.16.0.0/24.*mtu 1400') # delete the route with self.ip.routes['172.16.0.0/24'] as r: r.remove() assert '172.16.0.0/24' not in self.ip.routes.keys() assert not grep('ip ro', pattern='172.16.0.0/24') @skip_if_not_supported def _test_shadow(self, kind): ifA = self.get_ifname() a = self.ip.create(ifname=ifA, kind=kind).commit() if a._mode == 'explicit': a.begin() a.shadow().commit() assert ifA in self.ip.interfaces assert not grep('ip link', pattern=ifA) time.sleep(0.5) b = self.ip.create(ifname=ifA, kind=kind).commit() assert a == b assert grep('ip link', pattern=ifA) def test_shadow_bond(self): require_user('root') self._test_shadow('bond') def test_shadow_bridge(self): require_user('root') self._test_shadow('bridge') def test_shadow_dummy(self): require_user('root') self._test_shadow('dummy') def test_updown(self): require_user('root') if self.ip.interfaces[self.ifd]._mode == 'explicit': self.ip.interfaces[self.ifd].begin() self.ip.interfaces[self.ifd].up() self.ip.interfaces[self.ifd].commit() assert self.ip.interfaces[self.ifd].flags & 1 if self.ip.interfaces[self.ifd]._mode == 'explicit': self.ip.interfaces[self.ifd].begin() self.ip.interfaces[self.ifd].down() self.ip.interfaces[self.ifd].commit() assert not (self.ip.interfaces[self.ifd].flags & 1) def test_slave_data(self): require_user('root') ifBR = self.get_ifname() ifP = self.get_ifname() self.ip.debug = True bridge = self.ip.create(ifname=ifBR, kind='bridge').commit() port = self.ip.create(ifname=ifP, kind='dummy').commit() if self.ip.mode == 'explicit': bridge.begin() bridge.add_port(port) bridge.up() bridge.commit() li = port.nlmsg.get_attr('IFLA_LINKINFO') skind = li.get_attr('IFLA_INFO_SLAVE_KIND') sdata = li.get_attr('IFLA_INFO_SLAVE_DATA') self.ip.debug = False if skind is None or sdata is None: raise SkipTest('slave data not provided') assert sdata.get_attr('IFLA_BRPORT_STATE') is not None assert sdata.get_attr('IFLA_BRPORT_MODE') is not None def test_fail_ipaddr(self): require_user('root') ifA = self.get_ifname() i = self.ip.create(ifname=ifA, kind='dummy').commit() assert not len(i.ipaddr) if i._mode == 'explicit': i.begin() i.add_ip('123.456.789.1024/153') try: i.commit() except socket.error as e: if not e.args[0].startswith('illegal IP'): raise assert not len(i.ipaddr) if i._mode == 'explicit': i.begin() i.remove().commit() assert ifA not in self.ip.interfaces def test_json_dump(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() # set up the interface with self.ip.create(kind='dummy', ifname=ifA) as i: i.add_ip('172.16.0.1/24') i.add_ip('172.16.0.2/24') i.up() # make a backup backup = self.ip.interfaces[ifA].dump() assert isinstance(backup, dict) # remove index and protinfo -- make it portable del backup['index'] if 'protinfo' in backup: del backup['protinfo'] # serialize backup = json.dumps(backup) # remove the interface with self.ip.interfaces[ifA] as i: i.remove() # create again, but with different name self.ip.create(kind='dummy', ifname=ifB).commit() # load the backup # 1. prepare to the restore: bring it down with self.ip.interfaces[ifB] as i: i.down() # 2. please notice, the interface will be renamed after the backup with self.ip.interfaces[ifB] as i: i.load(json.loads(backup)) # check :) assert ifA in self.ip.interfaces assert ifB not in self.ip.interfaces assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr assert ('172.16.0.2', 24) in self.ip.interfaces[ifA].ipaddr assert self.ip.interfaces[ifA].flags & 1 def test_freeze_del(self): require_user('root') interface = self.ip.interfaces[self.ifd] # set up the interface with interface as i: i.add_ip('172.16.0.1/24') i.add_ip('172.16.1.1/24') i.up() # check assert ('172.16.0.1', 24) in interface.ipaddr assert ('172.16.1.1', 24) in interface.ipaddr assert interface.flags & 1 interface.freeze() # delete interface with an external routine remove_link(interface.ifname) # wait for a second time.sleep(1) # check if it is back ipdb = IPDB() try: ifc = ipdb.interfaces[self.ifd] assert ('172.16.0.1', 24) in ifc.ipaddr assert ('172.16.1.1', 24) in ifc.ipaddr assert ifc.flags & 1 except: raise finally: interface.unfreeze() ipdb.release() def test_freeze(self): require_user('root') interface = self.ip.interfaces[self.ifd] # set up the interface with interface as i: i.add_ip('172.16.0.1/24') i.add_ip('172.16.1.1/24') i.up() # check assert ('172.16.0.1', 24) in interface.ipaddr assert ('172.16.1.1', 24) in interface.ipaddr assert interface.flags & 1 # assert routine def probe(): # The freeze results are dynamic: it is not a real freeze, # it is a restore routine. So it takes time for results # to stabilize err = None for _ in range(3): err = None interface.ipaddr.set_target((('172.16.0.1', 24), ('172.16.1.1', 24))) interface.ipaddr.target.wait() try: assert ('172.16.0.1', 24) in interface.ipaddr assert ('172.16.1.1', 24) in interface.ipaddr assert interface.flags & 1 break except AssertionError as e: err = e continue except Exception as e: err = e break if err is not None: interface.unfreeze() i2.close() raise err # freeze interface.freeze() # change the interface somehow i2 = IPRoute() i2.addr('delete', interface.index, '172.16.0.1', 24) i2.addr('delete', interface.index, '172.16.1.1', 24) probe() # unfreeze self.ip.interfaces[self.ifd].unfreeze() try: i2.addr('delete', interface.index, '172.16.0.1', 24) i2.addr('delete', interface.index, '172.16.1.1', 24) except: pass finally: i2.close() # should be up, but w/o addresses interface.ipaddr.set_target(set()) interface.ipaddr.target.wait(3) assert ('172.16.0.1', 24) not in self.ip.interfaces[self.ifd].ipaddr assert ('172.16.1.1', 24) not in self.ip.interfaces[self.ifd].ipaddr assert self.ip.interfaces[self.ifd].flags & 1 def test_snapshots(self): require_user('root') ifB = self.get_ifname() # set up the interface with self.ip.interfaces[self.ifd] as i: i.add_ip('172.16.0.1/24') i.up() # check it assert ('172.16.0.1', 24) in self.ip.interfaces[self.ifd].ipaddr assert self.ip.interfaces[self.ifd].flags & 1 # make a snapshot s = self.ip.interfaces[self.ifd].snapshot() i = self.ip.interfaces[self.ifd] # check it assert i.last_snapshot_id() == s # unset the interface with self.ip.interfaces[self.ifd] as i: i.del_ip('172.16.0.1/24') i.down() # we can not rename the interface while it is up, # so do it in two turns with self.ip.interfaces[self.ifd] as i: i.ifname = ifB # check it assert ifB in self.ip.interfaces assert self.ifd not in self.ip.interfaces y = self.ip.interfaces[ifB] assert i == y assert ('172.16.0.1', 24) not in y.ipaddr assert not (y.flags & 1) # revert snapshot y.revert(s).commit() # check it assert ifB not in self.ip.interfaces assert self.ifd in self.ip.interfaces assert ('172.16.0.1', 24) in self.ip.interfaces[self.ifd].ipaddr assert self.ip.interfaces[self.ifd].flags & 1 @skip_if_not_supported def _test_ipv(self, ipv, kind): require_user('root') ifA = self.get_ifname() i = self.ip.create(kind=kind, ifname=ifA).commit() if self.ip.interfaces[ifA]._mode == 'explicit': self.ip.interfaces[ifA].begin() if ipv == 4: addr = '172.16.0.1/24' elif ipv == 6: addr = 'fdb3:84e5:4ff4:55e4::1/64' else: raise Exception('bad IP version') i.add_ip(addr).commit() pre_target = addr.split('/') target = (pre_target[0], int(pre_target[1])) assert target in i['ipaddr'] def test_ipv4_dummy(self): self._test_ipv(4, 'dummy') def test_ipv4_bond(self): self._test_ipv(4, 'bond') def test_ipv4_bridge(self): self._test_ipv(4, 'bridge') def test_ipv6_dummy(self): self._test_ipv(6, 'dummy') def test_ipv6_bond(self): self._test_ipv(6, 'bond') def test_ipv6_bridge(self): self._test_ipv(6, 'bridge') @skip_if_not_supported def test_create_tuntap_fail(self): try: self.ip.create(ifname='fAiL', kind='tuntap', mode='fail').commit() except: assert not grep('ip link', pattern='fAiL') return raise Exception('tuntap create succeded') @skip_if_not_supported def test_create_tuntap(self): require_user('root') ifA = self.get_ifname() self.ip.create(ifname=ifA, kind='tuntap', mode='tap', uid=1, gid=1).commit() assert ifA in self.ip.interfaces assert grep('ip link', pattern=ifA) @skip_if_not_supported def test_ovs_kind_aliases(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, kind='ovs-bridge').commit() self.ip.create(ifname=ifB, kind='openvswitch').commit() assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces assert grep('ip link', pattern=ifA) assert grep('ip link', pattern=ifB) @skip_if_not_supported def test_ovs_add_remove_port(self): require_user('root') ifOVS = self.get_ifname() self.ip.create(ifname=ifOVS, kind='ovs-bridge').commit() ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, kind='dummy') self.ip.create(ifname=ifB, peer='x' + ifB, kind='veth') self.ip.commit() # add ports if self.ip.mode == 'explicit': self.ip.interfaces[ifOVS].begin() self.ip.interfaces[ifOVS].\ add_port(self.ip.interfaces[ifA]).\ add_port(self.ip.interfaces[ifB]).\ commit() # assert self.ip.interfaces[ifA].master == \ self.ip.interfaces[ifOVS].index assert self.ip.interfaces[ifB].master == \ self.ip.interfaces[ifOVS].index assert self.ip.interfaces[ifA].index in \ self.ip.interfaces[ifOVS].ports assert self.ip.interfaces[ifB].index in \ self.ip.interfaces[ifOVS].ports # remove ports if self.ip.mode == 'explicit': self.ip.interfaces[ifOVS].begin() self.ip.interfaces[ifOVS].\ del_port(self.ip.interfaces[ifA]).\ del_port(self.ip.interfaces[ifB]).\ commit() # assert self.ip.interfaces[ifA].get('master') is None assert self.ip.interfaces[ifB].get('master') is None assert not self.ip.interfaces[ifOVS].ports def test_global_create(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, kind='dummy') self.ip.create(ifname=ifB, kind='dummy') self.ip.commit() assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces assert grep('ip link', pattern=ifA) assert grep('ip link', pattern=ifB) def test_global_priorities(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() ifC = self.get_ifname() a = self.ip.create(ifname=ifA, kind='dummy').commit() # if a._mode == 'explicit': a.begin() # prepare transaction: two interface creations # and one failure on an existing interface a.set_address('11:22:33:44:55:66') b = self.ip.create(ifname=ifB, kind='dummy') c = self.ip.create(ifname=ifC, kind='dummy') # now assign priorities b.ipdb_priority = 15 # will be execute first a.ipdb_priority = 10 # second -- and fail c.ipdb_priority = 5 # should not be executed # prepare watchdogs wdb = self.ip.watchdog(ifname=ifB) wdc = self.ip.watchdog(ifname=ifC) # run the transaction try: self.ip.commit() except NetlinkError: pass # control system state assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces assert ifC in self.ip.interfaces assert a.ipdb_scope == 'system' assert b.ipdb_scope == 'create' assert c.ipdb_scope == 'create' assert a.address != '11:22:33:44:55:66' assert grep('ip link', pattern=ifA) assert not grep('ip link', pattern=ifB) assert not grep('ip link', pattern=ifC) wdb.wait(1) wdc.wait(1) assert wdb.is_set assert not wdc.is_set def test_global_veth(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, peer=ifB, kind='veth') self.ip.commit() assert self.ip.interfaces[ifA]['ipdb_scope'] == 'system' assert self.ip.interfaces[ifB]['ipdb_scope'] == 'system' if self.ip.mode == 'explicit': self.ip.interfaces[ifA].begin() self.ip.interfaces[ifB].begin() self.ip.interfaces[ifA].remove() self.ip.interfaces[ifB].remove() self.ip.commit() assert ifA not in self.ip.interfaces assert ifB not in self.ip.interfaces def test_global_rollback(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() a = self.ip.create(ifname=ifA, kind='dummy').commit() # if a._mode == 'explicit': a.begin() a.remove() b = self.ip.create(ifname=ifB, kind='dummy') b.set_mtu(1500).set_address('11:22:33:44:55:66') try: self.ip.commit() except NetlinkError: pass assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces assert b.ipdb_scope == 'create' assert grep('ip link', pattern=ifA) assert not grep('ip link', pattern=ifB) def test_global_netns(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() ns = str(uuid.uuid4()) with IPDB(nl=NetNS(ns)) as nsdb: v1 = self.ip.create(ifname='x' + ifA, kind='veth', peer=ifA) v2 = self.ip.create(ifname='x' + ifB, kind='veth', peer=ifB) if v1._mode == 'explicit': v1.begin() v2.begin() v1.net_ns_fd = ns v2.net_ns_fd = ns self.ip.commit() nsdb.interfaces['x' + ifA].ifname = 'eth0' nsdb.interfaces['x' + ifB].ifname = 'eth1' nsdb.commit() if self.ip.interfaces[ifA]._mode == 'explicit': self.ip.interfaces[ifA].begin() self.ip.interfaces[ifB].begin() self.ip.interfaces[ifA].up() self.ip.interfaces[ifB].up() self.ip.commit() assert 'x' + ifA not in self.ip.interfaces assert 'x' + ifB not in self.ip.interfaces assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces assert self.ip.interfaces[ifA].flags & 1 assert self.ip.interfaces[ifB].flags & 1 if self.ip.interfaces[ifA]._mode == 'explicit': self.ip.interfaces[ifA].begin() self.ip.interfaces[ifB].begin() self.ip.interfaces[ifA].remove() self.ip.interfaces[ifB].remove() self.ip.commit() netns.remove(ns) @skip_if_not_supported def test_create_veth(self): require_user('root') ifA = self.get_ifname() ifB = self.get_ifname() self.ip.create(ifname=ifA, kind='veth', peer=ifB).commit() assert ifA in self.ip.interfaces assert ifB in self.ip.interfaces def test_create_fail(self): require_user('root') ifA = self.get_ifname() # create with mac 11:22:33:44:55:66 should fail i = self.ip.create(kind='dummy', ifname=ifA, address='11:22:33:44:55:66') try: i.commit() except NetlinkError: pass assert i._mode == 'invalid' assert ifA not in self.ip.interfaces def test_create_dqn(self): require_user('root') ifA = self.get_ifname() i = self.ip.create(kind='dummy', ifname=ifA) i.add_ip('172.16.0.1/255.255.255.0') i.commit() assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr assert '172.16.0.1/24' in get_ip_addr(interface=ifA) def test_create_double_reuse(self): require_user('root') ifA = self.get_ifname() # create an interface i1 = self.ip.create(kind='dummy', ifname=ifA).commit() try: # this call should fail on the very first step: # `bala` interface already exists self.ip.create(kind='dummy', ifname=ifA) except CreateException: pass # add `reuse` keyword -- now should pass i2 = self.ip.create(kind='dummy', ifname=ifA, reuse=True).commit() # assert that we have got references to the same interface assert i1 == i2 @skip_if_not_supported def _create_double(self, kind): require_user('root') ifA = self.get_ifname() self.ip.create(kind=kind, ifname=ifA).commit() try: self.ip.create(kind=kind, ifname=ifA).commit() except CreateException: pass def test_create_double_dummy(self): self._create_double('dummy') def test_create_double_bridge(self): self._create_double('bridge') def test_create_double_bond(self): self._create_double('bond') def test_create_plain(self): require_user('root') ifA = self.get_ifname() i = self.ip.create(kind='dummy', ifname=ifA) i.add_ip('172.16.0.1/24') i.commit() assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr assert '172.16.0.1/24' in get_ip_addr(interface=ifA) def test_create_and_remove(self): require_user('root') ifA = self.get_ifname() with self.ip.create(kind='dummy', ifname=ifA) as i: i.add_ip('172.16.0.1/24') assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr assert '172.16.0.1/24' in get_ip_addr(interface=ifA) with self.ip.interfaces[ifA] as i: i.remove() assert ifA not in self.ip.interfaces def test_dqn_mask(self): require_user('root') iface = self.ip.interfaces[self.ifd] with iface as i: i.add_ip('172.16.0.1/24') i.add_ip('172.16.0.2', mask=24) i.add_ip('172.16.0.3/255.255.255.0') i.add_ip('172.16.0.4', mask='255.255.255.0') assert ('172.16.0.1', 24) in iface.ipaddr assert ('172.16.0.2', 24) in iface.ipaddr assert ('172.16.0.3', 24) in iface.ipaddr assert ('172.16.0.4', 24) in iface.ipaddr @skip_if_not_supported def _create_master(self, kind, **kwarg): ifM = self.get_ifname() ifP1 = self.get_ifname() ifP2 = self.get_ifname() self.ip.create(kind='dummy', ifname=ifP1).commit() self.ip.create(kind='dummy', ifname=ifP2).commit() with self.ip.create(kind=kind, ifname=ifM, **kwarg) as i: i.add_port(self.ip.interfaces[ifP1]) i.add_ip('172.16.0.1/24') with self.ip.interfaces[ifM] as i: i.add_port(self.ip.interfaces[ifP2]) i.add_ip('172.16.0.2/24') assert ('172.16.0.1', 24) in self.ip.interfaces[ifM].ipaddr assert ('172.16.0.2', 24) in self.ip.interfaces[ifM].ipaddr assert '172.16.0.1/24' in get_ip_addr(interface=ifM) assert '172.16.0.2/24' in get_ip_addr(interface=ifM) assert self.ip.interfaces[ifP1].if_master == \ self.ip.interfaces[ifM].index assert self.ip.interfaces[ifP2].if_master == \ self.ip.interfaces[ifM].index with self.ip.interfaces[ifM] as i: i.del_port(self.ip.interfaces[ifP1]) i.del_port(self.ip.interfaces[ifP2]) i.del_ip('172.16.0.1/24') i.del_ip('172.16.0.2/24') assert ('172.16.0.1', 24) not in self.ip.interfaces[ifM].ipaddr assert ('172.16.0.2', 24) not in self.ip.interfaces[ifM].ipaddr assert '172.16.0.1/24' not in get_ip_addr(interface=ifM) assert '172.16.0.2/24' not in get_ip_addr(interface=ifM) assert self.ip.interfaces[ifP1].if_master is None assert self.ip.interfaces[ifP2].if_master is None def test_create_bridge(self): require_user('root') self._create_master('bridge') def test_create_bond(self): require_user('root') self._create_master('bond') def test_create_team(self): require_user('root') self._create_master('team') def test_create_ovs(self): require_user('root') self._create_master('openvswitch') def test_create_bond2(self): require_user('root') self._create_master('bond', bond_mode=2) @skip_if_not_supported def _create_macvx_mode(self, kind, mode): require_user('root') ifL = self.get_ifname() ifV = self.get_ifname() ifdb = self.ip.interfaces self.ip.create(kind='dummy', ifname=ifL).commit() self.ip.create(**{'kind': kind, 'link': ifdb[ifL], 'ifname': ifV, '%s_mode' % kind: mode}).commit() ip2 = IPDB() ifdb = ip2.interfaces try: assert ifdb[ifV].link == ifdb[ifL].index assert ifdb[ifV]['%s_mode' % kind] == mode except Exception: raise finally: ip2.release() def test_create_macvtap_vepa(self): return self._create_macvx_mode('macvtap', 'vepa') def test_create_macvtap_bridge(self): return self._create_macvx_mode('macvtap', 'bridge') def test_create_macvlan_vepa(self): return self._create_macvx_mode('macvlan', 'vepa') def test_create_macvlan_bridge(self): return self._create_macvx_mode('macvlan', 'bridge') def test_create_utf_name(self): require_user('root') ifO = 'ༀ' self.ip.create(kind='dummy', ifname=ifO).commit() assert ifO in self.ip.interfaces assert self.ip.nl.link_lookup(ifname=ifO) if self.ip.interfaces[ifO]._mode == 'explicit': self.ip.interfaces[ifO].begin() self.ip.interfaces[ifO].remove().commit() @skip_if_not_supported def test_create_gre(self): require_user('root') ifL = self.get_ifname() ifV = self.get_ifname() with self.ip.create(kind='dummy', ifname=ifL) as i: i.add_ip('172.16.0.1/24') i.up() self.ip.create(kind='gre', ifname=ifV, gre_local='172.16.0.1', gre_remote='172.16.0.2', gre_ttl=16).commit() ip2 = IPDB() ifdb = ip2.interfaces try: assert ifdb[ifV].gre_local == '172.16.0.1' assert ifdb[ifV].gre_remote == '172.16.0.2' assert ifdb[ifV].gre_ttl == 16 except Exception: raise finally: ip2.release() @skip_if_not_supported def test_create_vxlan(self): require_user('root') ifL = self.get_ifname() ifV = self.get_ifname() ifdb = self.ip.interfaces self.ip.create(kind='dummy', ifname=ifL).commit() self.ip.create(kind='vxlan', ifname=ifV, vxlan_link=ifdb[ifL], vxlan_id=101, vxlan_group='239.1.1.1').commit() ip2 = IPDB() ifdb = ip2.interfaces try: assert ifdb[ifV].vxlan_link == ifdb[ifL].index assert ifdb[ifV].vxlan_group == '239.1.1.1' assert ifdb[ifV].vxlan_id == 101 except Exception: raise finally: ip2.release() def test_create_vlan_by_interface(self): require_user('root') require_8021q() ifL = self.get_ifname() ifV = self.get_ifname() self.ip.create(kind='dummy', ifname=ifL).commit() self.ip.create(kind='vlan', ifname=ifV, link=self.ip.interfaces[ifL], vlan_id=101).commit() assert self.ip.interfaces[ifV].link == \ self.ip.interfaces[ifL].index def test_create_vlan_by_index(self): require_user('root') require_8021q() ifL = self.get_ifname() ifV = self.get_ifname() self.ip.create(kind='dummy', ifname=ifL).commit() self.ip.create(kind='vlan', ifname=ifV, link=self.ip.interfaces[ifL].index, vlan_id=101).commit() assert self.ip.interfaces[ifV].link == \ self.ip.interfaces[ifL].index def test_remove_secondaries(self): require_user('root') ifA = self.get_ifname() with self.ip.create(kind='dummy', ifname=ifA) as i: i.add_ip('172.16.0.1', 24) i.add_ip('172.16.0.2', 24) assert ifA in self.ip.interfaces assert ('172.16.0.1', 24) in self.ip.interfaces[ifA].ipaddr assert ('172.16.0.2', 24) in self.ip.interfaces[ifA].ipaddr assert '172.16.0.1/24' in get_ip_addr(interface=ifA) assert '172.16.0.2/24' in get_ip_addr(interface=ifA) if i._mode == 'explicit': i.begin() i.del_ip('172.16.0.1', 24) i.del_ip('172.16.0.2', 24) i.commit() assert ('172.16.0.1', 24) not in self.ip.interfaces[ifA].ipaddr assert ('172.16.0.2', 24) not in self.ip.interfaces[ifA].ipaddr assert '172.16.0.1/24' not in get_ip_addr(interface=ifA) assert '172.16.0.2/24' not in get_ip_addr(interface=ifA)
msg.get_attr('IFLA_IFNAME', '').startswith('bala_port'): # get corresponding interface -- in the case of # post-callbacks it is created already interface = ipdb.interfaces[msg['index']] # add it as a port to the bridge ipdb.interfaces.br0.add_port(interface) try: ipdb.interfaces.br0.commit() except Exception: pass # create IPDB instance ip = IPDB() # create watchdogs wd0 = ip.watchdog(ifname='br0') wd1 = ip.watchdog(ifname='bala_port0') wd2 = ip.watchdog(ifname='bala_port1') # create bridge ip.create(kind='bridge', ifname='br0').commit() # wait the bridge to be created wd0.wait() # register callback ip.register_callback(cb) # create ports ip.create(kind='dummy', ifname='bala_port0').commit() ip.create(kind='dummy', ifname='bala_port1').commit() # sleep for interfaces wd1.wait() wd2.wait()