systemd / pystemd

A thin Cython-based wrapper on top of libsystemd, focused on exposing the dbus API via sd-bus in an automated and easy to consume way.
GNU Lesser General Public License v2.1
409 stars 36 forks source link

pystemd & user services #52

Closed docent-net closed 4 years ago

docent-net commented 4 years ago

Hi,

I'm running a user service [1] defined in ~/.config/systemd/user/stub.service I'd like to manage this service via pystemd. There is no documentation for this kind of use, however I found an issue related to it where I read that pystemd should just work fine with user services.

So I tried something very simple:

bus = DBus(user_mode=True)
unit = Unit(b'stub.service', bus=bus, _autoload=True)

And I receive:

[...]
  File "/xxx/server_manager.py", line 22, in is_server_running
    unit = Unit(b'stub.service', bus=bus, _autoload=True)
  File "/xxx/lib/python3.8/site-packages/pystemd/systemd1/unit.py", line 19, in __init__
    super(Unit, self).__init__(
  File "/yyy/pyenv/versions/mc-server-manager/lib/python3.8/site-packages/pystemd/base.py", line 28, in __init__
    self.load()
  File "/yyy/pyenv/versions/mc-server-manager/lib/python3.8/site-packages/pystemd/base.py", line 89, in load
    unit_xml = self.get_introspect_xml()
  File "/yyy/pyenv/versions/mc-server-manager/lib/python3.8/site-packages/pystemd/base.py", line 75, in get_introspect_xml
    bus.call_method(
  File "pystemd/dbuslib.pyx", line 427, in pystemd.dbuslib.DBus.call_method
pystemd.dbusexc.DBusBaseError: [err -107]: Could not create DBus method
This is DBusBaseError, a base error for DBus (i bet you did not see that coming) if you need a special error, enhance pystemd.sysdexc module!.

My setup is Fedora 31, SELinux in permissive mode, cgroups v1, and this service is active:

➜  mc-server-manager git:(master) ✗ systemctl --user status stub.service
● stub.service - Stub server
     Loaded: loaded (/home/docent/.config/systemd/user/stub.service; enabled; vendor preset: disabled)
     Active: active (running) since Sat 2020-04-18 17:23:18 CEST; 7h ago
   Main PID: 457238 (sleep)
     CGroup: /user.slice/user-1000.slice/user@1000.service/stub.service
             └─457238 /usr/bin/sleep 86400

[1]

[Unit]
Description=A stub service
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/sleep 86400

NoNewPrivileges=true

[Install]
WantedBy=multi-user.targe
aleivag commented 4 years ago

Hello!!!...

First of all, thanks for using pystemd, and more importantly, doing propper research on it... i should document this behaviors, but i'm probably the second most lazy developer in the world (and i'm too lazy to find out who is the first one)..

your issue, i believe, is that you did not start the dbus when you create it. You see, in the issue you referenced, the example say:

In [12]: with DBus(user_mode=True) as bus, pystemd.systemd1.Unit("dotsync-poll.service", bus=bus) as service:
    ...:     print(service.ExecStart)

the __enter__ method on the DBus object https://github.com/facebookincubator/pystemd/blob/master/pystemd/dbuslib.pyx#L284-L286 calls self.open(). that's the thing you are missing, so

repro

Welcome to pystemd  0.8.dev interactive shell for python 3.7.5+ (default, Jan 24 2020, 11:19:43)
[GCC 7.x 20200121 (Facebook) 8.x].

In [1]: import pystemd
   ...: from pystemd.dbuslib import DBus

In [2]: dbus = DBus(user_mode=True)

In [4]: pystemd.systemd1.Unit("dotsync-poll.service", bus=dbus, _autoload=True)
---------------------------------------------------------------------------
DBusBaseError                             Traceback (most recent call last)
/data/users/aleivag/fbsource/fbcode/buck-out/dev/gen/libfb/py/pystemd/pystemd-shell#link-tree/pystemd/examples/shell.py in <module>
----> 1 pystemd.systemd1.Unit("dotsync-poll.service", bus=dbus, _autoload=True)

/data/users/aleivag/fbsource/fbcode/buck-out/dev/gen/libfb/py/pystemd/pystemd-shell#link-tree/pystemd/systemd1/unit.py in __init__(self, external_id, bus, _autoload)
     21             path=path,
     22             bus=bus,
---> 23             _autoload=_autoload,
     24         )

/data/users/aleivag/fbsource/fbcode/buck-out/dev/gen/libfb/py/pystemd/pystemd-shell#link-tree/pystemd/base.py in __init__(self, destination, path, bus, _autoload)
     26
     27         if _autoload:
---> 28             self.load()
     29
     30     def __enter__(self):

/data/users/aleivag/fbsource/fbcode/buck-out/dev/gen/libfb/py/pystemd/pystemd-shell#link-tree/pystemd/base.py in load(self, force)
     87             return
     88
---> 89         unit_xml = self.get_introspect_xml()
     90         decoded_destination = self.destination.decode()
     91

/data/users/aleivag/fbsource/fbcode/buck-out/dev/gen/libfb/py/pystemd/pystemd-shell#link-tree/pystemd/base.py in get_introspect_xml(self)
     78                     b"org.freedesktop.DBus.Introspectable",
     79                     b"Introspect",
---> 80                     [],
     81                 ).body
     82             )

/data/users/aleivag/fbsource/fbcode/buck-out/dev/gen/libfb/py/pystemd/pystemd-shell#link-tree/pystemd/dbuslib.pyx in pystemd.dbuslib.DBus.call_method()

DBusBaseError: [err -107]: Could not create DBus method
This is DBusBaseError, a base error for DBus (i bet you did not see that coming) if you need a special error, enhance pystemd.sysdexc module!.

opening the bus


In [5]: dbus = DBus(user_mode=True)

In [6]: dbus.__enter__()
Out[6]: <pystemd.dbuslib.DBus at 0x7ff456c068a0>

In [7]: e = _

In [8]: pystemd.systemd1.Unit("dotsync-poll.service", bus=e, _autoload=True)
Out[8]: <pystemd.systemd1.unit.Unit at 0x7ff456c138d0>

or


In [9]: dbus = DBus(user_mode=True)

In [10]: dbus.open()

In [11]: pystemd.systemd1.Unit("dotsync-poll.service", bus=dbus, _autoload=True)
Out[11]: <pystemd.systemd1.unit.Unit at 0x7ff456a80810>

but still... you wanna use the with context methods.

docent-net commented 4 years ago

Hi Alvaro!

Not using a context manager makes me even lazier I think XD

Thanks for your help and explanation. Yeah, I didn't notice the enter method and what it does.

And also thanks for great talk during 2018 All Systems Go. One of my favourites from that conference :)