Translate

Archives

PackageKit D-Bus Abstraction Layer

PackageKit uses an abstraction layer to allow a session user to manage software packages in a secure way. This abstraction layer is based on D-Bus. Essentially, it is a set of APIs exported through a D-Bus interface. Glib, qt and python and other language bindings are available. This abstraction layer enables applications to perform high-level package operations such as add or remove a package without having to know much about package management. PolicyKit (AKA PolKit) is incorporated to provide a fine grained policy mechanism for users.

D-Bus has two connections types (buses): System and Session. System interfaces normally run as root (otherwise they need rights to use it) whereas session connections runs on the user session. These two connections types have no communication with each other.

First of all, let us introspect org.freedesktop.PackageKit via the system bus to see what interfaces, methods and properties are available to us. A good utility to use is dbus-send.

# dbus-send --system --print-reply --reply-timeout=2000 --type=method_call \
  --dest=org.freedesktop.PackageKit  /org/freedesktop/PackageKit \ 
  org.freedesktop.DBus.Introspectable.Introspect

method return sender=:1.160 -> dest=:1.164 reply_serial=2
   string "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
                      "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!-- GDBus 2.38.2 -->
<node>
  <interface name="org.freedesktop.DBus.Properties">
    <method name="Get">
      <arg type="s" name="interface_name" direction="in"/>
      <arg type="s" name="property_name" direction="in"/>
      <arg type="v" name="value" direction="out"/>
    </method>
    <method name="GetAll">
      <arg type="s" name="interface_name" direction="in"/>
      <arg type="a{sv}" name="properties" direction="out"/>
    </method>
    <method name="Set">
      <arg type="s" name="interface_name" direction="in"/>
      <arg type="s" name="property_name" direction="in"/>
      <arg type="v" name="value" direction="in"/>
    </method>
    <signal name="PropertiesChanged">
      <arg type="s" name="interface_name"/>
      <arg type="a{sv}" name="changed_properties"/>
      <arg type="as" name="invalidated_properties"/>
    </signal>
  </interface>
  <interface name="org.freedesktop.DBus.Introspectable">
    <method name="Introspect">
      <arg type="s" name="xml_data" direction="out"/>
    </method>
  </interface>
  <interface name="org.freedesktop.DBus.Peer">
    <method name="Ping"/>
    <method name="GetMachineId">
      <arg type="s" name="machine_uuid" direction="out"/>
    </method>
  </interface>
  <interface name="org.freedesktop.PackageKit">
    <method name="CanAuthorize">
      <annotation name="org.freedesktop.DBus.GLib.Async" value="">
      </annotation>
      <arg type="s" name="action_id" direction="in">
      </arg>
      <arg type="u" name="result" direction="out">
      </arg>
    </method>
    <method name="CreateTransaction">
      <annotation name="org.freedesktop.DBus.GLib.Async" value="">
      </annotation>
      <arg type="o" name="object_path" direction="out">
      </arg>
    </method>
    <method name="GetTimeSinceAction">
      <arg type="u" name="role" direction="in">
      </arg>
      <arg type="u" name="seconds" direction="out">
      </arg>
    </method>
    <method name="GetTransactionList">
      <arg type="ao" name="transactions" direction="out">
      </arg>
    </method>
    <method name="StateHasChanged">
      <arg type="s" name="reason" direction="in">
      </arg>
    </method>
    <method name="SuggestDaemonQuit">
    </method>
    <method name="GetPackageHistory">
      <arg type="as" name="names" direction="in">
      </arg>
      <arg type="u" name="count" direction="in">
      </arg>
      <arg type="a{saa{sv}}" name="history" direction="out">
      </arg>
    </method>
    <method name="GetDaemonState">
      <arg type="s" name="state" direction="out">
      </arg>
    </method>
    <method name="SetProxy">
      <annotation name="org.freedesktop.DBus.GLib.Async" value="">
      </annotation>
      <arg type="s" name="proxy_http" direction="in">
      </arg>
      <arg type="s" name="proxy_https" direction="in">
      </arg>
      <arg type="s" name="proxy_ftp" direction="in">
      </arg>
      <arg type="s" name="proxy_socks" direction="in">
      </arg>
      <arg type="s" name="no_proxy" direction="in">
      </arg>
      <arg type="s" name="pac" direction="in">
      </arg>
    </method>
    <signal name="TransactionListChanged">
      <arg type="as" name="transactions">
      </arg>
    </signal>
    <signal name="RestartSchedule">
    </signal>
    <signal name="RepoListChanged">
    </signal>
    <signal name="UpdatesChanged">
    </signal>
    <signal name="Changed">
    </signal>
    <property type="u" name="VersionMajor" access="read">
    </property>
    <property type="u" name="VersionMinor" access="read">
    </property>
    <property type="u" name="VersionMicro" access="read">
    </property>
    <property type="s" name="BackendName" access="read">
    </property>
    <property type="s" name="BackendDescription" access="read">
    </property>
    <property type="s" name="BackendAuthor" access="read">
    </property>
    <property type="t" name="Roles" access="read">
    </property>
    <property type="t" name="Provides" access="read">
    </property>
    <property type="t" name="Groups" access="read">
    </property>
    <property type="t" name="Filters" access="read">
    </property>
    <property type="as" name="MimeTypes" access="read">
    </property>
    <property type="b" name="Locked" access="read">
    </property>
    <property type="u" name="NetworkState" access="read">
    </property>
    <property type="s" name="DistroId" access="read">
    </property>
  </interface>
