💡

Raspberry Pi + Yocto + RAUC + hawkbitでOTAアップデートの実装

に公開

作りたいもの

こちらのポータブルエッジサーバをOTAアップデートする仕組みを実装します。最新に近いバージョンの情報が少なかったので、実装課程を共有します。具体的には以下のものを実装します。

https://zenn.dev/takumique/articles/a451ffd2393b1f

なお、今回は実運用では無くローカルネットワーク上の実験のため、クラウドコストをかけずにアップデート配信サーバにもRasPiを使用しましたが、コンテナ化しているのでクラウド環境にも載せやすいと思います。

ポータブルエッジサーバ側:

  • Yocto: 5.0 (scarthgap)
    • LTSバージョンであることと、meta-rauc-communityにあるブランチがscarthgapまでだったため
  • RAUC(meta-rauc): scarthgapブランチのHEAD
    • rauc本体(アップデートバンドルを予備パーティションに書き込み、ブートパーティションをを切り替え)
    • rauc-hawkbit-updater(hawkbit-update-serverからアップデートバンドルをダウンロードしてrauc本体を起動する常駐サービス)
    • アップデートバンドルを作る仕組み
    • など
  • Raspberry Pi BSPへのパッチ(meta-rauc-community/meta-rauc-raspberrypi): scarthgapブランチのHEAD
    • ブートローダをu-bootにしてA/B(現用・予備)パーティション起動
    • パーティションテーブル
    • など

アップデート配信サーバ側:

  • RasPi OS(Yoctoではないです)
    • docker compose(実験なのでdocker composeでコンテナ群を実行します)
      • bithawk-update-server: 0.8.0
        • 最新の0.9.0ではエラーでtargetの作成ができなかったため(バグ?)
      • bithawk-simple-ui: 0.8.0
        • bithawk 0.5.0からWeb UIが削除され、独立したコンポーネントとなりました。Experimentalだそうです。
      • など

※hawkbitは構成をモノリシック・マイクロサービスから選べるようです。マイクロサービスの構成の場合、はDDI (Direct Device Integration)、DMF(Device Management Federation)、Managementの機能をマイクロサービス化します。今回はモノリシックな構成を使いましたが、スケーリングするにはDDIのインスタンスを増やした方が良いのでしょうね。この記事によるとDDIはhawkbitが直接デバイスと通信してアップデートを配信する方式、DMFは既存のdevice management機能(OMA-DMとか)と統合してDM経由でアップデートを配信する方式だそうです。なお、下図のManagement UIは0.5.0以降削除されています。

動作する全ソースコードをGitHubで公開しています。
https://github.com/takumique/build-sample/tree/scarthgap
https://github.com/takumique/meta-sample-bsp/tree/scarthgap
[scarthgap向け変更のみ]
https://github.com/takumique/meta-sample-connectivity/tree/scarthgap
https://github.com/takumique/meta-sample-ui/tree/scarthgap
https://github.com/takumique/meta-sample/tree/scarthgap

実装

ポータブルエッジサーバ側

ベースのYocto

こちらを参照してください。ブランチはscarthgap(pokyはscarthgap-5.0)に変更します。meta-sample*ではwalnascar向けからscarthgap向けに、主に2点変更しています。

  • .bbファイルのUNPACKDIRはscarthgapでは使用できないのでS=${WORKDIR}に変更。
変更前
S = "${WORKDIR}/sources"
UNPACKDIR = "${S}"
変更後
S = "${WORKDIR}"
  • 不足するPythonパッケージ(starlette, tzdata)を追加
ダウンロードするソースコード
git clone -b scarthgap-5.0 git://git.yoctoproject.org/poky
git clone -b scarthgap git://git.yoctoproject.org/meta-raspberrypi
git clone -b scarthgap git://git.openembedded.org/meta-openembedded
git clone -b scarthgap git://git.yoctoproject.org/meta-virtualization
git clone -b scarthgap git@github.com:takumique/build-sample.git
git clone -b scarthgap git@github.com:takumique/meta-sample-ui.git
git clone -b scarthgap git@github.com:takumique/meta-sample-connectivity.git
git clone -b scarthgap git@github.com:takumique/meta-sample.git

また、IMAGE_ROOTFS_EXTRA_SPACEによる空き容量の確保は10GBに変更します。(パーティションを2つ作るので容量が変わるため)

