summaryrefslogtreecommitdiffstats
path: root/doc/container.qdoc
blob: fd7070e4410ad690410d822b7284515c9154fb0b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
/****************************************************************************
**
** Copyright (C) 2019 Luxoft Sweden AB
** Copyright (C) 2018 Pelagicore AG
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Application Manager.
**
** $QT_BEGIN_LICENSE:FDL-QTAS$
** Commercial License Usage
** Licensees holding valid commercial Qt Automotive Suite licenses may use
** this file in accordance with the commercial license agreement provided
** with the Software or, alternatively, in accordance with the terms
** contained in a written agreement between you and The Qt Company.  For
** licensing terms and conditions see https://www.qt.io/terms-conditions.
** For further information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/

/*!

\page containers.html
\title Containers

In the application manager context, a \b container describes an execution environment for an
executable: either an application's binary or its runtime binary, in multi-process mode. The
container does not have to be something sophisticated like a Docker container, but can be as
simple as a Unix process.

\section1 Predefined Containers

The application manager comes with a one built-in container type: the \c process container,
that spawns a new Unix process to execute the requested binary.

In addition, you can find a basic integration of Pelagicore's
\l{https://github.com/Pelagicore/softwarecontainer}{software-containers} in \c
examples/softwarecontainers. This can be used as a blueprint to either create a customer-specific
production version of a softwarecontainers plugin, or to integrate another container solution.

\section1 Extend with Container Plugins

Custom container solutions can be added via plugins. These plugins need not to be built as part
of the application manager, but they need to be built against a private Qt module to get the
interface definition:

\badcode
TEMPLATE = lib
CONFIG += plugin
TARGET = mycontainer-plugin

QT += appman_plugininterfaces-private
\endcode

Then, you only have to implement two classes that derive from \c ContainerInterface
and from \c ContainerManagerInterface respectively:

\code
#include <QtAppManPluginInterfaces/containerinterface.h>

class SoftwareContainer : public ContainerInterface
{
    // ...
};

class SoftwareContainerManager : public QObject, public ContainerManagerInterface
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID AM_ContainerManagerInterface_iid)
    Q_INTERFACES(ContainerManagerInterface)

    // ....
};
\endcode

Be aware that your container plugin has to support a few basic requirements to support UI clients
in multi-process mode:
\list 1
  \li The plugin has to be able to forward Unix local sockets into the container. This is needed
      for both the \l{Qt Wayland Compositor}{Wayland} socket as well as for the private peer-to-peer
      D-Bus connection. If the plugin cannot map these sockets to the correct location within the
      container, the plugin then needs to modify the environment variables for the respective
      locations before passing them on to the container. The table below lists the relevant
      environment variables.
  \li To support hardware OpenGL acceleration, the container needs to have access to the necessary
      device. For GPUs that follow Linux standards, such as Intel, make sure to have /c{/dev/dri/*}
      available within the container.
  \li You have to implement PID mapping in your plugin; unless your container solution shares its
      PID namespace with the rest of the ssytem. This is necessary if you want to make use of the
      application manager's security features. Each connection coming into the application manager
      via the Wayland or D-Bus Unix local sockets is queried for the PID of the application that
      requests the connection. The application manager verifies these PIDs against the PIDs of all
      running applications via ContainerInterface::processId(). Connections that don't match a PID
      are not accepted. However, you can disable this behavior via the
      \l{no-security}{\c{--no-security}} command line option.
\endlist

The application manager uses the following environment variables to communicate various settings to
the application. A custom container plugin must forward these variables or adjust them accordingly:

\table
\header
  \li Name
  \li Description
\row
  \li \c{WAYLAND_DISPLAY}
  \li The path to the Wayland server socket. If your container uses its own filesystem namespace,
      make sure that this socket is forwarded accordingly.
\row
  \li \c{QT_QPA_PLATFORM}
  \li Always set to \c{wayland}.
\row
  \li \c{QT_IM_MODULE}
  \li Not set, but explicitly unset by the application manager. Make sure to leave it unset it, to
      use the automatic Wayland input method implementation.
\row
  \li \c{DBUS_SESSION_BUS_ADDRESS}
  \li The standard D-Bus session bus.
\row
  \li \c{AM_DBUS_PEER_ADDRESS}
  \li Holds the D-Bus socket identifier for the private peer-to-peer bus between the application
      manager and the application itself. If your container uses its own filesystem namespace,
      make sure that this socket is forwarded accordingly.
\row
  \li \c{AM_DBUS_NOTIFICATION_BUS_ADDRESS}
  \li Since the \c{org.freedesktop.Notifications} interface could be on a different bus from the
      rest of the D-Bus interfaces, the application manager needs to explicitly tell the
      application where to look for this interface.
\row
  \li \c{AM_BASE_DIR}
  \li The current directory for the application manager.
\row
  \li \c{AM_RUNTIME_SYSTEM_PROPERTIES}
  \li The public part of the \l{system-properties}{system properties}, encoded as a YAML document.
\row
  \li \c{AM_NO_DLT_LOGGING}
  \li Tells the application to not use DLT for logging.
\endtable

\section1 Configuration

A container configuration has three parts:

\list 1
  \li Configure which containers are available when \l{load-plugins}{loading} the container plugins
  \li Add specific settings for each \l{container-integration}{container integration} available
  \li Configure which container solution to \l{container-selection}{select} to run a specific
      application
\endlist

\target load-plugins
\section1 Load Container Plugins

To configure an existing container plugin for use in the application manager, you need to
add its full path to the list of plugins to load in the application manager's config file:

\badcode
plugins:
  container: [ "/full/path/to/softwarecontainers.so", "/another/plugin.so" ]
\endcode

Note that the application manager does \b not load plugins automatically if they are placed
in a specific directory, since container plugins control the central security mechanism for
separating applications.

\target container-integration
\section1 Add Container Integration Settings

Each container integration has a unique ID, which can be used to add settings to the
application manager's config file, such as:

\badcode
containers:
  process:
    defaultControlGroup: "foo"
  softwarecontainers:
    bar: [ 1, 2, 3 ]
\endcode

The \c process container accepts the following configuration settings:

\table
  \header
    \li Settings Name
    \li Type
    \li Description
  \row
    \target control group mapping
    \li \c controlGroups
    \li object
    \li A two-stage mapping object to allow for more readable code when dealing with \c cgroups
        from the System UI via Container::controlGroup. The top-level keys are readable group names
        that are used to interface with Container::controlGroup. The values themselves are maps
        between multiple low-level \c cgroup sub-system names and the actual \c cgroup names within
        those sub-systems, such as:

    \badcode
    controlGroups:
      foreGround:
        memory: mem1
        cpu: cpu_full
      backGround:
        memory: mem2
        cpu: cpu_minimal
    \endcode

  \row
    \li \c defaultControlGroup
    \li string
    \li The default control group for an application when it is first launched.
\endtable

For other container plugins, refer to their respective documentation.

\target container-selection
\section1 Container Selection Configuration

When you start an application from within the application manager, there are multiple ways to
control which container integration is used:

\list 1
  \li If the config file does not contain the \c containers/selection key, the container
      integration ID defaults to \c process.
  \li If the \c containers/selection key exists, its contents are parsed as a list of maps, where
      each map has a single mapping only. While this single mapping is awkward, it is necessary to
      preserve the order of the mappings. Each key is interpreted as a standard Unix wildcard
      expression that is matched against the application ID. The first match stops the algorithm
      and the mapping's value is used as the container integration ID. If no matches are found,=
      the resulting containter integration ID is an empty string.

    \badcode
    containers:
      selection:
      - com.pelagicore.*: "process"
      - com.navigation: "special-container"
      - '*': "softwarecontainers"  # a single asterisk needs to be quoted
    \endcode

  \li Afterwards, if the System UI did set the ApplicationManager::containerSelectionFunction
      property to a valid JavaScript function, this function is called with the first parameter set
      to the application's ID and the second parameter set to the container integration ID that
      resulted from step 1 and 2.

    \badcode
    ApplicationManager.containerSelectionFunction = function(appId, containerId) {
        var app = ApplicationManager.application(appId)
        if (app.capabilities.indexOf("non-secure") != -1)
            return "process"
        else
            return containerId
    }
    \endcode
\endlist

*/