</node>

Now let us introspect org.freedesktop.PackageKit via the session bus to see what interfaces, methods and properties are available to us on this bus:

# dbus-send --session --print-reply --reply-timeout=2000 --type=method_call \ 
   --dest=org.freedesktop.PackageKit  /org/freedesktop/PackageKit \
   org.freedesktop.DBus.Introspectable.Introspect

method return sender=:1.83 -> dest=:1.89 reply_serial=2
   string "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
  <interface name="org.freedesktop.DBus.Introspectable">
    <method name="Introspect">
      <arg name="data" direction="out" type="s"/>
    </method>
  </interface>
  <interface name="org.freedesktop.DBus.Properties">
    <method name="Get">
      <arg name="interface" direction="in" type="s"/>
      <arg name="propname" direction="in" type="s"/>
      <arg name="value" direction="out" type="v"/>
    </method>
    <method name="Set">
      <arg name="interface" direction="in" type="s"/>
      <arg name="propname" direction="in" type="s"/>
      <arg name="value" direction="in" type="v"/>
    </method>
    <method name="GetAll">
      <arg name="interface" direction="in" type="s"/>
      <arg name="props" direction="out" type="a{sv}"/>
    </method>
  </interface>
  <interface name="org.freedesktop.PackageKit.Modify">
    <method name="InstallPrinterDrivers">
      <arg name="xid" type="u" direction="in"/>
      <arg name="resources" type="as" direction="in"/>
      <arg name="interaction" type="s" direction="in"/>
    </method>
    <method name="RemovePackageByFiles">
      <arg name="xid" type="u" direction="in"/>
      <arg name="files" type="as" direction="in"/>
      <arg name="interaction" type="s" direction="in"/>
    </method>
    <method name="InstallResources">
      <arg name="xid" type="u" direction="in"/>
      <arg name="type" type="s" direction="in"/>
      <arg name="resources" type="as" direction="in"/>
      <arg name="interaction" type="s" direction="in"/>
    </method>
    <method name="InstallGStreamerResources">
      <arg name="xid" type="u" direction="in"/>
      <arg name="resources" type="as" direction="in"/>
      <arg name="interaction" type="s" direction="in"/>
    </method>
    <method name="InstallFontconfigResources">
      <arg name="xid" type="u" direction="in"/>
      <arg name="resources" type="as" direction="in"/>
      <arg name="interaction" type="s" direction="in"/>
    </method>
    <method name="InstallMimeTypes">
      <arg name="xid" type="u" direction="in"/>
      <arg name="mime_types" type="as" direction="in"/>
      <arg name="interaction" type="s" direction="in"/>
    </method>
    <method name="InstallPackageNames">
      <arg name="xid" type="u" direction="in"/>
      <arg name="packages" type="as" direction="in"/>
      <arg name="interaction" type="s" direction="in"/>
    </method>
    <method name="InstallCatalogs">
      <arg name="xid" type="u" direction="in"/>
      <arg name="files" type="as" direction="in"/>
      <arg name="interaction" type="s" direction="in"/>
    </method>
    <method name="InstallProvideFiles">
      <arg name="xid" type="u" direction="in"/>
      <arg name="files" type="as" direction="in"/>
      <arg name="interaction" type="s" direction="in"/>
    </method>
    <method name="InstallPackageFiles">
      <arg name="xid" type="u" direction="in"/>
      <arg name="files" type="as" direction="in"/>
      <arg name="interaction" type="s" direction="in"/>
    </method>
  </interface>
  <interface name="org.freedesktop.PackageKit.Query">
    <method name="SearchFile">
      <arg name="file_name" type="s" direction="in"/>
      <arg name="interaction" type="s" direction="in"/>
      <arg name="installed" type="b" direction="out"/>
      <arg name="package_name" type="s" direction="out"/>
    </method>
    <method name="IsInstalled">
      <arg name="package_name" type="s" direction="in"/>
      <arg name="interaction" type="s" direction="in"/>
      <arg name="installed" type="b" direction="out"/>
    </method>
  </interface>