local.conf
# add 10GiB of extra space (fits for 64GB SD card)
IMAGE_ROOTFS_EXTRA_SPACE = "1048576"

meta-rauc/meta-rauc-communityのインテグレーション

必要となるレイヤをダウンロードします。

git clone -b scarthgap https://github.com/rauc/meta-rauc.git
git clone -b scarthgap https://github.com/rauc/meta-rauc-community.git

bblayers.confに以下のレイヤを追加します。

bblayers.conf
  ${TOPDIR}/../meta-openembedded/meta-filesystems \
  ${TOPDIR}/../meta-rauc \
  ${TOPDIR}/../meta-rauc-community/meta-rauc-raspberrypi \

GitHubのREADMEに従ってlocal.confに以下を追加していきます。

local.conf
# enable u-boot
RPI_USE_U_BOOT = "1"

DISTRO_FEATURES:append = " rauc"

IMAGE_FSTYPES:append = " ext4"
CORE_IMAGE_EXTRA_INSTALL:append = " rauc"
CORE_IMAGE_EXTRA_INSTALL:append = " rauc-hawkbit-updater"

WKS_FILE = "sdimage-dual-raspberrypi.wks.in"

このバージョンの組み合わせでは、meta-rauc-community/meta-rauc-raspberrypiのu-bootのパッチがあたらずエラーとなってしまいました。仕方が無いのでmeta-rauc-community/meta-rauc-raspberrypi/recipes-bsp/u-boot/files/rpi_arm64_defconfig.patchを以下のように手動で変更しました。

meta-rauc-community/meta-rauc-raspberrypi/recipes-bsp/u-boot/files/rpi_arm64_defconfig.patch
Upstream-Status: Inappropriate [manually created]
--- git.orig/configs/rpi_arm64_defconfig
+++ git/configs/rpi_arm64_defconfig
@@ -57,3 +57,6 @@ CONFIG_SYS_WHITE_ON_BLACK=y
 CONFIG_VIDEO_BCM2835=y
 CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_PHYS_TO_BUS=y
+# squashfs support
+CONFIG_FS_SQUASHFS=y
+CONFIG_CMD_SQUASHFS=y

デバイス固有値のハンドリング

こちらの記事でNVRAM(EEPROMデバイスを使ったKey-Valueストア)を実装しました。これを使用してデバイス固有の情報(デバイスIDや、デバイスごとに異なる認証情報など)をハンドリングします。

今回はrauc_hawkbit_updaterのコンフィグをNVRAMの情報を使用してoverrideします。

  • hawkbit_server
  • target_name
  • auth_token

具体的にはType=oneshotBefore=rauc-hawkbit-updater.serviceのsystemd-serviceを作成し、シェルスクリプトを実行します。このシェルスクリプトからnvram-readでNVRAMからデバイス固有値を取得して/etc/rauc-hawkbit-updater/config.confを更新することで、NVRAMの内容を動作に反映させます。

なお、nvram-readはI2Cを使用するのでI2Cをenableします。ボーレートは100KHzにしました。

この部分の動作する全ソースコードをGitHubで公開しています。Yoctoに組み込むための設定は以下の通りです。

git clone -b scarthgap git@github.com:takumique/meta-sample-bsp.git
bblayers.conf
  ${TOPDIR}/../meta-sample-bsp \
local.conf
# enable interfaces
ENABLE_UART = "1"
ENABLE_I2C = "1"
KERNEL_MODULE_AUTOLOAD:rpi += "i2c-dev"

...

RPI_EXTRA_CONFIG:append = "dtparam=i2c_arm_baudrate=100000"

...

CORE_IMAGE_EXTRA_INSTALL:append = " libnvram"
CORE_IMAGE_EXTRA_INSTALL:append = " nvram-read"
CORE_IMAGE_EXTRA_INSTALL:append = " rauc-hawkbit-updater-config"

ビルド

通常通りビルドします。この際、raucをインテグレーションする前のビルド生成物が存在するとエラーとなるので、手動で削除してからビルドします。

cd <build>
rm -fr cache
rm -fr conf/downloads
rm -fr conf/sstate-cache
rm -fr conf/tmp
rm -f bitbake-cookerdaemon.log

bitbake core-image-base

こちらにあるようにSDカードにフラッシュします。

アップデート配信サーバ側

まずは普通にRasPi OSをSDカードに焼きます。

その後、RasPi上で普通にdockerをインストールします。

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo gpasswd -a $USER docker

