YaST/DBus Service/Description/Factory
From openSUSE
| Revision as of 15:07, 15 April 2009 Lslezak (Talk | contribs) � Previous diff |
Revision as of 08:48, 22 April 2009 Mvidner (Talk | contribs) proper "YaST" capitalization Next diff → |
||
| Line 1: | Line 1: | ||
| - | =The Yast DBus Namespace Service= | + | =The YaST DBus Namespace Service= |
| - | {{VersionNote|Factory|This article is about the latest development version of the Yast DBus service which is part of the Factory distribution. The current Factory version is 2.18.x, for other versions see [[YaST/DBus_Service/Versions]]}} | + | {{VersionNote|Factory|This article is about the latest development version of the YaST DBus service which is part of the Factory distribution. The current Factory version is 2.18.x, for other versions see [[YaST/DBus_Service/Versions]]}} |
| {{Info|This document describes the current state of the development version which is work in progress. The service may be changed anytime, this is unstable version.}} | {{Info|This document describes the current state of the development version which is work in progress. The service may be changed anytime, this is unstable version.}} | ||
| Line 12: | Line 12: | ||
| ---- | ---- | ||
| - | Yast DBus name space service enables to use the Yast libraries and functionality from other applications via DBus interface. | + | YaST DBus name space service enables to use the YaST libraries and functionality from other applications via DBus interface. |
| The advantages are | The advantages are | ||
| - | * Access to Yast functions from every programming language or application which supports communication via DBus. That means the functionality is even available in shell (via dbus-send or qdbus tool) or in a DBus browser (e.g. kdbus, qdbusviewer...) | + | * Access to YaST functions from every programming language or application which supports communication via DBus. That means the functionality is even available in shell (via dbus-send or qdbus tool) or in a DBus browser (e.g. kdbus, qdbusviewer...) |
| - | * PolicyKit integration - The service uses PolicyKit for checking user authorizations, this enables access to priviledged operations to non-root users. This is very important when using Yast as a backend in desktop oriented applications. | + | * PolicyKit integration - The service uses PolicyKit for checking user authorizations, this enables access to priviledged operations to non-root users. This is very important when using YaST as a backend in desktop oriented applications. |
| - | This service moves the DBus support to higher level - the original SCR DBus service exports only low-level Yast name space (SCR::). This service can export every Yast name space written in any supported programming language (YCP, Perl, Python, C++, Ruby). | + | This service moves the DBus support to higher level - the original SCR DBus service exports only low-level YaST name space (SCR::). This service can export every YaST name space written in any supported programming language (YCP, Perl, Python, C++, Ruby). |
| Line 26: | Line 26: | ||
| ---- | ---- | ||
| - | The DBus service is available in yast2-core-2.18.6 and newer. It is currently available in FACTORY, it will be included in openSUSE 11.2. The service is part of the basic Yast component, the service does not need any | + | The DBus service is available in yast2-core-2.18.6 and newer. It is currently available in FACTORY, it will be included in openSUSE 11.2. The service is part of the basic YaST component, the service does not need any |
| extra configuration, it is enabled by default. It uses PolicyKit for access control, unauthorized use is not possible. | extra configuration, it is enabled by default. It uses PolicyKit for access control, unauthorized use is not possible. | ||
| Line 35: | Line 35: | ||
| The service has DBus name '''org.opensuse.YaST.modules''' and it is available on the system bus. | The service has DBus name '''org.opensuse.YaST.modules''' and it is available on the system bus. | ||
| - | Yast name spaces are available as objects with path '''/org/opensuse/YaST/modules/<namespace_name>'''. Every exported object (Yast name space) has these interfaces: | + | YaST name spaces are available as objects with path '''/org/opensuse/YaST/modules/<namespace_name>'''. Every exported object (YaST name space) has these interfaces: |
| - | * '''org.opensuse.YaST.Values''' - This is the standard Yast DBus interface, it uses DBus data types directly. This interface tries to autoconvert the passed DBus values to YCP values if possible. E.g. string is converted to YCP symbol if the function expects a symbol parameter. | + | * '''org.opensuse.YaST.Values''' - This is the standard YaST DBus interface, it uses DBus data types directly. This interface tries to autoconvert the passed DBus values to YCP values if possible. E.g. string is converted to YCP symbol if the function expects a symbol parameter. |
| - | * '''org.opensuse.YaST.YCPValues''' - This interface accepts marshaled YCP values (see [[#Marshalling YCP Values]] section). Any YCP value can be passed via this interface. This interface is rather a workaround for using Yast functions which would not be accessible otherwise or to pass special values. This interface should not be needed normally, all officially supported functions must be accessible using '''org.opensuse.YaST.Values''' interface. | + | * '''org.opensuse.YaST.YCPValues''' - This interface accepts marshaled YCP values (see [[#Marshalling YCP Values]] section). Any YCP value can be passed via this interface. This interface is rather a workaround for using YaST functions which would not be accessible otherwise or to pass special values. This interface should not be needed normally, all officially supported functions must be accessible using '''org.opensuse.YaST.Values''' interface. |
| Each object exports only the methods of the underlying name space, the global variables are not exported. If they need to be accessible they should be wrapped in get()/set() functions. See [[#Exporting Global Variables from Name Spaces]] section. | Each object exports only the methods of the underlying name space, the global variables are not exported. If they need to be accessible they should be wrapped in get()/set() functions. See [[#Exporting Global Variables from Name Spaces]] section. | ||
| Line 44: | Line 44: | ||
| == The Module Manager Interface == | == The Module Manager Interface == | ||
| - | The service provides a special interface '''org.opensuse.YaST.modules.ModuleManager''' at object '''/org/opensuse/YaST/modules'''. This is the interface to access the Yast DBus service itself. | + | The service provides a special interface '''org.opensuse.YaST.modules.ModuleManager''' at object '''/org/opensuse/YaST/modules'''. This is the interface to access the YaST DBus service itself. |
| Currently there are available these methods: | Currently there are available these methods: | ||
| - | * '''Import(string name_space)''' - explicitly import an Yast name space. Because name spaces are imported automatically this method should not be normally needed. It is intended for graphical DBus browsers which can send only method requested to known objects. | + | * '''Import(string name_space)''' - explicitly import an YaST name space. Because name spaces are imported automatically this method should not be normally needed. It is intended for graphical DBus browsers which can send only method requested to known objects. |
| * '''Lock()''' and '''Unlock()''' - should be used for accessing state full functions from a long running client. These functions prevents from shutting down the service. The service is kept running when there is at least one running client which has called Lock() method. | * '''Lock()''' and '''Unlock()''' - should be used for accessing state full functions from a long running client. These functions prevents from shutting down the service. The service is kept running when there is at least one running client which has called Lock() method. | ||
| Line 73: | Line 73: | ||
| === PolicyKit Action ID === | === PolicyKit Action ID === | ||
| - | The service checks whether the requester is allowed to call the Yast function. Yast uses prefix '''org.opensuse.yast.modules''', name space name and function name to create the PolicyKit action ID. | + | The service checks whether the requester is allowed to call the YaST function. YaST uses prefix '''org.opensuse.yast.modules''', name space name and function name to create the PolicyKit action ID. |
| PolicyKit allows only lower case letters and numbers in action ID - name space and function name are therefore lower cased. | PolicyKit allows only lower case letters and numbers in action ID - name space and function name are therefore lower cased. | ||
| Line 114: | Line 114: | ||
| - | = How to export Yast functionality = | + | = How to export YaST functionality = |
| ---- | ---- | ||
| - | ''This section is important mainly for Yast developers and users who are interested in implementation details.'' | + | ''This section is important mainly for YaST developers and users who are interested in implementation details.'' |
| The Dbus service can export already existing functions. But to avoid some problems the exported functions should follow these rules because of completely different usage: | The Dbus service can export already existing functions. But to avoid some problems the exported functions should follow these rules because of completely different usage: | ||
| Line 123: | Line 123: | ||
| * The exported functions should be state less - no separate '''Read()''', '''Edit()''' and '''Write()''' functions, but a single function for each exported functionality - e.g. '''DeleteUser()''' which calls all needed functions.<br>The reason is that the name space exported via DBus service is just one instance (a singleton) shared by all clients. The current state may contain internal data from previous calls from another clients. Stateless functions ensure that the same pre-conditions are used in all cases.<br>Running multiple clients in parallel can lead to race conditions, data loss, miss-configuration or other severe problems. | * The exported functions should be state less - no separate '''Read()''', '''Edit()''' and '''Write()''' functions, but a single function for each exported functionality - e.g. '''DeleteUser()''' which calls all needed functions.<br>The reason is that the name space exported via DBus service is just one instance (a singleton) shared by all clients. The current state may contain internal data from previous calls from another clients. Stateless functions ensure that the same pre-conditions are used in all cases.<br>Running multiple clients in parallel can lead to race conditions, data loss, miss-configuration or other severe problems. | ||
| - | * Input and output parameters should have just basic data types like ''string'', ''integer''... Yast has more data types than DBus (e.g. ''symbol'') or it has a special value which cannot be transferred by DBus directly (''nil'') or the transferred value can be is useless out side the service (like a ''function pointer''). | + | * Input and output parameters should have just basic data types like ''string'', ''integer''... YaST has more data types than DBus (e.g. ''symbol'') or it has a special value which cannot be transferred by DBus directly (''nil'') or the transferred value can be is useless out side the service (like a ''function pointer''). |
| * Use single type containers, when using ''list'' or ''map'' types DBus requires the same type for all values, e.g. <tt>[1, 2, 3]</tt> can be converted to a DBus array while <tt>[1, "2", `symbol]</tt> cannot. | * Use single type containers, when using ''list'' or ''map'' types DBus requires the same type for all values, e.g. <tt>[1, 2, 3]</tt> can be converted to a DBus array while <tt>[1, "2", `symbol]</tt> cannot. | ||
| - | * DBus does not support some special characters in object and method names, especially double-colon (:) is problematic for Yast. The DBus service automatically replaces invalid characters to underscore (_). Example: '''YaPI::Samba''' module is available at '''YaPI__Samba''' DBus object. | + | * DBus does not support some special characters in object and method names, especially double-colon (:) is problematic for YaST. The DBus service automatically replaces invalid characters to underscore (_). Example: '''YaPI::Samba''' module is available at '''YaPI__Samba''' DBus object. |
| * The exported function names should not differ only in upper or lower case letters. The reason is that e.g. Function() and funtion() will have the same PolicyKit action ID (see [[PolicyKit Action ID]] section) and the access right would be shared between them which is usually not intended and it is error prone. | * The exported function names should not differ only in upper or lower case letters. The reason is that e.g. Function() and funtion() will have the same PolicyKit action ID (see [[PolicyKit Action ID]] section) and the access right would be shared between them which is usually not intended and it is error prone. | ||
| Line 153: | Line 153: | ||
| == Logging == | == Logging == | ||
| - | The service uses standard Yast log file <tt>/var/log/YaST2/y2log</tt>. The service log is marked with <tt>[y2dbus]</tt> component string on each line. | + | The service uses standard YaST log file <tt>/var/log/YaST2/y2log</tt>. The service log is marked with <tt>[y2dbus]</tt> component string on each line. |
| It is possible to enable debug logging with variable <tt>Y2LOG=1</tt>. | It is possible to enable debug logging with variable <tt>Y2LOG=1</tt>. | ||
| Line 169: | Line 169: | ||
| == SCR Service Integration == | == SCR Service Integration == | ||
| - | This new DBus service should replace the previous Yast SCR service. Currently the SCR name space is not exported because it must be handled specially. | + | This new DBus service should replace the previous YaST SCR service. Currently the SCR name space is not exported because it must be handled specially. |
| The reason is that SCR:: provides overloaded methods and every call must be resolved at runtime. Another reason is that the interpreter allows to start multiple SCR instances so it is handled in a different way than all other name spaces. | The reason is that SCR:: provides overloaded methods and every call must be resolved at runtime. Another reason is that the interpreter allows to start multiple SCR instances so it is handled in a different way than all other name spaces. | ||
Revision as of 08:48, 22 April 2009
The YaST DBus Namespace Service
| Version: Factory
| This article is about the latest development version of the YaST DBus service which is part of the Factory distribution. The current Factory version is 2.18.x, for other versions see YaST/DBus_Service/Versions |
| This document describes the current state of the development version which is work in progress. The service may be changed anytime, this is unstable version. |
Contents |
The Purpose of the Service
YaST DBus name space service enables to use the YaST libraries and functionality from other applications via DBus interface.
The advantages are
- Access to YaST functions from every programming language or application which supports communication via DBus. That means the functionality is even available in shell (via dbus-send or qdbus tool) or in a DBus browser (e.g. kdbus, qdbusviewer...)
- PolicyKit integration - The service uses PolicyKit for checking user authorizations, this enables access to priviledged operations to non-root users. This is very important when using YaST as a backend in desktop oriented applications.
This service moves the DBus support to higher level - the original SCR DBus service exports only low-level YaST name space (SCR::). This service can export every YaST name space written in any supported programming language (YCP, Perl, Python, C++, Ruby).
How to Install the Service
The DBus service is available in yast2-core-2.18.6 and newer. It is currently available in FACTORY, it will be included in openSUSE 11.2. The service is part of the basic YaST component, the service does not need any extra configuration, it is enabled by default. It uses PolicyKit for access control, unauthorized use is not possible.
How to Use the Service
The service has DBus name org.opensuse.YaST.modules and it is available on the system bus.
YaST name spaces are available as objects with path /org/opensuse/YaST/modules/<namespace_name>. Every exported object (YaST name space) has these interfaces:
- org.opensuse.YaST.Values - This is the standard YaST DBus interface, it uses DBus data types directly. This interface tries to autoconvert the passed DBus values to YCP values if possible. E.g. string is converted to YCP symbol if the function expects a symbol parameter.
- org.opensuse.YaST.YCPValues - This interface accepts marshaled YCP values (see #Marshalling YCP Values section). Any YCP value can be passed via this interface. This interface is rather a workaround for using YaST functions which would not be accessible otherwise or to pass special values. This interface should not be needed normally, all officially supported functions must be accessible using org.opensuse.YaST.Values interface.
Each object exports only the methods of the underlying name space, the global variables are not exported. If they need to be accessible they should be wrapped in get()/set() functions. See #Exporting Global Variables from Name Spaces section.
The Module Manager Interface
The service provides a special interface org.opensuse.YaST.modules.ModuleManager at object /org/opensuse/YaST/modules. This is the interface to access the YaST DBus service itself.
Currently there are available these methods:
- Import(string name_space) - explicitly import an YaST name space. Because name spaces are imported automatically this method should not be normally needed. It is intended for graphical DBus browsers which can send only method requested to known objects.
- Lock() and Unlock() - should be used for accessing state full functions from a long running client. These functions prevents from shutting down the service. The service is kept running when there is at least one running client which has called Lock() method.
Marshalling YCP Values
There is a special interface org.opensuse.yast.YCPValues for passing types or values which are not suppoerted directly by DBus. This interface uses a special structure for encoding any YCP value. The structure (let's call it bsv structure) has three components:
- boolean - nil flag, if it is true the structure represents nil value, all other flags are unused and have undefined state (there are just some dummy values to keep the same signature for all YCP values)
- string - name of the YCP type, e.g. string, integer, list...
- variant - the value transferred using same or similar DBus type, e.g. YCP symbol is transferred as DBus string, YCP list is transferred as DBus array... YCP containers are recursively encoded, the variant can be another bsv structure.
This encoding enables transferring values like [1, "2", `symbol, nil] which cannot be transferred via direct DBus values.
Access control via PolicyKit
PolicyKit Check
Each incoming method request is check by PolicyKit and the requested method is executed only when PolicyKit returns YES. If PolicyKit returns different result the service returns DBus exception org.freedesktop.PolicyKit.Error.NotAuthorized followed by the PolicyKit result (see http://hal.freedesktop.org/docs/PolicyKit/polkit-polkit-simple.html#polkit-dbus-error-generate).
The client should authorize itself if needed and call the method again (see http://hal.freedesktop.org/docs/PolicyKit/model-theory-of-operation.html for details).
PolicyKit Action ID
The service checks whether the requester is allowed to call the YaST function. YaST uses prefix org.opensuse.yast.modules, name space name and function name to create the PolicyKit action ID.
PolicyKit allows only lower case letters and numbers in action ID - name space and function name are therefore lower cased.
Example:
PolicyKit action ID for Mode::normal() call is org.opensuse.yast.modules.mode.normal.
Obtaining a PolicyKit Authorization
A PolicyKit authorization can be obtained
- implicitly from a *.policy configuration file
- the user authenticates as the administrator (root) user
polkit-auth --obtain org.opensuse.yast.modules.yapi-samba.getservicestatus
- the adminitrator grants the autorization to the user
polkit-auth --user lslezak --grant org.opensuse.yast.modules.yapi-samba.getservicestatus
Service start and shutdown
The service is started automatically by the DBus daemon when it is not running.
The service is automatically shut down when at least 2 minutes has elapsed since the last request. This prevents from consuming memory by an unused service.
The service does not import any name space at start up by default. The name spaces are dynamically imported when needed.
Examples
Here are examples how to invoke YaPI::Samba::GetServiceStatus() function. This example requires org.opensuse.yast.modules.yapi-samba.getservicestatus PolicyKit authorization, see #Obtaining a PolicyKit Authorization.
Python Example
import dbus
bus = dbus.SystemBus()
obj = bus.get_object('org.opensuse.YaST.modules', '/org/opensuse/YaST/modules/YaPI__Samba')
ifce=dbus.Interface(obj,'org.opensuse.YaST.Values')
result=ifce.GetServiceStatus()
print result
Shell Examples
dbus-send --system --dest=org.opensuse.YaST.modules --print-reply --type=method_call /org/opensuse/YaST/modules/YaPI__Samba org.opensuse.YaST.Values.GetServiceStatus
qdbus --system org.opensuse.YaST.modules /org/opensuse/YaST/modules/YaPI__Samba org.opensuse.YaST.Values.GetServiceStatus
How to export YaST functionality
This section is important mainly for YaST developers and users who are interested in implementation details.
The Dbus service can export already existing functions. But to avoid some problems the exported functions should follow these rules because of completely different usage:
- The exported functions should be state less - no separate Read(), Edit() and Write() functions, but a single function for each exported functionality - e.g. DeleteUser() which calls all needed functions.
The reason is that the name space exported via DBus service is just one instance (a singleton) shared by all clients. The current state may contain internal data from previous calls from another clients. Stateless functions ensure that the same pre-conditions are used in all cases.
Running multiple clients in parallel can lead to race conditions, data loss, miss-configuration or other severe problems.
- Input and output parameters should have just basic data types like string, integer... YaST has more data types than DBus (e.g. symbol) or it has a special value which cannot be transferred by DBus directly (nil) or the transferred value can be is useless out side the service (like a function pointer).
- Use single type containers, when using list or map types DBus requires the same type for all values, e.g. [1, 2, 3] can be converted to a DBus array while [1, "2", `symbol] cannot.
- DBus does not support some special characters in object and method names, especially double-colon (:) is problematic for YaST. The DBus service automatically replaces invalid characters to underscore (_). Example: YaPI::Samba module is available at YaPI__Samba DBus object.
- The exported function names should not differ only in upper or lower case letters. The reason is that e.g. Function() and funtion() will have the same PolicyKit action ID (see PolicyKit Action ID section) and the access right would be shared between them which is usually not intended and it is error prone.
- Each exported function (respective its action ID) must be defined in a PolicyKit configuration file. See PolicyKit documentation http://hal.freedesktop.org/docs/PolicyKit/polkit-conf.html#conf-declaring-actions . Defining a PolicyKit action ID means that the function is officially supported over the DBus service.
It is a good idea to validate the PolicyKit config during make check.
- The exported name space neither its imported name spaces should not define constructors. The reason is security - because of the auto-import functionality the constructor could potentially execute an action which is not allowed to the calling client. Another problem is that the constructor is called just once (at first import) and using constructor leads to a state full API which should be avoided.
- The exported function must not use any UI:: functions, the service cannot open any dialog because it has no terminal or X session and all UI:: calls will very likely fail. The service should be used as a backend providing some functionality to an application, UI should not be used in the service anyway.
Debugging
Starting the Service Manually
The service can be started explicitly using /usr/lib/YaST2/bin/yast_modules_dbus_server executable. The service may be owned only by root user, so it can be started only from a root shell. Use --disable-timer option to disable automatic shutdown feature.
The optional arguments can be used to pre-load requested name spaces.
Example:
/usr/lib/YaST2/bin/yast_modules_dbus_server --disable-timer Label Pkg
Logging
The service uses standard YaST log file /var/log/YaST2/y2log. The service log is marked with [y2dbus] component string on each line.
It is possible to enable debug logging with variable Y2LOG=1.
Reloading the DBus Configuration
During the development the service rarely refused to start claiming that it is already running. Reloading the DBus configuration solved the problem. Use ReloadConfig() method of the DBus daemon if it happens:
dbus-send --system --dest=org.freedesktop.DBus --print-reply --type=method_call / org.freedesktop.DBus.ReloadConfig
Future Enhancements
SCR Service Integration
This new DBus service should replace the previous YaST SCR service. Currently the SCR name space is not exported because it must be handled specially.
The reason is that SCR:: provides overloaded methods and every call must be resolved at runtime. Another reason is that the interpreter allows to start multiple SCR instances so it is handled in a different way than all other name spaces.
Exporting Global Variables from Name Spaces
Global variables could be exported via DBus object properties if really needed. Currently they have to be wrapped in get()/set() methods if they need to be exported.

