2016-09-14 17 views
3

sandbox가 아닌 Flatpak의 new Development DBus service to spawn a process on the host을 호출하려고합니다. Python에서 dbus 함수 호출을 통해 파일 설명 자 전달 (일명 flatpak의 HostCommand 호출)

나는 다음과 같은 코드 조각으로 왔어요의 DBUS 서비스를 호출하려면 다음

#!/usr/bin/env python 
import logging 
import os 
import sys 

import dbus 

def call_on_host(cmd): 
    "Calls Flatpak via DBus to spawn a process" 
    name = "org.freedesktop.Flatpak" 
    path = "/org/freedesktop/Flatpak/Development" 
    bus = dbus.SessionBus() 
    proxy = bus.get_object(name, path) 

    iface = "org.freedesktop.Flatpak.Development" 
    fp_helper = dbus.Interface(proxy, iface) 

    wd = '/tmp/' 
    read_fd, write_fd = os.pipe() 
    fds = {0:dbus.types.UnixFd(read_fd)} 
    envs = {'FOO':'bar'} 
    flags = 1 

    # cwd, cmd, fds, env, flags = ('/', ['ls'], {0:dbus.types.UnixFd(open('/etc/passwd'))}, {'foo':'bar'}, 1) 
    logging.info("Executing %r %r %r %r %r", wd, cmd, fds, envs, flags) 
    ret = fp_helper.HostCommand(wd, cmd, fds, envs, flags) 
    return ret 


logging.basicConfig(level=logging.DEBUG) 

print (call_on_host(sys.argv[1:])) 

은, 그러나, 너무 잘 작동하지 않습니다. Flatpak DBus 도우미는 값을받지 못합니다. 즉, 모두 NULL입니다.

$ python execute_on_host.py 'ls'/
INFO:root:Executing '/tmp/' ['ls'] {0: <dbus.UnixFd object at 0x7f4b5ae6c120>} {'FOO': 'bar'} 1 
Traceback (most recent call last): 
    File "execute_on_host.py", line 42, in <module> 
    print (call_on_host(sys.argv[1:])) 
    File "execute_on_host.py", line 35, in call_on_host 
    ret = fp_helper.HostCommand(wd, cmd, fds, envs, flags) 
    File "/usr/lib/python2.7/dist-packages/dbus/proxies.py", line 70, in __call__ 
    return self._proxy_method(*args, **keywords) 
    File "/usr/lib/python2.7/dist-packages/dbus/proxies.py", line 145, in __call__ 
    **keywords) 
    File "/usr/lib/python2.7/dist-packages/dbus/connection.py", line 651, in call_blocking 
    message, timeout) 
dbus.exceptions.DBusException: org.freedesktop.DBus.Error.InvalidArgs: No command 19430 given!!1 - *arg_argv[0] == 0 

저는 조금 혼란 스럽습니다. 프록시 객체에 대한 함수를 GVariants에 호출하기 전에 내 유형을 래핑해야합니까?

내가 모든 것을 서명 서비스를 호출 할 수 있는지 여부를 테스트하기 위해, 나는 this question에서 suff의 대부분을 훔친 다음과 같은 내놓았다 : 잘 작동

import unittest 

import os 
import sys 
import subprocess 
import time 

import dbus 
import dbus.service 
import dbus.glib 
import gobject 

class MyDBUSService(dbus.service.Object): 

    def __init__(self): 
     bus_name = dbus.service.BusName('test.helloservice', bus = dbus.SessionBus()) 
     dbus.service.Object.__init__(self, bus_name, '/test/helloservice') 

    def listen(self): 
     loop = gobject.MainLoop() 
     loop.run() 

    @dbus.service.method('test.helloservice', in_signature="ayaaya{uh}a{ss}u") 
    def hello(self, cwd, cmd, fds, env, flags): 
     print ([type(foo) for foo in (cwd, cmd, fds, env, flags)] ) 
     print ("cwd: %s" % cwd) 
     print ("cmd: %s" % cmd) 
     print ("fsd: %s" % fds) 
     r = os.fdopen(fds[0].take()).read() 
     return r 


class BaseTestCase(unittest.TestCase): 

    def setUp(self): 
     env = os.environ.copy() 
     self.p = subprocess.Popen(['python', __file__, 'server'], env=env) 
     # Wait for the service to become available 
     time.sleep(1) 
     assert self.p.stdout == None 
     assert self.p.stderr == None 

     open("/tmp/dbus-test", "w").write("Hello, World!") 

    def testHelloService(self): 
     bus = dbus.SessionBus() 
     helloservice = bus.get_object('test.helloservice', '/test/helloservice') 
     hello = helloservice.get_dbus_method('hello', 'test.helloservice') 
     cwd, cmd, fds, env, flags = ('/', ['ls'], {0:dbus.types.UnixFd(open('/tmp/dbus-test'))}, {'foo':'bar'}, 1) 
     r = hello(cwd, cmd, fds, env, flags) 
     assert r == "Hello, World!" 

    def tearDown(self): 
     # terminate() not supported in Python 2.5 
     #self.p.terminate() 
     os.kill(self.p.pid, 15) 


if __name__ == '__main__': 

    arg = "" 
    if len(sys.argv) > 1: 
     arg = sys.argv[1] 

    if arg == "server": 
     myservice = MyDBUSService() 
     myservice.listen() 

    else: 
     unittest.main() 

합니다.

그래서 궁금합니다. 어떻게 Python에서 Flatpak Development 서비스를 호출 할 수 있습니까?

답변

2

내 코드가 동일한 메시지가 버스를 통해 전송되는지 여부를 조사하기 위해 알려진 클라이언트가 해당 메시지를 보내는 경우 어떤 일이 발생하는지 확인하기 위해 dbus-monitor을 시작했습니다.

method call time=14743.5 sender=:1.6736 -> destination=org.freedesktop.Flatpak serial=8 path=/org/freedesktop/Flatpak/Development; interface=org.freedesktop.Flatpak.Development; member=HostCommand 
    array of bytes "/" + \0 
    array [ 
     array of bytes "ls" + \0 
    ] 
    array [ 
     dict entry(
     uint32 0 
     file descriptor 
       inode: 40 
       type: char 
    ) 
     dict entry(
     uint32 1 
     file descriptor 
       inode: 58091333 
       type: fifo 
    ) 
     dict entry(
     uint32 2 
     file descriptor 
       inode: 40 
       type: char 
    ) 
    ] 
    array [ 
     dict entry(
     string "CLUTTER_IM_MODULE" 
     string "xim" 
    ) 
    ] 
    uint32 1 

내 자신의 클라이언트가, 그러나, 제작 :

array of bytes "/" 
array [ 
    array of bytes "ls" 
] 
array [ 
    dict entry(
    uint32 0 
    file descriptor 
      inode: 1866322 
      type: file 
) 
] 
array [ 
    dict entry(
    string "FOO" 
    string "bar" 
) 
] 
uint32 1 

그래서 차이는 널 바이트 나는 다음 얻었다. 이를 내 코드에 추가하면 작동합니다. 이 문제에 관해서는 bug report입니다.