hawkbitはdockerhub上にイメージがあるのですが、x86用のみなのでRasPi上では動きません。そこでGitHubにあるDockerfileをベースにしてイメージをビルドします。(ベースイメージのeclipse-temurinがARM対応なのでいけます)今回はmetadataの保存にmysqlを使います。

hawkbit-update-server

このDockerfile、jarファイルをmavenのリポジトリからダウンロードして配置しているだけなのですが、MariaDBのJDBCドライバがインストールされないためmysqlと通信できません。Dockerfileを修正します。また、今回はdockerfileでvolumeをマウントしたいので、簡単のためhawkbitをrootで実行させています。

Dockerfile
# set Java
ARG JAVA_VERSION=21.0.8_9
# extracts spring layers from the app jar (to optimize boot)
FROM eclipse-temurin:${JAVA_VERSION}-jre-alpine as build

ARG HAWKBIT_APP=hawkbit-update-server
ARG HAWKBIT_VERSION=pass_as_buils_arg

ENV BUILD_DIR=/opt/hawkbit_build
RUN mkdir -p ${BUILD_DIR}
WORKDIR ${BUILD_DIR}

ENV APP=${HAWKBIT_APP}
ENV VERSION=${HAWKBIT_VERSION}

COPY KEY /

RUN set -x && \
  apk add --no-cache --virtual build-dependencies gnupg unzip libressl wget && \
  gpg --import /KEY && \
  wget -O /${APP}.jar --no-verbose https://repo1.maven.org/maven2/org/eclipse/hawkbit/${APP}/${VERSION}/${APP}-${VERSION}.jar && \
  wget -O /${APP}.jar.asc --no-verbose https://repo1.maven.org/maven2/org/eclipse/hawkbit/${APP}/${VERSION}/${APP}-${VERSION}.jar.asc && \
  gpg --batch --verify /${APP}.jar.asc /${APP}.jar && \
  java -Djarmode=tools -jar /${APP}.jar extract --layers --launcher --destination . && \
  rm /KEY /${APP}.jar /${APP}.jar.asc

RUN wget -O ./dependencies/BOOT-INF/lib/mariadb-java-client-3.4.2.jar --no-verbose https://repo1.maven.org/maven2/org/mariadb/jdbc/mariadb-java-client/3.4.2/mariadb-java-client-3.4.2.jar

FROM eclipse-temurin:${JAVA_VERSION}-jre-alpine

# RUN addgroup -S hawkbit_group && adduser -D hawkbit -G hawkbit_group
# RUN mkdir -p /artifactrepo && chown -R hawkbit /artifactrepo
# USER hawkbit

ENV BUILD_DIR=/opt/hawkbit_build

COPY --from=build ${BUILD_DIR}/dependencies/ /
COPY --from=build ${BUILD_DIR}/spring-boot-loader/ /
COPY --from=build ${BUILD_DIR}/snapshot-dependencies/ /
COPY --from=build ${BUILD_DIR}/application/ /

# VOLUME "/artifactrepo"

ARG CONTAINER_PORT=8080
EXPOSE ${CONTAINER_PORT}

ARG PROFILES=h2
ENV PROFILES=${PROFILES}
ARG X_MS=768m
ENV X_MS=${X_MS}
ARG X_MX=768m
ENV X_MX=${X_MX}
ARG XX_MAX_METASPACE_SIZE=250m
ENV XX_MAX_METASPACE_SIZE=${XX_MAX_METASPACE_SIZE}
ARG XX_METASPACE_SIZE=250m
ENV XX_METASPACE_SIZE=${XX_METASPACE_SIZE}
ARG XSS=300K
ENV XSS=${XSS}
ARG GC=G1
ENV GC=${GC}

ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -Dspring.profiles.active=${PROFILES} -Xms${X_MS} -Xmx${X_MX} -XX:MaxMetaspaceSize=${XX_MAX_METASPACE_SIZE} -XX:MetaspaceSize=${XX_METASPACE_SIZE} -Xss${XSS} -XX:+Use${GC}GC -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+HeapDumpOnOutOfMemoryError org.springframework.boot.loader.launch.JarLauncher ${@}"]

hawkbit-simple-ui

こちらはお手本のDockerfileがないので自前で作る必要があります。幸い、これもhawkbit-update-serverと同じくSpring Bootベースなので上記Dockerfileをベースにします。なお、JDBCドライバは不要です。

