Table of Contents:
The Apertis distribution provides a number of routes for managing updates to deployed devices. This document discusses utilising hawkBit, a domain independent back-end framework for rolling out software updates.
Design
The hawkBit data model defines a hierarchy of software that starts with a distribution, which can have (sub-)modules and these may have multiple artifacts. The hawkBit Data Model concept can be found here.
For Apertis, we want the device agent to be as simple as possible. So it should only need to check the hawkBit server for an update, download it and trigger installation.
Apertis uses OSTree to provide atomic update management. As part of the automated image generation OSTree static delta files are created which can be used to update existing OSTree installations.
When an OSTree static delta file has been created, a new distribution containing a single module for each build and for each Apertis release, type and architecture is created.
The OSTree static delta file is uploaded to the module as its single artifact.
Distribution and module version are based on the image version.
To be more concrete, when the image pipeline is building the armhf
fixedfunction
image it also builds a matching full static OSTree bundle named, for
instance, apertis_ostree_v2022-fixedfunction-armhf-uboot_v2022.0.delta
.
This bundle is uploaded to hawkBit under the
apertis_v2022-fixedfunction-armhf-uboot
module with version v2022.0
. This
module is linked to a distribution sharing the same name and version.
HawkBit backend installation
The hawkBit update server
can be installed using docker-compose (cf.
HawkBit Getting Started).
It needs a docker-compose.yml and an application.properties file to configure the hawkBit server.
docker-compose.yml file (based on docker-compose.yml):
#
# Copyright (c) 2018 Bosch Software Innovations GmbH and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
version: '3'
services:
# ---------------------
# MySQL service
# ---------------------
mysql:
image: "mysql:5.7"
environment:
MYSQL_DATABASE: "hawkbit"
MYSQL_USER: "root"
MYSQL_ALLOW_EMPTY_PASSWORD: "true"
restart: always
ports:
- "3306:3306"
labels:
NAME: "mysql"
# ---------------------
# HawkBit service
# ---------------------
hawkbit:
image: "hawkbit/hawkbit-update-server:latest-mysql"
environment:
- 'SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/hawkbit'
- 'SPRING_DATASOURCE_USERNAME=root'
restart: always
ports:
- "8080:8080"
volumes:
- ./application.properties:/opt/hawkbit/application.properties
labels:
NAME: "hawkbit"
application.properties file:
#
# Copyright (c) 2015 Bosch Software Innovations GmbH and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# User Security
spring.security.user.name=admin
spring.security.user.password={noop}admin
spring.main.allow-bean-definition-overriding=true
# DDI authentication configuration
hawkbit.server.ddi.security.authentication.anonymous.enabled=false
hawkbit.server.ddi.security.authentication.targettoken.enabled=true
hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=true
# Optional events
hawkbit.server.repository.publish-target-poll-event=false
## Configuration for DMF/RabbitMQ integration
#spring.rabbitmq.username=guest
#spring.rabbitmq.password=guest
#spring.rabbitmq.virtual-host=/
#spring.rabbitmq.host=localhost
#spring.rabbitmq.port=5672
# Define own users instead of default "admin" user:
hawkbit.server.im.users[0].username=apertis
hawkbit.server.im.users[0].password={noop}Apertis!
hawkbit.server.im.users[0].firstname=Apertis
hawkbit.server.im.users[0].lastname=HawkBit
hawkbit.server.im.users[0].permissions=ALL
# Enable CORS and specify the allowed origins:
#hawkbit.server.security.cors.enabled=true
#hawkbit.server.security.cors.allowedOrigins=http://localhost
Copy them to a directory and run:
$ docker-compose up -d
You can then connect to the hawkBit Management UI at server address and port 8080, with username apertis
and password Apertis!
.
Trigger a deployment from Apertis hawkBit update server
Deployment setup
The deployment of OSTree static delta files should be performed as part of the automated Apertis image build process, but can also be done manually.
Manually updating static delta to update server
Using the UI
Create a Software Module in Upload page
This allows to group multiple artifacts.
Click on + in Software Module panel and provide Type
, Name
, and Version
.
Multiple artifacts can be attached to the Software Module using the upload File
button.
Create a Distribution in Distributions page
The distribution is a collection of software module(s).
1st create the Distribution (+ sign in Distributions panel), which will require Name
and Version
info, then drag-and-drop required Software Module(s) on top of the newly created Distribution.
Using the API
1st we need to define some variables which will be used: name
, description
, version
and the delta_file
to upload, e.g.:
$ name="apertis_test-fixedfunction-armhf-uboot"
$ description="Apertis test fixedfunction for armhf uboot"
$ version="v1.0"
$ delta_file="apertis_ostree_fixedfunction-armhf-uboot.delta"
Create a Software Module
$ curl --user admin:admin 'http://localhost:8080/rest/v1/softwaremodules' -i -X POST -H 'Content-Type: application/json;charset=UTF-8' -d '[ {"vendor" : "Apertis","name" : "$name","description" : "$description", "type" : "os", "version" : "$version" } ]'
[{"createdBy":"admin","createdAt":1568627145649,"lastModifiedBy":"admin","lastModifiedAt":1568627145649,"name":"apertis_test-fixedfunction-armhf-uboot","description":"Apertis test fixedfunction for armhf uboot","version":"v1.0","type":"os","vendor":"Apertis","deleted":false,"_links":{"self":{"href":"http://localhost:8080/rest/v1/softwaremodules/1"}},"id":1}]
Upload an artifact to a Software Module
This will use the href
link returned during the Software Module creation.
$ curl --user admin:admin 'http://localhost:8080/rest/v1/softwaremodules/1/artifacts' -i -X POST -H 'Content-Type: multipart/form-data' -F 'file=@$delta_file'
{"createdBy":"admin","createdAt":1568627195280,"lastModifiedBy":"admin","lastModifiedAt":1568627195280,"hashes":{"sha1":"d3b582709d7574e92e16671c5f097fda7795f832","md5":"c368c561a9279f60f7a1b04eabf63d58"},"providedFilename":"apertis_ostree_fixedfunction-armhf-uboot.delta","size":21,"_links":{"self":{"href":"http://localhost:8080/rest/v1/softwaremodules/1/artifacts/1"},"download":{"href":"http://localhost:8080/rest/v1/softwaremodules/1/artifacts/1/download"}},"id":1}
Create a Distribution
the will use the module id
returned during the Software Module creation.
$ curl --user admin:admin 'http://localhost:8080/rest/v1/distributionsets/' -i -X POST -H 'Content-Type: application/json;charset=UTF-8' -d '[ {"requiredMigrationStep" : false,"name" : "$name","description" : "$description", "type" : "os", "version" : "$version", "modules" : [ {"id" : 1} ] } ]'
[{"createdBy":"admin","createdAt":1568627754940,"lastModifiedBy":"admin","lastModifiedAt":1568627754940,"name":"apertis_test-fixedfunction-armhf-uboot","description":"Apertis test fixedfunction for armhf uboot","version":"v1.0","modules":[{"createdBy":"admin","createdAt":1568627145649,"lastModifiedBy":"admin","lastModifiedAt":1568627195295,"name":"apertis_test-fixedfunction-armhf-uboot","description":"Apertis test fixedfunction for armhf uboot","version":"v1.0","type":"os","vendor":"Apertis","deleted":false,"_links":{"self":{"href":"http://localhost:8080/rest/v1/softwaremodules/1"}},"id":1}],"requiredMigrationStep":false,"type":"os","complete":true,"deleted":false,"_links":{"self":{"href":"http://localhost:8080/rest/v1/distributionsets/1"}},"id":1}]
Deployment to target(s)
There is 2 ways two start the distribution deployment: manually for a specific target, or to multiple targets using a filter.
Manually deploy to one target
From the Deployment page, simply drag-n-drop the distribution on top of the desired target.
Rollout deployment to multiple targets
This needs to create a filter in Target Filters page by clicking on + sign, and providing a Name
, the filter string
(e.g. attribute.isoCode==DE
), the Action type
and the Start type
.
Action type
is related to how the target should manage the update:- forced: immediately
- soft: based on user approval or device update time plan
- time forced: soft then forced after a specific time
- download only: device is supposed to only download the update and not install it
Start type
is related to the rollout:- manual: starts on user action
- auto: starts immediately after rollout is created
- scheduled: start as soon as rollout is ready and the set time has passed
:exclamation: Do not forget to save the filter.
Then, we are now able to create the deployment in Rollout page by clicking on + sign, giving it a Name
and selecting the Distribution, Filter and the number of group to use.
Target device
Target authentication
Target devices are identified in hawkBit by there Controller Id
and Target Token
.
Any Controller Id
can be chosen, but should be unique.
A Target token
is generated automatically for each new device added using the UI.
A device can be added manually in the hawkBit management UI, or multiple devices can be added by uploading a csv file containing:
Controller_Id_1,targetName1
Controller_Id_2,targetName2
…
A device can also be added using the Management API, allowing to set the Target Token
:
$ curl --user 'admin:admin' 'http://localhost:8080/rest/v1/targets' -i -X POST -H 'Content-Type: application/json;charset=UTF-8' -d '[ {"securityToken" : "2345678DGGDGFTDzztgf","address" : "https://192.168.0.1","controllerId" : "Controller_Id_1","name" : "Controller 1","description" : "Test controller 1"} ]' -v
apertis-hawkbit-agent
The apertis-hawkbit-agent is a component in the OSTree-based images to poll
hawkBit update server, and in case of an update is available to download it
and trigger apertis-update-manager
to apply it.
Installation
Add apertis-hawkbit-agent
package using apt
action to debos image.
Configuration
The server URL
, Controller ID
and Target Token
are mandatory and are located in /etc/apertis-hawbit-agent.ini
on the device, they should be uncommented and set to their respective values.
Controller Id
and Target Token
can be retrieved from Target details in Hawkbit HMI deployment page.
The final configuration file should look like:
[server]
base-uri=http://<IP_address_or_URL_to_HawkBit_server>:8080
controller-id=<ControllerID>
key-token=<DeviceToken>
The apertis-hawkbit-agent
should be enabled by running:
$ sudo systemctl enable apertis-hawkbit-agent
After reboot, the device should be able to connect to hawkBit update server and retrieve updates.
Possible improvements
- Stabilizing the hawkBit instance
- Optimize resource consumption by moving away from full static bundles
- Use hawkBit tags for the distributions, setting type and architecture. This will allow to easily find the right distribution to send to a specific target or set of targets.
- Improve Apertis hawkBit agent interaction with Apertis Update Manager by calling the
RegisterSystemUpgradeHandler
DBus method, and callingApplySystemUpgrade
when all artifacts has been applied, which may happen with partial upgrades. - Send successful feedback from Apertis hawkBit agent to hawkBit update server only after reboot of the upgraded system went well.