8.4. Local system module#
The UMC server provides management services that are provided by so called UMC modules. These modules are implemented in Python (backend) and in JavaScript (web frontend). The following page provides information about developing and packaging of UMC modules. It is important to know the details of Architecture.
The package univention-management-console-dev provides the command umc-create-module, which can be used to create a template for a custom UMC module.
8.4.1. Python API#
The Python API for the UMC is defined in the Python module
univention.management.console.base
.
8.4.2. UMC module API (Python and JavaScript)#
A UMC module consists of three components
A XML document containing the definition.
The Python module defining the command functions.
The JavaScript frontend providing the web frontend.
8.4.2.1. XML definition#
The UMC server knows three types of resources that define the functionality it can provide:
- UMC modules
provide commands that can be executed if the required permission is given.
- Syntax types
can be used to verify the correctness of command attributes defined by the UMC client in the request message or return values provided by the UMC modules.
- Categories
help to define a structure and to sort the UMC modules by its type of functionality.
All these resources are defined in XML files. The details are described in the following sections
8.4.2.1.1. Module definition#
The UMC server does not load the Python modules to get the details about the
modules name, description and functionality. Therefore, each UMC module must
provide an XML file containing this kind of information. The following example
defines a module with the id udm
:
<?xml version="1.0" encoding="UTF-8"?>
<umc version="2.0">
<module id="udm" icon="udm/module" version="1.0">
<name>Univention Directory Manager</name>
<description>Manages all UDM modules</description>
<flavor icon="udm-users" id="users/user">
<name>Users</name>
<description>Managing users</description>
</flavor>
<categories>
<category name="domain"/>
</categories>
<command name="udm/query" function="query"/>
<command name="udm/containers" function="containers"/>
</module>
</umc>
The element module
defines the basic details of a
UMC module.
id
This identifier must be unique among the modules of an UMC server. Other files may extend the definition of a module by adding more flavors or categories.
icon
The value of this attribute defines an identifier for the icon that should be used for the module. Details for installing icons can be found in the Packaging.
The child elements name
and description
define the English human
readable name and description of the module. For other translations the build
tools will create translation files. Details can be found in the
Packaging.
This example defines a so called flavor. A flavor defines a new name, description and icon for the same UMC module. This can be used to show several virtual modules in the overview of the web frontend. Additionally, the flavor is passed to the UMC server with each request i.e. the UMC module has the possibility to act differently for a specific flavor.
As the next element categories
is defined in the example. The child elements
category
set the categories within the overview where the module should be
shown. Each module can be part of multiple categories. The attribute name
is
the internal identifier of a category.
At the end of the definition file a list of commands is specified. The UMC server only passes commands to a UMC module that are defined. A command definition has two attributes:
name
is the name of the command that is passed to the UMC module. Within the HTTP request it is the URL path after
/univention/command/
.function
defines the method to be invoked within the Python module when the command is called.
8.4.2.1.2. Category definition#
The predefined set of categories can be extended by each module.
<?xml version="1.0" encoding="UTF-8"?>
<umc version="2.0">
<categories>
<category id="favorites">
<name>Favorites</name>
</category>
<category id="system">
<name>System</name>
</category>
<category id="wizards">
<name>Wizards</name>
</category>
<category id="monitor">
<name>Surveillance</name>
</category>
</categories>
</umc>
8.4.2.2. Python module#
The Python API for UMC modules primarily consists of one base class that must be implemented. As an addition the Python API provides some helpers:
Exception classes
Translation support
Logging functions
UCR access
In the definition file, the UMC module specifies functions for the commands
provided by the module. These functions must be implemented as methods of the
class Instance
that inherits from
univention.management.console.base.Base
.
The following Python code example matches the definition in the previous section:
# SPDX-FileCopyrightText: 2021-2024 Univention GmbH
#
# SPDX-License-Identifier: AGPL-3.0-only
from univention.management.console import Translation
from univention.management.console.base import Base, UMC_Error
from univention.management.console.config import ucr
from univention.management.console.log import MODULE
from univention.management.console.modules.decorators import sanitize
from univention.management.console.modules.sanitizers import IntegerSanitizer
_ = Translation('univention-management-console-modules-udm').translate
class Instance(Base):
def init(self):
"""Initialize the module with some values"""
super(Instance, self).init()
self.data = [int(x) for x in ucr.get('some/examle/ucr/variable', '1,2,3').split(',')]
def query(self, request):
"""get all values of self.data"""
self.finished(request.id, self.data)
@sanitize(item=IntegerSanitizer(required=True))
def get(self, request):
"""get a specific item of self.data"""
try:
item = self.data[request.options['item']]
except IndexError:
MODULE.error('A invalid item was accessed.')
raise UMC_Error(_('The item %d does not exists.') % (request.options['item'],), status=400)
self.finished(request.id, self.data[item])
@sanitize(IntegerSanitizer(required=True))
def put(self, request):
"""replace all data with the list provided in request.options"""
self.data = request.options
self.finished(request.id, None)
Each command methods has one parameter that contains the UMC request. Such an object has the following properties:
id
the unique identifier of the request.
options
contains the arguments for the command. For most commands it is a dictionary.
flavor
the name of the flavor that was used to invoke the command. This might be
None
.
The method init()
in the example is invoked when the module process starts.
It could for example be used to initialize a database connection.
The other methods in the example will serve specific requests. To respond to a
request the function finished()
must be invoked. To validate the request
body the decorator @sanitize
might be used with various sanitizers defined
in univention.management.console.modules.sanitizers
.
For a way to send an error message back to the client the UMC_Error
can be raised with the error message as argument and an optional HTTP status
code. The base class for modules provides some properties and methods that could
be useful when writing UMC modules:
username
The username of the owner of this session.
user_dn
The DN of the user or None if the user is only a local user.
password
The password of the user.
init()
Is invoked after the module process has been initialized. At that moment, the settings, like locale and username and password are available.
destroy()
Is invoked before the module process shuts down.
8.4.2.3. UMC store API#
In order to encapsulate and ease the access to module data from the JavaScript side, a store object offers a unified way to query and modify module data.
The UMC JavaScript API comes with an object store implementation of the Dojo store API. This allows the JavaScript code to access/modify module data and to observe changes on the data in order to react immediately. The following methods are supported:
- get(id)#
Returns a dictionary of all properties for the object with the specified identifier.
- put(dictionary, options)#
modifies an object with the corresponding properties and an optional dictionary of options.
- add(dictionary, options)#
Adds a new object with the corresponding properties and an optional dictionary of options.
- remove(id)#
Removes the object with the specified identifier.
- query(dictionary)#
Queries a list of objects (returned as list of dictionaries) corresponding to the given query which is represented as dictionary. Note that not all object properties need to be returned in order to save bandwidth.
The UMC object store class in JavaScript will be able to communicate directly with the Python module if the following methods are implemented:
- module/get()#
Expects as input a list if unique IDs (as strings) and returns a list of dictionaries as result. Each dictionary entry holds all object properties.
- module/put()#
Expects as input a list of dictionaries where each entry has the properties
object
andoptions
. The propertyobject
holds all object properties to be set (i.e., this may also be a subset of all possible properties) as a dictionary. The second propertyoptions
is an optional dictionary that holds additional options as a dictionary.
- module/add()#
Expects similar input values as
module/put()
.
- module/remove()#
Expects as input a list of dictionaries where each entry has the properties
object
(containing the object’s unique ID (as string)) andoptions
. The options property can be necessary as a removal might be executed in different ways (recursively, shallow removal etc.).
- module/query()#
Expects as input a dictionary with entries that specify the query parameters and returns a list of dictionaries. Each entry may hold only a subset of all possible object properties.
Further references:
8.4.3. Packaging#
A UMC module consists of several files that must be installed at a specific location. As this mechanism is always the same there are debhelper tools making package creation for UMC modules very easy.
The following example is based on the package for the UMC module UCR.
A UMC module may be part of a source package with multiple binary packages. The examples uses a own source package for the module.
As a first step create a source package with the following directories and files:
univention-management-console-module-ucr/
univention-management-console-module-ucr/debian/
univention-management-console-module-ucr/debian/univention-management-console-module-ucr.umc-modules
univention-management-console-module-ucr/debian/rules
univention-management-console-module-ucr/debian/changelog
univention-management-console-module-ucr/debian/control
univention-management-console-module-ucr/debian/copyright
All these files are standard Debian packaging files except
univention-management-console-module-ucr.umc-modules
. This file contains
information about the locations of the UMC module source files:
Module: ucr
Python: umc/python
Definition: umc/ucr.xml
Syntax: umc/syntax/ucr.xml
Javascript: umc/js
Icons: umc/icons
The keys in this file of the following meaning:
Module
The internal name of the module
Python
A directory that contains the Python package for the UMC module
Definition
The filename of the XML file with the module definition
Javascript
A directory containing the JavaScript source code
Icons
A directory containing the icons required by the modules web frontend
Syntax
(optional)The filename of the XML file with the syntax definitions
Category
(optional)The filename of the XML file with the category definitions
The directory structure for such a UMC module file would look like this:
univention-management-console-module-ucr/umc/
univention-management-console-module-ucr/umc/syntax/
univention-management-console-module-ucr/umc/syntax/ucr.xml
univention-management-console-module-ucr/umc/js/
univention-management-console-module-ucr/umc/js/ucr.js
univention-management-console-module-ucr/umc/js/de.po
univention-management-console-module-ucr/umc/de.po
univention-management-console-module-ucr/umc/icons/
univention-management-console-module-ucr/umc/icons/16x16/
univention-management-console-module-ucr/umc/icons/16x16/ucr.png
univention-management-console-module-ucr/umc/icons/24x24/
univention-management-console-module-ucr/umc/icons/24x24/ucr.png
univention-management-console-module-ucr/umc/icons/64x64/
univention-management-console-module-ucr/umc/icons/64x64/ucr.png
univention-management-console-module-ucr/umc/icons/32x32/
univention-management-console-module-ucr/umc/icons/32x32/ucr.png
univention-management-console-module-ucr/umc/ucr.xml
univention-management-console-module-ucr/umc/python/
univention-management-console-module-ucr/umc/python/ucr/
univention-management-console-module-ucr/umc/python/ucr/de.po
univention-management-console-module-ucr/umc/python/ucr/__init__.py
If such a package has been created a few things need to be adjusted
debian/rules
#!/usr/bin/make -f %: dh $@ --with umc,python3
debian/control
Source: univention-management-console-module-ucr Section: univention Priority: optional Maintainer: Univention GmbH <packages@univention.de> Build-Depends: debhelper-compat (= 12), dh-python, python3-all, univention-management-console-dev (>= 12.0.2), Standards-Version: 4.3.0.3 Package: univention-management-console-module-ucr Architecture: all Depends: univention-management-console-server, Provides: ${python3:Provides}, Description: UMC module for UCR This package contains the UMC module for Univention Configuration Registry