def test_dummy0_unloaded(object): require_user('root') # firstly unload the dummy module with open(os.devnull, 'w') as fnull: subprocess.call(['modprobe', '-r', 'dummy'], stdout=fnull, stderr=fnull) ip = None try: # now create the dummy0 -- it will cause the # module autoload ip = IPDB() # that must succeed ip.create(ifname='dummy0', kind='dummy').commit() # just in case: the second attempt must fail on the # create() stage, even w/o any commit() try: ip.create(ifname='dummy0', kind='dummy') except CreateException: pass except Exception: raise finally: if ip is not None: ip.release()
def test_commit_barrier(self): require_user("root") ifname = uifname() # barrier 0 try: ip = IPDB() config.commit_barrier = 0 ts1 = time.time() ip.create(ifname=ifname, kind="dummy").commit() ts2 = time.time() assert 0 < (ts2 - ts1) < 1 except: raise finally: config.commit_barrier = 0.2 ip.interfaces[ifname].remove().commit() ip.release() # barrier 5 try: ip = IPDB() config.commit_barrier = 5 ts1 = time.time() ip.create(ifname=ifname, kind="dummy").commit() ts2 = time.time() assert 5 < (ts2 - ts1) < 6 except: raise finally: config.commit_barrier = 0.2 ip.interfaces[ifname].remove().commit() ip.release()
def test_move_ns_pid(self): foo = str(uuid4()) bar = str(uuid4()) ifA = uifname() netnsmod.create(foo) netnsmod.create(bar) ns_foo = IPDB(nl=NetNS(foo)) ns_bar = IPDB(nl=NetNS(bar)) try: ns_foo.create(ifname=ifA, kind='dummy').commit() with ns_foo.interfaces[ifA] as iface: iface.net_ns_pid = ns_bar.nl.server.pid assert ifA in ns_bar.interfaces.keys() assert ifA not in ns_foo.interfaces.keys() with ns_bar.interfaces[ifA] as iface: iface.net_ns_pid = ns_foo.nl.server.pid assert ifA not in ns_bar.interfaces.keys() assert ifA in ns_foo.interfaces.keys() finally: ns_foo.release() ns_bar.release() netnsmod.remove(foo) netnsmod.remove(bar)
class TestDirect(object): def setup(self): self.ifname = uifname() self.ip = IPDB(mode='direct') try: self.ip.create(ifname=self.ifname, kind='dummy') except: pass def teardown(self): try: self.ip.interfaces[self.ifname].remove() except KeyError: pass self.ip.release() def test_context_fail(self): require_user('root') try: with self.ip.interfaces[self.ifname] as i: i.down() except TypeError: pass def test_create(self): require_user('root') ifname = uifname() assert ifname not in self.ip.interfaces self.ip.create(ifname=ifname, kind='dummy') assert ifname in self.ip.interfaces self.ip.interfaces[ifname].remove() assert ifname not in self.ip.interfaces def test_updown(self): require_user('root') assert not (self.ip.interfaces[self.ifname].flags & 1) self.ip.interfaces[self.ifname].up() assert self.ip.interfaces[self.ifname].flags & 1 self.ip.interfaces[self.ifname].down() assert not (self.ip.interfaces[self.ifname].flags & 1) def test_exceptions_last(self): try: self.ip.interfaces.lo.last() except TypeError: pass def test_exception_review(self): try: self.ip.interfaces.lo.review() except TypeError: pass
class _TestDhcpClient(object): def setup(self): require_user('root') require_executable('busybox') self.ip = IPDB() # create internal network self.if1 = uifname() self.if2 = uifname() self.ip.create(kind='veth', ifname=self.if1, peer=self.if2).commit() # set interfaces up with self.ip.interfaces[self.if1] as i: i.add_ip('172.16.101.1/24') i.up() with self.ip.interfaces[self.if2] as i: i.up() # prepare configuration for udhcpd with open('udhcpd.conf.in', 'r') as conf_in: with open('udhcpd.conf', 'w') as conf_out: conf_out.write('interface %s\n' % self.if1) conf_out.write(conf_in.read()) # run busybox dhcp server on $if1 with open(os.devnull, 'w') as fnull: subprocess.check_call(['busybox', 'udhcpd', 'udhcpd.conf'], stdout=fnull, stderr=fnull) def teardown(self): # read pid from file and kill the server with open('udhcpd.pid', 'r') as pid_file: pid = int(pid_file.read()) os.kill(pid, 15) # teardown interfaces (enough to remove only master) self.ip.interfaces[self.if1].remove().commit() # release IPDB self.ip.release() # remove configuration file os.unlink('udhcpd.conf') # collect garbage gc.collect() def test_defaults(self): msg = dhclient.action(self.if2) assert msg['yiaddr'].startswith('172.16.101.') assert msg['op'] == BOOTREPLY assert msg['options']['message_type'] == DHCPACK assert msg['options']['router'] == ['172.16.101.1'] assert msg['options']['server_id'] == '172.16.101.1' assert msg['options']['subnet_mask'] == '255.255.255.0' assert set(msg['options']['name_server']) ==\ set(('172.16.101.1', '172.16.101.2'))
def createInterface(self): ipdb = IPDB() ipdb.create(ifname=self.veth0, kind='veth', peer=self.veth1).commit() with ipdb.interfaces[self.veth0] as i: i.up() with ipdb.interfaces[self.veth1] as i: i.up() i.net_ns_fd = self.nsname with ipdb.interfaces[self.bridge_iface] as i: i.add_port(ipdb.interfaces[self.veth0]) ipdb.release()
def createService(name, terminalName, svcId): subprocess.call(["ovs-vsctl", "add-br", "vs-" + name]) if_svc_name = name if_terminal_name = name + '_' + terminalName ip_host = IPDB() ip_host.create(ifname=if_svc_name, kind='veth', peer=if_terminal_name).commit() with ip_host.interfaces[if_svc_name] as veth: veth.up() with ip_host.interfaces[if_terminal_name] as veth: veth.up() ip_host.release() subprocess.call(["ovs-vsctl", "add-port", "vs-" + name, if_svc_name]) subprocess.call(["ovs-vsctl", "add-port", "br0", if_terminal_name]) subprocess.call(["ovs-vsctl", "set", "port", if_terminal_name, "tag=" + str(svcId)]) return json.dumps({ 'status' : 'created service'})
def test_create(self): require_user('root') nsid = str(uuid4()) ipdb_main = IPDB() ipdb_test = IPDB(nl=NetNS(nsid)) if1 = uifname() if2 = uifname() # create VETH pair ipdb_main.create(ifname=if1, kind='veth', peer=if2).commit() # move the peer to netns with ipdb_main.interfaces[if2] as veth: veth.net_ns_fd = nsid # assign addresses with ipdb_main.interfaces[if1] as veth: veth.add_ip('172.16.200.1/24') veth.up() with ipdb_test.interfaces[if2] as veth: veth.add_ip('172.16.200.2/24') veth.up() # ping peer try: with open('/dev/null', 'w') as fnull: subprocess.check_call(['ping', '-c', '1', '172.16.200.2'], stdout=fnull, stderr=fnull) ret_ping = True except Exception: ret_ping = False # check ARP time.sleep(0.5) ret_arp = '172.16.200.1' in list(ipdb_test.interfaces[if2].neighbours) # ret_arp = list(ipdb_test.interfaces.v0p1.neighbours) # cleanup ipdb_main.interfaces[if1].remove().commit() ipdb_main.release() ipdb_test.release() netnsmod.remove(nsid) assert ret_ping assert ret_arp assert nsid not in netnsmod.listnetns()
def createEndpoint(name, svcName, endpointtype): if endpointtype == 'ns': ip_host = IPDB() ip_host.create(ifname=name, kind='veth', peer=name + '_' + svcName).commit() ip_ns = IPDB(nl=NetNS(name)) with ip_host.interfaces[name] as veth: veth.net_ns_fd = name veth.up() with ip_host.interfaces[name + '_' + svcName] as veth: veth.up() subprocess.call(["ovs-vsctl", "add-port", "vs-" + svcName, name + '_' + svcName]) ip_host.release() ip_ns.release() nsp = NSPopen(name, ['dhclient', '-lf', '/tmp/' + name + '.lease', name], stdout=subprocess.PIPE) nsp.wait() nsp.release() if endpointtype == 'lxc': subprocess.call(['/usr/bin/lxc-clone','template',name]) lxcUpOvsScript = '#!/bin/bash\n' lxcUpOvsScript += 'BRIDGE="vs-'+ svcName + '"\n' lxcUpOvsScript += 'ovs-vsctl --if-exists del-port $BRIDGE $5\n' lxcUpOvsScript += 'ovs-vsctl add-port $BRIDGE $5\n' f = open('/var/lib/lxc/' + name + '/ovsup.sh','w+') f.write(lxcUpOvsScript) f.close() lxcDownOvsScript = '#!/bin/bash\n' lxcDownOvsScript += 'BRIDGE="vs-'+ svcName + '"\n' lxcDownOvsScript += 'ovs-vsctl --if-exists del-port $BRIDGE $5\n' f = open('/var/lib/lxc/' + name + '/ovsdown.sh','w+') f.write(lxcDownOvsScript) f.close() os.chmod('/var/lib/lxc/' + name + '/ovsup.sh',stat.S_IRWXU) os.chmod('/var/lib/lxc/' + name + '/ovsdown.sh',stat.S_IRWXU) lxcConfig = 'lxc.include = /usr/share/lxc/config/ubuntu.common.conf\n' lxcConfig += 'lxc.arch = x86_64\n' lxcConfig += 'lxc.rootfs = /var/lib/lxc/' + name + '/rootfs\n' lxcConfig += 'lxc.utsname = ' + name + '\n' lxcConfig += 'lxc.network.type = veth\n' lxcConfig += 'lxc.network.veth.pair = ' + name + '\n' lxcConfig += 'lxc.network.script.up = /var/lib/lxc/' + name + '/ovsup.sh\n' lxcConfig += 'lxc.network.script.down = /var/lib/lxc/' + name + '/ovsdown.sh\n' lxcConfig += 'lxc.network.flags = up\n' f = open('/var/lib/lxc/' + name + '/config','w+') f.write(lxcConfig) f.close() subprocess.call(['/usr/bin/lxc-start','-d','-n',name]) pass return json.dumps({ 'status' : 'created endpoint'})
def test_dummy0_loaded(object): require_user("root") # assert the module is loaded ifA = uifname() ip = IPDB() ip.create(ifname=ifA, kind="dummy").commit() try: # try to create and fail in create() ip.create(ifname="dummy0", kind="dummy") except CreateException: pass except Exception: raise finally: ip.interfaces[ifA].remove().commit() ip.release()
class TestDhcpClient(object): def setup(self): require_user("root") require_executable("busybox") self.ip = IPDB() # create internal network self.if1 = "dh1-%i" % os.getpid() self.if2 = "dh2-%i" % os.getpid() self.ip.create(kind="veth", ifname=self.if1, peer=self.if2).commit() # set interfaces up with self.ip.interfaces[self.if1] as i: i.add_ip("172.16.101.1/24") i.up() with self.ip.interfaces[self.if2] as i: i.up() # prepare configuration for udhcpd with open("udhcpd.conf.in", "r") as conf_in: with open("udhcpd.conf", "w") as conf_out: conf_out.write("interface %s\n" % self.if1) conf_out.write(conf_in.read()) # run busybox dhcp server on $if1 with open(os.devnull, "w") as fnull: subprocess.check_call(["busybox", "udhcpd", "udhcpd.conf"], stdout=fnull, stderr=fnull) def teardown(self): # read pid from file and kill the server with open("udhcpd.pid", "r") as pid_file: pid = int(pid_file.read()) os.kill(pid, 15) # teardown interfaces (enough to remove only master) self.ip.interfaces[self.if1].remove().commit() # release IPDB self.ip.release() # remove configuration file os.unlink("udhcpd.conf") def test_defaults(self): msg = dhclient.action(self.if2) assert msg["yiaddr"].startswith("172.16.101.") assert msg["op"] == BOOTREPLY assert msg["options"]["message_type"] == DHCPACK assert msg["options"]["router"] == ["172.16.101.1"] assert msg["options"]["server_id"] == "172.16.101.1" assert msg["options"]["subnet_mask"] == "255.255.255.0" assert set(msg["options"]["name_server"]) == set(("172.16.101.1", "172.16.101.2"))
def test_rename_plus_ipv6(self): require_user('root') mtu = 1280 # mtu must be >= 1280 if you plan to use IPv6 txqlen = 2000 nsid = str(uuid4()) ipdb_main = IPDB() ipdb_test = IPDB(nl=NetNS(nsid)) if1 = uifname() if2 = uifname() if3 = uifname() # create ipdb_main.create(kind='veth', ifname=if1, peer=if2, mtu=mtu, txqlen=txqlen).commit() # move with ipdb_main.interfaces[if2] as veth: veth.net_ns_fd = nsid # set it up with ipdb_test.interfaces[if2] as veth: veth.add_ip('fdb3:84e5:4ff4:55e4::1/64') veth.add_ip('fdff:ffff:ffff:ffc0::1/64') veth.mtu = mtu veth.txqlen = txqlen veth.up() veth.ifname = if3 veth = ipdb_test.interfaces.get(if3, None) ipdb_main.release() ipdb_test.release() netnsmod.remove(nsid) # check everything assert ('fdb3:84e5:4ff4:55e4::1', 64) in veth.ipaddr assert ('fdff:ffff:ffff:ffc0::1', 64) in veth.ipaddr assert veth.flags & 1 assert veth.mtu == mtu assert veth.txqlen == txqlen
def create(self): iface = self.containerName + 'veth0' ifacePeer = self.containerName + 'veth1' ip_main = IPDB() ip_sub = IPDB(nl=NetNS(self.containerName)) ip_main.create(ifname=iface, kind='veth', peer=ifacePeer).commit() with ip_main.interfaces[ifacePeer] as veth: veth.net_ns_fd = self.containerName with ip_main.interfaces[iface] as veth: veth.up() ip_main.release() with ip_sub.interfaces[ifacePeer] as veth: #if not self.containerDhcp: if not hasattr(self, 'containerDhcp'): veth.add_ip(self.containerIp) if hasattr(self, 'containerMac'): veth.address = self.containerMac ip_sub.release() ns = NetNS(self.containerName) idx = ns.link_lookup(ifname=ifacePeer)[0] ns.link('set', index=idx, net_ns_fs=self.containerName, ifname='eth0') ns.link('set', index=idx, net_ns_fs=self.containerName, state='up') if hasattr(self, 'containerGateway'): request = {"dst": "0.0.0.0/0", "gateway": self.containerGateway} ns.route("add", **IPRouteRequest(request)) ns.close() subprocess.call(["ovs-vsctl", "add-port", "br0", iface]) dockerControl = DockerControl(self.containerObject) if hasattr(self, 'containerDhcp'): dhcpCmd = 'dhclient eth0' dockerControl.runCmd(dhcpCmd) addressCmd = 'ip address show dev eth0' addressInfo = dockerControl.runCmd(addressCmd) addressInfoList = addressInfo.splitlines() macAddressInfo = addressInfoList[1].split()[1] ipAddressInfo = addressInfoList[2].split()[1] ipAddressInfoDict = dict({ 'containerName': self.containerName, 'macAddress': macAddressInfo, 'ipAddress': ipAddressInfo }) return json.dumps(ipAddressInfoDict)
def create_interface(self): ifname = self.__intf_info["ifname"] IP_ROUTE = IPRoute() if len(IP_ROUTE.link_lookup(ifname=ifname)) > 0: self.logger_topo.warning("ip link {} exists so not create it.".format(ifname)) IP_ROUTE.close() return if self.__peer: if len(IP_ROUTE.link_lookup(ifname=self.__peer)) > 0: self.logger_topo.warning("ip link {} exists so not create it.".format(ifname)) IP_ROUTE.close() return else: # Close IP_ROUTE first anyway IP_ROUTE.close() ps_intf = r"^\d+: (?P<intf>[\w-]+): " p_intf = re.compile(ps_intf, re.MULTILINE) _, out, _ = exec_cmd_in_namespace(self.__namespace, ["ip", "link"]) m_intf = p_intf.findall(out) if ifname in m_intf: self.logger_topo.warning("ip link {} exists in namespace {} so not create it.". format(ifname, self.__namespace)) return MAIN_IPDB = IPDB() MAIN_IPDB.create(ifname=ifname, kind="veth" if self.__peer else "dummy", peer=self.__peer).commit() with MAIN_IPDB.interfaces[ifname] as veth: try: veth.net_ns_fd = self.__namespace except netlink.exceptions.NetlinkError as e: MAIN_IPDB.release() if e.code == 17: # "File exists" pass else: raise e MAIN_IPDB.release() self.logger_topo.info("interface {} in namespace {} is created, peer: {}.". format(ifname, self.__namespace, self.__peer))
def createInterfaces(): ip = IPDB() ifdb = ip.interfaces tunGW = None while tunGW == None: tunGW = getTunGW() #Create VXLAN. with ip.create(ifname='vxlan0', kind='vxlan', vxlan_id=42, vxlan_group=str(tunGW), vxlan_port=4789) as vxlan: vxlan.up() #Make sure the ethernet interface is up ifdb.eth0.up() #Create a bridge interface that will bridge the eth0 interface with the vxlan with ip.create(kind='bridge', ifname='br0') as br: br.add_port(ifdb.eth0) br.add_port(ifdb.vxlan0) br.up() return 0
def create(self): iface = self.containerName + "veth0" ifacePeer = self.containerName + "veth1" ip_main = IPDB() ip_sub = IPDB(nl=NetNS(self.containerName)) ip_main.create(ifname=iface, kind="veth", peer=ifacePeer).commit() with ip_main.interfaces[ifacePeer] as veth: veth.net_ns_fd = self.containerName with ip_main.interfaces[iface] as veth: veth.up() ip_main.release() with ip_sub.interfaces[ifacePeer] as veth: # if not self.containerDhcp: if not hasattr(self, "containerDhcp"): veth.add_ip(self.containerIp) if hasattr(self, "containerMac"): veth.address = self.containerMac ip_sub.release() ns = NetNS(self.containerName) idx = ns.link_lookup(ifname=ifacePeer)[0] ns.link("set", index=idx, net_ns_fs=self.containerName, ifname="eth0") ns.link("set", index=idx, net_ns_fs=self.containerName, state="up") if hasattr(self, "containerGateway"): request = {"dst": "0.0.0.0/0", "gateway": self.containerGateway} ns.route("add", **IPRouteRequest(request)) ns.close() subprocess.call(["ovs-vsctl", "add-port", "br0", iface]) dockerControl = DockerControl(self.containerObject) if hasattr(self, "containerDhcp"): dhcpCmd = "dhclient eth0" dockerControl.runCmd(dhcpCmd) addressCmd = "ip address show dev eth0" addressInfo = dockerControl.runCmd(addressCmd) addressInfoList = addressInfo.splitlines() macAddressInfo = addressInfoList[1].split()[1] ipAddressInfo = addressInfoList[2].split()[1] ipAddressInfoDict = dict( {"containerName": self.containerName, "macAddress": macAddressInfo, "ipAddress": ipAddressInfo} ) return json.dumps(ipAddressInfoDict)
def create_bridge(br_name, phy_ip): """ Create a bridge for connecting the container clients to the network. :param br_name: Name of the bridge to create. :param phy_ip: IP of the physical interface to include in the bridge. :return: True if success, False if failure """ log.info("Creating bridge %s." % br_name) assert (phy_ip.startswith('10.') or phy_ip.startswith('192.')) ipdb = IPDB() if br_name in ipdb.interfaces.keys(): log.fatal("A bridge/interface with the name %s already exists!" % br_name) return False phy_eth = None for eth in ipdb.interfaces.keys(): if type(eth) is int: continue for ip, netmask in ipdb.interfaces[eth]['ipaddr']: log.debug("%s: %s" % (eth, ip)) if ip == phy_ip: phy_eth = (eth, ip, netmask) break if phy_eth is None: log.fatal("Could not find an interface with IP '%s'!" % phy_ip) return False log.info("Using interface %s for the bridge." % str(phy_eth)) log.debug("Creating bridge with ifname %s." % br_name) with ipdb.create(kind='bridge', ifname=br_name) as br: br.add_port(ipdb.interfaces[phy_eth[0]]) br.up() br.add_ip('%s/%s' % (phy_eth[1], phy_eth[2])) log.debug("Removing IP %s from interface %s." % (phy_eth[1], phy_eth)) with ipdb.interfaces[phy_eth[0]] as i: i.del_ip('%s/%s' % (phy_eth[1], phy_eth[2])) ipdb.commit() ipdb.release() return True
def test_vrouter(self): require_user('root') nsid = str(uuid.uuid4()) ns = NetNS(nsid) ipdb = IPDB() ipns = IPDB(nl=ns) try: ipdb.create(ifname='ve0p0', peer='ve0p1', kind='veth').commit() ipdb.interfaces.ve0p1.net_ns_fd = nsid ipdb.commit() with ipns.interfaces.ve0p1 as i: i.set_ifname('eth0') i.up() except: raise finally: ipdb.interfaces.ve0p0.remove() ipdb.commit() ipdb.release() ipns.release() ns.remove()
class _TestIPDBRaces(object): def setup(self): self.ip = IPDB() def teardown(self): self.ip.release() def test_initdb(self): tnum = len(threading.enumerate()) for _ in range(RESPAWNS): len(self.ip.interfaces.keys()) len(self.ip.routes.keys()) len(self.ip.rules.keys()) self.ip.initdb() assert len(threading.enumerate()) <= tnum def _ports_mtu_race(self, kind): port1 = (self.ip.create(ifname=uifname(), kind='dummy', mtu=1280).commit()) port2 = (self.ip.create(ifname=uifname(), kind='dummy').commit()) master = (self.ip.create(ifname=uifname(), kind=kind).commit()) try: master.add_port(port1).commit() master.add_port(port2).commit() except: raise finally: port1.remove().commit() port2.remove().commit() master.remove().commit() def test_bridge_mtu(self): require_user('root') for _ in range(300): self._ports_mtu_race('bridge')
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)
# An example how to use command chaining in IPDB from pyroute2 import IPDB ip = IPDB() # create slave ports ip.create(ifname='bo0p0', kind='dummy').commit() ip.create(ifname='bo0p1', kind='dummy').commit() # set up bonding ip.create(ifname='bo0', kind='bond', bond_mode=2).\ add_port(ip.interfaces.bo0p0).\ add_port(ip.interfaces.bo0p1).\ add_ip('172.16.0.1/24').\ add_ip('172.16.0.2/24').\ option('mtu', 1400).\ up().\ commit() for i in ('bo0p0', 'bo0p1', 'bo0'): try: ip.interfaces[i].remove().commit() except: pass ip.release()
class TestExplicit(object): ip = None mode = 'explicit' def setup(self): self.ap = AddrPool() self.iftmp = 'pr2x{0}' self.ifaces = [] self.ifd = self.get_ifname() create_link(self.ifd, kind='dummy') self.ip = IPDB(mode=self.mode) def get_ifname(self): naddr = self.ap.alloc() ifname = self.iftmp.format(naddr) self.ifaces.append(ifname) return ifname def teardown(self): for name in self.ifaces: try: with self.ip.interfaces[name] as i: i.remove() except: 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_ips(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) 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(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_route_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_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) 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') require_bond() self._test_shadow('bond') def test_shadow_bridge(self): require_user('root') require_bridge() 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_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 -- make it portable del backup['index'] # 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 t = self.ip.interfaces[ifB].load(json.loads(backup)) self.ip.interfaces[ifB].commit(transaction=t) # 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(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 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') 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') 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_ovs_kind_aliases(self): require_user('root') require_executable('ovs-vsctl') 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) 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 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 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') require_bridge() self._create_master('bridge') def test_create_bond(self): require_user('root') require_bond() self._create_master('bond') def test_create_team(self): require_user('root') require_executable('teamd') require_executable('teamdctl') self._create_master('team') def test_create_ovs(self): require_user('root') require_executable('ovs-vsctl') self._create_master('openvswitch') def test_create_bond2(self): require_user('root') require_bond() self._create_master('bond', bond_mode=2) 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_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() 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)
def execRequest(self, action, data): if action == 'NetworkDriver.DiscoverNew': return HttpResponse(200,'json',{ }).response if action == 'NetworkDriver.DiscoverDelete': return HttpResponse(200,'json',{ }).response if action == 'Plugin.Activate': return HttpResponse(200,'json',{ 'Implements': ['NetworkDriver','IPAM'] }).response if action == 'NetworkDriver.GetCapabilities': return HttpResponse(200,'json',{ 'Scope':scope}).response if action == 'IPAM.GetDefaultAddressSpaces': requestPool = {} return HttpResponse(200,'json',requestPool).response if action == 'NetworkDriver.CreateNetwork': networkId = data['NetworkID'][:8] pool = data['IPv4Data'][0]['Pool'] gateway = data['IPv4Data'][0]['Gateway'].split('/')[0] displayName = '' if len(data['IPv6Data']) > 0: v6pool = data['IPv6Data'][0]['Pool'] v6gateway = data['IPv6Data'][0]['Gateway'] if 'name' in data['Options']['com.docker.network.generic']: displayName = data['Options']['com.docker.network.generic']['name'] if 'rt' in data['Options']['com.docker.network.generic']: rtList = data['Options']['com.docker.network.generic']['rt'].split(',') if len(data['IPv6Data']) > 0: openContrailVN = OpenContrailVN(networkId, displayName = displayName).create(pool, gateway, v6subnet=v6pool, v6gateway = v6gateway, rtList = rtList, displayName = displayName) else: openContrailVN = OpenContrailVN(networkId, displayName = displayName).create(pool, gateway, rtList = rtList, displayName = displayName) else: if len(data['IPv6Data']) > 0: openContrailVN = OpenContrailVN(networkId, displayName = displayName).create(pool, gateway, v6subnet=v6pool, v6gateway = v6gateway, displayName = displayName) else: openContrailVN = OpenContrailVN(networkId, displayName = displayName).create(pool, gateway, displayName = displayName) networkInfo = {} networkInfo['NetworkID'] = data['NetworkID'] return HttpResponse(200,'json',networkInfo).response if action == 'NetworkDriver.DeleteNetwork': networkId = data['NetworkID'][:8] openContrailVN = OpenContrailVN(networkId).delete() return HttpResponse(200,'json',{ }).response if action == 'NetworkDriver.CreateEndpoint': networkId = data['NetworkID'][:8] endpointId = data['EndpointID'] ipAddress = data['Interface']['Address'] if data['Interface']['AddressIPv6']: ipv6Address = data['Interface']['AddressIPv6'] OpenContrailEndpoint(endpointId).create(networkId, ipAddress, ipv6Address) else: OpenContrailEndpoint(endpointId).create(networkId, ipAddress) interface = {} interface['Interface'] = {} return HttpResponse(200,'json',interface).response if action == 'NetworkDriver.DeleteEndpoint': endpointId = data['EndpointID'] OpenContrailEndpoint(endpointId).delete() vethIdHost = 'veth' + endpointId[:8] + 'p0' ip = IPDB() with ip.interfaces[vethIdHost] as veth: veth.remove() return HttpResponse(200,'json',{ }).response if action == 'NetworkDriver.EndpointOperInfo': endpointInfo = {} endpointInfo['NetworkID'] = data['NetworkID'] endpointInfo['EndpointID'] = data['EndpointID'] return HttpResponse(200,'json',endpointInfo).response if action == 'NetworkDriver.Join': networkId = data['NetworkID'][:8] endpointId = data['EndpointID'] sandboxKey = data['SandboxKey'].split("/")[5] hostId = endpointId[:8] vethIdHost = 'veth' + hostId + 'p0' vethIdContainer = 'veth' + hostId vn = OpenContrailVN(networkId).VNget() subnet = vn.network_ipam_refs[0]['attr'].ipam_subnets[0] gateway = subnet.default_gateway result = OpenContrailEndpoint(endpointId).join(networkId, sandboxKey) mac = result['mac'] ip = IPDB() ip.create(ifname=vethIdHost, kind='veth', peer=vethIdContainer).commit() with ip.interfaces[vethIdHost] as veth: veth.up() with ip.interfaces[vethIdContainer] as veth: veth.address = mac OpenContrailEndpoint(endpointId).vrouterPortControl(result, 'add') joinInfo = {} joinInfo['InterfaceName'] = {} joinInfo['InterfaceName']['SrcName'] = vethIdContainer joinInfo['InterfaceName']['DstPrefix'] = 'eth' joinInfo['Gateway'] = gateway joinInfo['StaticRoutes'] = [] #ipAddress = data['Interface']['Address'] return HttpResponse(200,'json',joinInfo).response if action == 'NetworkDriver.ProgramExternalConnectivity': return HttpResponse(200,'json',{ }).response if action == 'NetworkDriver.RevokeExternalConnectivity': return HttpResponse(200,'json',{ }).response if action == 'NetworkDriver.Leave': return HttpResponse(200,'json',{ }).response
Master is an interface to add VLAN to, e.g. eth0 or tap0 or whatever else. Without parameters use tap0 as the default. ''' import sys from pyroute2 import IPDB ip = IPDB() try: if len(sys.argv) == 2: # Get master interface from the command line master = ip[sys.argv[1]]['index'] else: # Or use tap0 interface as an example master = ip.tap0.index # or the same: master = ip['tap0']['index'] with ip.create(kind='vlan', ifname='v101', link=master, vlan_id=101) as i: # Arguments for ip.create() are executed before the transaction, # in the IPRoute.link('add', ...) call. If create() fails, the # interface became invalid and is not operable, you can safely # drop it. # # Here goes the rest of transaction. If it fails, the interface # continues to work, only failed transaction gets dropped. i.add_ip('10.251.0.1', 24) i.add_ip('10.251.0.2', 24) i.mtu = 1400 finally: ip.release()
class TestExplicit(object): ip = None mode = 'explicit' def setup(self): self.ap = AddrPool() self.iftmp = 'pr2x{0}' self.ifaces = [] self.ifd = self.get_ifname() create_link(self.ifd, kind='dummy') self.ip = IPDB(mode=self.mode) def get_ifname(self): naddr = self.ap.alloc() ifname = self.iftmp.format(naddr) self.ifaces.append(ifname) return ifname def teardown(self): for name in self.ifaces: try: with self.ip.interfaces[name] as i: i.remove() except: 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_ips(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) 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(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_route_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_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) 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') require_bond() self._test_shadow('bond') def test_shadow_bridge(self): require_user('root') require_bridge() 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_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 -- make it portable del backup['index'] # 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 t = self.ip.interfaces[ifB].load(json.loads(backup)) self.ip.interfaces[ifB].commit(transaction=t) # 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(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 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') 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') 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_ovs_kind_aliases(self): require_user('root') require_executable('ovs-vsctl') 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) 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 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 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') require_bridge() self._create_master('bridge') def test_create_bond(self): require_user('root') require_bond() self._create_master('bond') def test_create_team(self): require_user('root') require_executable('teamd') require_executable('teamdctl') self._create_master('team') def test_create_ovs(self): require_user('root') require_executable('ovs-vsctl') self._create_master('openvswitch') def test_create_bond2(self): require_user('root') require_bond() self._create_master('bond', bond_mode=2) 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_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() 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)
#!/usr/bin/python from pprint import pprint from pyroute2 import IPRoute from pyroute2 import IPDB from pyroute2.common import uifname # high-level interface ipdb = IPDB() interface = ipdb.create(ifname=uifname(), kind='dummy').\ commit().\ add_ip('172.16.0.1/24').\ add_ip('172.16.0.2/24').\ commit() # low-level interface just to get raw messages ip = IPRoute() a = [x for x in ip.get_addr() if x['index'] == interface['index']] print('\n8<--------------------- left operand') pprint(a[0]) print('\n8<--------------------- right operand') pprint(a[1]) print('\n8<--------------------- complement') pprint(a[0] - a[1]) print('\n8<--------------------- intersection') pprint(a[0] & a[1]) interface.remove().commit() ip.close()
class TestExplicit(object): ip = None mode = 'explicit' def setup(self): create_link('dummyX', 'dummy') self.ip = IPDB(mode=self.mode) def teardown(self): for name in ('bala_port0', 'bala_port1', 'dummyX', 'bala', 'bv101'): try: with self.ip.interfaces[name] as i: i.remove() except KeyError: pass except NetlinkError as e: if e.code != 19: # No such device raise self.ip.release() 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_ips(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) def test_callback_positive(self): require_user('root') assert 'dummyX' in self.ip.interfaces # test callback, that adds an address by itself -- # just to check the possibility def cb(snapshot, transaction): self.ip.nl.addr('add', self.ip.interfaces.dummyX.index, address='172.16.22.1', mask=24) # register callback and check CB chain length self.ip.interfaces.dummyX.register_callback(cb) assert len(self.ip.interfaces.dummyX._callbacks) == 1 # create a transaction and commit it if self.ip.interfaces.dummyX._mode == 'explicit': self.ip.interfaces.dummyX.begin() self.ip.interfaces.dummyX.add_ip('172.16.21.1/24') self.ip.interfaces.dummyX.commit() # the second address added w/o watchdogs, # so we have to wait time.sleep(1) # added address should be there assert ('172.16.21.1', 24) in self.ip.interfaces.dummyX.ipaddr # and the one, added by the callback, too assert ('172.16.22.1', 24) in self.ip.interfaces.dummyX.ipaddr # unregister callback self.ip.interfaces.dummyX.unregister_callback(cb) assert len(self.ip.interfaces.dummyX._callbacks) == 0 def test_callback_negative(self): require_user('root') assert 'dummyX' in self.ip.interfaces # test exception to differentiate class CBException(Exception): pass # test callback, that always fail def cb(snapshot, transaction): raise CBException() # register callback and check CB chain length self.ip.interfaces.dummyX.register_callback(cb) assert len(self.ip.interfaces.dummyX._callbacks) == 1 # create a transaction and commit it; should fail # 'cause of the callback if self.ip.interfaces.dummyX._mode == 'explicit': self.ip.interfaces.dummyX.begin() self.ip.interfaces.dummyX.add_ip('172.16.21.1/24') try: self.ip.interfaces.dummyX.commit() except CBException: pass # added address should be removed assert ('172.16.21.1', 24) not in self.ip.interfaces.dummyX.ipaddr # unregister callback self.ip.interfaces.dummyX.unregister_callback(cb) assert len(self.ip.interfaces.dummyX._callbacks) == 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') assert 'bala' not in self.ip.interfaces assert 'dummyX' in self.ip.interfaces if self.ip.interfaces.dummyX._mode == 'explicit': self.ip.interfaces.dummyX.begin() self.ip.interfaces.dummyX.ifname = 'bala' self.ip.interfaces.dummyX.commit() assert 'bala' in self.ip.interfaces assert 'dummyX' not in self.ip.interfaces if self.ip.interfaces.bala._mode == 'explicit': self.ip.interfaces.bala.begin() self.ip.interfaces.bala.ifname = 'dummyX' self.ip.interfaces.bala.commit() assert 'bala' not in self.ip.interfaces assert 'dummyX' in self.ip.interfaces 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 assert grep('ip ro', pattern='172.16.0.0/24.*127.0.0.1') # change a 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 a 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 assert not grep('ip ro', pattern='172.16.0.0/24') def _test_shadow(self, kind): a = self.ip.create(ifname='bala', kind=kind).commit() if a._mode == 'explicit': a.begin() a.shadow().commit() assert 'bala' in self.ip.interfaces assert not grep('ip link', pattern='bala') b = self.ip.create(ifname='bala', kind=kind).commit() assert a == b assert grep('ip link', pattern='bala') def test_shadow_bond(self): require_user('root') require_bond() self._test_shadow('bond') def test_shadow_bridge(self): require_user('root') require_bridge() self._test_shadow('bridge') def test_shadow_dummy(self): require_user('root') self._test_shadow('dummy') def test_updown(self): require_user('root') assert not (self.ip.interfaces.dummyX.flags & 1) if self.ip.interfaces.dummyX._mode == 'explicit': self.ip.interfaces.dummyX.begin() self.ip.interfaces.dummyX.up() self.ip.interfaces.dummyX.commit() assert self.ip.interfaces.dummyX.flags & 1 if self.ip.interfaces.dummyX._mode == 'explicit': self.ip.interfaces.dummyX.begin() self.ip.interfaces.dummyX.down() self.ip.interfaces.dummyX.commit() assert not (self.ip.interfaces.dummyX.flags & 1) def test_cfail_rollback(self): require_user('root') require_bridge() # create ports with self.ip.create(kind='dummy', ifname='bala_port0'): pass with self.ip.create(kind='dummy', ifname='bala_port1'): pass assert 'bala_port0' in self.ip.interfaces assert 'bala_port1' in self.ip.interfaces # commits should fail clear_fail_bit(_FAIL_COMMIT) clear_fail_bit(_FAIL_ROLLBACK) try: # create bridge with self.ip.create(kind='bridge', ifname='bala') as i: i.add_ip('172.16.0.1/24') i.add_ip('172.16.0.2/24') i.add_port(self.ip.interfaces.bala_port0) i.add_port(self.ip.interfaces.bala_port1) except RuntimeError: pass finally: # set bit again set_fail_bit(_FAIL_COMMIT) set_fail_bit(_FAIL_ROLLBACK) # expected results: # 1. interface created # 2. no addresses # 3. no ports assert 'bala' in self.ip.interfaces assert 'bala_port0' in self.ip.interfaces assert 'bala_port1' in self.ip.interfaces assert ('172.16.0.1', 24) not in self.ip.interfaces.bala.ipaddr assert ('172.16.0.2', 24) not in self.ip.interfaces.bala.ipaddr assert self.ip.interfaces.bala_port0.index not in \ self.ip.interfaces.bala.ports assert self.ip.interfaces.bala_port1.index not in \ self.ip.interfaces.bala.ports def test_cfail_commit(self): require_user('root') require_bridge() # create ports with self.ip.create(kind='dummy', ifname='bala_port0'): pass with self.ip.create(kind='dummy', ifname='bala_port1'): pass assert 'bala_port0' in self.ip.interfaces assert 'bala_port1' in self.ip.interfaces # commits should fail clear_fail_bit(_FAIL_COMMIT) try: # create bridge with self.ip.create(kind='bridge', ifname='bala') as i: i.add_ip('172.16.0.1/24') i.add_ip('172.16.0.2/24') i.add_port(self.ip.interfaces.bala_port0) i.add_port(self.ip.interfaces.bala_port1) except AssertionError: pass finally: # set bit again set_fail_bit(_FAIL_COMMIT) # expected results: # 1. interface created # 2. no addresses # 3. no ports assert 'bala' in self.ip.interfaces assert 'bala_port0' in self.ip.interfaces assert 'bala_port1' in self.ip.interfaces assert ('172.16.0.1', 24) not in self.ip.interfaces.bala.ipaddr assert ('172.16.0.2', 24) not in self.ip.interfaces.bala.ipaddr assert self.ip.interfaces.bala_port0.index not in \ self.ip.interfaces.bala.ports assert self.ip.interfaces.bala_port1.index not in \ self.ip.interfaces.bala.ports def test_fail_ipaddr(self): require_user('root') assert 'bala' not in self.ip.interfaces i = self.ip.create(ifname='bala', 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 'bala' not in self.ip.interfaces def test_create_fail(self): require_user('root') assert 'bala' not in self.ip.interfaces # create with mac 11:22:33:44:55:66 should fail i = self.ip.create(kind='dummy', ifname='bala', address='11:22:33:44:55:66') try: i.commit() except NetlinkError: pass assert i._mode == 'invalid' assert 'bala' not in self.ip.interfaces def test_create_dqn(self): require_user('root') assert 'bala' not in self.ip.interfaces i = self.ip.create(kind='dummy', ifname='bala') i.add_ip('172.16.0.1/255.255.255.0') i.commit() assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr assert '172.16.0.1/24' in get_ip_addr(interface='bala') def test_create_plain(self): require_user('root') assert 'bala' not in self.ip.interfaces i = self.ip.create(kind='dummy', ifname='bala') i.add_ip('172.16.0.1/24') i.commit() assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr assert '172.16.0.1/24' in get_ip_addr(interface='bala') def test_create_and_remove(self): require_user('root') assert 'bala' not in self.ip.interfaces with self.ip.create(kind='dummy', ifname='bala') as i: i.add_ip('172.16.0.1/24') assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr assert '172.16.0.1/24' in get_ip_addr(interface='bala') with self.ip.interfaces.bala as i: i.remove() assert 'bala' not in self.ip.interfaces def _create_master(self, kind, **kwarg): require_user('root') assert 'bala' not in self.ip.interfaces assert 'bala_port0' not in self.ip.interfaces assert 'bala_port1' not in self.ip.interfaces self.ip.create(kind='dummy', ifname='bala_port0').commit() self.ip.create(kind='dummy', ifname='bala_port1').commit() with self.ip.create(kind=kind, ifname='bala', **kwarg) as i: i.add_port(self.ip.interfaces.bala_port0) i.add_port(self.ip.interfaces.bala_port1) i.add_ip('172.16.0.1/24') assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr assert '172.16.0.1/24' in get_ip_addr(interface='bala') assert self.ip.interfaces.bala_port0.if_master == \ self.ip.interfaces.bala.index assert self.ip.interfaces.bala_port1.if_master == \ self.ip.interfaces.bala.index with self.ip.interfaces.bala as i: i.del_port(self.ip.interfaces.bala_port0) i.del_port(self.ip.interfaces.bala_port1) i.del_ip('172.16.0.1/24') assert ('172.16.0.1', 24) not in self.ip.interfaces.bala.ipaddr assert '172.16.0.1/24' not in get_ip_addr(interface='bala') assert self.ip.interfaces.bala_port0.if_master is None assert self.ip.interfaces.bala_port1.if_master is None def test_create_bridge(self): require_bridge() self._create_master('bridge') def test_create_bond(self): require_bond() self._create_master('bond') def test_create_bond2(self): require_bond() self._create_master('bond', bond_mode=2) def test_create_vlan_by_interface(self): require_user('root') require_8021q() assert 'bala' not in self.ip.interfaces assert 'bv101' not in self.ip.interfaces self.ip.create(kind='dummy', ifname='bala').commit() self.ip.create(kind='vlan', ifname='bv101', link=self.ip.interfaces.bala, vlan_id=101).commit() assert self.ip.interfaces.bv101.if_master == \ self.ip.interfaces.bala.index def test_create_vlan_by_index(self): require_user('root') require_8021q() assert 'bala' not in self.ip.interfaces assert 'bv101' not in self.ip.interfaces self.ip.create(kind='dummy', ifname='bala').commit() self.ip.create(kind='vlan', ifname='bv101', link=self.ip.interfaces.bala.index, vlan_id=101).commit() assert self.ip.interfaces.bv101.if_master == \ self.ip.interfaces.bala.index def test_remove_secondaries(self): require_user('root') assert 'bala' not in self.ip.interfaces with self.ip.create(kind='dummy', ifname='bala') as i: i.add_ip('172.16.0.1', 24) i.add_ip('172.16.0.2', 24) assert 'bala' in self.ip.interfaces assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr assert ('172.16.0.2', 24) in self.ip.interfaces.bala.ipaddr assert '172.16.0.1/24' in get_ip_addr(interface='bala') assert '172.16.0.2/24' in get_ip_addr(interface='bala') 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.bala.ipaddr assert ('172.16.0.2', 24) not in self.ip.interfaces.bala.ipaddr assert '172.16.0.1/24' not in get_ip_addr(interface='bala') assert '172.16.0.2/24' not in get_ip_addr(interface='bala')
from pprint import pprint from pyroute2 import IPDB ip = IPDB() # create an interface i = ip.create(kind='dummy', ifname='pr2test').commit() prev_state = i.nlmsg # change the state i.address = '00:11:22:33:44:55' i.up() i.commit() # show, what has been changed, excluding statistics -- # it changes all the time pprint((i.nlmsg - prev_state).strip( ('IFLA_AF_SPEC', 'IFLA_STATS', 'IFLA_STATS64', 'IFLA_LINKINFO', 'IFLA_MAP'))) i.remove().commit() ip.release()
# 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() ip.unregister_callback(cb) # cleanup for i in ('bala_port0', 'bala_port1', 'br0'):
from pyroute2.common import uifname p0 = uifname() ### # # "Pre" callbacks are executed before the message # gets processed by IPDB, and in synchronous manner. # Normally, you will not need these callbacks, but # they can be useful to perform some hacks # def cb(ipdb, msg, action): if action == 'RTM_NEWLINK': msg['flags'] = 1234 # create IPDB instance ip = IPDB() # register "pre" callback ip.register_callback(cb, mode='pre') # create an interface ip.create(kind='dummy', ifname=p0).commit() # assert flags assert ip.interfaces[p0].flags == 1234 # cleanup ip.interfaces[p0].remove() ip.interfaces[p0].commit() # release Netlink socket ip.release()
class Ipdb: def __init__(self): self.ipdb_controller = None def connect(self, netnspath=None): """Initializa a IPDB object local or over remote netns Args: param1 (string): The netns path to connect for remote management """ try: if netnspath: self.ipdb_controller = IPDB(nl=NetNS(netnspath)) else: self.ipdb_controller = IPDB() except Exception: logging.error('Cannot connect to the namespace indicate') return def create_interface_bridge(self, name): """Create a linux bridge interface over ipdb, Args: name (string): iface name to create """ try: if self.ipdb_controller: self.ipdb_controller.create(ifname=name, kind='bridge').commit() except Exception: logging.error('Cannot create linux bridge interface') return def create_interface(self, name, peer_id=None): """Create interface veth over ipdb, returning a tuple of the iface names created Args: name (string): iface name to create peer_id (string)(optional): According to the type, it is used to compose the iface name of the peer associated Returns: attr1, attr2 (string, string): tuple of interface names created """ try: if self.ipdb_controller: name_iface_peer = name + '_' + peer_id self.ipdb_controller.create(ifname=name, kind='veth', peer=name_iface_peer).commit() return name, name_iface_peer except Exception: logging.error('Cannot create interface') return '', '' def change_status_interface(self, name, status): """Change the status of interface to up|down Args: name (string): iface name to create status (string): status change to (up|down) """ try: with self.ipdb_controller.interfaces[name] as iface: if status == 'up': iface.up() if status == 'down': iface.down() except Exception: logging.error('Cannot change interface status') return def move_interface_tonetns(self, name, netns): """Move inteface to another namespace Args: name (string): iface name to create status (string): status change to (up|down) """ try: with self.ipdb_controller.interfaces[name] as iface: iface.net_ns_fd = netns except Exception: logging.error('Cannot change interface to ' + netns + ' namespace') return def add_port_interface(self, name, iface_port): """Add port to interface (normally for bridge ones) Args: name (string): iface name to attach port iface_port (string): iface name to be attached """ try: with self.ipdb_controller.interfaces[name] as iface: iface.add_port(iface_port) except Exception: logging.error('Cannot add port to interface') return def change_addr_interface(self, name, ip, mask): """Change addr to interface Args: name (string): iface name modify ip_addr ip (string): ip address to establish mask (string): netmask to establish """ try: with self.ipdb_controller.interfaces[name] as iface: iface.add_ip(ip + '/' + mask) except Exception: logging.error('Cannot add port to interface') return
#!/usr/bin/python from pprint import pprint from pyroute2 import IPRoute from pyroute2 import IPDB # high-level interface ipdb = IPDB() interface = ipdb.create(ifname='pr2test', kind='dummy').\ commit().\ add_ip('172.16.0.1/24').\ add_ip('172.16.0.2/24').\ commit() # low-level interface just to get raw messages ip = IPRoute() a = [x for x in ip.get_addr() if x['index'] == interface['index']] print('\n8<--------------------- left operand') pprint(a[0]) print('\n8<--------------------- right operand') pprint(a[1]) print('\n8<--------------------- complement') pprint(a[0] - a[1]) print('\n8<--------------------- intersection') pprint(a[0] & a[1]) interface.remove().commit() ip.release() ipdb.release()
from pyroute2 import IPDB ip = IPDB() # create dummy interface to host routes on ip.create(kind='dummy', ifname='pr2test').\ add_ip('172.16.1.1/24').\ up().\ commit() # create a route with ip.routes.add({'dst': '172.16.0.0/24', 'gateway': '172.16.1.2'}) as r: pass # modify it with ip.routes['172.16.0.0/24'] as r: r.gateway = '172.16.1.3' # cleanup with ip.routes['172.16.0.0/24'] as r: r.remove() ip.interfaces.pr2test.remove().commit() ip.release()
class ConfigApplier(object): def __init__(self): self.ip = IPDB() def _setIpConfig(self, iface): ipConfig = iface.ipConfig if ipConfig.ipaddr: self.removeIpConfig(iface) with self.ip.interfaces[iface.name] as i: i.add_ip('%s/%s' % (ipConfig.ipaddr, ipConfig.netmask)) if ipConfig.gateway and ipConfig.defaultRoute: ipwrapper.routeAdd(['default', 'via', ipConfig.gateway]) def removeIpConfig(self, iface): ipwrapper.addrFlush(iface.name) def setIfaceMtu(self, iface, mtu): with self.ip.interfaces[iface] as i: i['mtu'] = int(mtu) def setBondingMtu(self, iface, mtu): self.setIfaceMtu(iface, mtu) def ifup(self, iface): with self.ip.interfaces[iface.name] as i: i.up() if iface.ipConfig.bootproto == 'dhcp': dhclient = DhcpClient(iface.name) dhclient.start(iface.ipConfig.async) def ifdown(self, iface): with self.ip.interfaces[iface.name] as i: i.down() dhclient = DhcpClient(iface.name) dhclient.shutdown() def setIfaceConfigAndUp(self, iface): if iface.ip: self._setIpConfig(iface) if iface.mtu: self.setIfaceMtu(iface.name, iface.mtu) self.ifup(iface) def addBridge(self, bridge): self.ip.create(kind='bridge', ifname=bridge.name).commit() def addBridgePort(self, bridge): with self.ip.interfaces[bridge.name] as i: i.add_port(self.ip.interfaces[bridge.port.name]) def removeBridge(self, bridge): with self.ip.interfaces[bridge.name] as i: i.remove() def removeBridgePort(self, bridge): with self.ip.interfaces[bridge.name] as i: i.del_port(self.ip.interfaces[bridge.port.name]) def addVlan(self, vlan): link = self.ip.interfaces[vlan.device.name].index self.ip.create(kind='vlan', ifname=vlan.name, link=link, vlan_id=vlan.tag).commit() def removeVlan(self, vlan): with self.ip.interfaces[vlan.name] as i: i.remove() def addBond(self, bond): if bond.name not in netinfo.bondings(): self.ip.create(kind='bond', ifname=bond.name).commit() def removeBond(self, bond): with self.ip.interfaces[bond.name] as i: i.remove() def addBondSlave(self, bond, slave): self.ifdown(slave) with self.ip.interfaces[bond.name] as i: i.add_port(self.ip.interfaces[slave.name]) self.ifup(slave) def removeBondSlave(self, bond, slave): with self.ip.interfaces[bond.name] as i: i.del_port(self.ip.interfaces[slave.name]) def addBondOptions(self, bond): logging.debug('Add bond options %s', bond.options) for option in bond.options.split(): key, value = option.split('=') with open(netinfo.BONDING_OPT % (bond.name, key), 'w') as f: f.write(value) def createLibvirtNetwork(self, network, bridged, iface, qosInbound=None, qosOutbound=None): netXml = libvirt.createNetworkDef(network, bridged, iface, qosInbound, qosOutbound) libvirt.createNetwork(netXml) def removeLibvirtNetwork(self, network): libvirt.removeNetwork(network) def releaseSocket(self): self.ip.release()
class TestExplicit(object): ip = None mode = 'explicit' def setup(self): create_link('dummyX', 'dummy') self.ip = IPDB(mode=self.mode) def teardown(self): self.ip.release() remove_link('bala_port0') remove_link('bala_port1') remove_link('dummyX') remove_link('bala') remove_link('bv101') 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_ips(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) def test_callback_positive(self): require_user('root') assert 'dummyX' in self.ip.interfaces # test callback, that adds an address by itself -- # just to check the possibility def cb(snapshot, transaction): self.ip.nl.addr('add', self.ip.interfaces.dummyX.index, address='172.16.22.1', mask=24) # register callback and check CB chain length self.ip.interfaces.dummyX.register_callback(cb) assert len(self.ip.interfaces.dummyX._callbacks) == 1 # create a transaction and commit it if self.ip.interfaces.dummyX._mode == 'explicit': self.ip.interfaces.dummyX.begin() self.ip.interfaces.dummyX.add_ip('172.16.21.1/24') self.ip.interfaces.dummyX.commit() # added address should be there assert ('172.16.21.1', 24) in self.ip.interfaces.dummyX.ipaddr # and the one, added by the callback, too assert ('172.16.22.1', 24) in self.ip.interfaces.dummyX.ipaddr # unregister callback self.ip.interfaces.dummyX.unregister_callback(cb) assert len(self.ip.interfaces.dummyX._callbacks) == 0 def test_callback_negative(self): require_user('root') assert 'dummyX' in self.ip.interfaces # test exception to differentiate class CBException(Exception): pass # test callback, that always fail def cb(snapshot, transaction): raise CBException() # register callback and check CB chain length self.ip.interfaces.dummyX.register_callback(cb) assert len(self.ip.interfaces.dummyX._callbacks) == 1 # create a transaction and commit it; should fail # 'cause of the callback if self.ip.interfaces.dummyX._mode == 'explicit': self.ip.interfaces.dummyX.begin() self.ip.interfaces.dummyX.add_ip('172.16.21.1/24') try: self.ip.interfaces.dummyX.commit() except CBException: pass # added address should be removed assert ('172.16.21.1', 24) not in self.ip.interfaces.dummyX.ipaddr # unregister callback self.ip.interfaces.dummyX.unregister_callback(cb) assert len(self.ip.interfaces.dummyX._callbacks) == 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') assert 'bala' not in self.ip.interfaces assert 'dummyX' in self.ip.interfaces if self.ip.interfaces.dummyX._mode == 'explicit': self.ip.interfaces.dummyX.begin() self.ip.interfaces.dummyX.ifname = 'bala' self.ip.interfaces.dummyX.commit() assert 'bala' in self.ip.interfaces assert 'dummyX' not in self.ip.interfaces if self.ip.interfaces.bala._mode == 'explicit': self.ip.interfaces.bala.begin() self.ip.interfaces.bala.ifname = 'dummyX' self.ip.interfaces.bala.commit() assert 'bala' not in self.ip.interfaces assert 'dummyX' in self.ip.interfaces def test_updown(self): require_user('root') assert not (self.ip.interfaces.dummyX.flags & 1) if self.ip.interfaces.dummyX._mode == 'explicit': self.ip.interfaces.dummyX.begin() self.ip.interfaces.dummyX.up() self.ip.interfaces.dummyX.commit() assert self.ip.interfaces.dummyX.flags & 1 if self.ip.interfaces.dummyX._mode == 'explicit': self.ip.interfaces.dummyX.begin() self.ip.interfaces.dummyX.down() self.ip.interfaces.dummyX.commit() assert not (self.ip.interfaces.dummyX.flags & 1) def test_ancient_bridge(self): require_user('root') # create ports with self.ip.create(kind='dummy', ifname='bala_port0'): pass with self.ip.create(kind='dummy', ifname='bala_port1'): pass assert 'bala_port0' in self.ip.interfaces assert 'bala_port1' in self.ip.interfaces set_ancient(True) # create bridge try: with self.ip.create(kind='bridge', ifname='bala') as i: i.add_ip('172.16.0.1/24') i.add_ip('172.16.0.2/24') i.add_port(self.ip.interfaces.bala_port0) i.add_port(self.ip.interfaces.bala_port1) finally: set_ancient(False) assert 'bala' in self.ip.interfaces assert 'bala_port0' in self.ip.interfaces assert 'bala_port1' in self.ip.interfaces assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr assert ('172.16.0.2', 24) in self.ip.interfaces.bala.ipaddr assert self.ip.interfaces.bala_port0.index in \ self.ip.interfaces.bala.ports assert self.ip.interfaces.bala_port1.index in \ self.ip.interfaces.bala.ports def test_cfail_rollback(self): require_user('root') # create ports with self.ip.create(kind='dummy', ifname='bala_port0'): pass with self.ip.create(kind='dummy', ifname='bala_port1'): pass assert 'bala_port0' in self.ip.interfaces assert 'bala_port1' in self.ip.interfaces # commits should fail clear_fail_bit(_FAIL_COMMIT) clear_fail_bit(_FAIL_ROLLBACK) try: # create bridge with self.ip.create(kind='bridge', ifname='bala') as i: i.add_ip('172.16.0.1/24') i.add_ip('172.16.0.2/24') i.add_port(self.ip.interfaces.bala_port0) i.add_port(self.ip.interfaces.bala_port1) except RuntimeError: pass finally: # set bit again set_fail_bit(_FAIL_COMMIT) set_fail_bit(_FAIL_ROLLBACK) # expected results: # 1. interface created # 2. no addresses # 3. no ports assert 'bala' in self.ip.interfaces assert 'bala_port0' in self.ip.interfaces assert 'bala_port1' in self.ip.interfaces assert ('172.16.0.1', 24) not in self.ip.interfaces.bala.ipaddr assert ('172.16.0.2', 24) not in self.ip.interfaces.bala.ipaddr assert self.ip.interfaces.bala_port0.index not in \ self.ip.interfaces.bala.ports assert self.ip.interfaces.bala_port1.index not in \ self.ip.interfaces.bala.ports def test_cfail_commit(self): require_user('root') # create ports with self.ip.create(kind='dummy', ifname='bala_port0'): pass with self.ip.create(kind='dummy', ifname='bala_port1'): pass assert 'bala_port0' in self.ip.interfaces assert 'bala_port1' in self.ip.interfaces # commits should fail clear_fail_bit(_FAIL_COMMIT) try: # create bridge with self.ip.create(kind='bridge', ifname='bala') as i: i.add_ip('172.16.0.1/24') i.add_ip('172.16.0.2/24') i.add_port(self.ip.interfaces.bala_port0) i.add_port(self.ip.interfaces.bala_port1) except AssertionError: pass finally: # set bit again set_fail_bit(_FAIL_COMMIT) # expected results: # 1. interface created # 2. no addresses # 3. no ports assert 'bala' in self.ip.interfaces assert 'bala_port0' in self.ip.interfaces assert 'bala_port1' in self.ip.interfaces assert ('172.16.0.1', 24) not in self.ip.interfaces.bala.ipaddr assert ('172.16.0.2', 24) not in self.ip.interfaces.bala.ipaddr assert self.ip.interfaces.bala_port0.index not in \ self.ip.interfaces.bala.ports assert self.ip.interfaces.bala_port1.index not in \ self.ip.interfaces.bala.ports def test_create_fail(self): require_user('root') assert 'bala' not in self.ip.interfaces # create with mac 11:22:33:44:55:66 should fail i = self.ip.create(kind='dummy', ifname='bala', address='11:22:33:44:55:66') try: i.commit() except NetlinkError: pass assert i._mode == 'invalid' assert 'bala' not in self.ip.interfaces def test_create_plain(self): require_user('root') assert 'bala' not in self.ip.interfaces i = self.ip.create(kind='dummy', ifname='bala') i.add_ip('172.16.0.1/24') i.commit() assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr assert '172.16.0.1/24' in get_ip_addr(interface='bala') def test_create_and_remove(self): require_user('root') assert 'bala' not in self.ip.interfaces with self.ip.create(kind='dummy', ifname='bala') as i: i.add_ip('172.16.0.1/24') assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr assert '172.16.0.1/24' in get_ip_addr(interface='bala') with self.ip.interfaces.bala as i: i.remove() assert 'bala' not in self.ip.interfaces def _create_master(self, kind): require_user('root') assert 'bala' not in self.ip.interfaces assert 'bala_port0' not in self.ip.interfaces assert 'bala_port1' not in self.ip.interfaces self.ip.create(kind='dummy', ifname='bala_port0').commit() self.ip.create(kind='dummy', ifname='bala_port1').commit() with self.ip.create(kind=kind, ifname='bala') as i: i.add_port(self.ip.interfaces.bala_port0) i.add_port(self.ip.interfaces.bala_port1) i.add_ip('172.16.0.1/24') assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr assert '172.16.0.1/24' in get_ip_addr(interface='bala') assert self.ip.interfaces.bala_port0.if_master == \ self.ip.interfaces.bala.index assert self.ip.interfaces.bala_port1.if_master == \ self.ip.interfaces.bala.index with self.ip.interfaces.bala as i: i.del_port(self.ip.interfaces.bala_port0) i.del_port(self.ip.interfaces.bala_port1) i.del_ip('172.16.0.1/24') assert ('172.16.0.1', 24) not in self.ip.interfaces.bala.ipaddr assert '172.16.0.1/24' not in get_ip_addr(interface='bala') assert self.ip.interfaces.bala_port0.if_master is None assert self.ip.interfaces.bala_port1.if_master is None def test_create_bridge(self): self._create_master('bridge') def test_create_bond(self): self._create_master('bond') def test_create_vlan(self): require_user('root') assert 'bala' not in self.ip.interfaces assert 'bv101' not in self.ip.interfaces self.ip.create(kind='dummy', ifname='bala').commit() self.ip.create(kind='vlan', ifname='bv101', link=self.ip.interfaces.bala.index, vlan_id=101).commit() assert self.ip.interfaces.bv101.if_master == \ self.ip.interfaces.bala.index def test_remove_secondaries(self): require_user('root') assert 'bala' not in self.ip.interfaces with self.ip.create(kind='dummy', ifname='bala') as i: i.add_ip('172.16.0.1', 24) i.add_ip('172.16.0.2', 24) assert 'bala' in self.ip.interfaces assert ('172.16.0.1', 24) in self.ip.interfaces.bala.ipaddr assert ('172.16.0.2', 24) in self.ip.interfaces.bala.ipaddr assert '172.16.0.1/24' in get_ip_addr(interface='bala') assert '172.16.0.2/24' in get_ip_addr(interface='bala') 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.bala.ipaddr assert ('172.16.0.2', 24) not in self.ip.interfaces.bala.ipaddr assert '172.16.0.1/24' not in get_ip_addr(interface='bala') assert '172.16.0.2/24' not in get_ip_addr(interface='bala')
''' Example: python ./examples/create_bond.py Creates bond interface. ''' from pyroute2 import IPDB ip = IPDB() try: # The same scheme works for bridge interfaces too: you # can create a bridge interface and enslave some ports # to it just as below. ip.create(kind='dummy', ifname='port0').commit() ip.create(kind='dummy', ifname='port1').commit() with ip.create(kind='bond', ifname='bond,james') as i: # enslave two interfaces: tap0 and tap1 i.add_port(ip.interfaces.port0) i.add_port(ip.interfaces.port1) # make an example more scary: add IPs to the bond,james i.add_ip('10.251.0.1/24') i.add_ip('10.251.0.2/24') finally: for i in ('port0', 'port1', 'bond,james'): try: ip.interfaces[i].remove().commit() except: pass
def execRequest(self, action, data): if action == 'Plugin.Activate': return HttpResponse(200, 'json', { 'Implements': ['NetworkDriver', 'IPAM'] }).response if action == 'NetworkDriver.GetCapabilities': return HttpResponse(200, 'json', {'Scope': 'local'}).response if action == 'IPAM.GetDefaultAddressSpaces': requestPool = {} return HttpResponse(200, 'json', requestPool).response if action == 'IPAM.RequestPool': self.subnet = data['Pool'] requestPool = {} requestPool['Pool'] = self.subnet return HttpResponse(200, 'json', requestPool).response if action == 'IPAM.RequestAddress': plen = self.subnet.split('/')[1] requestAddress = {} if 'Address' not in data: reply = { 'error': 'missing gateway, specify one with --gateway' } return HttpResponse(500, 'json', reply).response requestAddress['Address'] = data['Address'] + '/' + plen return HttpResponse(200, 'json', requestAddress).response if action == 'IPAM.ReleaseAddress': address = {} address['Address'] = data['Address'] return HttpResponse(200, 'json', address).response if action == 'IPAM.ReleasePool': pool = {} return HttpResponse(200, 'json', pool).response if action == 'NetworkDriver.CreateNetwork': subnet = data['IPv4Data'][0]['Pool'] gateway = data['IPv4Data'][0]['Gateway'].split('/')[0] rtList = [] if 'rt' in data['Options']['com.docker.network.generic']: rt = data['Options']['com.docker.network.generic']['rt'] rtList = rt.split(',') openContrailVN = OpenContrailVN(data['NetworkID']).createNw( subnet, gateway, rtList) return HttpResponse(200, 'json', {}).response if action == 'NetworkDriver.DeleteNetwork': openContrailVN = OpenContrailVN(data['NetworkID']).deleteNw() return HttpResponse(200, 'json', {}).response if action == 'NetworkDriver.CreateEndpoint': networkId = data['NetworkID'] endpointId = data['EndpointID'] hostId = endpointId[:8] ipAddress = data['Interface']['Address'] result = OpenContrailVirtualMachineInterface(hostId).createVmi( networkId, ipAddress) interface = {} interface['Interface'] = {} interface['Interface']['MacAddress'] = result['mac'] return HttpResponse(200, 'json', interface).response if action == 'NetworkDriver.DeleteEndpoint': endpointId = data['EndpointID'] hostId = endpointId[:8] OpenContrailVirtualMachineInterface(hostId).deleteVmi() endpointId = data['EndpointID'] vethIdHost = 'veth' + endpointId[:8] + 'p0' ip = IPDB() with ip.interfaces[vethIdHost] as veth: veth.remove() return HttpResponse(200, 'json', {}).response if action == 'NetworkDriver.EndpointOperInfo': endpointInfo = {} endpointInfo['NetworkID'] = data['NetworkID'] endpointInfo['EndpointID'] = data['EndpointID'] return HttpResponse(200, 'json', endpointInfo).response if action == 'NetworkDriver.Join': endpointId = data['EndpointID'] hostId = endpointId[:8] networkId = data['NetworkID'] vethIdHost = 'veth' + endpointId[:8] + 'p0' vethIdContainer = 'veth' + endpointId[:8] vn = OpenContrailVN(networkId).VNget() subnet = vn.network_ipam_refs[0]['attr'].ipam_subnets[0] gateway = subnet.default_gateway mac = OpenContrailVirtualMachineInterface(hostId).getMac() ip = IPDB() ip.create(ifname=vethIdHost, kind='veth', peer=vethIdContainer).commit() with ip.interfaces[vethIdHost] as veth: veth.up() with ip.interfaces[vethIdContainer] as veth: veth.address = mac joinInfo = {} joinInfo['InterfaceName'] = {} joinInfo['InterfaceName']['SrcName'] = vethIdContainer joinInfo['InterfaceName']['DstPrefix'] = 'eth' joinInfo['Gateway'] = gateway #joinInfo['GatewayIPv6'] = '2000::2' joinInfo['StaticRoutes'] = [] #staticRoute = {} #staticRoute['Destination'] = '2.2.2.0/24' #staticRoute['RouteType'] = 0 #staticRoute['NextHop'] = '1.1.1.1' #joinInfo['StaticRoutes'].append(staticRoute) return HttpResponse(200, 'json', joinInfo).response if action == 'NetworkDriver.Leave': return HttpResponse(200, 'json', {}).response
def prepare_namespaces(graph, dry_run=False, instance_id=None): """ Create a veth-connected mesh from :data:`graph` :param networkx.Graph graph: The graph defining the test mesh :param bool dry_run: If set makes Meshinery not touch any namespaces :param str instance_id: If set changes the middle section of each namespace's name; current PID by default :return networkx.Graph: The same graph containing runtime attributes """ if instance_id is None: instance_id = os.getpid() # Create namespaces for node_name in graph.nodes: ns_name = 'meshinery-{}-{}'.format(instance_id, node_name) logging.info('Adding namespace "{}"'.format(ns_name)) if not dry_run: # Establish the namespace ns = NetNS(ns_name) ipdb = IPDB(nl=ns) ipdb.interfaces['lo'].up().commit() ipdb.commit() ipdb.release() # Enable forwarding sysctl_cmd = shlex.split( 'sysctl -w net.ipv4.conf.all.forwarding=1 net.ipv6.conf.all.forwarding=1' ) subprocess.run(sysctl_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).check_returncode() graph.node[node_name]['netns'] = ns_name graph.node[node_name]['interfaces'] = [ ] # Needed so that we can safely append later # Create veth bridges for node_name, neigh_name in graph.edges: neighbors = graph[node_name] node = graph.node[node_name] neigh = graph.node[neigh_name] # If an edge hasn't been created yet node_iface = '{}-{}'.format(node_name, neigh_name) neigh_iface = '{}-{}'.format(neigh_name, node_name) if not dry_run: node_ns_handle = NetNS(node['netns']) neigh_ns_handle = NetNS(neigh['netns']) ipdb = IPDB() # Create namespace-aware IPDB handles node_ipdb = IPDB(nl=node_ns_handle) neigh_ipdb = IPDB(nl=neigh_ns_handle) # Create a veth pair ipdb.create(ifname=node_iface, kind='veth', peer=neigh_iface).commit() # Assign node IP ipdb.interfaces[node_iface]['net_ns_fd'] = node['netns'] ipdb.commit() node_ipdb.interfaces[node_iface].add_ip(node['ip']) node_ipdb.interfaces[node_iface].up().commit() # Assign neighbor IP ipdb.interfaces[neigh_iface].add_ip(neigh['ip']) ipdb.interfaces[neigh_iface]['net_ns_fd'] = neigh['netns'] ipdb.commit() neigh_ipdb.interfaces[neigh_iface].add_ip(neigh['ip']) neigh_ipdb.interfaces[neigh_iface].up().commit() ipdb.release() node_ipdb.release() neigh_ipdb.release() node['interfaces'].append(node_iface) neigh['interfaces'].append(neigh_iface) logging.debug('Created %s and %s interfaces' % (node_iface, neigh_iface)) ipdb.release()
i.remove() if 'tap' + args.ifname in ip.interfaces: with ip.interfaces['tap' + args.ifname] as i: i.remove() if brige_name in ip.interfaces: with ip.interfaces[brige_name] as i: i.remove() for ifn in range(args.ifnum): netns = NetNS('node' + str(ifn)) netns.close() netns.remove() else: for ifn in range(args.ifnum): iface = args.ifname + str(ifn) if not iface in ip.interfaces: ip.create(kind='veth', ifname=iface, peer=iface + '.1').commit() ip.create(kind='tuntap', ifname='tap' + args.ifname, mode='tap').commit() with ip.create(kind='bridge', ifname=brige_name) as i: for ifn in range(args.ifnum): iface = args.ifname + str(ifn) i.add_port(ip.interfaces[iface]) i.add_port(ip.interfaces['tap' + args.ifname]) if args.ipv4: i.add_ip(local_addr4 + '1/24') if args.ipv6: i.add_ip(local_addr6 + '1/64') i.up()
Creates dummy interface. ''' from pyroute2 import IPDB ip = IPDB() try: # dummy, bridge and bond interfaces are created in the # same way -- just use appropriate name # # Warning! do not use name 'bond0' # Warning! do not use name 'dummy0' # details of this restriction are in the documentation # # possible kinds: # * bond # * bridge # * dummy # * vlan -- see /examples/create_vlan.py # dummy = ip.create(kind='dummy', ifname='dummy_name') dummy.commit() finally: try: dummy.remove().commit() except: pass ip.release()
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() ip.unregister_callback(cb) # cleanup for i in ('bala_port0', 'bala_port1', 'br0'):
class InfrasimNamespace(object): def __init__(self, vswitch_instance, ns_info): self.__ns_info = ns_info self.name = ns_info['name'] self.ip = IPRoute() # self.ipdb = IPDB(nl=NetNS(self.name)) self.main_ipdb = IPDB() self.__vswitch = vswitch_instance @staticmethod def get_namespaces_list(): return netns.listnetns() def build_one_namespace(self): self._create_namespace() for intf in self.__ns_info["interfaces"]: # get name ifname = intf["ifname"] if intf.get("pair") is False: self.create_single_virtual_intf_in_ns(intf) else: global interface_index self.create_ip_link_in_ns(ifname, "veth{}".format(interface_index)) if 'bridge' in intf: self.create_bridge(intf=ifname, br_name=intf['bridge']['ifname']) self.__vswitch.add_port("veth{}".format(interface_index)) idx = self.ip.link_lookup( ifname="veth{}".format(interface_index))[0] self.ip.link("set", index=idx, state="up") interface_index += 1 def _create_namespace(self): if self.name in self.get_namespaces_list(): print "name space {} exists.".format(self.name) return netns.create(self.name) def del_namespace(self): if self.name in netns.listnetns(): netns.remove(self.name) def create_single_virtual_intf_in_ns(self, intf): ifname = intf['ifname'] if len(self.ip.link_lookup(ifname=ifname)) > 0: print "ip link {} exists so not create it.".format(ifname) return self.main_ipdb.create(ifname=ifname, kind="dummy").commit() with self.main_ipdb.interfaces[ifname] as veth: veth.net_ns_fd = self.name if 'bridge' in intf: self.create_bridge(intf=ifname, br_name=intf['bridge']['ifname']) def create_ip_link_in_ns(self, ifname, peername): if len(self.ip.link_lookup(ifname=ifname)) > 0: print "ip link {} exists so not create it.".format(ifname) return if len(self.ip.link_lookup(ifname=peername)) > 0: print "ip link {} exists so not create it.".format(peername) return # create link peer self.main_ipdb.create(ifname=ifname, kind="veth", peer=peername).commit() with self.main_ipdb.interfaces[ifname] as veth: veth.net_ns_fd = self.name def exec_cmd_in_namespace(self, cmd): start_process(["ip", "netns", "exec", self.name] + cmd) def link_up_all(self): # setup lo # self.exec_cmd_in_namespace(["ifdown", "lo"]) # self.exec_cmd_in_namespace(["ifup", "lo"]) self.exec_cmd_in_namespace(["ip", "link", "set", "dev", "lo", "up"]) for intf_info in self.__ns_info["interfaces"]: if "bridge" in intf_info: self.exec_cmd_in_namespace( ["ip", "link", "set", "dev", intf_info["ifname"], "up"]) self.exec_cmd_in_namespace( ["ifdown", intf_info["bridge"]["ifname"]]) self.exec_cmd_in_namespace( ["ifup", intf_info["bridge"]["ifname"]]) else: self.exec_cmd_in_namespace(["ifdown", intf_info["ifname"]]) self.exec_cmd_in_namespace(["ifup", intf_info["ifname"]]) def create_bridge(self, intf="einf0", br_name="br0"): self.exec_cmd_in_namespace(["brctl", "addbr", "{}".format(br_name)]) self.exec_cmd_in_namespace( ["brctl", "addif", "{}".format(br_name), intf]) self.exec_cmd_in_namespace( ["brctl", "setfd", "{}".format(br_name), "0"]) self.exec_cmd_in_namespace( ["brctl", "sethello", "{}".format(br_name), "1"]) self.exec_cmd_in_namespace( ["brctl", "stp", "{}".format(br_name), "no"]) self.exec_cmd_in_namespace(["ifconfig", intf, "promisc"]) def build_ns_configuration(self): netns_path = "/etc/netns" ns_network_dir = os.path.join(netns_path, self.name, "network") if_down_dir = os.path.join(ns_network_dir, "if-down.d") if not os.path.exists(if_down_dir): os.makedirs(if_down_dir) if_post_down_dir = os.path.join(ns_network_dir, "if-post-down.d") if not os.path.exists(if_post_down_dir): os.makedirs(if_post_down_dir) if_pre_up_dir = os.path.join(ns_network_dir, "if-pre-up.d") if not os.path.exists(if_pre_up_dir): os.makedirs(if_pre_up_dir) if_up_dir = os.path.join(ns_network_dir, "if-up.d") if not os.path.exists(if_up_dir): os.makedirs(if_up_dir) content = "" content += "auto lo\n" content += "iface lo inet loopback\n" content += "\n" intf_list = [] for intf_info in self.__ns_info["interfaces"]: intf_obj = Interface(intf_info) intf_list.append(intf_obj) for iobj in intf_list: content += iobj.compose() with open(os.path.join(ns_network_dir, "interfaces"), "w") as f: f.write(content)
class ConfigApplier(object): def __init__(self): self.ip = IPDB() def _setIpConfig(self, iface): ipv4 = iface.ipv4 ipv6 = iface.ipv6 if ipv4.address or ipv6.address: self.removeIpConfig(iface) if ipv4.address: with self.ip.interfaces[iface.name] as i: i.add_ip(ipv4.address + '/' + ipv4.netmask) if ipv4.gateway and ipv4.defaultRoute: self.ip.routes.add({'dst': 'default', 'gateway': ipv4.gateway}).commit() if ipv6.address: with self.ip.interfaces[iface.name] as i: i.add_ip(ipv6.address) if ipv6.gateway: self.ip.routes.add({'dst': 'default', 'gateway': ipv6.gateway}).commit() if ipv6.ipv6autoconf is not None: with open('/proc/sys/net/ipv6/conf/%s/autoconf' % iface.name, 'w') as ipv6_autoconf: ipv6_autoconf.write('1' if ipv6.ipv6autoconf else '0') def removeIpConfig(self, iface): ipwrapper.addrFlush(iface.name) def setIfaceMtu(self, iface, mtu): with self.ip.interfaces[iface] as i: i['mtu'] = int(mtu) def setBondingMtu(self, iface, mtu): self.setIfaceMtu(iface, mtu) def ifup(self, iface): with self.ip.interfaces[iface.name] as i: i.up() if iface.ipv4.bootproto == 'dhcp': runDhclient(iface) if iface.ipv6.dhcpv6: runDhclient(iface, 6) def ifdown(self, iface): with self.ip.interfaces[iface.name] as i: i.down() dhclient = DhcpClient(iface.name) dhclient.shutdown() def setIfaceConfigAndUp(self, iface): if iface.ipv4 or iface.ipv6: self._setIpConfig(iface) if iface.mtu: self.setIfaceMtu(iface.name, iface.mtu) self.ifup(iface) def addBridge(self, bridge): self.ip.create(kind='bridge', ifname=bridge.name).commit() def addBridgePort(self, bridge): with self.ip.interfaces[bridge.name] as i: i.add_port(self.ip.interfaces[bridge.port.name]) def removeBridge(self, bridge): with self.ip.interfaces[bridge.name] as i: i.remove() def removeBridgePort(self, bridge): with self.ip.interfaces[bridge.name] as i: i.del_port(self.ip.interfaces[bridge.port.name]) def addVlan(self, vlan): link = self.ip.interfaces[vlan.device.name].index self.ip.create(kind='vlan', ifname=vlan.name, link=link, vlan_id=vlan.tag).commit() def removeVlan(self, vlan): with self.ip.interfaces[vlan.name] as i: i.remove() def addBond(self, bond): if bond.name not in netinfo.bondings(): self.ip.create(kind='bond', ifname=bond.name).commit() def removeBond(self, bond): with self.ip.interfaces[bond.name] as i: i.remove() def addBondSlave(self, bond, slave): self.ifdown(slave) with self.ip.interfaces[bond.name] as i: i.add_port(self.ip.interfaces[slave.name]) self.ifup(slave) def removeBondSlave(self, bond, slave): with self.ip.interfaces[bond.name] as i: i.del_port(self.ip.interfaces[slave.name]) def addBondOptions(self, bond): logging.debug('Add bond options %s', bond.options) for option in bond.options.split(): key, value = option.split('=') with open(netinfo.BONDING_OPT % (bond.name, key), 'w') as f: f.write(value) def createLibvirtNetwork(self, network, bridged=True, iface=None): netXml = libvirt.createNetworkDef(network, bridged, iface) libvirt.createNetwork(netXml) def removeLibvirtNetwork(self, network): libvirt.removeNetwork(network) def releaseSocket(self): self.ip.release()
from pyroute2 import IPDB from pyroute2.common import uifname p0 = uifname() ip = IPDB() # create dummy interface to host routes on ip.create(kind='dummy', ifname=p0).add_ip('172.16.1.1/24').up().commit() # create a route with ip.routes.add({'dst': '172.16.0.0/24', 'gateway': '172.16.1.2'}) as r: pass # modify it with ip.routes['172.16.0.0/24'] as r: r.gateway = '172.16.1.3' # cleanup with ip.routes['172.16.0.0/24'] as r: r.remove() ip.interfaces[p0].remove().commit() ip.release()
from pprint import pprint from pyroute2 import IPDB from pyroute2.common import uifname ip = IPDB(debug=True) # create an interface i = ip.create(kind='dummy', ifname=uifname()).commit() prev_state = i.nlmsg # change the state i.address = '00:11:22:33:44:55' i.up() i.commit() # show, what has been changed, excluding statistics -- # it changes all the time pprint((i.nlmsg - prev_state).strip(('IFLA_AF_SPEC', 'IFLA_STATS', 'IFLA_STATS64', 'IFLA_LINKINFO', 'IFLA_MAP'))) i.remove().commit() ip.release()
def execRequest(self, action, data): if action == 'Plugin.Activate': return HttpResponse(200,'json',{ 'Implements': ['NetworkDriver','IPAM'] }).response if action == 'NetworkDriver.GetCapabilities': return HttpResponse(200,'json',{ 'Scope':'local'}).response if action == 'IPAM.GetDefaultAddressSpaces': requestPool = {} return HttpResponse(200,'json',requestPool).response if action == 'IPAM.RequestPool': self.subnet = data['Pool'] requestPool = {} requestPool['Pool'] = self.subnet return HttpResponse(200,'json',requestPool).response if action == 'IPAM.RequestAddress': plen = self.subnet.split('/')[1] requestAddress = {} if 'Address' not in data: reply = { 'error':'missing gateway, specify one with --gateway' } return HttpResponse(500,'json',reply).response requestAddress['Address'] = data['Address'] + '/' + plen return HttpResponse(200,'json',requestAddress).response if action == 'IPAM.ReleaseAddress': address = {} address['Address'] = data['Address'] return HttpResponse(200,'json',address).response if action == 'IPAM.ReleasePool': pool = {} return HttpResponse(200,'json',pool).response if action == 'NetworkDriver.CreateNetwork': subnet = data['IPv4Data'][0]['Pool'] gateway = data['IPv4Data'][0]['Gateway'].split('/')[0] rtList = [] if 'rt' in data['Options']['com.docker.network.generic']: rt = data['Options']['com.docker.network.generic']['rt'] rtList = rt.split(',') openContrailVN = OpenContrailVN(data['NetworkID']).createNw(subnet, gateway, rtList) return HttpResponse(200,'json',{ }).response if action == 'NetworkDriver.DeleteNetwork': openContrailVN = OpenContrailVN(data['NetworkID']).deleteNw() return HttpResponse(200,'json',{ }).response if action == 'NetworkDriver.CreateEndpoint': networkId = data['NetworkID'] endpointId = data['EndpointID'] hostId = endpointId[:8] ipAddress = data['Interface']['Address'] result = OpenContrailVirtualMachineInterface(hostId).createVmi(networkId, ipAddress) interface = {} interface['Interface'] = {} interface['Interface']['MacAddress'] = result['mac'] return HttpResponse(200,'json',interface).response if action == 'NetworkDriver.DeleteEndpoint': endpointId = data['EndpointID'] hostId = endpointId[:8] OpenContrailVirtualMachineInterface(hostId).deleteVmi() endpointId = data['EndpointID'] vethIdHost = 'veth' + endpointId[:8] + 'p0' ip = IPDB() with ip.interfaces[vethIdHost] as veth: veth.remove() return HttpResponse(200,'json',{ }).response if action == 'NetworkDriver.EndpointOperInfo': endpointInfo = {} endpointInfo['NetworkID'] = data['NetworkID'] endpointInfo['EndpointID'] = data['EndpointID'] return HttpResponse(200,'json',endpointInfo).response if action == 'NetworkDriver.Join': endpointId = data['EndpointID'] hostId = endpointId[:8] networkId = data['NetworkID'] vethIdHost = 'veth' + endpointId[:8] + 'p0' vethIdContainer = 'veth' + endpointId[:8] vn = OpenContrailVN(networkId).VNget() subnet = vn.network_ipam_refs[0]['attr'].ipam_subnets[0] gateway = subnet.default_gateway mac = OpenContrailVirtualMachineInterface(hostId).getMac() ip = IPDB() ip.create(ifname=vethIdHost, kind='veth', peer=vethIdContainer).commit() with ip.interfaces[vethIdHost] as veth: veth.up() with ip.interfaces[vethIdContainer] as veth: veth.address = mac joinInfo = {} joinInfo['InterfaceName'] = {} joinInfo['InterfaceName']['SrcName'] = vethIdContainer joinInfo['InterfaceName']['DstPrefix'] = 'eth' joinInfo['Gateway'] = gateway #joinInfo['GatewayIPv6'] = '2000::2' joinInfo['StaticRoutes'] = [] #staticRoute = {} #staticRoute['Destination'] = '2.2.2.0/24' #staticRoute['RouteType'] = 0 #staticRoute['NextHop'] = '1.1.1.1' #joinInfo['StaticRoutes'].append(staticRoute) return HttpResponse(200,'json',joinInfo).response if action == 'NetworkDriver.Leave': return HttpResponse(200,'json',{ }).response
''' Example: python ./examples/create_bond.py Creates bond interface. ''' from pyroute2 import IPDB ip = IPDB(mode='explicit') try: # The same scheme works for bridge interfaces too: you # can create a bridge interface and enslave some ports # to it just as below. with ip.create(kind='bond', ifname='bond,james') as i: # enslave two interfaces: tap0 and tap1 i.add_port(ip.interfaces.tap0) i.add_port(ip.interfaces.tap1) # make an example more scary: add IPs to the bond,james i.add_ip('10.251.0.1/24') i.add_ip('10.251.0.2/24') finally: ip.release()
Master is an interface to add VLAN to, e.g. eth0 or tap0 or whatever else. Without parameters use tap0 as the default. ''' from pyroute2 import IPDB from pyroute2.common import uifname ip = IPDB() try: # unique interface names ms = uifname() vn = uifname() master = ip.create(ifname=ms, kind='dummy').commit() with ip.create(kind='vlan', ifname=vn, link=master, vlan_id=101) as i: # Arguments for ip.create() are executed before the transaction, # in the IPRoute.link('add', ...) call. If create() fails, the # interface became invalid and is not operable, you can safely # drop it. # # Here goes the rest of transaction. If it fails, the interface # continues to work, only failed transaction gets dropped. i.add_ip('10.251.0.1', 24) i.add_ip('10.251.0.2', 24) i.mtu = 1400 finally: try:
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)
def create_ns(br_name, ns_name, ns_ip, ns_netmask, if_description, add_if): """ :param br_name: :param ns_name: :param ns_ip: :param ns_netmask: :param if_description: :param add_if: :return: """ # start the main network settings database: ipdb = IPDB() # Check if the bridge exists if br_name not in ipdb.interfaces.keys(): log.fatal("Could not find bridge %s!" % br_name) sys.exit(-1) # veth naming ifname = "%s_%s_p%%d" % (ns_name, if_description) if (ifname % 0) in ipdb.interfaces.keys(): log.fatal("%s already exists as interface!" % (ifname % 0)) return False log.debug("Creating veth pair %s - %s for namespace %s." % (ifname % 0, ifname % 1, ns_name)) if ns_name in netns.listnetns() and not add_if: log.warning("Namespace %s already exists!" % ns_name) # Create/configure a network namespace ipdb_ns = IPDB(nl=NetNS(ns_name)) # Make sure lo is up in the namespace ipdb_ns.interfaces["lo"].up().commit() # Create veth pair ipdb.create(kind='veth', ifname=(ifname % 0), peer=(ifname % 1)).commit() # Move peer veth into the netns with ipdb.interfaces[(ifname % 1)] as veth: veth.net_ns_fd = ns_name with ipdb.interfaces[(ifname % 0)] as veth: veth.up() # wait for iface to be moved to ns time.sleep(0.1) ns_ip = '%s/%s' % (ns_ip, ns_netmask) log.debug("Assigning IP %s to %s." % (ns_ip, (ifname % 1))) with ipdb_ns.interfaces[(ifname % 1)] as veth: veth.add_ip(ns_ip) veth.up() log.debug("Adding port %s to bridge %s." % ((ifname % 0), br_name)) ipdb.interfaces[br_name].add_port((ifname % 0)) ipdb.commit() return True
''' Example: python ./examples/create_vlan.py [master] Master is an interface to add VLAN to, e.g. eth0 or tap0 or whatever else. Without parameters use tap0 as the default. ''' from pyroute2 import IPDB ip = IPDB() try: master = ip.create(ifname='pr2test', kind='dummy').commit() with ip.create(kind='vlan', ifname='v101', link=master, vlan_id=101) as i: # Arguments for ip.create() are executed before the transaction, # in the IPRoute.link('add', ...) call. If create() fails, the # interface became invalid and is not operable, you can safely # drop it. # # Here goes the rest of transaction. If it fails, the interface # continues to work, only failed transaction gets dropped. i.add_ip('10.251.0.1', 24) i.add_ip('10.251.0.2', 24) i.mtu = 1400 finally: try: ip.interfaces.pr2test.remove().commit() except: pass
class ConfigApplier(object): def __init__(self): self.ip = IPDB() def _setIpConfig(self, iface): ipv4 = iface.ipv4 ipv6 = iface.ipv6 if ipv4.address or ipv6.address: self.removeIpConfig(iface) if ipv4.address: with self.ip.interfaces[iface.name] as i: i.add_ip(ipv4.address + '/' + ipv4.netmask) if ipv4.gateway and ipv4.defaultRoute: self.ip.routes.add({ 'dst': 'default', 'gateway': ipv4.gateway }).commit() if ipv6.address: with self.ip.interfaces[iface.name] as i: i.add_ip(ipv6.address) if ipv6.gateway: self.ip.routes.add({ 'dst': 'default', 'gateway': ipv6.gateway }).commit() if ipv6.ipv6autoconf is not None: with open('/proc/sys/net/ipv6/conf/%s/autoconf' % iface.name, 'w') as ipv6_autoconf: ipv6_autoconf.write('1' if ipv6.ipv6autoconf else '0') def removeIpConfig(self, iface): ipwrapper.addrFlush(iface.name) def setIfaceMtu(self, iface, mtu): with self.ip.interfaces[iface] as i: i['mtu'] = int(mtu) def setBondingMtu(self, iface, mtu): self.setIfaceMtu(iface, mtu) def ifup(self, iface): with self.ip.interfaces[iface.name] as i: i.up() if iface.ipv4.bootproto == 'dhcp': dhclient.run(iface.name, 4, iface.ipv4.defaultRoute, iface.duid_source, iface.blockingdhcp) if iface.ipv6.dhcpv6: dhclient.run(iface.name, 6, iface.ipv6.defaultRoute, iface.duid_source, iface.blockingdhcp) def ifdown(self, iface): with self.ip.interfaces[iface.name] as i: i.down() dhclient.stop(iface.name) def setIfaceConfigAndUp(self, iface): if iface.ipv4 or iface.ipv6: self._setIpConfig(iface) if iface.mtu: self.setIfaceMtu(iface.name, iface.mtu) self.ifup(iface) def addBridge(self, bridge): self.ip.create(kind='bridge', ifname=bridge.name).commit() def addBridgePort(self, bridge): with self.ip.interfaces[bridge.name] as i: i.add_port(self.ip.interfaces[bridge.port.name]) def removeBridge(self, bridge): with self.ip.interfaces[bridge.name] as i: i.remove() def removeBridgePort(self, bridge): with self.ip.interfaces[bridge.name] as i: i.del_port(self.ip.interfaces[bridge.port.name]) def addVlan(self, vlan): link = self.ip.interfaces[vlan.device.name].index self.ip.create(kind='vlan', ifname=vlan.name, link=link, vlan_id=vlan.tag).commit() def removeVlan(self, vlan): with self.ip.interfaces[vlan.name] as i: i.remove() def addBond(self, bond): if bond.name not in netinfo.bondings(): self.ip.create(kind='bond', ifname=bond.name).commit() def removeBond(self, bond): with self.ip.interfaces[bond.name] as i: i.remove() def addBondSlave(self, bond, slave): self.ifdown(slave) with self.ip.interfaces[bond.name] as i: i.add_port(self.ip.interfaces[slave.name]) self.ifup(slave) def removeBondSlave(self, bond, slave): with self.ip.interfaces[bond.name] as i: i.del_port(self.ip.interfaces[slave.name]) def addBondOptions(self, bond): logging.debug('Add bond options %s', bond.options) # 'custom' is not a real bond option, it just piggybacks custom values options = remove_custom_bond_option(bond.options) for option in options.split(): key, value = option.split('=') with open(netinfo.BONDING_OPT % (bond.name, key), 'w') as f: f.write(value) def createLibvirtNetwork(self, network, bridged=True, iface=None): netXml = libvirt.createNetworkDef(network, bridged, iface) libvirt.createNetwork(netXml) def removeLibvirtNetwork(self, network): libvirt.removeNetwork(network) def releaseSocket(self): self.ip.release()
from pyroute2 import IPDB from pyroute2.common import uifname ip = IPDB() try: # create unique interface names p0 = uifname() p1 = uifname() ms = uifname() # The same scheme works for bridge interfaces too: you # can create a bridge interface and enslave some ports # to it just as below. ip.create(kind='dummy', ifname=p0).commit() ip.create(kind='dummy', ifname=p1).commit() with ip.create(kind='bond', ifname=ms) as i: # enslave two interfaces i.add_port(ip.interfaces[p0]) i.add_port(ip.interfaces[p1]) # make an example more scary: add IPs i.add_ip('10.251.0.1/24') i.add_ip('10.251.0.2/24') finally: for i in (p0, p1, ms): try: ip.interfaces[i].remove().commit() except:
i.remove() if 'tap'+args.ifname in ip.interfaces: with ip.interfaces['tap'+args.ifname] as i: i.remove() if brige_name in ip.interfaces: with ip.interfaces[brige_name] as i: i.remove() for ifn in range(args.ifnum): netns = NetNS('node'+str(ifn)) netns.close() netns.remove() else: for ifn in range(args.ifnum): iface = args.ifname+str(ifn) if not iface in ip.interfaces: ip.create(kind='veth', ifname=iface, peer=iface+'.1').commit() ip.create(kind='tuntap', ifname='tap'+args.ifname, mode='tap').commit() with ip.create(kind='bridge', ifname=brige_name) as i: for ifn in range(args.ifnum): iface = args.ifname+str(ifn) i.add_port(ip.interfaces[iface]) i.add_port(ip.interfaces['tap'+args.ifname]) if args.ipv4: i.add_ip(local_addr4+'1/24') if args.ipv6: i.add_ip(local_addr6+'1/64') i.up() with ip.interfaces['tap'+args.ifname] as tap:
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)