I'm trying to start a new process from within an already created namespace (named 'test').
I've looked into a few methods including nsenter:
import subprocess
from nsenter import Namespace
with Namespace(mypid, 'net'):
# output network interfaces as seen from within the mypid's net NS:
subprocess.check_output(['ip', 'a'])
But I cant seem to find a reference of where to find the var, mypid...!
Ideally I'd like to keep dependancies like nsenter to a minimum (for portability) so i'd probably like to go down the ctypes route, something like (although there is no syscall for netns...):
nsname = 'test'
netnspath = '%s%s' % ('/run/netns/', nsname)
netnspath = netnspath.encode('ascii')
libc = ctypes.CDLL('libc.so.6')
printdir(libc)
fd = open(netnspath)
print libc.syscall(???, fd.fileno())
OR (taken from http://tech.zalando.com/posts/entering-kernel-namespaces-with-python.html)
import ctypes
libc = ctypes.CDLL('libc.so.6')
# replace MYPID with the container's PID
fd = open('/proc/<MYPID>/ns/net')
libc.setns(fd.fileno(), 0)
# we are now inside MYPID's network namespace
However, I still have to know the PID, plus my libc does not have setns!
Any thoughts on how I could obtain the PID would be great!
TIA!
The problem with the
nsenter
module is that you need to provide it with the PID of a process that is already running inside your target namespace. This means that you can't actually use this module to make use of a network namespace that you have created using something likeip netns add
.The kernel's
setns()
system call takes a file descriptor rather than a PID. If you're willing to solve it withctypes
, you can do something like this:If your libc doesn't have the
setns()
call, you may be out of luck (although where are you running that you have a kernel recent enough to support network namespaces but a libc that doesn't?).Assuming you have a namespace named "blue" available (
ip netns add blue
) you can run:Note that you must run this code as
root
.