def initContainerNetwork(self, network=None): if not network: try: network = Network(None) network.name = 'cygnet_internal' network.address = self['internal_ip'] if not self.ovs_client.bridgeExists(network.name): self.ovs_client.addBridge(network.name) self.ovs_client.setBridgeProperty(network.name, 'stp_enable', True) except KeyError as e: print("OpenvSwitch: CYGNET_INTERNAL_IP \ environment variable not found") raise e else: network.name = "cygnet_" + network.id[:8] if not self.ovs_client.bridgeExists(network.name): self.ovs_client.addBridge(network.name) self.ovs_client.setBridgeProperty(network.name, 'stp_enable', True) ip = IPDB() ifaces = ip.interfaces ifaces[network.name].begin() ifaces[network.name].add_ip(network.address, network.mask) ifaces[network.name].up() ifaces[network.name].commit() ip.release() self.interfaces.append(network) return network
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 __ovs_setup(self): if not self.ovs_client.bridgeExists('cygnet0'): self.ovs_client.addBridge('cygnet0') self.ovs_client.addPort('cygnet0', self.external_iface) elif not self.ovs_client.portExists(self.external_iface): self.ovs_client.addPort('cygnet0', self.external_iface) ip = IPDB() ifaces = ip.interfaces ifaces.cygnet0.begin() addrs= ip.interfaces[self.external_iface].ipaddr.raw addr = None for address, attrs in addrs.items(): if __getIPv4Addr__([address]) == None: continue addr = address ifaces.cygnet0.add_ip(addr[0], int(addr[1])) ifaces.cygnet0.up() ifaces.cygnet0.commit() ifaces[self.external_iface].begin() ifaces[self.external_iface].down() ifaces[self.external_iface].commit() ifaces[self.external_iface].begin() ifaces[self.external_iface].up() ifaces[self.external_iface].commit() 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_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()
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_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)
def test_fail_released(self): ip = IPDB() ip.release() try: ip.interfaces.lo.up() except RuntimeError: pass
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
def test_ipdb(self): require_user('root') ip = IPDB() try: assert ip._nl_async is False assert len(ip.interfaces.keys()) > 1 except: raise finally: ip.release()
def destroyInterface(self): ipdb = IPDB() with ipdb.interfaces[self.bridge_iface] as i: i.del_port(ipdb.interfaces[self.veth0]) with ipdb.interfaces[self.veth0] as i: i.remove() ipdb.release()
def deleteService(name, terminalName): if_svc_name = name if_terminal_name = name + '_' + terminalName ip_host = IPDB() with ip_host.interfaces[if_terminal_name] as veth: veth.remove() ip_host.release() subprocess.call(["ovs-vsctl", "del-port", "vs-" + name, if_svc_name]) subprocess.call(["ovs-vsctl", "del-port", "br0", if_terminal_name]) subprocess.call(["ovs-vsctl", "del-br", "vs-" + name]) return json.dumps({ 'status' : 'deleted service'})
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 initalize(self): ip = IPDB() try: # Check if public interface is up self.addr = __getIPv4Addr__(list(ip.interfaces.br1.ipaddr)) self.addr = self.addr[0], str(self.addr[1]) self.interfaces.append(('br1', self.addr)) except Exception as e: print(e) finally: ip.release() self.range_buckets[int(self.addr[0].split(".")[-1])] = 1 return self.addr
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 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 initalize(self): # check if our setup already exists self.__ovs_setup() ip = IPDB() try: # Check if public interface is up self.addr = __getIPv4Addr__(list(ip.interfaces.cygnet0.ipaddr)) self.addr = self.addr[0], str(self.addr[1]) #self.interfaces.append(('cygnet0', self.addr)) except Exception as e: raise e finally: ip.release() self.range_buckets[int(self.addr[0].split(".")[-1])] = 1 return self.addr
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_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 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 TestPopen(TestBasic): def setup(self): self.ipdb = IPDB() self.io = io.BytesIO() self.con = subprocess.Popen(['python', '%s/bin/ipdb' % TMPDIR], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) def teardown(self): self.ipdb.release() def feed(self, script): out, err = self.con.communicate(script.encode('ascii')) self.io.write(out) self.con.wait()
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 _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_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
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')
def find_ip(iface): if not iface or iface == 'any': return ('0.0.0.0','') if_ip4 = None if_ip6 = None ipdb = IPDB() try: for ip in ipdb.interfaces[iface].ipaddr: if_ip = ipaddress.ip_address(ip[0]) if isinstance(if_ip, ipaddress.IPv4Address): if_ip4 = ip[0] elif isinstance(if_ip, ipaddress.IPv6Address): if not if_ip.is_link_local: if_ip6 = ip[0] if if_ip4 and if_ip6: break except Exception as e: pass finally: ipdb.release() return (if_ip4, if_ip6)
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()
class TestDirect(object): def setup(self): create_link('dummyX', 'dummy') self.ip = IPDB(mode='direct') def teardown(self): self.ip.release() remove_link('dummyX') def test_context_fail(self): try: with self.ip.interfaces.lo as i: i.down() except TypeError: pass print("cfail done") def test_updown(self): require_user('root') assert not (self.ip.interfaces['dummyX'].flags & 1) self.ip.interfaces['dummyX'].up() assert self.ip.interfaces['dummyX'].flags & 1 self.ip.interfaces['dummyX'].down() assert not (self.ip.interfaces['dummyX'].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
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 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()
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 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()
def createService(data): print data name = data['name'] svcId = data['Id'] svcIdString = str(data['Id']) ip = data['dhcpip'] network = data['subnet'] customer = data['customer'] routetarget = data['routetarget'] terminal = data['terminal'] vr = data['virtualrouter'] if 'move' in data: move = data['move'] oldvr = data['oldvr'] oldId = data['oldId'] else: move = False if 'add' in data: add = data['add'] else: add = False print name if_svc_name = name + '_' + svcIdString if_svc_peer_name = name + '_' + svcIdString + '_v' ip_ns = IPDB(nl=NetNS(name + '_' + svcIdString)) ip_host = IPDB() ip_host.create(ifname=if_svc_name, kind='veth', peer=if_svc_peer_name).commit() subprocess.call(["ovs-vsctl", "add-port", "br0", if_svc_name]) subprocess.call(["ovs-vsctl", "set", "port", if_svc_name, "tag=" + str(svcId)]) netmask = network.split('/')[1] ip = ip + '/' + netmask createDhcpConfig(name, network, vr, customer, svcIdString) with ip_host.interfaces[if_svc_name] as veth: veth.up() with ip_host.interfaces[if_svc_peer_name] as veth: veth.net_ns_fd = name + '_' + svcIdString with ip_ns.interfaces[if_svc_peer_name] as veth: veth.address = 'de:ad:be:ef:ba:be' veth.add_ip(ip) veth.up() ip_host.release() ip_ns.release() nsp = NSPopen(name + '_' + svcIdString, ['dnsmasq', '-C', '/etc/dnsmasq.d/' + name + '.conf'], stdout=subprocess.PIPE) nsp.wait() nsp.release() if not move or add: try: vn = createVirtualNetwork(customer, name, network, routetarget) except: print 'failed to create VN' phInt = getPhysicalInterface(vr, serviceInterface) lif = createLogicalInterface(phInt, name + '_' + svcIdString, str(svcId)) if move: oldlif = getLogicalInterface(oldvr, name + '_' + str(oldId)) if oldlif.get_virtual_machine_interface_refs(): for vmInt in oldlif.get_virtual_machine_interface_refs(): vmIntObj = vnc_client.virtual_machine_interface_read(id = vmInt['uuid']) ''' if vmIntObj.get_instance_ip_back_refs(): for instIp in vmIntObj.get_instance_ip_back_refs(): instIpObj = vnc_client.instance_ip_read(id = instIp['uuid']) epIp = instIpObj.get_instance_ip_address() epMac = vmIntObj.get_virtual_machine_interface_mac_addresses().get_mac_address()[0] vn = getVirtualNetwork(customer, name) vmInterface = createVirtualMachineInterface(customer, name, epMac) createInstanceIp(epIp, vmInterface, vn) lif.add_virtual_machine_interface(vmInterface) ''' oldlif.del_virtual_machine_interface(vmIntObj) lif.add_virtual_machine_interface(vmIntObj) vnc_client.logical_interface_update(oldlif) vnc_client.logical_interface_update(lif) ''' if os.path.isfile('/mnt/' + name + '.lease'): f = open('/mnt/' + name + '.lease', 'r') leases = f.readlines() f.close() for lease in leases: epMac = lease.split(' ')[1] epIp = lease.split(' ')[2] vn = getVirtualNetwork(customer, name) vmInterface = createVirtualMachineInterface(customer, name, epMac) createInstanceIp(epIp, vmInterface, vn) lif.add_virtual_machine_interface(vmInterface) vnc_client.logical_interface_update(lif) ''' return json.dumps({ 'status' : 'created service'})
def main(): ip = IPDB() s = set([interface.ifname for interface in ip.interfaces.values()]) try: s.remove('lo') s.remove('metadata') except: logger.error("Metadata or lo not found!\n") try: with open('/monroe/config') as configfile: config = json.load(configfile) nodeid = config['nodeid'] except: nodeid = 'could-not-get-id' try: with open('/monroe/config') as configfile: config = json.load(configfile) operator = config['operator'] except: operator = 'N/A' subprocess.call(['mkdir', '/tmp/res/']) result_files = [] for item in s: if item in ['op0', 'op1', 'op2']: logger.debug("Running on interface: " + item) try: subprocess.call(['route', 'del', 'default']) subprocess.call(['route', 'add', 'default', 'dev', item]) add_dns(item) process = subprocess.Popen( ['java', '-jar', '/opt/monroe/NetalyzrCLI.jar'], stdout=subprocess.PIPE) result = process.communicate()[0] wr_str = "/tmp/res/mnr-" + nodeid + "_" + item try: dnsproc = subprocess.Popen(['cat', '/etc/resolv.conf'], stdout=subprocess.PIPE) result_dns = dnsproc.communicate()[0] except Exception as e: result_dns = e with open(wr_str, 'w') as wr_file: wr_file.write("ID: " + str(nodeid) + "\n") wr_file.write("Interface: " + item + "\n") wr_file.write("Operator: " + str(operator) + "\n") wr_file.write("Resolv.conf:\n" + str(result_dns) + "\n") result_files.append(wr_str) with open(wr_str, 'a') as wr_file: wr_file.write(result) process = subprocess.Popen([ 'curl', 'https://stat.ripe.net/data/whats-my-ip/data.json' ], stdout=subprocess.PIPE) result = process.communicate()[0] with open(wr_str, 'a') as wr_file: wr_file.write(result) except Exception as e: logger.error(e) for result_file in result_files: try: subprocess.call(['/usr/bin/mv', result_file, '/monroe/results/']) except: pass 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): 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')
if sys.platform[:3] == 'win': print('Intended to be executed in a mininet Linux environment.') raise RuntimeError() try: from pyroute2 import IPDB except ImportError: print('Dependency missing: pip install pyroute2') sys.exit(1) ip = IPDB() SIM_BCAST = ip.interfaces[[ x for x in ip.interfaces if ip.interfaces[x]['state'] == 'up' and isinstance(x, str) and str(x) != 'lo' ][0]].ipaddr[0]['broadcast'] ip.release() del ip SIM_PORT = 20202 # UDP port used for the simulation information exchange between the different RTUs BUFFER_SIZE = 512 DATA_FMT = '<IIIIIff' # Sender-ID Receiver-ID Message-ID IARG-0 IARG-1 FARG-0 FARG-1 # Message ID MSG_WERE = 0 MSG_ISAT = 1 MSG_GETV = 2 MSG_VOLT = 3 MSG_GREQ = 4 MSG_TREQ = 5 MSG_UKWN = 99
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()
with ip.interfaces[iface] as i: i.up() ip_ns = IPDB(nl=nns) try: with ip_ns.interfaces.lo as lo: lo.up() with ip_ns.interfaces[iface1] as i: if args.ipv4: i.add_ip(local_addr4 + str(ifn + 8) + '/24') if args.ipv6: i.add_ip(local_addr6 + str(ifn + 8) + '/64') i.up() finally: ip_ns.release() nsp = NSPopen(nns.netns, [ "tc", "qdisc", "add", "dev", iface1, "root", "netem", "delay", str(args.delay) + "ms", str(int(args.delay / 2)) + "ms", "loss", str(args.loss) + "%", "25%" ], stdout=subprocess.PIPE) #print(nsp.communicate()[0].decode()) nsp.communicate() nsp.wait() nsp.release() if args.ipv4:
class NetworkBackendBridgedPyroute2( NetworkBackendBridged.NetworkBackendBridged()): """ Use pyroute2 to setup the network. """ def __init__(self, network_backend_boot_strapper): super(NetworkBackendBridgedPyroute2, self).__init__(network_backend_boot_strapper) self.ipdb = None def get_ipdb(self): global ipdb if self.ipdb is None: from pyroute2 import IPDB # ipdb = IPDB() # https://github.com/svinota/pyroute2/issues/304#issuecomment-259275184 import pyroute2.netlink.rtnl as rtnl GROUPS = rtnl.RTNLGRP_LINK | rtnl.RTNLGRP_NEIGH | rtnl.RTNLGRP_IPV4_IFADDR | rtnl.RTNLGRP_IPV6_IFADDR | rtnl.RTNLGRP_IPV4_ROUTE | rtnl.RTNLGRP_IPV6_ROUTE | rtnl.RTNLGRP_IPV4_MROUTE GROUPS = \ rtnl.RTNLGRP_LINK | \ rtnl.RTNLGRP_NEIGH | \ rtnl.RTNLGRP_IPV4_IFADDR | \ rtnl.RTNLGRP_IPV4_ROUTE | \ rtnl.RTNLGRP_IPV4_MROUTE | \ rtnl.RTNLGRP_IPV6_IFADDR | \ rtnl.RTNLGRP_IPV6_ROUTE | \ rtnl.RTNLGRP_MPLS_ROUTE # rtnl.RTNLGRP_NONE |\ # rtnl.RTNLGRP_NOTIFY |\ # rtnl.RTNLGRP_IPV4_RULE |\ # rtnl.RTNLGRP_DECnet_IFADDR |\ # rtnl.RTNLGRP_DECnet_ROUTE |\ # rtnl.RTNLGRP_DECnet_RULE |\ # rtnl.RTNLGRP_IPV6_MROUTE |\ # rtnl.RTNLGRP_IPV6_IFINFO |\ # rtnl.RTNLGRP_IPV6_PREFIX |\ # rtnl.RTNLGRP_IPV6_RULE | \ # rtnl.RTNLGRP_NOP2 |\ # rtnl.RTNLGRP_NOP4 |\ # rtnl.RTNLGRP_TC |\ # .*_ROUTE # AttributeError: 'IPDB' object has no attribute 'routes' # .*_IFADDR # AttributeError: 'IPDB' object has no attribute 'by_name' self.ipdb = IPDB(nl_async="process", nl_bind_groups=GROUPS) # import pyroute2 # ipr = pyroute2.IPRoute() # ipb = pyroute2.IPBatch() # ipb.link("add", index=550, kind="dummy", ifname="test2") # ipr.sendto(ipb.batch, (0, 0)) # ipdb = IPDB(nl_async="process") # run_shell("renice -n {} {}".format(-20, self.ipdb.mnl.async_cache.pid)) run_shell("chrt -f -p {} {}".format( 1, self.ipdb.mnl.async_cache.pid)) return self.ipdb def do_network_topology_change(self): # TOOD: REMOVE? with lock: super(NetworkBackendBridgedPyroute2, self).do_network_topology_change() try: ipdb = self.get_ipdb() get_ipdb_logger().info("commit()") ipdb.commit() # for interface in ipdb.by_name.keys(): # ifc = ipdb.interfaces[interface] # tx = None # e_count = 0 # while True: # try: # if tx is None: # tx = ifc.current_tx # if tx is not None: # ifc.commit(transaction=tx) # ifc.drop() # # IPRoute.get_links() # # break # except: # e_count += 1 # if e_count > 3: # break except Exception as e: try: log.critical(e.__dict__) except BaseException: pass # try: # log.critical(e.debug['traceback']) # except: # pass # try: # log.critical(e.debug['transaction']) # except: # pass raise def reset(self): super(NetworkBackendBridgedPyroute2, self).reset() log.debug("stopping ipdb instance") if self.ipdb: self.ipdb.release() self.ipdb = None
def test_fail_released(self): ip = IPDB() ip.release() assert len(ip.interfaces.keys()) == 0
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)
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)
class TestBasic(object): def readfunc(self, prompt): ret = self.queue.get() if ret is None: raise Exception("EOF") else: return ret def setup(self): self.ipdb = IPDB() if sys.version_info[0] == 2: self.io = io.BytesIO() else: self.io = io.StringIO() self.queue = Queue() self.con = Console(stdout=self.io) self.con.isatty = False self.thread = threading.Thread(target=self.con.interact, args=[ self.readfunc, ]) self.thread.start() def feed(self, script): for line in script.split("\n"): self.queue.put(line) self.queue.put(None) self.thread.join() self.thread = None self.io.flush() def teardown(self): if self.thread is not None: self.queue.put(None) self.thread.join() self.ipdb.release() try: self.con.close() except: pass # 8<---------------- test routines ------------------------------ def test_dump_lo(self): self.feed(scripts['test_dump_lo']) interface = json.loads(self.io.getvalue()) assert interface['address'] == '00:00:00:00:00:00' # # ip addresses not present in the NDB dumps yet # # assert ('127.0.0.1', 8) in interface['ipaddr'] def _test_ensure(self): require_user('root') self.feed(scripts['test_ensure']) assert 'test01' in self.ipdb.interfaces assert ('172.16.189.5', 24) in self.ipdb.interfaces.test01.ipaddr self.ipdb.interfaces.test01.remove().commit() def test_comments_bang(self): require_user('root') self.feed(scripts['test_comments_bang']) interface = json.loads(self.io.getvalue()) assert interface['address'] == '00:11:22:33:44:55' assert interface['ifname'] == 'test01' def test_comments_hash(self): require_user('root') self.feed(scripts['test_comments_hash']) interface = json.loads(self.io.getvalue()) assert interface['address'] == '00:11:22:33:44:55' assert interface['ifname'] == 'test01' def test_comments_mixed(self): require_user('root') self.feed(scripts['test_comments_mixed']) interface = json.loads(self.io.getvalue()) assert interface['address'] == '00:11:22:33:44:55' assert interface['ifname'] == 'test01'
class Console(code.InteractiveConsole): def __init__(self, stdout=None): global HAS_READLINE self.ipdb = IPDB() self.ptr = self.ipdb self.ptrname = None self.stack = [] self.matches = [] self.isatty = sys.stdin.isatty() self.prompt = '' self.stdout = stdout or sys.stdout self.set_prompt() code.InteractiveConsole.__init__(self) if HAS_READLINE: readline.parse_and_bind('tab: complete') readline.set_completer(self.completer) readline.set_completion_display_matches_hook(self.display) def close(self): self.ipdb.release() def write(self, text=''): self.lprint(text) def pprint(self, text=''): pprint(text, stream=self.stdout) self.stdout.flush() def lprint(self, text='', end='\n'): print(text, file=self.stdout, end=end) self.stdout.flush() def help(self): self.lprint("Built-in commands: \n" "debug\t-- run pdb (if installed)\n" "exit\t-- exit cli\n" "ls\t-- list current namespace\n" ".\t-- print the current object\n" ".. or ;\t-- one level up\n") def set_prompt(self, prompt=None): if self.isatty: if isinstance(self.ptr, Interface): self.prompt = 'if : %s > ' % (self.ptr.ifname) elif prompt is not None: self.prompt = '%s > ' % (prompt) else: self.prompt = '%s > ' % (self.ptr.__class__.__name__) self.prompt = '%s@%s : %s' % (getpass.getuser(), (socket.gethostname().split('.')[0]), self.prompt) def convert(self, arg): if re.match('^[0-9]+$', arg): return int(arg) else: return arg def interact(self, readfunc=None): if readfunc is None: readfunc = self.raw_input if self.isatty: self.lprint("IPDB cli prototype") while True: try: cmd = readfunc(self.prompt) except: self.lprint() break # strip comments fbang = cmd.find('!') fhash = cmd.find('#') if fbang >= 0: cmd = cmd[:fbang] if cmd.find('#') >= 0: cmd = cmd[:fhash] # skip empty strings if not len(cmd.strip()): continue # calculate leading whitespaces lcmd = cmd.lstrip() lspaces = len(cmd) - len(lcmd) # strip all whitespaces cmd = cmd.strip() # compare spaces with self.ptr if not self.isatty: while self.stack and self.stack[-1][2] >= lspaces: # pop stack self.ptr, self.ptrname, spaces = self.stack.pop() # compare spaces if spaces == lspaces: break elif spaces < lspaces: self.lprint('indentation warning: <%s>' % cmd) break self.set_prompt(self.ptrname) if not cmd: continue elif cmd == 'debug': if HAS_PDB: pdb.set_trace() else: self.lprint("pdb is not available") elif cmd == 'exit': break elif cmd == 'ls': self.lprint(dir(self.ptr)) elif cmd == 'help': self.help() elif cmd == '.': self.lprint(repr(self.ptr)) elif cmd in ('..', ';'): if self.stack: self.ptr, self.ptrname, lspaces = self.stack.pop() self.set_prompt(self.ptrname) else: # parse the command line into tokens # # symbols .:/ etc. are needed to represent IP addresses # as whole tokens # # quotes should be stripped # parser = shlex.shlex(cmd) parser.wordchars += '.:/-+*' pre_tokens = list(parser) tokens = [] for token in pre_tokens: if token[0] == token[-1] and token[0] in ("\"'"): tokens.append(token[1:-1]) else: tokens.append(token) # an attribute obj = getattr(self.ptr, tokens[0], None) if obj is None: # try a kay try: obj = self.ptr[self.convert(cmd)] except Exception: self.lprint('object not found') continue if hasattr(obj, '__call__'): argv = [] kwarg = {} length = len(tokens) x = 1 while x < len(tokens): # is it a kwarg? if x < length - 2 and tokens[x + 1] == '=': kwarg[tokens[x]] = self.convert(tokens[x + 2]) x += 3 else: argv.append(self.convert(tokens[x])) x += 1 try: ret = obj(*argv, **kwarg) if ret and not isinstance(ret, (Transactional, IPDB)): self.pprint(ret) except: self.showtraceback() else: if isinstance(obj, (basestring, int, float)): # is it a simple attribute? if isinstance(self.ptr, Transactional) and \ len(tokens) > 1: # set it self.ptr[tokens[0]] = self.convert(tokens[1]) else: # or print it self.pprint(self.ptr[tokens[0]]) else: # otherwise change the context self.stack.append((self.ptr, self.ptrname, lspaces)) self.ptr = obj self.ptrname = tokens[0] self.set_prompt(tokens[0]) def completer(self, text, state): if state == 0: d = [x for x in dir(self.ptr) if x.startswith(text)] if isinstance(self.ptr, dict): keys = [str(y) for y in self.ptr.keys()] d.extend([x for x in keys if x.startswith(text)]) self.matches = d try: return self.matches[state] except: pass def display(self, line, matches, length): self.lprint() self.lprint(matches) self.lprint('%s%s' % (self.prompt, line), end='')
disable_ipv6=True)) # For each namespace that want to connect to the ebpf bridge # We link it to the dummy interface behind which we run ebpf learning/forwarding code # logically: Attaching individual namespace interface into the ebpf bridge. # programmatically: running ebpf engress code on each interface temp_index=1 for host in host_info: ipr.tc("add", "ingress", host[1].index, "ffff:") ipr.tc("add-filter", "bpf", host[1].index, ":1", fd=ingress_fn.fd, name=ingress_fn.name, parent="ffff:", action="drop", classid=1) # Passing namespace interface info to dataplane module. conf[c_int(temp_index)] = c_int(host[1].index) temp_index=temp_index+1 try: sim = BridgeSimulation(ipdb) sim.start() input("Press enter to quit:") except Exception,e: print str(e) if "sim" in locals(): for p in sim.processes: p.kill(); p.wait(); p.release() finally: if "ebpf_br" in ipdb.interfaces: ipdb.interfaces["ebpf_br"].remove().commit() if "sim" in locals(): sim.release() ipdb.release() null.close()
def clean(graph, dry_run=False, instance_id=None, strays=False): """ Remove namespaces listed in :data:`graph` and stop scripts :param networkx.Graph graph: The graph for which we want to clean up :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 after cleanup """ if instance_id is None: instance_id = os.getpid() # Remove namespaces and kill running commands if applicable for node_name in graph: node = graph.node[node_name] netns_name = 'meshinery-{}-{}'.format(instance_id, node_name) try: if not dry_run: netns.remove(netns_name) logging.info('Removed namespace {}'.format(netns_name)) # The namespace does not exist except FileNotFoundError as e: logging.debug('Namespace {} doesn\'t exist - not removing'.format( netns_name)) # Grab the per-node command and see if it's still running cmd_handle = node.get('command_handle') if cmd_handle is not None: if cmd_handle.poll() is not None: logging.warn('{}: "{}" was not running at cleanup time'.format( node_name, node['command'])) # Play nice - send initial SIGTERM cmd_handle.terminate() logging.debug('{}: Sent SIGTERM to PID {} ("{}")'.format( node['netns'], cmd_handle.pid, node['command'])) # Wait the specified/default time before nuclear option command_exit_delay = node.get('command_exit_delay', DEFAULT_COMMAND_EXIT_TIMEOUT) time.sleep(command_exit_delay) # Send the SIGKILL if applicable if cmd_handle.poll() is None: cmd_handle.kill() logging.debug( '{nn}: "{cmd}" was SIGKILLed (was PID {pid})'.format( nn=node_name, cmd=node['command'], pid=cmd_handle.pid)) else: logging.debug( '{nn}: "{cmd}" quit gracefully. (was PID {pid})'.format( nn=node_name, cmd=node['command'], pid=cmd_handle.pid)) stdout, stderr = cmd_handle.communicate() logging.debug('{nn}: "{cmd}" stdout:\n{out}'.format( nn=node_name, cmd=node['command'], out=str(stdout, 'utf-8'))) logging.debug('{nn}: "{cmd}" stderr:\n{err}'.format( nn=node_name, cmd=node['command'], err=str(stderr, 'utf-8'))) else: logging.debug('{}: No command to stop.'.format(node_name)) # Remove stray interfaces if strays: ipdb = IPDB() for node_name_a, node_name_b in graph.edges: if_name = '{}-{}'.format(node_name_a, node_name_b) try: ipdb.interfaces[if_name].remove() logging.info('Removed stray interface {}'.format(if_name)) except KeyError as e: logging.debug( 'Stray interface {} doesn\'t exist -- not removing'.format( if_name)) ipdb.commit() ipdb.release()