Interfaces are executables that are placed in the
/usr/share/mender-orchestrator/interfaces/v1 directory, where v1 is a
reference to the version of the protocol. Mender Orchestrator will look for
Interfaces in this directory.
Interfaces are modelled after Update Modules from the Mender Client, and are very similar in nature.
One key difference is that the Orchestrator may execute installations for
several Components at once, by executing Interfaces either in parallel or
in series. The ordering is defined by the order field in the update_strategy
section of the Manifest. See Ordering below.
Interfaces correspond to the Interface types defined in your Topology. Each Component type in the Topology specifies which interface to use for updates.
The installation states for one single Component consist of the following states:
DownloadArtifactInstallArtifactRebootArtifactVerifyRebootArtifactCommitCleanupThese are all execute in the order listed, given that there are no errors. There are also some additional error states:
ArtifactRollbackArtifactRollbackRebootArtifactVerifyRollbackRebootArtifactFailureThere are also a few calls in addition to the states that don't perform any action, but which just gather information:
SupportsRollbackNeedsArtifactRebootNeedsUnpackedArtifactProvidePayloadFileSizesInventoryProvidesIdentitySupportsRollback is described under the ArtifactRollback
state, NeedsArtifactReboot under the
ArtifactReboot state, NeedsUnpackedArtifact and
ProvidePayloadFileSizes under the Download state, and the
remaining ones under their own headers.
In this section we define "order group" as being all Components whose order field
in the update_strategy section of the Manifest is the same.
The ordering works like this:
This order group executes the following states, in order:
DownloadArtifactInstallArtifactReboot (if applicable)ArtifactVerifyReboot (if applicable)Each individual state may be executed in parallel for multiple different Components, but will wait for all Components to finish before moving on to the next state.
When there are no more order groups left, we restart from the lowest one, and execute the state:
ArtifactCommitAnd then loop over all the order groups, just like in step 2 and 3.
When all order groups are done again, we start from the lowest one again, and execute the state:
CleanupAnd then loop over all the order groups, just like in step 2 and 3.
If there is a failure at any point during steps 2 to 4, this happens:
ArtifactRollbackArtifactRollbackRebootArtifactVerifyRollbackRebootArtifactFailureWhen there are no more order groups, we change direction of traversal back to normal, start from the lowest one, and execute the state:
CleanupAnd then loop over all the order groups.
Any failures in the rollback ordering is ignored, except for failure in
ArtifactVerifyRollbackReboot (see notes for that specific
state).
Download stateThis state executes while the Artifact is still being streamed, and allows
grabbing the file streams directly while they are downloading, instead of
storing them first. See streams under File API below.
Important: An Interface must not install the update in the final
location during the Download state, because checksums are not verified until
after the streaming stage is over. If it must be streamed to the final location
(such as for example a partition), it should be stored in an inactive state, so
that it is not accidentally used, and then it should be activated in the
ArtifactInstall stage. Failure to do so can lead to the Interface being
vulnerable to security attacks.
Before the Download state is entered the Interface will be called with the
NeedsUnpackedArtifact query, to which the Interface must answer:
No - One single stream will be passed to Interface, containing the full
artifact, including headers.
Yes - The individual payload files inside the artifact will be streamed one
by one. This is the default, and answering nothing has the same effect.
Answering No allows for passing the artifact to a downstream consumer, such as
the Mender Client, or a different host. Answering Yes means that the files
inside the artifact are streamed, which is usually more convenient when those
files are being installed directly.
Then, the Interface will receive the ProvidePayloadFileSizes query, to which
it must answer:
No - No file sizes will be provided during the Download state. This is the
default, and answering nothing has the same effect.
Yes - Download will not be called, and DownloadWithFileSizes will be
called instead. The state behaves the same as the Download state, except
that file sizes are provided when streaming payload files.
ArtifactInstall stateExecutes after Download and should be used to install the update into its
final destination, or activate an already installed, but deactivated update.
ArtifactReboot stateBefore ArtifactReboot is considered, the Interface is called with the
NeedsArtifactReboot query:
The Interface should print one of the valid responses:
No - Mender will not run ArtifactReboot. This is the same as returning
nothing, and hence the default.Automatic - Mender will not call the Interface with the ArtifactReboot
argument, but will instead perform one single reboot itself. The intended use
of this response is to group the reboots of several Interfaces into one
reboot. This is usually the best choice for all Interfaces that just
require a normal reboot, but Interfaces that reboot a peripheral device may
need to use Yes instead, and implement their own method.Yes - Mender will run the Interface with the ArtifactReboot
argument. Use this when you want to reboot a peripheral device that's
connected to the host. Don't use this if you want to reboot the host that
Mender runs on; use Automatic instead.Note: Even though the Interface won't be called with the
ArtifactReboot argument when using Automatic, ArtifactReboot still counts
as having executed -- as far as the conditional logic is concerned.
If any Interface returns Automatic, then a reboot of the device will be
performed after the ArtifactReboot state of all Interfaces in the same
"order group" that responded Yes have been executed. "Order group" means all
Interfaces for components that are using the same order field in the
manifest.
Note: The NeedsArtifactReboot query is guaranteed to be carried out after
ArtifactInstall has been executed. In other words it is possible to, for
example, query package managers whether a reboot is required after it has
installed a package.
ArtifactVerifyReboot stateExecutes after ArtifactReboot has run, if it runs at all.
ArtifactVerifyReboot should be used to verify that the reboot has
been performed correctly, and that it was not rolled back by an external
component, such as a watch dog or the boot loader. A common use of the script is
to make sure the correct partition has been booted.
ArtifactCommit stateExecutes after all components have finished ArtifactVerifyReboot, if
ArtifactVerifyReboot runs at all, or else after
ArtifactInstall. ArtifactCommit must be used to remove/disable automatic
rollback mechanisms, such as for example the automatic rollback that a
bootloader might do. This essentially makes the update permanent, but it is
important to retain enough data so that an explicit ArtifactRollback can still
roll back the update. If additional steps are required to clean up the rollback
data, this should be done in the Cleanup state instead.
Cleanup stateCleanup executes unconditionally at the end of all the other states,
regardless of all outcomes. Cleanup can be used to clean up various temporary
files that might have been used during an update, but should not be used to make
any changes. For example, cleaning up an update that has failed,
returning it to the previous state, should rather be done in the
ArtifactRollback state. However, rollback data that has been kept around in
order to facilite a rollback (which never happened), should be cleaned up in
Cleanup.
It is not necessary to clean up files inside the official update Interface file tree, since these will be cleaned up automatically, including any temporary files.
Cleanup is the only additional state that executes if Download fails.
ArtifactRollback stateArtifactRollback is only considered in some circumstances. When a rollback is
being considered, Mender Orchestrator calls the Interface with the
SupportsRollback query.
The exact time is not specified, but it is always after Download has
completed, and before either ArtifactRollbackReboot or ArtifactFailure are
executed. If the installation is successful it may not be called at all.
The Interface can respond with the following responses:
No - Signals that the Interface does not support rollback. This is the
same as responding with nothing, and hence the defaultYes - Signals that the Interface supports rollback and it should be
handled by calling ArtifactRollback and possibly ArtifackRollbackReboot
states (if the Interface requested reboot in the NeedsArtifactReboot
query)ArtifactRollback then executes whenever:
SupportsRollback call has returned a non-No responseArtifactInstall has started executingArtifactInstallArtifactRebootArtifactVerifyRebootArtifactCommitIt should be used to roll back to the previously installed software, either by restoring a backup or deactivating the new software so that the old software becomes active again.
ArtifactRollbackReboot stateArtifactRollbackReboot executes whenever:
NeedsArtifactReboot query has returned YesArtifactRollback has executedAs an alternative to invoking ArtifactRollbackReboot, Mender instead calls the
reboot command if:
NeedsArtifactReboot query has returned Automaticreboot command instead of calling ArtifactRebootArtifactRollback has executedThe reboot command execution follows the same mechanics as those described in
the ArtifactReboot state.
Additionally, ArtifactRollbackReboot (or the reboot command) will execute if
the next state, ArtifactVerifyRollbackReboot has executed and returned
failure. This will only happen a limited number of times, to avoid endless
reboot loops.
ArtifactVerifyRollbackReboot stateArtifactVerifyRollbackReboot executes whenever:
ArtifactRollbackReboot has executedThis state should be used to verify that the system or peripheral was
successfully rebooted back into its old state. Note that if this returns
failure, the reboot will be attempted again using the ArtifactRollbackReboot
state. Mender will only try a limited number of times before moving on to the
ArtifactFailure state, but if ArtifactVerifyRollbackReboot keeps returning
failure the system may be left in a permanently inconsistent state.
ArtifactFailure stateArtifactFailure executes whenever:
ArtifactInstall, ArtifactReboot, ArtifactVerifyReboot or
ArtifactCommit has failed or experiences a spontaneous rebootArtifactRollback and ArtifactRollbackReboot, if they
execute at allArtifactFailure can be used to perform any reverts or cleanups that need to be
done when an Artifact install has failed. For example the Interface may
undo a data migration step that was done before or during the install.
Inventory queryThe Inventory query is not called as part of an installation, but as a means to
gather information about Components. When called, it is expected to print the
inventory data of the relevant Component type and ID. See
Execution below to find out how the type and ID are obtained.
The output format is the same as for Mender inventory scripts. This consists of "key=value" pairs, with no spaces, separated by newlines. Printing list data is supported by using the same key multiple times.
Provides queryThe Provides query is not called as part of an installation, but as a means to
gather information about Components. When called, it is expected to print the
Provides data (also called "software versions") of the relevant Component type
and ID. See Software
versioning for
more information about what Provides values are, and see Execution
below to find out how the type and ID are obtained.
The output format is the same as the output from the Mender Client
show-provides command, which consists of "key=value" pairs, with no spaces,
separated by newlines. Unlike in the Inventory query, list data is not
permitted in Provides data.
Identity queryThe Identity query is called during Component initialization to determine the unique Component ID for this specific Component instance. This is called before any update operations begin and is used to establish the Component's identity dynamically.
The output format should be a single line containing:
id=<component_id>
Where <component_id> is a unique identifier for this Component instance. For example:
id=R123
Note: The Component ID returned by Identity becomes the unique identifier for this Component and is used in all subsequent Interface calls as well as in the work directory structure.
This document describes the file layout of the directory that is given to update
Interfaces when they launch. This directory will be pre-filled with certain
pieces of information from the orchestrator, and must be used by update
Interfaces. Each Component from the Manifest gets its own directory, and update
Interfaces are executed independently from each other, though they can execute
at the same time if their order field in the Manifest is the same.
-<DIRECTORY>
|
+---version
|
+---current_artifact_group
|
+---current_artifact_name
|
+---current_device_type
|
+---header
| |
| +---artifact_group
| |
| +---artifact_name
| |
| +---payload_type
| |
| +---header-info
| |
| +---type-info
| |
| `---meta-data
|
`---tmp
In addition it may contain one of these two trees, depending on context. The "streams tree":
-<DIRECTORY>
|
+---stream-next
|
`---streams
|
+---<STREAM-1>
+---<STREAM-2>
`---<STREAM-n> ...
or the "files tree":
-<DIRECTORY>
|
`---files
|
+---<FILE-1>
+---<FILE-2>
`---<FILE-n> ...
versionsversion is the version of Interface protocol (this document). This is
reflected by the location of the Interface, which is always inside v1
folder (for version 1).
current_artifact_group, current_artifact_name and current_device_typecurrent_artifact_group, current_artifact_name and current_device_type
correspond to the currently provided Artifact group, name and device type, which
is obtained using the Provides query to the Interface. They contain
pure values, unlike the original files that contain key/value pairs.
headerThe header directory contains the verbatim headers from the header.tar.gz
header file of the Artifact, in addition to a few extra files. One Artifact can
contain payloads for several Interfaces, so the three files: files,
type-info and meta-data are taken from the indexed subfolder currently being
processed by Mender.
artifact_group and artifact_nameartifact_group and artifact_name contain the group and name of the Artifact
that is being installed, respectively. This is the same information as that
which is available inside header/header-info, under the artifact_provides -> artifact_groupandartifact_name` keys, and is merely for convenience.
payload_typepayload_type contains the type of the payload which is current being installed
using this file tree. It is always one of the elements from the payloads list
in the header-info file, under the type key. It is also the name of the
currently executing Interface.
payload_type will always be the nth from the payloads list, which n is the
index number which can be found in the path to the file tree.
tmptmp is merely a convenience directory that the Interface can use for
temporary storage. It is guaranteed to exist, to be empty, and to be cleaned up
after the update has completed (or failed). The Interface is not obligated to
use this directory, it can also use other, more suited locations if desirable,
but then the Interface must clean it up by implementing the Cleanup state.
The streams tree only exists during the Download state, which is when the
download is still being streamed from the Mender Server. If the Interface
doesn't want to perform its own streaming, and just wishes to save the streams
to files, it can simply do nothing in the Download state, and Mender Client will
automatically save the streams in the "files tree".
stream-next is a named pipe which is intended to be read in a loop, where each
time it lists the next stream available for streaming inside the streams
directory. The path returned will have exactly two components: which directory
it is in, and the name of the pipe which is used to stream the content. For
example:
streams/pkg-file.deb
streams/patch.diff
Each entry is a named pipe which can be used to stream the content from the
update. The stream is taken from the data/nnnn.tar.gz payload that corresponds
to the indexed subfolder being processed by Mender, just like the header.
When there are no more streams left, reading stream-next will result in a zero
length read. The Interface must not attempt to read stream-next again
after receiving a zero length read, or the update procedure may hang.
Important: Reads must proceed in the following order: one complete read of
stream-next (will always be exactly one line), then read the stream it
returned, then another full read of stream-next, and so on. In addition, each
stream can only be read once. If this is not followed the Interface may
hang.
Important: An Interface must not install the update in the final
location during the streaming stage, because checksums are not verified until
after the streaming stage is over. If it must be streamed to the final location
(such as for example a partition), it should be stored in an inactive state, so
that it is not accidentally used, and then be activated in the ArtifactInstall
stage. Failure to do so can mean that the Interface will be vulnerable to
security attacks.
If the Interface answered Yes to the ProvidePayloadFileSizes query, then
the streaming process is slightly different. First of all, the Download state
is not called, and DownloadWithFileSizes is called instead. Second, each line
obtained from stream-next will contain the file size as well, separated from
the file name by a space. For example:
streams/pkg-file.deb 45853
streams/patch.diff 201
Everything else remains the same as with the regular Download state.
The file tree only exists in the ArtifactInstall and later states, and only
if the streams were not consumed during the Download state. In this case
the Orchestrator will download the streams automatically and put them in the file tree.
The files directory contains the payloads from the Artifact, and is taken from
the data/nnnn.tar.gz payload that corresponds to the indexed subfolder being
processed by the Orchestrator, just like the header.
The API may be expanded in the future with additional entries in the file and streams trees. This may happen without increasing the version number, as long as compatibility is maintained with the existing entries. Therefore the update Interface should not assume that the entries described in the current revision of the Interface specification are the only entries.
Since the API may be expanded in the future with additional calls and states, all Interfaces should simply print nothing and return zero if they are invoked with an unknown first argument.
For all the states, the Interface is called once for each state that occurs, with the working directory set to the directory where the File API resides. It is called with at least three arguments, plus any number of optional arguments following that:
Interface_args list in the TopologyNote: The Component ID is NOT passed as an argument to the Interface. Instead, it is determined dynamically by the Orchestrator calling the Identity query and using the returned value.
For example:
# Normal update state call
update-module \
ArtifactInstall \
/data/mender/modules/0000 \
component_type
Returning any non-zero value in the Interface triggers a failure, and will invoke the relevant failure states.
© 2025 Northern.tech AS