</node>


In general, you must introspect both the system and session buses to obtain an accurate and complete list of all the methods and properties available to you. As you can see from the above, PackageKit exposes a large number of methods and properties to us.

Another useful utility which provides the same information in a more compact form is qdbus.

# qdbus org.freedesktop.PackageKit
/
/org
/org/freedesktop
/org/freedesktop/PackageKit

# qdbus --system org.freedesktop.PackageKit /org/freedesktop/PackageKit
qmethod QDBusVariant org.freedesktop.DBus.Properties.Get(QString interface_name, QString property_name)
method QVariantMap org.freedesktop.DBus.Properties.GetAll(QString interface_name)
signal void org.freedesktop.DBus.Properties.PropertiesChanged(QString interface_name, QVariantMap changed_properties, QStringList invalidated_properties)
method void org.freedesktop.DBus.Properties.Set(QString interface_name, QString property_name, QDBusVariant value)
method QString org.freedesktop.DBus.Introspectable.Introspect()
method QString org.freedesktop.DBus.Peer.GetMachineId()
method void org.freedesktop.DBus.Peer.Ping()
property read QString org.freedesktop.PackageKit.BackendAuthor
property read QString org.freedesktop.PackageKit.BackendDescription
property read QString org.freedesktop.PackageKit.BackendName
property read QString org.freedesktop.PackageKit.DistroId
property read qulonglong org.freedesktop.PackageKit.Filters
property read qulonglong org.freedesktop.PackageKit.Groups
property read bool org.freedesktop.PackageKit.Locked
property read QStringList org.freedesktop.PackageKit.MimeTypes
property read uint org.freedesktop.PackageKit.NetworkState
property read qulonglong org.freedesktop.PackageKit.Provides
property read qulonglong org.freedesktop.PackageKit.Roles
property read uint org.freedesktop.PackageKit.VersionMajor
property read uint org.freedesktop.PackageKit.VersionMicro
property read uint org.freedesktop.PackageKit.VersionMinor
method uint org.freedesktop.PackageKit.CanAuthorize(QString action_id)
signal void org.freedesktop.PackageKit.Changed()
method QDBusObjectPath org.freedesktop.PackageKit.CreateTransaction()
method QString org.freedesktop.PackageKit.GetDaemonState()
method QDBusRawType::a{saa{sv}} org.freedesktop.PackageKit.GetPackageHistory(QStringList names, uint count)
method uint org.freedesktop.PackageKit.GetTimeSinceAction(uint role)
method QList org.freedesktop.PackageKit.GetTransactionList()
signal void org.freedesktop.PackageKit.RepoListChanged()
signal void org.freedesktop.PackageKit.RestartSchedule()
method void org.freedesktop.PackageKit.SetProxy(QString proxy_http, QString proxy_https, QString proxy_ftp, QString proxy_socks, QString no_proxy, QString pac)
method void org.freedesktop.PackageKit.StateHasChanged(QString reason)
method void org.freedesktop.PackageKit.SuggestDaemonQuit()
signal void org.freedesktop.PackageKit.TransactionListChanged(QStringList transactions)
signal void org.freedesktop.PackageKit.UpdatesChanged()

