{"id":27492,"date":"2020-08-01T12:20:19","date_gmt":"2020-08-01T10:20:19","guid":{"rendered":"https:\/\/pi3g.com\/?p=27492"},"modified":"2020-08-01T12:20:19","modified_gmt":"2020-08-01T10:20:19","slug":"enabling-and-disabling-a-systemd-service-in-python-using-dbus","status":"publish","type":"post","link":"https:\/\/pi3g.com\/de\/enabling-and-disabling-a-systemd-service-in-python-using-dbus\/","title":{"rendered":"Aktivierung und Deaktivierung eines systemd-Dienstes in Python mit DBus"},"content":{"rendered":"<p>The upcoming picockpit-client reacts to deletion events from the frontend <strong>by disabling it\u2019s service<\/strong> (the application will stay installed, however).<\/p>\n<p>Similarly, when you decide to run picockpit-client connect again, the service will be re-enabled and started automatically for you.<\/p>\n<p>This is possible using the <strong>Python DBus interface<\/strong>.<\/p>\n<p>the DBus is a bus system for interacting with other applications. The applications &amp; system services publish a certain interface over the DBus, which you can use.<\/p>\n<h1>Here\u2019s how to do it:<\/h1>\n<h2>disable a service:<\/h2>\n<blockquote>\n<p>import dbus<\/p>\n<p>system_bus = dbus.SystemBus()<br \/>\nsystemd1 = system_bus.get_object(&#8216;org.freedesktop.systemd1&#8217;, &#8216;\/org\/freedesktop\/systemd1&#8217;)<br \/>\nmanager = dbus.Interface(systemd1, &#8216;org.freedesktop.systemd1.Manager&#8217;)<br \/>\nmanager.DisableUnitFiles([&#8216;picockpit-client.service&#8217;], False)<\/p>\n<p>manager.Reload()<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2020\/08\/image.png\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"140\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2020\/08\/image_thumb.png\" border=\"0\"><\/a><\/p>\n<p>\nWe open the <strong>SystemBus <\/strong>\u2013 there is a SessionBus as well ( dbus.SessionBus() ) which is used to interact with a user session. In this case we want to access System services, however.<\/p>\n<p>up to manager these are \u201cstandard\u201d calls \u2013 in order to access systemd you need to go through them.<\/p>\n<p>the next line is where we instruct the manager to DisableUnitFiles. Here\u2019s some more notes about that:<\/p>\n<ul>\n<li>the first variable is an array of strings \u2013 even if you want to disable just one service, you pass it as an array.<\/li>\n<li>you pass in the name of your service including the \u2018.service\u2019 part \u2013 e.g. <em>picockpit-client.service<\/em><\/li>\n<li>the second variable is required and would be False to disable for every boot (and True to disable just for this runtime)<\/li>\n<\/ul>\n<p>Here\u2019s the signature for DisableUnitFiles from <a href=\"https:\/\/www.freedesktop.org\/wiki\/Software\/systemd\/dbus\/\">the official DBus \/ systemd \/ Freedesktop.org documentation<\/a>:<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2020\/08\/image-1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"257\" height=\"50\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2020\/08\/image_thumb-1.png\" border=\"0\"><\/a><\/p>\n<p><strong>Note, it is important to provide all variables when interacting with the DBus interface! <\/strong>They are <strong>not <\/strong>optional and \u201cset to sane defaults\u201d, as you might be used from many other interfaces \/ APIs.<\/p>\n<p>Finally, I\u2019ve read online that the changes need to be committed by using <strong>manager.Reload() <\/strong>(the documentation says: Reload() may be invoked to reload all unit files)<\/p>\n<h2>enable and start a service:<\/h2>\n<blockquote>\n<p>import dbus<\/p>\n<p>system_bus = dbus.SystemBus()<br \/>\nsystemd1 = system_bus.get_object(&#8216;org.freedesktop.systemd1&#8217;, &#8216;\/org\/freedesktop\/systemd1&#8217;)<br \/>\nmanager = dbus.Interface(systemd1, &#8216;org.freedesktop.systemd1.Manager&#8217;)<br \/>\nmanager.EnableUnitFiles([&#8216;picockpit-client.service&#8217;], False, True)<br \/>\nmanager.Reload()<br \/>\njob = manager.RestartUnit(&#8216;picockpit-client.service&#8217;, &#8216;fail&#8217;)<\/p>\n<\/blockquote>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2020\/08\/image-2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"819\" height=\"154\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2020\/08\/image_thumb-2.png\" border=\"0\"><\/a><\/p>\n<p>Similar to the above, with the following difference for EnableUnitFiles:<\/p>\n<ul>\n<li>there are two boolean variables after the array of strings which NEED to be passed in<\/li>\n<li>the first boolean variable, as above, determines whether the service is to be enabled for just this runtime (True) or generally (False); <\/li>\n<li>the second boolean variable is, somewhat cryptically, described as: \u201cThe second one controls whether symlinks pointing to other units shall be replaced if necessary.\u201d. I have decided to set it to True.<\/li>\n<\/ul>\n<p>Here\u2019s the EnableUnitFiles signature from the documentation:<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2020\/08\/image-3.png\"><img loading=\"lazy\" decoding=\"async\" width=\"244\" height=\"64\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2020\/08\/image_thumb-3.png\" border=\"0\"><\/a><\/p>\n<p>Looking at it, my choice of \u201cTrue\u201d might possibly  not be sensible for other applications (\u201cforce\u201d implies a kind of override of security).<\/p>\n<p>Finally, <strong>RestartUnit<\/strong> to actually start the service:<\/p>\n<ul>\n<li>note that this takes a string value, not an array of strings<\/li>\n<li>the second value is a string specifying the mode. Please refer to the <a href=\"https:\/\/www.freedesktop.org\/wiki\/Software\/systemd\/dbus\/\">official documentation<\/a> for the different modes which are possible.<\/li>\n<\/ul>\n<p>Here is the RestartUnit signature:<\/p>\n<p><a href=\"https:\/\/pi3g.com\/wp-content\/uploads\/2020\/08\/image-4.png\"><img loading=\"lazy\" decoding=\"async\" width=\"229\" height=\"65\" title=\"image\" style=\"display: inline; background-image: none;\" alt=\"image\" src=\"https:\/\/pi3g.com\/wp-content\/uploads\/2020\/08\/image_thumb-4.png\" border=\"0\"><\/a><\/p>\n<p>Note: I do not handle the return values, ideally and especially for critical applications, you would want to look into that \u2013 refer to the <a href=\"https:\/\/www.freedesktop.org\/wiki\/Software\/systemd\/dbus\/\">official documentation<\/a>.<\/p>\n<h1>Errors<\/h1>\n<h2>Signature mismatch<\/h2>\n<blockquote>\n<p><strong>ERROR:dbus.connection:Unable to set arguments ([&#8216;picockpit-client.service&#8217;],) according to signature &#8216;asb&#8217;: &lt;class &#8216;TypeError&#8217;&gt;: More items found in D-Bus signature than in Python arguments<\/strong><\/p>\n<\/blockquote>\n<p>If you get an error like above, check whether you are passing all the parameters as required by the signature in the documentation.<\/p>\n<p>In this case I had (wrong):<\/p>\n<blockquote>\n<p>manager.DisableUnitFiles([&#8216;picockpit-client.service&#8217;])<\/p>\n<\/blockquote>\n<p>instead of the correct:<\/p>\n<blockquote>\n<p>manager.DisableUnitFiles([&#8216;picockpit-client.service&#8217;], False)<\/p>\n<\/blockquote>\n<p>Also be sure to check if you are passing in a string (<strong>s<\/strong>), where an array of strings (<strong>as<\/strong>) is required.<\/p>\n<p><strong><br \/><\/strong><\/p>\n<h1>Ref<\/h1>\n<ul>\n<li><a href=\"https:\/\/dbus.freedesktop.org\/doc\/dbus-python\/tutorial.html\">https:\/\/dbus.freedesktop.org\/doc\/dbus-python\/tutorial.html<\/a><\/li>\n<li><a href=\"https:\/\/www.freedesktop.org\/wiki\/Software\/systemd\/dbus\/\">https:\/\/www.freedesktop.org\/wiki\/Software\/systemd\/dbus\/<\/a>&nbsp;<strong>&lt;\u2014the documentation \/ API for Dbus \/ systemd<\/strong><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Der kommende picockpit-client reagiert auf L\u00f6schvorg\u00e4nge des Frontends, indem er seinen Dienst deaktiviert (die Anwendung bleibt jedoch installiert). Wenn Sie sich entscheiden, picockpit-client connect erneut zu starten, wird der Dienst wieder aktiviert und automatisch f\u00fcr Sie gestartet. Dies ist \u00fcber die Python DBus-Schnittstelle m\u00f6glich. Der DBus ist ein Bussystem zur Interaktion mit...<\/p>","protected":false},"author":830,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[402,432,610,1],"tags":[845,848,850,849,826,540,631,572,846,851,852,847,492],"class_list":["post-27492","post","type-post","status-publish","format-standard","hentry","category-development","category-picockpit","category-python","category-raspberrypi-blog","tag-d-bus","tag-dbus","tag-disable","tag-enable","tag-error","tag-howto","tag-problem","tag-python","tag-python-3","tag-service","tag-services","tag-systemd","tag-variables"],"_links":{"self":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/27492","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/users\/830"}],"replies":[{"embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/comments?post=27492"}],"version-history":[{"count":1,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/27492\/revisions"}],"predecessor-version":[{"id":27493,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/posts\/27492\/revisions\/27493"}],"wp:attachment":[{"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/media?parent=27492"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/categories?post=27492"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pi3g.com\/de\/wp-json\/wp\/v2\/tags?post=27492"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}