def test_fd_leaks(self): for i in range(RESPAWNS): nsid = 'leak_%i' % i ns = NetNS(nsid) ns.close() ns.remove() if hasattr(atexit, '_exithandlers'): assert ns.close not in atexit._exithandlers
def test_fd_leaks(self): namespaces = [] for i in range(RESPAWNS): nsid = "leak_%i" % i ns = NetNS(nsid) ns.close() ns.remove() namespaces.append(ns) if sys.version_info > (3, 2) and sys.version_info < (3, 6): for n in namespaces: assert_raises(OSError, fcntl.fcntl, n.server.sentinel, fcntl.F_GETFD)
def test_create_from_path(self): ns_dir = tempfile.mkdtemp() # Create namespace ns_name = str(uuid4()) nspath = '%s/%s' % (ns_dir, ns_name) temp_ns = NetNS(nspath) temp_ns.close() fd = open(nspath) self._test_create(nspath, fd.fileno()) fd.close() netnsmod.remove(nspath) assert ns_name not in netnsmod.listnetns() assert ns_name not in netnsmod.listnetns(ns_dir)
def destroy(self, nsname = 'ns', service = 'ZV'): if self.nsname == '': self.nsname = nsname if not self.is_exist(self.nsname): logging.info("[NS:%s] Namespace is not exist" % (self.nsname)) return if self.service == '': self.service = service if self.ns == None: self.ns = NetNS(self.nsname) if self.veth0 == '': self.veth0 = 'veth0' + self.nsname if self.veth1 == '': self.veth1 = 'veth1' + self.nsname if self.bridge_iface == '': self.bridge_iface = self.service + '-BR' self.destroyInterface() self.ns.close() self.ns.remove() logging.info("[NS:%s] Destroy namespace" % (self.nsname))
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_get_netns_info(self): require_user('root') nsname = str(uuid.uuid4()) netns = NetNS(nsname) try: peer = {'ifname': self.uifname(), 'net_ns_fd': nsname} ifname = self._create_veth(peer) # get veth veth = self.ip.link('get', ifname=ifname)[0] target = veth.get_attr('IFLA_LINK_NETNSID') for info in self.ip.get_netns_info(): path = info.get_attr('NSINFO_PATH') assert path.endswith(nsname) netnsid = info['netnsid'] if target == netnsid: break else: raise KeyError('peer netns not found') finally: netns.close() netns.remove()
def test_vrouter(self): require_user('root') nsid = str(uuid.uuid4()) ns = NetNS(nsid) ipdb = IPDB() ipns = IPDB(nl=ns) try: ipdb.create(ifname='ve0p0', peer='ve0p1', kind='veth').commit() ipdb.interfaces.ve0p1.net_ns_fd = nsid ipdb.commit() with ipns.interfaces.ve0p1 as i: i.set_ifname('eth0') i.up() except: raise finally: ipdb.interfaces.ve0p0.remove() ipdb.commit() ipdb.release() ipns.release() ns.remove()
def test_netns(self): ns = NetNS(str(uuid.uuid4())) try: assert len(ns.get_links()) > 1 except: raise finally: ns.close() ns.remove()
def _test_create(self, ns_name, ns_fd=None): require_user('root') ipdb_main = IPDB() ipdb_test = IPDB(nl=NetNS(ns_name)) 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 = ns_fd or ns_name # 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() assert ret_ping assert ret_arp
def _ns_worker(netns_path, worker_index, success): with IPRoute() as ip, NetNS(netns_path) as ns: try: veth_outside = 'veth%s-o' % worker_index veth_inside = 'veth%s-i' % worker_index ip.link('add', ifname=veth_outside, kind='veth', peer=veth_inside) veth_outside_idx = ip.link_lookup(ifname=veth_outside)[0] ip.link('set', index=veth_outside_idx, state='up') veth_inside_idx = ip.link_lookup(ifname=veth_inside)[0] ip.link('set', index=veth_inside_idx, net_ns_fd=netns_path) veth_inside_idx = ns.link_lookup(ifname=veth_inside)[0] ns.link('set', index=veth_inside_idx, state='up') except Exception: success[0] = False finally: if veth_outside_idx is not None: ip.link('del', index=veth_outside_idx)
def test_fd_leaks(self): namespaces = [] for i in range(RESPAWNS): nsid = 'leak_%i' % i ns = NetNS(nsid) ns.close() ns.remove() namespaces.append(ns) if sys.version_info > (3, 2) and sys.version_info < (3, 6): for n in namespaces: assert_raises(OSError, fcntl.fcntl, n.server.sentinel, fcntl.F_GETFD)
def test_create_veth_attrs(self): require_user('root') nsname = str(uuid.uuid4()) netns = NetNS(nsname) try: peer = {'ifname': self.uifname(), 'net_ns_fd': nsname} self._create_veth(peer) assert len(self.ip.link_lookup(ifname=peer['ifname'])) == 0 assert len(netns.link_lookup(ifname=peer['ifname'])) > 0 finally: netns.close() netns.remove()
def test_create_tuntap(self): require_user('root') # actually this test checks the nlsocket plugin feedback # in a pair of remote client/server foo = str(uuid4()) tun = uifname() tap = uifname() with IPDB(nl=NetNS(foo)) as ip: ip.create(ifname=tun, kind='tuntap', mode='tun').commit() ip.create(ifname=tap, kind='tuntap', mode='tap').commit() assert tun in ip.interfaces.keys() assert tap in ip.interfaces.keys() ip.interfaces[tun].remove().commit() ip.interfaces[tap].remove().commit() assert tun not in ip.interfaces.keys() assert tap not in ip.interfaces.keys() netnsmod.remove(foo)
def create(self, nsname = 'ns', service = 'ZV'): signal.signal(signal.SIGINT, self.kill) signal.signal(signal.SIGTERM, self.kill) if self.is_exist(nsname): logging.info("[NS:%s] Namespace is exist" % (nsname)) return self.nsname = nsname self.service = service self.ns = NetNS(self.nsname) self.veth0 = 'veth0' + self.nsname self.veth1 = 'veth1' + self.nsname self.bridge_iface = self.service + '-BR' self.createInterface() logging.info("[NS:%s] Create namespace" % (self.nsname))
def test_rename_plus_ipv6(self): require_user('root') mtu = 1280 # mtu must be >= 1280 if you plan to use IPv6 txqlen = 2000 nsid = str(uuid4()) ipdb_main = IPDB() ipdb_test = IPDB(nl=NetNS(nsid)) if1 = uifname() if2 = uifname() if3 = uifname() # create ipdb_main.create(kind='veth', ifname=if1, peer=if2, mtu=mtu, txqlen=txqlen).commit() # move with ipdb_main.interfaces[if2] as veth: veth.net_ns_fd = nsid # set it up with ipdb_test.interfaces[if2] as veth: veth.add_ip('fdb3:84e5:4ff4:55e4::1/64') veth.add_ip('fdff:ffff:ffff:ffc0::1/64') veth.mtu = mtu veth.txqlen = txqlen veth.up() veth.ifname = if3 veth = ipdb_test.interfaces.get(if3, None) ipdb_main.release() ipdb_test.release() netnsmod.remove(nsid) # check everything assert ('fdb3:84e5:4ff4:55e4::1', 64) in veth.ipaddr assert ('fdff:ffff:ffff:ffc0::1', 64) in veth.ipaddr assert veth.flags & 1 assert veth.mtu == mtu assert veth.txqlen == txqlen
def teardown(self): ''' 1. close the test NDB 2. remove the registered interfaces, ignore not existing ''' self.ndb.close() self.ipr.close() for (ifname, nsname) in self.interfaces.items(): try: ipr = None # # spawn ipr to remove the interface if nsname is not None: ipr = NetNS(nsname) else: ipr = IPRoute() # # lookup the interface index index = list(ipr.link_lookup(ifname=ifname)) if len(index): index = index[0] else: # # ignore not existing interfaces continue # # try to remove it ipr.link('del', index=index) except NetlinkError as e: # # ignore if removed (t.ex. by another process) if e.code != errno.ENODEV: raise finally: if ipr is not None: ipr.close() for nsname in self.namespaces: netns.remove(nsname) for net in self.ipnets: free_network(net)
def setup_netns(netns_names, ipdb): netns.create(netns_names.netns) with ipdb.interfaces[netns_names.veth1] as veth1: veth1.net_ns_fd = netns_names.netns ns = IPDB(nl=NetNS(netns_names.netns)) with ns.interfaces.lo as lo: lo.up() with ns.interfaces[netns_names.veth1] as veth1: veth1.address = netns_names.mac veth1.add_ip(netns_names.ip) veth1.up() ns.routes.add({ 'dst': 'default', 'gateway': config.IP_GATEWAY.split('/')[0] }).commit()
def test_create_tuntap(self): # on CentOS 6.5 this test causes kernel panic if platform.linux_distribution()[:2] == ('CentOS', '6.5'): raise SkipTest('to avoid possible kernel panic') # actually this test checks the nlsocket plugin feedback # in a pair of remote client/server foo = str(uuid4()) tun = uifname() tap = uifname() with IPDB(nl=NetNS(foo)) as ip: ip.create(ifname=tun, kind='tuntap', mode='tun').commit() ip.create(ifname=tap, kind='tuntap', mode='tap').commit() assert tun in ip.interfaces.keys() assert tap in ip.interfaces.keys() ip.interfaces[tun].remove().commit() ip.interfaces[tap].remove().commit() assert tun not in ip.interfaces.keys() assert tap not in ip.interfaces.keys() netnsmod.remove(foo)
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)
def get_ipaddr_data(response_type): if response_type == 'real': ip = NetNS('dp', flags=os.O_CREAT) physical = ip.link("get", index=ip.link_lookup(ifname="eth0")[0]) mac_address = physical[0].get_attr('IFLA_ADDRESS') try: interface = ip.get_addr(label='eth0', family=AF_INET) ip_address = interface[0].get_attr('IFA_ADDRESS') cidr = interface[0]['prefixlen'] gateway = ip.get_default_routes( family=AF_INET)[0].get_attr('RTA_GATEWAY') except IndexError as idxerror: print("Not finding an interface yet") ip_address = 'N/A' cidr = 0 gateway = 'N/A' except Exception as e: raise e finally: print("closing socket") ip.close() elif response_type == 'mock': ip_address = '192.168.0.5' cidr = 24 gateway = '192.168.0.1' else: ip_address = 'N/A' cidr = 0 gateway = 'N/A' j = { 'mac_address': mac_address, 'ip_address': ip_address, 'subnet_mask': cidr_to_netmask(cidr), 'gateway': gateway } return j
def mocker_exec(uuid1, *argv): ''' exec <container_id> <command> - запускает указанную команду внутри уже запущенного указанного контейнера ''' netns_name = 'netns_' + str(uuid1) cmd = argv file_log = open(btrfs_path + '/' + uuid1 + '/' + uuid1 + '.log', 'a') file = open(btrfs_path + '/' + uuid1 + '/' + uuid1 + '.cmd', 'a') file.write(str(cmd)) file.close() def in_cgroup(): try: pid = os.getpid() cg = Cgroup(uuid1) netns.setns(netns_name) cg.add(pid) except Exception as e: traceback.print_exc() file_log.write("Failed to preexecute function") file_log.write(e) cmd = list(argv) file_log.write('Running ' + cmd[0] + '\n') process = subprocess.Popen(cmd, preexec_fn=in_cgroup, shell=True) process.wait() file_log.write('Error ') file_log.write(str(process.stderr) + '\n') file_log.write('Final\n') NetNS(netns_name).close() #netns.remove(netns_name) file_log.write('done\n') print('Creating', uuid1)
def _forward(name, self, *args, **kwargs): print("Forward <%s> method" % name) return getattr(self._sock, name)(*args, **kwargs) for name in _socketmethods: f = partial(_forward, name) f.__name__ = name setattr(SocketWrapper, name, types.MethodType(f, self)) def fileno(self): # for some obscure reason, we can not implement `fileno()` # proxying as above, so just make a hardcore version return self._sock.fileno() def dup(self): return self.__class__(_sock=self._sock.dup()) config.SocketBase = SocketWrapper print(netns.listnetns()) ### # # Being run via the root module, real IPRoute import is postponed, # to inspect the code, refer to `pyroute2/__init__.py` # ns = NetNS('test') print(ns.get_addr()) ns.close()
def run(self, *args, **kwargs): images = ImagesCommand().list_images() image_name = kwargs['<name>'] ip_last_octet = 103 # TODO : configurable match = [i[3] for i in images if i[0] == image_name][0] target_file = os.path.join(_base_dir_, match) with open(target_file) as tf: image_details = json.loads(tf.read()) # setup environment details state = json.loads(image_details['history'][0]['v1Compatibility']) # Extract information about this container env_vars = state['config']['Env'] start_cmd = subprocess.list2cmdline(state['config']['Cmd']) working_dir = state['config']['WorkingDir'] id = uuid.uuid1() # unique-ish name name = 'c_' + str(id.fields[5])[:4] # unique-ish mac mac = str(id.fields[5])[:2] layer_dir = os.path.join(_base_dir_, match.replace('.json', ''), 'layers', 'contents') with IPDB() as ipdb: veth0_name = 'veth0_' + name veth1_name = 'veth1_' + name netns_name = 'netns_' + name bridge_if_name = 'bridge0' existing_interfaces = ipdb.interfaces.keys() # Create a new virtual interface with ipdb.create(kind='veth', ifname=veth0_name, peer=veth1_name) as i1: i1.up() if bridge_if_name not in existing_interfaces: ipdb.create(kind='bridge', ifname=bridge_if_name).commit() i1.set_target('master', bridge_if_name) # Create a network namespace netns.create(netns_name) # move the bridge interface into the new namespace with ipdb.interfaces[veth1_name] as veth1: veth1.net_ns_fd = netns_name # Use this network namespace as the database ns = IPDB(nl=NetNS(netns_name)) with ns.interfaces.lo as lo: lo.up() with ns.interfaces[veth1_name] as veth1: veth1.address = "02:42:ac:11:00:{0}".format(mac) veth1.add_ip('10.0.0.{0}/24'.format(ip_last_octet)) veth1.up() ns.routes.add({'dst': 'default', 'gateway': '10.0.0.1'}).commit() try: # setup cgroup directory for this user user = os.getlogin() create_user_cgroups(user) # First we create the cgroup and we set it's cpu and memory limits cg = Cgroup(name) cg.set_cpu_limit( 50) # TODO : get these as command line options cg.set_memory_limit(500) # Then we a create a function to add a process in the cgroup def in_cgroup(): try: pid = os.getpid() cg = Cgroup(name) for env in env_vars: log.info('Setting ENV %s' % env) os.putenv(*env.split('=', 1)) # Set network namespace netns.setns(netns_name) # add process to cgroup cg.add(pid) os.chroot(layer_dir) if working_dir != '': log.info("Setting working directory to %s" % working_dir) os.chdir(working_dir) except Exception as e: traceback.print_exc() log.error("Failed to preexecute function") log.error(e) cmd = start_cmd log.info('Running "%s"' % cmd) process = subprocess.Popen(cmd, preexec_fn=in_cgroup, shell=True) process.wait() print(process.stdout) log.error(process.stderr) except Exception as e: traceback.print_exc() log.error(e) finally: log.info('Finalizing') NetNS(netns_name).close() netns.remove(netns_name) ipdb.interfaces[veth0_name].remove() log.info('done')
def get_ns(self): nsname = self.get_ns_name() ns = NetNS(nsname) return ns
def connect_nodes_to_switch(self): """ This will create veth pairs for all links definid in the network config. Each veth will also be moved to the correct network namespace. """ client_low = docker.APIClient() self.start_containers() ip = IPRoute() # Check if netns folder exists. If not, create one for netns to look intp if not os.path.exists("/var/run/netns"): os.mkdir("/var/run/netns") for link in self.network_config["links"]: device1 = link["device1"] device2 = link["device2"] pid_device1 = client_low.inspect_container(device1)["State"]["Pid"] pid_device2 = client_low.inspect_container(device2)["State"]["Pid"] # Interface names. Naming convention will be different dempending on connection type iface_device1 = "" iface_device2 = "" # If connectiong to switch. Make sure it is setup if link["type"] == "Node_to_Switch": switch_is_setup = os.path.exists(f"/proc/{pid_device2}/ns/net") # Wait until switch is setup max_wait_seconds = 10 seconds_waited = 0 while not switch_is_setup and seconds_waited <= max_wait_seconds: switch_is_setup = os.path.exists(f"/proc/{pid_device2}/ns/net") time.sleep(1) seconds_waited += 1 # Check if namespaces are addad. If not add simlinuk to namespace if not os.path.islink(f"/var/run/netns/{device1}"): os.symlink( f"/proc/{pid_device1}/ns/net", f"/var/run/netns/{device1}", ) if not os.path.islink(f"/var/run/netns/{device2}"): if not os.path.exists(f"/var/run/netns/{device2}"): os.symlink( f"/proc/{pid_device2}/ns/net", f"/var/run/netns/{device2}", ) iface_device1 = f"{link['device1']}_{link['device1_port']}" iface_device2 = f"{link['device2']}_{link['device2_port']}" # Create Veth pair and put them in the right namespace ip.link("add", ifname=iface_device1, peer=iface_device2, kind="veth") id_node = ip.link_lookup(ifname=iface_device1)[0] ip.link("set", index=id_node, state="up") ip.link("set", index=id_node, net_ns_fd=link["device1"]) id_switch = ip.link_lookup(ifname=iface_device2)[0] ip.link("set", index=id_switch, state="up") ip.link("set", index=id_switch, net_ns_fd=link["device2"]) # Start all veth port in Nodes ns = NetNS(device1) ns.link("set", index=id_node, state="up") if "ipv4_addr" in self.network_config["nodes"][device1]: ns.addr( "add", index=id_node, address=self.network_config["nodes"][device1]["ipv4_addr"], prefixlen=24, ) if "ipv6_addr" in link: continue if link["type"] == "Switch_to_Switch": switch_is_setup1 = os.path.exists(f"/proc/{pid_device1}/ns/net") switch_is_setup2 = os.path.exists(f"/proc/{pid_device2}/ns/net") max_wait_seconds = 10 seconds_waited = 0 while not switch_is_setup1 and switch_is_setup2: switch_is_setup1 = os.path.exists(f"/proc/{pid_device1}/ns/net") switch_is_setup2 = os.path.exists(f"/proc/{pid_device2}/ns/net") time.sleep(1) seconds_waited += 1 # Check if namespaces are addad. If not add simlink to namespace if not os.path.islink(f"/var/run/netns/{device1}"): os.symlink( f"/proc/{pid_device1}/ns/net", f"/var/run/netns/{device1}", ) if not os.path.islink(f"/var/run/netns/{device2}"): if not os.path.exists(f"/var/run/netns/{device2}"): os.symlink( f"/proc/{pid_device2}/ns/net", f"/var/run/netns/{device2}", ) iface_switch1 = f"{link['device1']}_{link['device1_port']}" iface_switch2 = f"{link['device2']}_{link['device2_port']}" # Create Veth pair and put them in the right namespace ip.link("add", ifname=iface_switch1, peer=iface_switch2, kind="veth") id_switch1 = ip.link_lookup(ifname=iface_switch1)[0] ip.link("set", index=id_switch1, state="up") ip.link("set", index=id_switch1, net_ns_fd=link["device1"]) id_switch2 = ip.link_lookup(ifname=iface_switch2)[0] ip.link("set", index=id_switch2, state="up") ip.link("set", index=id_switch2, net_ns_fd=link["device2"]) # Start all veth in all the switches for switch in self.switches: ns = NetNS(switch.name) net_interfaces = ns.get_links() for interface in net_interfaces[2:]: iface_name = interface["attrs"][0][1] id_switch = ns.link_lookup(ifname=iface_name)[0] ns.link("set", index=id_switch, state="up")
def _create_tunnel(self, namespace, peer): ip = IPRoute() ns = NetNS(namespace) conn_id = self._connection_identifier(peer) conn_hash = hashlib.md5( (conn_id + namespace).encode('utf-8')).hexdigest() vxlan_name = 'sdvx' + conn_hash[:6] vni = int(conn_hash[:6], 16) ip.link('add', ifname=vxlan_name, kind='vxlan', vxlan_id=vni, vxlan_local=self._local_address, vxlan_group=peer, vxlan_port=4789) vxlan = ip.link_lookup(ifname=vxlan_name)[0] ip.link('set', index=vxlan, net_ns_fd=namespace) vxlan = ns.link_lookup(ifname=vxlan_name)[0] ns.link('set', index=vxlan, mtu=1500) ns.link('set', index=vxlan, state='up') bridge = ns.link_lookup(ifname='shoutbr0')[0] ns.link('set', index=vxlan, master=bridge) ip.close() ns.close()
def _create_namespace(self, namespace): ip = IPRoute() ns = NetNS(namespace) ns.link('add', ifname='shoutbr0', kind='bridge') bridge = ns.link_lookup(ifname='shoutbr0')[0] ns.link('set', index=bridge, mtu=1450) ns.link('set', index=bridge, state='up') if self._raft.is_leader: for peer in self._peers: self._create_tunnel(namespace, peer) else: while self._relay_ip is None: logger.warning('waiting') time.sleep(0.5) self._create_tunnel(namespace, self._relay_ip) ip.close() ns.close()
def mocker_run(uuid1, *args): ''' run <image_id> <command> - создает контейнер из указанного image_id и запускает его с указанной командой ''' id = uuid.uuid4() uuid_name = 'ps_' + str(id.fields[5])[:4] mac = str(id.fields[5])[:2] if mocker_check(uuid1) == 1: print('No image named ' + str(uuid1)) return if mocker_check(uuid_name) == 0: print(uuid_name) print('UUID conflict, retrying...') return cmd = args ip_last_octet = 103 with IPDB() as ipdb: veth0_name = 'veth0_' + str(uuid_name) veth1_name = 'veth1_' + str(uuid_name) netns_name = 'netns_' + str(uuid_name) bridge_if_name = 'bridge0' existing_interfaces = ipdb.interfaces.keys() with ipdb.create(kind='veth', ifname=veth0_name, peer=veth1_name) as i1: i1.up() if bridge_if_name not in existing_interfaces: ipdb.create(kind='bridge', ifname=bridge_if_name).commit() i1.set_target('master', bridge_if_name) netns.create(netns_name) with ipdb.interfaces[veth1_name] as veth1: veth1.net_ns_fd = netns_name ns = IPDB(nl=NetNS(netns_name)) with ns.interfaces.lo as lo: lo.up() with ns.interfaces[veth1_name] as veth1: veth1.address = "02:42:ac:11:00:{0}".format(mac) veth1.add_ip('10.0.0.{0}/24'.format(ip_last_octet)) veth1.up() ns.routes.add({'dst': 'default', 'gateway': '10.0.0.1'}).commit() btrfsutil.create_snapshot(btrfs_path + '/' + uuid1, btrfs_path + '/' + uuid_name) file_log = open(btrfs_path + '/' + uuid_name + '/' + uuid_name + '.log', 'w') file = open(btrfs_path + '/' + uuid_name + '/' + uuid_name + '.cmd', 'w') file.write(str(cmd)) file.close() cg = Cgroup(uuid_name) cg.set_cpu_limit(50) cg.set_memory_limit(500) def in_cgroup(): try: pid = os.getpid() cg = Cgroup(uuid_name) netns.setns(netns_name) cg.add(pid) except Exception as e: traceback.print_exc() file_log.write("Failed to preexecute function") file_log.write(e) cmd = list(args) file_log.write('Running ' + cmd[0] + '\n') process = subprocess.Popen(cmd, preexec_fn=in_cgroup, shell=True) process.wait() file_log.write('Error ') file_log.write(str(process.stderr) + '\n') file_log.write('Final\n') NetNS(netns_name).close() #netns.remove(netns_name) file_log.write('done\n') print('Creating', uuid_name)
def test_fd_leaks(self): for i in range(RESPAWNS): nsid = 'leak_%i' % i ns = NetNS(nsid) ns.close() ns.remove()
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()
def get_ns_addr(): with NetNS(netns=netns) as ipr: inet = ipr.get_addr(label=ifname) ret = inet[0]["attrs"][0][1] return ret
def get_mac_ns(): with NetNS(netns=netns) as ipr: idx = ipr.link_lookup(ifname=ifname) inet = ipr.link("get", index=idx) ret = inet[0]['attrs'][19][1] return ret
def _delete_endpoint(self, request, response): logger.debug('endpoint.delete') network_id = request['NetworkID'] endpoint_id = request['EndpointID'] veth0_name = 'veth%s0' % endpoint_id[:6] namespace = 'sdns' + network_id[:6] ns = NetNS(namespace) veth0 = ns.link_lookup(ifname=veth0_name)[0] ns.link('set', index=veth0, router=0) ns.link('set', index=veth0, state='down') ns.link('del', index=veth0) ns.close() return {}
print("Custom socket wrapper init done") def _forward(name, self, *args, **kwargs): print("Forward <%s> method" % name) return getattr(self._sock, name)(*args, **kwargs) for name in _socketmethods: f = partial(_forward, name) f.__name__ = name setattr(SocketWrapper, name, types.MethodType(f, self)) def fileno(self): # for some obscure reason, we can not implement `fileno()` # proxying as above, so just make a hardcore version return self._sock.fileno() def dup(self): return self.__class__(_sock=self._sock.dup()) config.SocketBase = SocketWrapper print(netns.listnetns()) ### # # Being run via the root module, real IPRoute import is postponed, # to inspect the code, refer to `pyroute2/__init__.py` # ns = NetNS('test') print(ns.get_addr()) ns.close()
class NetworkNamespace: def __init__(self): self.nsname = '' self.service = '' self.veth0 = '' self.veth1 = '' self.bridge_iface = '' self.ns = None def create(self, nsname = 'ns', service = 'ZV'): signal.signal(signal.SIGINT, self.kill) signal.signal(signal.SIGTERM, self.kill) if self.is_exist(nsname): logging.info("[NS:%s] Namespace is exist" % (nsname)) return self.nsname = nsname self.service = service self.ns = NetNS(self.nsname) self.veth0 = 'veth0' + self.nsname self.veth1 = 'veth1' + self.nsname self.bridge_iface = self.service + '-BR' self.createInterface() logging.info("[NS:%s] Create namespace" % (self.nsname)) def destroy(self, nsname = 'ns', service = 'ZV'): if self.nsname == '': self.nsname = nsname if not self.is_exist(self.nsname): logging.info("[NS:%s] Namespace is not exist" % (self.nsname)) return if self.service == '': self.service = service if self.ns == None: self.ns = NetNS(self.nsname) if self.veth0 == '': self.veth0 = 'veth0' + self.nsname if self.veth1 == '': self.veth1 = 'veth1' + self.nsname if self.bridge_iface == '': self.bridge_iface = self.service + '-BR' self.destroyInterface() self.ns.close() self.ns.remove() logging.info("[NS:%s] Destroy namespace" % (self.nsname)) def is_exist(self, nsname = 'ns'): if nsname in netns.listnetns(): return True else: return False 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 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 kill(self, sig, frame): os._exit(0)
def create_ns(br_name, ns_name, ns_ip, ns_netmask, if_description, add_if): """ :param br_name: :param ns_name: :param ns_ip: :param ns_netmask: :param if_description: :param add_if: :return: """ # start the main network settings database: ipdb = IPDB() # Check if the bridge exists if br_name not in ipdb.interfaces.keys(): log.fatal("Could not find bridge %s!" % br_name) sys.exit(-1) # veth naming ifname = "%s_%s_p%%d" % (ns_name, if_description) if (ifname % 0) in ipdb.interfaces.keys(): log.fatal("%s already exists as interface!" % (ifname % 0)) return False log.debug("Creating veth pair %s - %s for namespace %s." % (ifname % 0, ifname % 1, ns_name)) if ns_name in netns.listnetns() and not add_if: log.warning("Namespace %s already exists!" % ns_name) # Create/configure a network namespace ipdb_ns = IPDB(nl=NetNS(ns_name)) # Make sure lo is up in the namespace ipdb_ns.interfaces["lo"].up().commit() # Create veth pair ipdb.create(kind='veth', ifname=(ifname % 0), peer=(ifname % 1)).commit() # Move peer veth into the netns with ipdb.interfaces[(ifname % 1)] as veth: veth.net_ns_fd = ns_name with ipdb.interfaces[(ifname % 0)] as veth: veth.up() # wait for iface to be moved to ns time.sleep(0.1) ns_ip = '%s/%s' % (ns_ip, ns_netmask) log.debug("Assigning IP %s to %s." % (ns_ip, (ifname % 1))) with ipdb_ns.interfaces[(ifname % 1)] as veth: veth.add_ip(ns_ip) veth.up() log.debug("Adding port %s to bridge %s." % ((ifname % 0), br_name)) ipdb.interfaces[br_name].add_port((ifname % 0)) ipdb.commit() return True
def delportns(): with NetNS(netns=netns) as ipr: inet = ipr.link_lookup(ifname=ifname)[0] ipr.link("del", index=inet)
from pyroute2.netlink.exceptions import NetlinkError import consul import logging from netconst import * vxlan_ns = "overns" consul_host = "consul" consul_prefix = "demo" logging.basicConfig(format='%(levelname)s %(message)s', level=logging.INFO) ipr = NetNS(vxlan_ns) ipr.bind() c = consul.Consul(host=consul_host, port=8500) idx, root_keys = c.kv.get(consul_prefix + "/", keys=True, separator="/") logging.debug("Root Keys: {}".format(",".join(root_keys))) while True: msg = ipr.get() for m in msg: logging.debug('Received an event: {}'.format(m['event'])) if m['event'] != 'RTM_GETNEIGH': continue logging.debug("Received a Neighbor miss")
def delportns(): with NetNS(netns=netns) as ipr: for i in slaves: slave = ipr.link_lookup(ifname=i)[0] ipr.link("set", index=slave, master=0)
def _ns_add_ifc(self, name, ns_ifc, ifc_base_name=None, in_ifc=None, out_ifc=None, ipaddr=None, macaddr=None, fn=None, cmd=None, action="ok", disable_ipv6=False): if name in self.ipdbs: ns_ipdb = self.ipdbs[name] else: try: nl = NetNS(name) self.namespaces.append(nl) except KeyboardInterrupt: # remove the namespace if it has been created pyroute2.netns.remove(name) raise ns_ipdb = IPDB(nl) self.ipdbs[nl.netns] = ns_ipdb if disable_ipv6: cmd1 = [ "sysctl", "-q", "-w", "net.ipv6.conf.default.disable_ipv6=1" ] nsp = NSPopen(ns_ipdb.nl.netns, cmd1) nsp.wait() nsp.release() ns_ipdb.interfaces.lo.up().commit() if in_ifc: in_ifname = in_ifc.ifname with in_ifc as v: # move half of veth into namespace v.net_ns_fd = ns_ipdb.nl.netns else: # delete the potentially leaf-over veth interfaces ipr = IPRoute() for i in ipr.link_lookup(ifname='%sa' % ifc_base_name): ipr.link_remove(i) ipr.close() try: out_ifc = self.ipdb.create(ifname="%sa" % ifc_base_name, kind="veth", peer="%sb" % ifc_base_name).commit() in_ifc = self.ipdb.interfaces[out_ifc.peer] in_ifname = in_ifc.ifname with in_ifc as v: v.net_ns_fd = ns_ipdb.nl.netns except KeyboardInterrupt: # explicitly remove the interface out_ifname = "%sa" % ifc_base_name if out_ifname in self.ipdb.interfaces: self.ipdb.interfaces[out_ifname].remove().commit() raise if out_ifc: out_ifc.up().commit() ns_ipdb.interfaces.lo.up().commit() in_ifc = ns_ipdb.interfaces[in_ifname] with in_ifc as v: v.ifname = ns_ifc if ipaddr: v.add_ip("%s" % ipaddr) if macaddr: v.address = macaddr v.up() if disable_ipv6: cmd1 = [ "sysctl", "-q", "-w", "net.ipv6.conf.%s.disable_ipv6=1" % out_ifc.ifname ] subprocess.call(cmd1) if fn and out_ifc: self.ipdb.nl.tc("add", "ingress", out_ifc["index"], "ffff:") self.ipdb.nl.tc("add-filter", "bpf", out_ifc["index"], ":1", fd=fn.fd, name=fn.name, parent="ffff:", action=action, classid=1) if cmd: self.processes.append(NSPopen(ns_ipdb.nl.netns, cmd)) return (ns_ipdb, out_ifc, in_ifc)
ip = IPDB() if args.remove: # cleanup interfaces for ifn in range(args.ifnum): iface = args.ifname + str(ifn) if iface in ip.interfaces: with ip.interfaces[iface] as i: i.remove() if 'tap' + args.ifname in ip.interfaces: with ip.interfaces['tap' + args.ifname] as i: i.remove() if brige_name in ip.interfaces: with ip.interfaces[brige_name] as i: i.remove() for ifn in range(args.ifnum): netns = NetNS('node' + str(ifn)) netns.close() netns.remove() else: for ifn in range(args.ifnum): iface = args.ifname + str(ifn) if not iface in ip.interfaces: ip.create(kind='veth', ifname=iface, peer=iface + '.1').commit() ip.create(kind='tuntap', ifname='tap' + args.ifname, mode='tap').commit() with ip.create(kind='bridge', ifname=brige_name) as i: for ifn in range(args.ifnum): iface = args.ifname + str(ifn)
ip = IPDB() if args.remove: # cleanup interfaces for ifn in range(args.ifnum): iface = args.ifname+str(ifn) if iface in ip.interfaces: with ip.interfaces[iface] as i: i.remove() if 'tap'+args.ifname in ip.interfaces: with ip.interfaces['tap'+args.ifname] as i: i.remove() if brige_name in ip.interfaces: with ip.interfaces[brige_name] as i: i.remove() for ifn in range(args.ifnum): netns = NetNS('node'+str(ifn)) netns.close() netns.remove() else: for ifn in range(args.ifnum): iface = args.ifname+str(ifn) if not iface in ip.interfaces: ip.create(kind='veth', ifname=iface, peer=iface+'.1').commit() ip.create(kind='tuntap', ifname='tap'+args.ifname, mode='tap').commit() with ip.create(kind='bridge', ifname=brige_name) as i: for ifn in range(args.ifnum): iface = args.ifname+str(ifn) i.add_port(ip.interfaces[iface]) i.add_port(ip.interfaces['tap'+args.ifname])
def switchoffns(): with NetNS(netns=netns) as ipr: inet = ipr.link_lookup(ifname=ifname)[0] ipr.link("set", index=inet, state="down") ipr.close()