# qdbus org.freedesktop.PackageKit /org/freedesktop/PackageKit
method QString org.freedesktop.DBus.Introspectable.Introspect()
method QDBusVariant org.freedesktop.DBus.Properties.Get(QString interface, QString propname)
method QVariantMap org.freedesktop.DBus.Properties.GetAll(QString interface)
method void org.freedesktop.DBus.Properties.Set(QString interface, QString propname, QDBusVariant value)
method void org.freedesktop.PackageKit.Modify.InstallCatalogs(uint xid, QStringList files, QString interaction)
method void org.freedesktop.PackageKit.Modify.InstallFontconfigResources(uint xid, QStringList resources, QString interaction)
method void org.freedesktop.PackageKit.Modify.InstallGStreamerResources(uint xid, QStringList resources, QString interaction)
method void org.freedesktop.PackageKit.Modify.InstallMimeTypes(uint xid, QStringList mime_types, QString interaction)
method void org.freedesktop.PackageKit.Modify.InstallPackageFiles(uint xid, QStringList files, QString interaction)
method void org.freedesktop.PackageKit.Modify.InstallPackageNames(uint xid, QStringList packages, QString interaction)
method void org.freedesktop.PackageKit.Modify.InstallPrinterDrivers(uint xid, QStringList resources, QString interaction)
method void org.freedesktop.PackageKit.Modify.InstallProvideFiles(uint xid, QStringList files, QString interaction)
method void org.freedesktop.PackageKit.Modify.InstallResources(uint xid, QString type, QStringList resources, QString interaction)
method void org.freedesktop.PackageKit.Modify.RemovePackageByFiles(uint xid, QStringList files, QString interaction)
method bool org.freedesktop.PackageKit.Query.IsInstalled(QString package_name, QString interaction)
method bool org.freedesktop.PackageKit.Query.SearchFile(QString file_name, QString interaction, QString& package_name)


Note: the default bus for qdbus is the session bus. Use –system to specify the system bus.

PackageKit properties can be easily retrieved using org.freedesktop.DBus.Properties.Get as shown in these examples:

# dbus-send --system --print-reply  --dest=org.freedesktop.PackageKit  \
    /org/freedesktop/PackageKit org.freedesktop.DBus.Properties.Get  \  
    string:'org.freedesktop.PackageKit' string:'BackendName'

method return sender=:1.225 -> dest=:1.224 reply_serial=2
   variant       string "yum"

# dbus-send --system --print-reply  --dest=org.freedesktop.PackageKit  \
    /org/freedesktop/PackageKit org.freedesktop.DBus.Properties.Get \ 
    string:'org.freedesktop.PackageKit' string:'VersionMajor'

method return sender=:1.233 -> dest=:1.232 reply_serial=2
   variant       uint32 0

# dbus-send --system --print-reply  --dest=org.freedesktop.PackageKit  \
   /org/freedesktop/PackageKit org.freedesktop.DBus.Properties.Get \
   string:'org.freedesktop.PackageKit' string:'VersionMinor'

method return sender=:1.233 -> dest=:1.235 reply_serial=2
   variant       uint32 8

# dbus-send --system --print-reply  --dest=org.freedesktop.PackageKit  \
   /org/freedesktop/PackageKit org.freedesktop.DBus.Properties.Get \
   string:'org.freedesktop.PackageKit' string:'VersionMicro'

method return sender=:1.233 -> dest=:1.235 reply_serial=2
   variant       uint32 13


So it looks like yum is the backend and the version number is 0.8,13 which was released on 2013-11-22.

There are two DBus interfaces exposed on the session bus: Query and Modify. As their names suggests query is used for querying packages and modify is used to modify packages.

In the following examples, we check to see if the bash package is installed. Both dbus-send and qdbus versions are provided.

# qdbus org.freedesktop.PackageKit /org/freedesktop/PackageKit \
  org.freedesktop.PackageKit.Query.IsInstalled "bash" 0

true

# dbus-send --session --print-reply --type=method_call --reply-timeout=2000 \ 
   --dest=org.freedesktop.PackageKit  /org/freedesktop/PackageKit \ 
   org.freedesktop.PackageKit.Query.IsInstalled string:'bash' string:'0'