Dockerfile
# set Java
ARG JAVA_VERSION=21.0.8_9
# extracts spring layers from the app jar (to optimize boot)
FROM eclipse-temurin:${JAVA_VERSION}-jre-alpine AS build

ARG HAWKBIT_APP=hawkbit-simple-ui
ARG HAWKBIT_VERSION=pass_as_buils_arg

ENV BUILD_DIR=/opt/hawkbit_build
RUN mkdir -p ${BUILD_DIR}
WORKDIR ${BUILD_DIR}

ENV APP=${HAWKBIT_APP}
ENV VERSION=${HAWKBIT_VERSION}

COPY KEY /

RUN set -x && \
  apk add --no-cache --virtual build-dependencies gnupg unzip libressl wget && \
  gpg --import /KEY && \
  wget -O /${APP}.jar --no-verbose https://repo1.maven.org/maven2/org/eclipse/hawkbit/${APP}/${VERSION}/${APP}-${VERSION}.jar && \
  wget -O /${APP}.jar.asc --no-verbose https://repo1.maven.org/maven2/org/eclipse/hawkbit/${APP}/${VERSION}/${APP}-${VERSION}.jar.asc && \
  gpg --batch --verify /${APP}.jar.asc /${APP}.jar && \
  java -Djarmode=tools -jar /${APP}.jar extract --layers --launcher --destination . && \
  rm /KEY /${APP}.jar /${APP}.jar.asc

FROM eclipse-temurin:${JAVA_VERSION}-jre-alpine

RUN addgroup -S hawkbit_group && adduser -D hawkbit -G hawkbit_group
RUN mkdir -p /artifactrepo && chown -R hawkbit /artifactrepo
USER hawkbit

ENV BUILD_DIR=/opt/hawkbit_build

COPY --from=build ${BUILD_DIR}/dependencies/ /
COPY --from=build ${BUILD_DIR}/spring-boot-loader/ /
COPY --from=build ${BUILD_DIR}/snapshot-dependencies/ /
COPY --from=build ${BUILD_DIR}/application/ /

ARG CONTAINER_PORT=8088
EXPOSE ${CONTAINER_PORT}

ARG X_MS=768m
ENV X_MS=${X_MS}
ARG X_MX=768m
ENV X_MX=${X_MX}
ARG XX_MAX_METASPACE_SIZE=250m
ENV XX_MAX_METASPACE_SIZE=${XX_MAX_METASPACE_SIZE}
ARG XX_METASPACE_SIZE=250m
ENV XX_METASPACE_SIZE=${XX_METASPACE_SIZE}
ARG XSS=300K
ENV XSS=${XSS}
ARG GC=G1
ENV GC=${GC}

ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -Xms${X_MS} -Xmx${X_MX} -XX:MaxMetaspaceSize=${XX_MAX_METASPACE_SIZE} -XX:MetaspaceSize=${XX_METASPACE_SIZE} -Xss${XSS} -XX:+Use${GC}GC -XX:+UseStringDeduplication -XX:+UseCompressedOops -XX:+HeapDumpOnOutOfMemoryError org.springframework.boot.loader.launch.JarLauncher ${@}"]

compose.yaml

上記をビルド・起動するためのcompose.yamlです。SPRING_SERVLET_MULTIPART_MAX_FILE_SIZEはアップロードするアップデートバンドルファイルの最大サイズです。とりあえず1024MBにしておきました。

