def test_move_ns_fd(self): foo = str(uuid4()) bar = str(uuid4()) ifA = uifname() ifB = uifname() netnsmod.create(foo) netnsmod.create(bar) with IPDB(nl=NetNS(foo)) as ip: ip.create(ifname=ifA, kind='veth', peer=ifB).commit() assert ifA in ip.interfaces.keys() assert ifB in ip.interfaces.keys() with ip.interfaces[ifB] as intf: intf.net_ns_fd = bar assert ifA in ip.interfaces.keys() assert ifB not in ip.interfaces.keys() with IPDB(nl=NetNS(bar)) as ip: assert ifA not in ip.interfaces.keys() assert ifB in ip.interfaces.keys() ip.interfaces[ifB].remove().commit() assert ifA not in ip.interfaces.keys() assert ifB not in ip.interfaces.keys() with IPDB(nl=NetNS(foo)) as ip: assert ifA not in ip.interfaces.keys() assert ifB not in ip.interfaces.keys() netnsmod.remove(foo) netnsmod.remove(bar)
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_create_peer_attrs(self): foo = str(uuid4()) bar = str(uuid4()) ifA = uifname() ifB = uifname() netnsmod.create(foo) netnsmod.create(bar) with IPDB(nl=NetNS(foo)) as ip: ip.create(ifname=ifA, kind='veth', peer={ 'ifname': ifB, 'net_ns_fd': bar }).commit() assert ifA in ip.interfaces.keys() assert ifB not in ip.interfaces.keys() with IPDB(nl=NetNS(bar)) as ip: assert ifA not in ip.interfaces.keys() assert ifB in ip.interfaces.keys() ip.interfaces[ifB].remove().commit() assert ifA not in ip.interfaces.keys() assert ifB not in ip.interfaces.keys() with IPDB(nl=NetNS(foo)) as ip: assert ifA not in ip.interfaces.keys() assert ifB not in ip.interfaces.keys() netnsmod.remove(foo) netnsmod.remove(bar)
def test_create_peer_attrs(self): foo = str(uuid4()) bar = str(uuid4()) ifA = uifname() ifB = uifname() netnsmod.create(foo) netnsmod.create(bar) with IPDB(nl=NetNS(foo)) as ip: ip.create(ifname=ifA, kind='veth', peer={'ifname': ifB, 'net_ns_fd': bar}).commit() assert ifA in ip.interfaces.keys() assert ifB not in ip.interfaces.keys() with IPDB(nl=NetNS(bar)) as ip: assert ifA not in ip.interfaces.keys() assert ifB in ip.interfaces.keys() ip.interfaces[ifB].remove().commit() assert ifA not in ip.interfaces.keys() assert ifB not in ip.interfaces.keys() with IPDB(nl=NetNS(foo)) as ip: assert ifA not in ip.interfaces.keys() assert ifB not in ip.interfaces.keys() netnsmod.remove(foo) netnsmod.remove(bar)
def _add_namespace(self, name, address, netmaskLength): """ Creates a namespace with the given name, and creates a veth interface with one endpoint inside the namespace which has the given address and netmask length. The peer end of veth interface can be used to connect the namespace to a bridge. """ self._remove_namespace_if_exists(name) netns.create(name) veth_name = "veth0" _remove_interface_if_exists(self.vethPeer) # Create the veth pair and set one endpoint to the namespace. with IPRoute() as ipr: ipr.link('add', ifname=veth_name, kind='veth', peer=self.vethPeer) idx = ipr.link_lookup(ifname=veth_name)[0] ipr.link('set', index=idx, net_ns_fd=name) # Assign address to the veth interface and bring it up. with IPDB(nl=NetNS(name)) as ipdb: with ipdb.interfaces[veth_name] as veth: veth.add_ip('%s/%d' % ( address, netmaskLength, )) veth.up() # Bring the loopback interface up. with ipdb.interfaces['lo'] as lo: lo.up()
def create_netns(name, **kwargs): """Create a network namespace. :param name: The name of the namespace to create """ try: netns.create(name, **kwargs) except OSError as e: if e.errno != errno.EEXIST: raise
def create_netns(name, **kwargs): """Create a network namespace. :param name: The name of the namespace to create """ try: netns.create(name, libc=_get_cdll()) except OSError as e: if e.errno != errno.EEXIST: raise
def test_auto_netns(self): newns = str(uuid.uuid4()) assert self.ndb.interfaces.count() > 0 assert len(tuple(self .ndb .interfaces .summary(match={'target': 'netns/%s' % newns}))) == 0 netns.create(newns) self.ndb.interfaces.wait(**{'target': 'netns/%s' % newns}) netns.remove(newns)
def create(self, path): netnspath = netns._get_netnspath(path) try: netns.create(netnspath, self.libc) except OSError as e: raise NetlinkError(e.errno) info = self.ipr._dump_one_ns(netnspath, set()) info['header']['type'] = RTM_NEWNETNS info['event'] = 'RTM_NEWNETNS' del info['value'] return info,
def runc(rootfs_path, command, as_root, overlay): container_id = str(uuid4()) netns.create(container_id) set_host_veth(container_id) # Detach from pid namespace so that our child get's a clean /proc with the new namespace print_info("Memory limit:", "{0:.2S}".format(HumanSize(DEFAULT_limit_in_bytes))) unshare(CLONE_NEWPID) pid = os.fork() if pid == 0: child(rootfs_path, command, container_id, as_root, overlay) exit(0) return parent(pid)
def setup(self): require_user('root') self.interfaces = [] self.log_id = str(uuid.uuid4()) self.ipnets = [allocate_network() for _ in range(2)] self.ipranges = [[str(x) for x in net] for net in self.ipnets] self.ndb = NDB(db_provider=self.db_provider, db_spec=self.db_spec, log='../ndb-%s-%s.log' % (os.getpid(), self.log_id), rtnl_debug=True) if self.nsname: netns.create(self.nsname) (self.ndb.sources.add(netns=self.nsname))
def __createNetns(self, phyIfaceIndex): netnsName = self.__getNetnsName() (pvdIfaceName, pvdIfaceIndex) = self.__getPvdIfaceParams() netns.create(netnsName) LOG.debug('network namespace {0} created'.format(netnsName)) # create a virtual interface where PvD parameters are going to be configured, then move the interface to the new network namespace self.ipRoot.link_create(ifname=pvdIfaceName, index=pvdIfaceIndex, kind=self.__PVD_IFACE_TYPE, link=phyIfaceIndex) LOG.debug('macvlan {0} created in default network namespace'.format(pvdIfaceName)) pvdIfaceIndex = self.ipRoot.link_lookup(ifname=pvdIfaceName) self.ipRoot.link('set', index=pvdIfaceIndex[0], net_ns_fd=netnsName) LOG.debug('macvlan {0} moved to network namespace {1}'.format(pvdIfaceName, netnsName)) # change the namespace and get new NETLINK handles to operate in new namespace netns.setns(netnsName) LOG.debug('network namespace switched to {0}'.format(netnsName)) ip = IPRoute() ipdb = IPDB() ipdb.register_callback(self.__onIfaceStateChange) # disable kernel to auto-configure the interface associated with the PvD, let the pvdman to solely control interface configuration acceptRaConfFile = self.__ACCEPT_RA_CONF_FILE.replace(self.__IFACENAME_REPLACE_PATTERN, pvdIfaceName) acceptRaConfFile = open(acceptRaConfFile, 'w') acceptRaConfFile.write('0') LOG.debug('processing of RAs by kernel disabled in {0}'.format(acceptRaConfFile.name)) # return to a default network namespace to not cause a colision with other modules # ip and ipdb handles continue to work in the target network namespace netns.setns(self.__NETNS_DEFAULT_NAME) LOG.debug('network namespace switched to default') # get new index since interface has been moved to a different namespace loIfaceIndex = ip.link_lookup(ifname=self.__LOOPBACK_IFACE_NAME) if (len(loIfaceIndex) > 0): loIfaceIndex = loIfaceIndex[0] pvdIfaceIndex = ip.link_lookup(ifname=pvdIfaceName) if (len(pvdIfaceIndex) > 0): pvdIfaceIndex = pvdIfaceIndex[0] # start interfaces ip.link_up(loIfaceIndex) ip.link_up(pvdIfaceIndex) # clear network configuration if exists ip.flush_addr(index=pvdIfaceIndex) ip.flush_routes(index=pvdIfaceIndex) ip.flush_rules(index=pvdIfaceIndex) LOG.debug('macvlan {0} in network namespace {1} initialized'.format(pvdIfaceName, netnsName)) return (netnsName, pvdIfaceName, ip)
def setup(self): require_user('root') try: netns.create(NS_NAME) except OSError as e: if e.errno == errno.EEXIST: netns.remove(NS_NAME) netns.create(NS_NAME) else: raise try: check_output([NFT_BIN_PATH, "-f", "nftables.ruleset"]) except OSError as e: if e.errno == errno.ENOENT: raise SkipTest("You must install nftables for the test") else: raise
def deploy(topo): """Deploy a given topology with network namespace Args: topo (nx.Graph): the network topo to be deployed """ # sanity check should be done outside # add nodes, each as a network namespace for n in topo.nodes(): netns.create(n) # add links and attribute each interface to proper network namespace ip = IPRoute() for (i, j, intf_pair) in topo.edges.data('interfaces'): print(i, j, intf_pair) ip.link('add', ifname=intf_pair[0], kind='veth', peer=intf_pair[1]) for ns, intf in zip([i, j], intf_pair): intf_idx = ip.link_lookup(ifname=intf)[0] ip.link('set', index=intf_idx, net_ns_fd=ns)
def _add_namespace(self, name, address, netmaskLength): """ Creates a namespace with the given name, and creates a veth interface with one endpoint inside the namespace which has the given address and netmask length. The peer end of veth interface can be used to connect the namespace to a bridge. """ self._remove_namespace_if_exists(name) netns.create(name) veth_name = "veth0" _remove_interface_if_exists(self.vethPeer) with NDB() as ndb: # # Add netns to the NDB sources # # ndb.interfaces["lo"] is a short form of # ndb.interfaces[{"target": "localhost", "ifname": "lo"}] # # To address interfaces/addresses/routes wthin a netns, use # ndb.interfaces[{"target": netns_name, "ifname": "lo"}] ndb.sources.add(netns=name) # # Create veth (ndb.interfaces.create( ifname=veth_name, kind="veth", peer=self.vethPeer, state="up", ).commit().set(net_ns_fd=name).commit()) # # .interfaces.wait() returns an interface object when # it becomes available on the specified source (ndb.interfaces.wait( target=name, ifname=veth_name).set(state="up").add_ip( "%s/%s" % (address, netmaskLength)).commit()) # (ndb.interfaces[{ "target": name, "ifname": "lo" }].set(state="up").commit())
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_ns_pids(self): def waiting_child(fd): while True: if not os.read(fd, 32): exit(0) require_user('root') foo = str(uuid4()) netnsmod.create(foo) netnsmod.pushns(foo) foo_pid, foo_fd = os.forkpty() if not foo_pid: waiting_child(foo_fd) netnsmod.popns() pids = netnsmod.ns_pids() try: assert pids[foo] == [foo_pid] finally: os.close(foo_fd) netnsmod.remove(foo)
def set_namespace(self, namespace, *args, **kwargs): print(f'[N] VNic setting namespace "{namespace}" for {self.ports["sink_name"]}(index: {self.ports["sink"]})') try: netns.create(namespace) except FileExistsError: pass # Already exists, we can use it below. with IPRoute() as ip: try: ip.link('set', index=self.ports['sink'], net_ns_fd=namespace) except: print(f'[N] VNic can\'t change namespace for {self.ports["sink_name"]}. Most likely because it\'s already enslaved to a namespace.') datastore['nics'][self.ports['sink_name']].namespace = namespace # TODO: Move this logic into machine setup. # At the start, VirtualNic was only used for machines, but it is used for so much more these days.. # Because NetNS() or IPRoute() or IPDB() appears to be lacking the support to create # interfaces within a namespace, we'll have to revert to shell-commands. o = sys_command(f'ip netns exec {namespace} ip link add link {self.ports["sink_name"]} type macvtap mode bridge') if len(o) <= 0: o = sys_command(f"ip netns exec {namespace} /bin/bash -c 'ip link set macvtap0 address {self.mac} up'") else: print(f'[E] Could not create a virtual macvtap for {self.ports["sink_name"]}') print(o) self.tap_interface = None o = sys_command(f"ip netns exec {namespace} /bin/bash -c 'ls /sys/class/net/macvtap0/'") for file in o.decode('UTF-8').split('\n'): if file[:3] == 'tap': self.tap_interface = file break if not self.tap_interface: print('[E] VirtualNic() could not create a virtual macvtap for the tap interface.') # with NetNS(namespace) as ns: # with IPDB(nl=ns) as ip: # ip.link('add', ifname=self.ports['sink'], kind='macvtap') #mode=vepa | bridge(default) self.namespace = namespace
def main(argv): if (len(argv) != 2): print('Usage: python pvdtest_veth.py PVD_ID') print('PVD_ID := name of the interface that contains PvD-related network configuration') sys.exit() # Get user-entered PVD ID pvdId = sys.argv[1] # Create IPRoute object for manipulation with a default network namespace ipMain = IPRoute() # Create a PvD-related network namespace pvdNetnsName = getPvdNetnsName(pvdId); if (pvdNetnsName in netns.listnetns()): netns.remove(pvdNetnsName) netns.create(pvdNetnsName) # Create IPRoute object for manipulation with a PvD-related network namespace netns.setns(pvdNetnsName) ipPvd = IPRoute() # Activate loopback interface in a PvD-related network namespace loIndex = ipPvd.link_lookup(ifname='lo')[0] ipPvd.link_up(loIndex) # Get addresses from a PvD-related network interface pvdIfIndex = ipMain.link_lookup(ifname=getPvdIfName(pvdId))[0] pvdAddresses = ipMain.get_addr(index=pvdIfIndex) # Get current routes pvdRoutes = ipMain.get_routes() # Create bridge bridge = getPvdBridgeName(pvdId) ipMain.link_create(ifname=bridge, kind='bridge') # Create veth interface (veth0, veth1) = getPvdVethNames(pvdId) ipMain.link_create(ifname=veth0, kind='veth', peer=veth1) # Move one end of the veth interafce to a PvD-related network namespace veth1Index = ipMain.link_lookup(ifname=veth1)[0] ipMain.link('set', index=veth1Index, net_ns_fd=pvdNetnsName) # Shut down and remove addresses from the PvD interface before adding it to the bridge ipMain.link_down(pvdIfIndex) ipMain.flush_addr(pvdIfIndex) # Make a bridge between PvD interface and one end of veth interface veth0Index = ipMain.link_lookup(ifname=veth0)[0] bridgeIndex = ipMain.link_lookup(ifname=bridge)[0] ipMain.link('set', index=veth0Index, master=bridgeIndex) ipMain.link('set', index=pvdIfIndex, master=bridgeIndex) # Activate bridge and connected interfaces ipMain.link_up(pvdIfIndex) ipMain.link_up(veth0Index) ipMain.link_up(bridgeIndex) ipPvd.link_up(veth1Index) # Configure bridge and another end of the veth interface with PvD-related network parameters + add routes ipMain.flush_routes() ipPvd.flush_routes() for address in pvdAddresses: ipAddress = broadcastAddress = netmask = addrFamily = None for attr in address['attrs']: if attr[0] == 'IFA_ADDRESS': ipAddress = attr[1] if attr[0] == 'IFA_BROADCAST': broadcastAddress = attr[1] netmask = address['prefixlen'] addrFamily = address['family'] # Configure bridge try: ipMain.addr('add', index=bridgeIndex, family=addrFamily, address=ipAddress, broadcast=broadcastAddress, mask=netmask) except: pass # Configure veth try: ipPvd.addr('add', index=veth1Index, family=addrFamily, address=ipAddress, broadcast=broadcastAddress, mask=netmask) except: pass # Configure routes # Some routes are added during interface IP address/netmask configuration, skip them if already there ipNetwork = IPNetwork(ipAddress + '/' + str(netmask)) try: ipMain.route('add', dst=str(ipNetwork.network), mask=netmask, oif=bridgeIndex, src=ipAddress, rtproto='RTPROT_STATIC', rtscope='RT_SCOPE_LINK') except: pass try: ipPvd.route('add', dst=str(ipNetwork.network), mask=netmask, oif=veth1Index, src=ipAddress, rtproto='RTPROT_STATIC', rtscope='RT_SCOPE_LINK') except: pass # Fing gateway(s) and add default routes defGateways = [] for route in pvdRoutes: for attr in route['attrs']: if (attr[0] == 'RTA_GATEWAY' and attr[1] not in defGateways): defGateways.append(attr[1]) if (len(defGateways) > 0): ipMain.route('add', dst='0.0.0.0', oif=bridgeIndex, gateway=defGateways[0], rtproto='RTPROT_STATIC') ipPvd.route('add', dst='0.0.0.0', oif=veth1Index, gateway=defGateways[0], rtproto='RTPROT_STATIC')
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 dummy(): """This method aim is to validate that we can use privsep in functests.""" namespace = 'dummy-%s' % uuidutils.generate_uuid() pynetns.create(namespace) pynetns.remove(namespace)
def _create_namespace(self): if self.name in self.get_namespaces_list(): print "name space {} exists.".format(self.name) return netns.create(self.name)
def 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 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)
#!/usr/bin/python from pyroute2 import netns from socket import AF_INET from pyroute2 import IPRoute # get access to the netlink socket ip = IPRoute() # print interfaces # print(ip.get_links()) # NOTE: do this in case veth or netns exist: # ip link del v0p0; ip netns del test netns.create('test') # create VETH pair and move v0p1 to netns 'test' ip.link_create(ifname='v0p0', peer='v0p1', kind='veth') idx = ip.link_lookup(ifname='v0p1')[0] ip.link('set', index=idx, net_ns_fd='test') # bring v0p0 up and add an address idx = ip.link_lookup(ifname='v0p0')[0] ip.link('set', index=idx, state='up') ip.addr('add', index=idx,