method return sender=:1.83 -> dest=:1.86 reply_serial=2
   boolean true

# qdbus org.freedesktop.PackageKit /org/freedesktop/PackageKit  \ 
   org.freedesktop.PackageKit.Query.IsInstalled "bashii" 10

false

The following examples find the package name for an installed or available pathname and indicates whether the package is currently installed or not:

# qdbus org.freedesktop.PackageKit /org/freedesktop/PackageKit  \
   org.freedesktop.PackageKit.Query.SearchFile "/bin/bash" 0

true
bash

# dbus-send --session --print-reply --type=method_call --reply-timeout=2000 \ 
   --dest=org.freedesktop.PackageKit  /org/freedesktop/PackageKit \
   org.freedesktop.PackageKit.Query.SearchFile string:'/bin/bash' string:'0'

method return sender=:1.83 -> dest=:1.85 reply_serial=2
   boolean true
   string "bash"

In these examples, we install the zsh (Z-Shell), then uninstall this package and finally display the associated package management history.

# dbus-send --session --print-reply --type=method_call --dest=org.freedesktop.PackageKit \
   /org/freedesktop/PackageKit org.freedesktop.PackageKit.Modify.InstallPackageNames \
   uint32:1 array:string:"zsh" string:''

method return sender=:1.83 -> dest=:1.97 reply_serial=2

# zsh
# exit

# dbus-send --session --print-reply --type=method_call --dest=org.freedesktop.PackageKit \
    /org/freedesktop/PackageKit org.freedesktop.PackageKit.Modify.RemovePackageByFiles \ 
    uint32:1 array:string:"/bin/zsh" string:''

method return sender=:1.83 -> dest=:1.98 reply_serial=2

# dbus-send --system --print-reply --type=method_call --dest=org.freedesktop.PackageKit  \ 
    /org/freedesktop/PackageKit org.freedesktop.PackageKit.GetPackageHistory \ 
    array:string:"zsh"  uint32:10

method return sender=:1.290 -> dest=:1.289 reply_serial=2
   array [
      dict entry(
         string "zsh"
         array [
            array [
               dict entry(
                  string "info"
                  variant                      uint32 12
               )
               dict entry(
                  string "source"
                  variant                      string "fedora"
               )
               dict entry(
                  string "version"
                  variant                      string "5.0.2-6.fc20"
               )
               dict entry(
                  string "timestamp"
                  variant                      uint64 1385769600
               )
               dict entry(
                  string "user-id"
                  variant                      uint32 0
               )
            ]
         ]
      )
   ]

# dbus-send --session --print-reply --type=method_call --dest=org.freedesktop.PackageKit  \
    /org/freedesktop/PackageKit org.freedesktop.PackageKit.Modify.InstallPackageNames  \ 
    uint32:2 array:string:"zsh" string:'never'

method return sender=:1.9 -> dest=:1.10 reply_serial=2


The timestamp value shown above is the number of seconds since the UNIX Epoch.

In the last example above the third parameter is the string ‘never’. This parameter indicates what type of UI interaction should be provided to the user; in this case no interaction. Here is a description of the valid values from org.freedesktop.PackageKit.xml

       <arg type="s" name="interaction" direction="in">
        <doc:doc>
          <doc:summary>
            <doc:para>
              An interaction mode that specifies which UI elements should be shown
              or hidden different from the user default, e.g.
              <doc:tt>hide-confirm-search,hide-confirm-deps,hide-confirm-install,show-progress</doc:tt>.
              The show options are:
              <doc:tt>show-confirm-search,show-confirm-deps,show-confirm-install,show-progress,show-finished,show-warning</doc:tt>.
              The hide options are:
              <doc:tt>hide-confirm-search,hide-confirm-deps,hide-confirm-install,hide-progress,hide-finished,hide-warning</doc:tt>.
              Convenience options such as:
              <doc:tt>never</doc:tt>, <doc:tt>defaults</doc:tt> or <doc:tt>always</doc:tt>.
              are also available.
            </doc:para>
          </doc:summary>
        </doc:doc>
      </arg>


BTW, if you have never used the zsh shell, I highly recommend you try it; it is far superior to the bash shell.

Comments are closed.