compose.yaml
services:
  hawkbit-update-server:
    build:
      context: ./hawkbit-update-server
      dockerfile: Dockerfile
      args:
        HAWKBIT_VERSION: 0.8.0
    # image: hawkbit/hawkbit-update-server:0.8.0
    environment:
      - 'PROFILES=mysql'
      - 'SPRING_DATASOURCE_URL=jdbc:mariadb://mysql:3306/hawkbit?allowPublicKeyRetrieval=true'
      - 'SPRING_DATASOURCE_USERNAME=root'
      - 'SPRING_DATASOURCE_PASSWORD=password'
      - 'SPRING_RABBITMQ_HOST=rabbitmq'
      - 'SPRING_RABBITMQ_PORT=5672'
      - 'SPRING_RABBITMQ_VIRTUALHOST=/'
      - 'SPRING_RABBITMQ_USERNAME=guest'
      - 'SPRING_RABBITMQ_PASSWORD=guest'
    ports:
      - 8080:8080
    volumes:
      - ./hawkbit-artifactrepo:/artifactrepo
    depends_on:
      mysql:
        condition: service_healthy
      rabbitmq:
        condition: service_started
    restart: unless-stopped
  hawkbit-simple-ui:
    build:
      context: ./hawkbit-simple-ui
      dockerfile: Dockerfile
      args:
        HAWKBIT_VERSION: 0.8.0
    # image: hawkbit/hawkbit-simple-ui:0.8.0
    environment:
      - 'SPRING_APPLICATION_JSON={"hawkbit.server.mgmtUrl": "http://hawkbit-update-server:8080"}'
      - 'SPRING_SERVLET_MULTIPART_MAX_FILE_SIZE=1024MB'
      - 'SPRING_SERVLET_MULTIPART_MAX_REQUEST_SIZE=1024MB'
    ports:
      - 8088:8088
    depends_on:
      hawkbit-update-server:
        condition: service_started
    restart: unless-stopped
  mysql:
    image: mysql:9.4
    environment:
      - 'MYSQL_ROOT_HOST=%'
      - 'MYSQL_ROOT_PASSWORD=password'
      - 'MYSQL_DATABASE=hawkbit'
      - 'MYSQL_USER=hawkbit'
      - 'MYSQL_PASSWORD=password'
      - 'MYSQL_TCP_PORT=3306'
    ports:
      - 3306:3306
    volumes:
      - ./mysql-data:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "--user=root", "--password=password"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s
    restart: unless-stopped
  rabbitmq:
    image: rabbitmq:4-management-alpine
    environment:
      - 'RABBITMQ_DEFAULT_VHOST=/'
      - 'RABBITMQ_DEFAULT_USER=guest'
      - 'RABBITMQ_DEFAULT_PASS=guest'
    ports:
      - 15672:15672
      - 5672:5672
    restart: unless-stopped

これをdocker compose up --buildすればサーバが起動します。(データベースのスキーマのマイグレーションがあり時間がかかります。ログに下記のように出るまで待ちます。)

hawkbit-update-server-1  | 2025-08-07T04:08:11.796Z  INFO 1 --- [update-server] [:] [           main] org.eclipse.hawkbit.app.Start            : Started Start in 88.196 seconds (process running for 91.506)

操作

※hawkbit-simple-uiの画面はExperimentalだからか、あまり洗練されていません。

1: アップデート配信サーバ側の初期設定とターゲットデバイス登録

ログインと設定

ブラウザでhttp://<アップデート配信サーバのIP>:8088/を開いて、hawkbit-simple-uiのログイン画面を表示します。ディフォルトのユーザ/パスはadmin/adminです。

後述のSecurity Tokenで認証を行うため、この認証フローをenableにする設定をします。左のメニューからConfigを選択、authentication.targettoken.enabledをチェックし、下の方にある[Save]ボタンを押します。

Targetの作成

左のメニューからTargetsを選択、右下の[+]ボタンを押します。Register Targetポップアップが表示されるのでController IDにデバイス毎にユニークなIDを入力します。ここではtest-targetです。

登録できました。リストのアイテムをクリックすると詳細が表示されます。

このController IDおよびSecurity Tokenがデバイス固有値となります。これをデバイスに設定する必要があります。(後述のStep 2)

Filterの作成

Filterは登録された全デバイスのサブセットとなるデバイス群を定義します。このデバイス群ごとにアップデートを配信するので、機種・仕向け等ごとなどでデバイス群を作ります。

後ほどRolloutの登録に必要なので設定しておきます。Raw Filterの入力にパターンを入力して右のセーブボタンを押すと保存されます。

パターンの書式はここに書いてあります。私はシンプルにname==test-targetで登録しました。

2: ポータブルエッジサーバ側にターゲットデバイスの登録内容を反映

起動させる

通常通り起動するだけです。rauc statusコマンドでA/Bどちらのパーティションから起動しているかわかります。

アップデート前起動時
=== System Info ===
Compatible:  raspberrypi3-64
Variant:     
Booted from: rootfs.0 (A)

=== Bootloader ===
Activated: rootfs.1 (B)

=== Slot States ===
x [rootfs.1] (/dev/mmcblk0p3, ext4, inactive)
      bootname: B
      boot status: good

o [rootfs.0] (/dev/mmcblk0p2, ext4, booted)
      bootname: A
      mounted: /
      boot status: good

デバイス固有値の設定

