Esempio n. 1
0
def NSPopenServer(nsname, flags, channel_in, channel_out, argv, kwarg):
    # set netns
    try:
        setns(nsname, flags=flags, libc=kwarg.pop('libc', None))
    except Exception as e:
        channel_out.put(e)
        return
    # create the Popen object
    child = subprocess.Popen(*argv, **kwarg)
    for fname in ['stdout', 'stderr', 'stdin']:
        obj = getattr(child, fname)
        if obj is not None:
            fproxy = NSPopenFile(obj)
            setattr(child, fname, fproxy)

    # send the API map
    channel_out.put(None)

    while True:
        # synchronous mode
        # 1. get the command from the API
        try:
            call = channel_in.get()
        except:
            (et, ev, tb) = sys.exc_info()
            try:
                channel_out.put({'code': 500, 'data': ev})
            except:
                pass
            break

        # 2. stop?
        if call['name'] == 'release':
            break

        # 3. run the call
        try:
            # get the object namespace
            ns = call.get('namespace')
            obj = child
            if ns:
                for step in ns.split('.'):
                    obj = getattr(obj, step)
            attr = getattr(obj, call['name'])
            if isinstance(attr, (types.MethodType,
                                 types.FunctionType,
                                 types.BuiltinMethodType)):
                result = attr(*call['argv'], **call['kwarg'])
            else:
                result = attr
            channel_out.put({'code': 200, 'data': result})
        except:
            (et, ev, tb) = sys.exc_info()
            channel_out.put({'code': 500, 'data': ev})
    child.wait()
Esempio n. 2
0
    def __init__(self, netns, flags=os.O_CREAT, target=None, libc=None):
        self.netns = netns
        self.flags = flags
        target = target or netns
        trnsp_in, self.remote_trnsp_out = [Transport(FD(x))
                                           for x in os.pipe()]
        self.remote_trnsp_in, trnsp_out = [Transport(FD(x))
                                           for x in os.pipe()]

        self.child = os.fork()
        if self.child == 0:
            # child process
            trnsp_in.close()
            trnsp_out.close()
            trnsp_in.file_obj.close()
            trnsp_out.file_obj.close()
            try:
                setns(self.netns, self.flags, libc=libc)
            except OSError as e:
                (self
                 .remote_trnsp_out
                 .send({'stage': 'init', 'error': e}))
                os._exit(e.errno)
            except Exception as e:
                (self.
                 remote_trnsp_out
                 .send({'stage': 'init',
                        'error': OSError(errno.ECOMM,
                                         str(e),
                                         self.netns)}))
                os._exit(255)

            try:
                Server(self.remote_trnsp_in,
                       self.remote_trnsp_out,
                       target=target)
            finally:
                os._exit(0)

        try:
            self.remote_trnsp_in.close()
            self.remote_trnsp_out.close()
            super(NetNS, self).__init__(trnsp_in, trnsp_out)
            self.target = target
        except Exception:
            self.close()
            raise
        atexit.register(self.close)
        self.marshal = MarshalRtnl()
Esempio n. 3
0
def Server(trnsp_in, trnsp_out, netns=None, target='localhost'):
    def stop_server(signum, frame):
        Server.run = False

    Server.run = True
    signal.signal(signal.SIGTERM, stop_server)

    try:
        if netns is not None:
            netnsmod.setns(netns)
        ipr = IPRoute(target=target)
        lock = ipr._sproxy.lock
        ipr._s_channel = ProxyChannel(trnsp_out, 'broadcast')
    except Exception as e:
        trnsp_out.send({'stage': 'init', 'error': e})
        return 255

    inputs = [ipr.fileno(), trnsp_in.fileno()]
    broadcasts = {ipr.fileno(): ipr}
    outputs = []

    # all is OK so far
    trnsp_out.send({'stage': 'init', 'uname': config.uname, 'error': None})

    # 8<-------------------------------------------------------------
    while Server.run:
        try:
            events, _, _ = select.select(inputs, outputs, inputs)
        except:
            continue
        for fd in events:
            if fd in broadcasts:
                sock = broadcasts[fd]
                bufsize = sock.getsockopt(SOL_SOCKET, SO_RCVBUF) // 2
                with lock:
                    error = None
                    data = None
                    try:
                        data = sock.recv(bufsize)
                    except Exception as e:
                        error = e
                        error.tb = traceback.format_exc()
                    trnsp_out.send(
                        {'stage': 'broadcast', 'data': data, 'error': error}
                    )
            elif fd == trnsp_in.fileno():
                cmd = trnsp_in.recv_cmd()
                if cmd['stage'] == 'shutdown':
                    ipr.close()
                    data = struct.pack('IHHQIQQ', 28, 2, 0, 0, 104, 0, 0)
                    trnsp_out.send(
                        {'stage': 'broadcast', 'data': data, 'error': None}
                    )
                    return
                elif cmd['stage'] == 'reconstruct':
                    error = None
                    try:
                        msg = cmd['argv'][0]()
                        msg.load(pickle.loads(cmd['argv'][1]))
                        ipr.sendto_gate(msg, cmd['argv'][2])
                    except Exception as e:
                        error = e
                        error.tb = traceback.format_exc()
                    trnsp_out.send(
                        {
                            'stage': 'reconstruct',
                            'error': error,
                            'return': None,
                            'cookie': cmd['cookie'],
                        }
                    )

                elif cmd['stage'] == 'command':
                    error = None
                    try:
                        ret = getattr(ipr, cmd['name'])(
                            *cmd['argv'], **cmd['kwarg']
                        )
                        if (
                            cmd['name'] == 'bind'
                            and ipr._brd_socket is not None
                        ):
                            inputs.append(ipr._brd_socket.fileno())
                            broadcasts[
                                ipr._brd_socket.fileno()
                            ] = ipr._brd_socket
                    except Exception as e:
                        ret = None
                        error = e
                        error.tb = traceback.format_exc()
                    trnsp_out.send(
                        {
                            'stage': 'command',
                            'error': error,
                            'return': ret,
                            'cookie': cmd['cookie'],
                        }
                    )