こちらの記事でNVRAM(EEPROMデバイスを使ったKey-Valueストア)を実装しました。nvram-writeを使用してデバイス固有の情報(デバイスIDや、デバイスごとに異なる認証情報など)をEEPROMデバイスに書き込みます。

まずは書き込みたいKey-Valueを格納したjsonファイルを作成します。hawkbit_serverに<アップデート配信サーバのIP>:8088を設定、target_nameおよびauth_tokenに前述のController IDおよびSecurity Tokenをコピペします。

test.json
{
  "hawkbit_server": "192.168.1.201:8080",
  "target_name": "test-target",
  "auth_token": "hoge"
}

このjsonファイルを使ってEEPROMに書き込むのにnvram-writeコマンドを使用します。

nvram-write -v -c test.json

ログを表示しておく

アップデートの様子を確認するため、rauc-hawkbit-updaterのログを表示します。

journalctl -u rauc-hawkbit-updater -f

3: アップデートバンドルの準備

Yoctoのビルドホストでの作業となります。何かソフトを変更して、以下のコマンドで作成できます。(ソフトは変更しなくてもOKです。アップデート後のソフトは何も変わりませんが。)

bitbake update-bundle

アップデートバンドル(squashfsイメージ)が出来上がるので、分かりやすいところにコピーしておきます。差分では無いのでそれなりに大きいです。

cp ./tmp/deploy/images/raspberrypi3-64/update-bundle-raspberrypi3-64.raucb ~

4: アップデート配信サーバ側でアップデートバンドルの配信を登録

Software Moduleの作成

左のメニューからSoftware Modulesを選択、右下の[+]ボタンを押します。Create Software Moduleポップアップが表示されるのでType, Name, Versionを入力します。ここではOS, test-software-module, 1です。

[Create]ボタンを押すと、続いて対象のファイルをアップロードします。

アップロードが完了したら[Finish]ボタンを押します。リストに登録されました。

Distribution Setの作成

一度に配信したい複数のSoftware Modulesを束ねたものがDistribution Setです。これを作ります。
左のメニューからDistribution Setsを選択、右下の[+]ボタンを押します。Create Distribution Setポップアップが表示されるのでType, Name, Versionを入力します。ここではOS only, test-distribution-set, 1です。

[Create]ボタンを押すと、続いて対象のSoftware Moduleを選択します。[+]ボタンを押します。

先ほど作成したtest-software-moduleを追加します。

最後に[Finish]ボタンを押します。リストに登録されました。

Rolloutの作成

最後に配信イベントであるRolloutを登録します。
左のメニューからRolloutsを選択、右下の[+]ボタンを押します。Create Rolloutポップアップが表示されるので名前、Distribution Set、1で作成したFilterを入力し、[Create]ボタンを押します。(なおStart TypeはManualにしておきます)リストに登録されました。

直後のStatusはcreatingで、これがreadyになると配信できるのですが、自動では表示が更新されません。ちょっと待ってからブラウザのページの再読込をするとreadyになり、配信開始ボタンが表示されると思います。(Start TypeをManualにしたのでこのボタンでスタート)

配信開始ボタンを押すとStatusがrunningになり、配信が開始されます。

5: ポータブルエッジサーバ側のアップデートを確認

配信のチェックはディフォルトで10分間核で行われます。2のログがこのようになります。

Aug 07 01:48:51 raspberrypi3-64 rauc-hawkbit-updater[356]: Checking for new software...
Aug 07 01:48:51 raspberrypi3-64 rauc-hawkbit-updater[356]: No new software.


Aug 07 01:53:52 raspberrypi3-64 rauc-hawkbit-updater[356]: Checking for new software...
Aug 07 01:53:52 raspberrypi3-64 rauc-hawkbit-updater[356]: New software ready for download (Name: test-target, Version: 1, Size: 58115952 bytes, URL: http://192.168.1.4:8080/DEFAULT/controller/v1/test-target/softwaremodules/1/artifacts/update-bundle-raspberrypi3-64.raucb)
Aug 07 01:53:52 raspberrypi3-64 rauc-hawkbit-updater[356]: Start downloading: http://192.168.1.4:8080/DEFAULT/controller/v1/test-target/softwaremodules/1/artifacts/update-bundle-raspberrypi3-64.raucb
Aug 07 01:53:55 raspberrypi3-64 rauc-hawkbit-updater[356]: Download complete. 35.46 MB/s
Aug 07 01:53:55 raspberrypi3-64 rauc-hawkbit-updater[356]: File checksum OK.
Aug 07 01:53:55 raspberrypi3-64 rauc-hawkbit-updater[356]: Installing: /tmp/bundle.raucb : installing
Aug 07 01:53:55 raspberrypi3-64 rauc-hawkbit-updater[356]: installing
Aug 07 01:53:55 raspberrypi3-64 rauc-hawkbit-updater[356]: Installing: /tmp/bundle.raucb :   0% Installing
Aug 07 01:53:55 raspberrypi3-64 rauc-hawkbit-updater[356]:   0% Installing
Aug 07 01:53:55 raspberrypi3-64 rauc-hawkbit-updater[356]: Installing: /tmp/bundle.raucb :   0% Determining slot states
Aug 07 01:53:55 raspberrypi3-64 rauc-hawkbit-updater[356]:   0% Determining slot states
Aug 07 01:53:55 raspberrypi3-64 rauc-hawkbit-updater[356]: Installing: /tmp/bundle.raucb :  10% Determining slot states done.
Aug 07 01:53:55 raspberrypi3-64 rauc-hawkbit-updater[356]:  10% Determining slot states done.
Aug 07 01:53:55 raspberrypi3-64 rauc-hawkbit-updater[356]: Installing: /tmp/bundle.raucb :  10% Checking bundle
Aug 07 01:53:55 raspberrypi3-64 rauc-hawkbit-updater[356]:  10% Checking bundle
Aug 07 01:53:55 raspberrypi3-64 rauc-hawkbit-updater[356]: Installing: /tmp/bundle.raucb :  10% Verifying signature
Aug 07 01:53:55 raspberrypi3-64 rauc-hawkbit-updater[356]:  10% Verifying signature

...

Aug 07 01:54:03 raspberrypi3-64 rauc-hawkbit-updater[356]: Installing: /tmp/bundle.raucb :  99% Copying image to rootfs.1
Aug 07 01:54:03 raspberrypi3-64 rauc-hawkbit-updater[356]:  99% Copying image to rootfs.1
Aug 07 01:54:16 raspberrypi3-64 rauc-hawkbit-updater[356]: Installing: /tmp/bundle.raucb :  99% Copying image to rootfs.1 done.
Aug 07 01:54:16 raspberrypi3-64 rauc-hawkbit-updater[356]:  99% Copying image to rootfs.1 done.
Aug 07 01:54:16 raspberrypi3-64 rauc-hawkbit-updater[356]: Installing: /tmp/bundle.raucb :  99% Updating slots done.
Aug 07 01:54:16 raspberrypi3-64 rauc-hawkbit-updater[356]:  99% Updating slots done.
Aug 07 01:54:16 raspberrypi3-64 rauc-hawkbit-updater[356]: Installing: /tmp/bundle.raucb : 100% Installing done.
Aug 07 01:54:16 raspberrypi3-64 rauc-hawkbit-updater[356]: 100% Installing done.
Aug 07 01:54:16 raspberrypi3-64 rauc-hawkbit-updater[356]: Installing: /tmp/bundle.raucb : idle
Aug 07 01:54:16 raspberrypi3-64 rauc-hawkbit-updater[356]: idle
Aug 07 01:54:16 raspberrypi3-64 rauc-hawkbit-updater[356]: Software bundle installed successfully.

rauc statusはこのようになりました。

アップデート後・再起動前
=== System Info ===
Compatible:  raspberrypi3-64
Variant:     
Booted from: rootfs.1 (B)

=== Bootloader ===
Activated: rootfs.1 (B)

=== Slot States ===
x [rootfs.1] (/dev/mmcblk0p3, ext4, booted)
      bootname: B
      mounted: /
      boot status: good

o [rootfs.0] (/dev/mmcblk0p2, ext4, inactive)
      bootname: A
      boot status: good

再起動します。するとBパーティションから起動し、rauc statusはこのようになります。

アップデート後・再起動後
=== System Info ===
Compatible:  raspberrypi3-64
Variant:     
Booted from: rootfs.1 (B)

=== Bootloader ===
Activated: rootfs.1 (B)

=== Slot States ===
x [rootfs.1] (/dev/mmcblk0p3, ext4, booted)
      bootname: B
      mounted: /
      boot status: good

o [rootfs.0] (/dev/mmcblk0p2, ext4, inactive)
      bootname: A
      boot status: good

これでOTAアップデートが完了しました。

Discussion