Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • eclipse/oniro-core/sysota
  • pastanki/sysota
2 results
Show changes
Commits on Source (410)
Showing
with 477 additions and 213 deletions
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Huawei Inc.
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Huawei Inc.
.spread-reuse.*.yaml
.spread-reuse.yaml
cmd/sysotad/rauc-custom-boot-handler
cmd/sysotad/rauc-post-install-handler
cmd/sysotad/rauc-pre-install-handler
cmd/sysotad/sysotad
cmd/sysota-mux/rauc-custom-boot-handler
cmd/sysota-mux/rauc-post-install-handler
cmd/sysota-mux/rauc-pre-install-handler
cmd/sysota-mux/sysota-mux
cmd/sysota-mux/sysotactl
cmd/sysota-mux/sysotad
config.sysota.mk
configure
data/systemd/system/sysotad.service
man/sysota.state.ini.5
man/sysotad.conf.5
man/*.7
man/*.5
sysota-*.tar.gz
sysota-*.tar.gz.asc
......@@ -5,132 +5,208 @@ stages:
- compliance
- test
- build
- integration-test
- integration
include:
- project: OSTC/infrastructure/pipelines
file: 'reuse.yaml'
- template: 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml'
reuse:
extends: .reuse
- remote: 'https://gitlab.com/zygoon/go-gitlab-ci/-/raw/master/go.yml'
.go:
image: golang:latest
variables:
REPO_NAME: git.ostc-eu.org/OSTC/OHOS/components/sysota
GOPATH: /tmp/go
before_script:
- mkdir -p $GOPATH/src/"$(dirname "$REPO_NAME")"
- ln -svf "$CI_PROJECT_DIR" "$GOPATH/src/$REPO_NAME"
- mkdir -p /tmp/go
- cd "$GOPATH/src/$REPO_NAME"
# The project requires Go 1.16 compatibility.
# For Yocto Kirkstone the baseline will move to Go 1.18.
CI_GO_VERSION: "1.16"
format:
extends: .go
stage: test
dco:
interruptible: true
tags: [kvm] # Technically we want x86_64 or aarch64 but there's no OR syntax for tags, this is a way to cheat.
stage: compliance
image: christophebedard/dco-check:latest
rules:
- if: $CI_MERGE_REQUEST_ID
- if: $CI_EXTERNAL_PULL_REQUEST_IID
- if: $CI_COMMIT_BRANCH == '$CI_DEFAULT_BRANCH'
script:
- go fmt ./...
# Work around a bug in dco-check affecting pipelines for merge requests.
# https://github.com/christophebedard/dco-check/issues/104
- |
if [ "${CI_MERGE_REQUEST_EVENT_TYPE:-}" = detached ]; then
git fetch -a # so that we can resolve branch names below
export CI_COMMIT_BRANCH="$CI_COMMIT_REF_NAME";
export CI_COMMIT_BEFORE_SHA="$CI_MERGE_REQUEST_DIFF_BASE_SHA";
export CI_MERGE_REQUEST_SOURCE_BRANCH_SHA="$(git rev-parse "origin/$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME")";
export CI_MERGE_REQUEST_TARGET_BRANCH_SHA="$(git rev-parse "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME")";
fi
- dco-check --default-branch-from-remote --verbose
spell:
stage: test
reuse:
interruptible: true
stage: compliance
tags: [x86_64] # The aarch64 binary is actually an x86_64 binary.
image:
name: registry.ostc-eu.org/ostc/containers/ostc-npx-cspell:latest
name: fsfe/reuse:latest
entrypoint: [""]
script:
# TODO(zyga): remove this and re-generate the container.
- rm -rf /root/.npm
# Note that the particular options are duplicated with what's defined in
# Makefile. To avoid this we'd have to get zmk as an installable dependency
# and replace everything below with "make static-check -j" but this is
# somewhat complex given the starting docker image.
- "npx cspell lint '**/*.go' '**/*.md' '**/*.yaml' '**/*.json' '**/*.txt' '**/*.log' '**/*.mk' Makefile '.tours/*.tour' 'man/*.in'"
- reuse lint
test:
extends: .go
stage: test
go-test:
tags: [$RUNNER_OS, $RUNNER_ARCH]
parallel:
matrix:
- RUNNER_OS: linux
RUNNER_ARCH: [x86_64, aarch64, armv7l]
CI_GO_VERSION: ["1.16", latest]
before_script:
# Set up caching.
- !reference [.go, before_script]
- echo -e "\e[0Ksection_start:$(date +%s):install_debian[collapsed=true]\r\e[0KInstalling Debian dependencies..."
# Install dbus-daemon and squashfs-tools which are used by dbus and
# squashfs-tools tests. The golang:latest image is based on Debian so we
# can just apt-get install it.
- apt-get update && apt-get install -y dbus squashfs-tools
# Restore cache from place it is deposited to
- mkdir -p $(go env GOPATH)/pkg/mod
- test -d .go/pkg/mod && ( mkdir -p .go/pkg && mv .go/pkg/mod $(go env GOPATH)/pkg)
- rm -rf .go
- go install honnef.co/go/tools/cmd/staticcheck@latest
- echo -e "\e[0Ksection_end:$(date +%s):install_debian\r\e[0K"
# Install go package for emitting GitLab friendly coverage information.
- echo -e "\e[0Ksection_start:$(date +%s):install_cover\r\e[0KInstalling Go coverage dependencies..."
- go install github.com/boumenot/gocover-cobertura@latest
- go install github.com/jgautheron/goconst/cmd/goconst@latest
- go install github.com/kisielk/errcheck@latest
- go install github.com/bombsimon/wsl/v3/...@latest
- go install github.com/gordonklaus/ineffassign@latest
- echo -e "\e[0Ksection_end:$(date +%s):install_cover\r\e[0K"
script:
- go vet ./...
- $(go env GOPATH)/bin/staticcheck ./...
- $(go env GOPATH)/bin/goconst -set-exit-status ./...
- $(go env GOPATH)/bin/errcheck ./...
- $(go env GOPATH)/bin/wsl ./...
- $(go env GOPATH)/bin/ineffassign ./...
- go test -coverprofile=coverage.txt -covermode count ./...
- echo -e "\e[0Ksection_start:$(date +%s):test\r\e[0KTesting..."
- go test $(case $(uname -m) in x86_64|aarch64) echo -race ;; esac) -coverprofile=coverage.txt -covermode atomic ./...
- echo -e "\e[0Ksection_end:$(date +%s):test\r\e[0K"
- echo -e "\e[0Ksection_start:$(date +%s):test_coverage[collapsed=true]\r\e[0KGenerating coverage report..."
- go tool cover -func=coverage.txt
- $(go env GOPATH)/bin/gocover-cobertura <coverage.txt >"$CI_PROJECT_DIR"/coverage.xml
after_script:
# Save cache for pickup by GitLab
- mkdir -p .go/pkg
- mv $(go env GOPATH)/pkg/mod .go/pkg
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .go/pkg/mod
- echo -e "\e[0Ksection_end:$(date +%s):test_coverage\r\e[0K"
artifacts:
paths:
- coverage.xml
reports:
cobertura: coverage.xml
spread-qemu-hirsute:
stage: integration-test
image: registry.ostc-eu.org/ostc/containers/ostc-dev-next:latest
.build-with-kaniko:
stage: build
# This is artificially limited because we don't handle build tags correctly
# and the other side of this job requires x86_64 (for spread).
tags: [x86_64]
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
script:
- |
set -xe
mkdir -p /kaniko/.docker
printf '{"auths":{"%s":{"auth":"%s"}}}\n' "$CI_REGISTRY" "$(printf '%s:%s' "$CI_REGISTRY_USER" "$CI_REGISTRY_PASSWORD" | base64)" > /kaniko/.docker/config.json
BUILD_DATE="$(date '+%FT%T%z' | sed -E -n 's/(\+[0-9]{2})([0-9]{2})$/\1:\2/p')" #rfc 3339 date
BUILD_TITLE=$(echo "$CI_PROJECT_TITLE" | tr " " "_")
IMAGE_LABELS="$(cat <<EOM
--label build-date=$BUILD_DATE
--label com.gitlab.ci.cijoburl=$CI_JOB_URL
--label com.gitlab.ci.commiturl=$CI_PROJECT_URL/commit/$CI_COMMIT_SHA
--label com.gitlab.ci.email=$GITLAB_USER_EMAIL
--label com.gitlab.ci.mrurl=$CI_PROJECT_URL/-/merge_requests/$CI_MERGE_REQUEST_ID
--label com.gitlab.ci.pipelineurl=$CI_PIPELINE_URL
--label com.gitlab.ci.tagorbranch=$CI_COMMIT_REF_NAME
--label com.gitlab.ci.user=$CI_SERVER_URL/$GITLAB_USER_LOGIN
--label org.opencontainers.image.authors=$CI_SERVER_URL/$GITLAB_USER_LOGIN
--label org.opencontainers.image.created=$BUILD_DATE
--label org.opencontainers.image.description=$BUILD_TITLE
--label org.opencontainers.image.documentation=$CI_PROJECT_URL
--label org.opencontainers.image.licenses=$CI_PROJECT_URL
--label org.opencontainers.image.ref.name=$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
--label org.opencontainers.image.revision=$CI_COMMIT_SHA
--label org.opencontainers.image.source=$CI_PROJECT_URL
--label org.opencontainers.image.title=$BUILD_TITLE
--label org.opencontainers.image.url=$CI_PROJECT_URL
--label org.opencontainers.image.vendor=$CI_SERVER_URL/$GITLAB_USER_LOGIN
--label org.opencontainers.image.version=$CI_COMMIT_TAG
--label vcs-url=$CI_PROJECT_URL
EOM
)"
ADDITIONAL_TAG_LIST="$CI_COMMIT_REF_NAME $CI_COMMIT_SHORT_SHA"
if [ "$CI_COMMIT_BRANCH" = "$CI_DEFAULT_BRANCH" ]; then
ADDITIONAL_TAG_LIST="$ADDITIONAL_TAG_LIST latest";
fi
if [ -n "$ADDITIONAL_TAG_LIST" ]; then
for TAG in $ADDITIONAL_TAG_LIST; do
FORMATTED_TAG_LIST="$FORMATTED_TAG_LIST --tag $CI_REGISTRY_IMAGE:$TAG "
done
fi
FORMATTED_TAG_LIST="$(echo "$FORMATTED_TAG_LIST" | sed -e 's/--tag/--destination/g')"
echo "Building and shipping image to $CI_REGISTRY_IMAGE"
exec /kaniko/executor --context "$CI_PROJECT_DIR/$CONTAINER_PATH" --dockerfile "$CI_PROJECT_DIR/$CONTAINER_PATH/Dockerfile" --destination $CI_REGISTRY_IMAGE/$CONTAINER_PATH $IMAGE_LABELS
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
changes:
- $CONTAINER_PATH/*
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
changes:
- $CONTAINER_PATH/*
spell:
interruptible: true
stage: test
image:
name: registry.booting.oniroproject.org/distro/oniro/npm-cspell:latest
tags: [x86_64] # TODO(zyga): publish a container ourselves or switch to node containers.
script:
# Note that the particular options are duplicated with what's defined in
# Makefile. To avoid this we'd have to get zmk as an installable dependency
# and replace everything below with "make static-check -j" but this is
# somewhat complex given the starting docker image.
- "cspell lint '**/*.go' '**/*.md' '**/*.yaml' '**/*.json' '**/*.txt' '**/*.log' '**/*.mk' Makefile '.tours/*.tour' 'man/*.in'"
docker-spread:
extends: .build-with-kaniko
variables:
CONTAINER_PATH: docker/spread
spread-qemu:
interruptible: true
# TODO(zyga): depend on amd64/linux cross build explicitly when
# GitLab supports this: https://gitlab.com/gitlab-org/gitlab/-/issues/254821
stage: integration
needs:
- job: go-test
artifacts: false
image: registry.booting.oniroproject.org/distro/components/sysota/docker/spread:latest
tags: [kvm, x86_64] # TODO(zyga): build this container locally, add aarch64 support
variables:
DEBIAN_FRONTEND: noninteractive
tags: [experimental, qemu-friendly]
SPREAD_QEMU_KVM: "1"
TRANSFER_METER_FREQUENCY: "2s"
ARTIFACT_COMPRESSION_LEVEL: "fast"
CACHE_COMPRESSION_LEVEL: "fastest"
parallel:
matrix:
- VERSION_CODENAME: [impish]
ID: [ubuntu]
ID_VERSION: ["21.10"]
- VERSION_CODENAME: [jammy]
ID: [ubuntu]
ID_VERSION: ["22.04"]
before_script:
- mkdir -p .cache
- mkdir -p ~/.spread/qemu
- |
set -ex
if [ ! -e .cache/autopkgtest-hirsute-amd64.img.zst ]; then
time apt-get update
time apt-get dist-upgrade -y
time apt-get install -y autopkgtest qemu-system-x86 zstd python3-distro-info genisoimage
if [ ! -e .cache/autopkgtest-$VERSION_CODENAME-amd64.img ]; then
# Prepare a qemu image that is useful for testing. For now this is just
# a vanilla Hirsute (Ubuntu 21.04) image with some packages
# pre-installed to speed up the project prepare step in spread.yaml.
# a vanilla Ubuntu image with some packages pre-installed to speed up
# the project prepare step in spread.yaml.
cd .cache
time autopkgtest-buildvm-ubuntu-cloud -r hirsute --post-command "apt-get install ssh golang-go zmk rauc-service squashfs-tools jq"
# Zstd is very fast and compresses the mostly-empty image efficiently.
time zstd autopkgtest-hirsute-amd64.img
time autopkgtest-buildvm-ubuntu-cloud -r $VERSION_CODENAME --post-command "apt-get install ssh golang-go zmk rauc-service squashfs-tools jq git && apt-get install -d postgresql"
cd ..
fi
- time unzstd .cache/autopkgtest-hirsute-amd64.img.zst -o ~/.spread/qemu/ubuntu-21.04-64.img
- ln -s $CI_PROJECT_DIR/.cache/autopkgtest-$VERSION_CODENAME-amd64.img ~/.spread/qemu/$ID-$ID_VERSION-64.img
script:
- 'time spread -v qemu:'
- 'time spread -v qemu:$ID-$ID_VERSION-64:'
cache:
# If the image needs to be rebuilt, just bump this number.
key: autopkgtest-image-hirsute-5
paths:
- .cache/autopkgtest-hirsute-amd64.img.zst
build:
extends: .go
stage: build
script:
- go build ./cmd/sysotad
artifacts:
paths:
- sysotad
cache:
key: ${CI_COMMIT_REF_SLUG}
key: autopkgtest-image-$VERSION_CODENAME-8
# The image compresses well. Don't compress it here, GitLab will compress
# it automatically as a part of the cache creation step.
paths:
- .go/pkg/mod
- .cache/autopkgtest-$VERSION_CODENAME-amd64.img
......@@ -3,7 +3,7 @@
terminal:
image:
name: registry.ostc-eu.org/ostc/containers/ostc-dev:latest
name: ubuntu:20.04
tags: [experimental, qemu-friendly, webterm-friendly]
script:
# The Web IDE needs enough time to connect to the session. Once connected this
......
......@@ -94,13 +94,13 @@
},
{
"file": "spread.yaml",
"description": "Back to `spread.yaml`. We will now look at the specific test suites we have defined and what they contain.\n\nThe first suite is placed in `cmd/sysotad/tests/`. It contains various assorted tests as it was the first test suite that was defined. Over time tests placed here may move to a more appropriate location.\n\nWhen moving tests across suites please keep in mind that the test most likely relies on what happens in the suite `prepare` or `prepare-each` snippets. It's good practice to organize suites so that they are scoped but otherwise have a familiar environment, so less context is required to understand what happens in practice.",
"description": "Back to `spread.yaml`. We will now look at the specific test suites we have defined and what they contain.\n\nThe first suite is placed in `cmd/sysotad/spread.suite/`. It contains various assorted tests as it was the first test suite that was defined. Over time tests placed here may move to a more appropriate location.\n\nWhen moving tests across suites please keep in mind that the test most likely relies on what happens in the suite `prepare` or `prepare-each` snippets. It's good practice to organize suites so that they are scoped but otherwise have a familiar environment, so less context is required to understand what happens in practice.",
"line": 62,
"title": "The sysotad suite"
},
{
"file": "spread.yaml",
"description": "The next suite is the `boot/piboot/tests/`.\n\nHere we mainly look at how the `piboot` boot-loader backend operates by calling it in a simulated environment.",
"description": "The next suite is the `boot/piboot/spread.suite/`.\n\nHere we mainly look at how the `piboot` boot-loader backend operates by calling it in a simulated environment.",
"line": 80,
"title": "The piboot suite"
},
......
......@@ -21,53 +21,53 @@
"title": "The boot/testboot package"
},
{
"file": "cmd/sysotad/main.go",
"description": "The `cmd/sysotad` directory actually holds the `main` package, this is because it builds the primary and only executable instead of a library.\n\nThis package is pretty small as, as all it really does it to look at the name under which the executable was invoked and to forward the execution to one of the sub-packages which implement the actual `sysotad` or `rauc-custom-boot-handler` or `rauc-{pre,post}-install-handler`.\n\nThis dispatch trick helps save space as Go's static linking model creates inherently large binaries. By putting all the binaries into one file, we amortize the static linking tax.\n\nCurrently sysotad, on a x86_64 system, is about 3MB after stripping. This is large but not remarkable given the statically linked libraries inside.",
"file": "cmd/sysota-mux/main.go",
"description": "The `cmd/sysota-mux` directory actually holds the `main` package, this is because it builds the primary and only executable instead of a library.\n\nThis package is pretty small as, as all it really does it to look at the name under which the executable was invoked and to forward the execution to one of the sub-packages which implement the actual `sysotad` or `rauc-custom-boot-handler` or `rauc-{pre,post}-install-handler`.\n\nThis dispatch trick helps save space as Go's static linking model creates inherently large binaries. By putting all the binaries into one file, we amortize the static linking tax.\n\nCurrently sysotad, on a x86_64 system, is about 3MB after stripping. This is large but not remarkable given the statically linked libraries inside.",
"line": 6,
"title": "The cmd/sysotad package"
"title": "The cmd/sysota-mux package"
},
{
"file": "cmd/rauc-custom-boot-handler/cmd.go",
"description": "The `rauc-custom-boot-handler` is the command line handling for RAUC custom boot handler.\n\nAll this package does is to handle the command line arguments, connect to D-Bus, and pass on the baton to `boothandler.Command`.\n\nThe same pattern repeats for all the other RAUC handlers. The command line tool forwards the request, over D-Bus, to SystemOTA. This way the handlers are not privileged, single instate is guaranteed and `sysotad` can implement locking internally in the process.\n\nThis way we also build APIs for other parts of the platform to use, not just Go libraries.",
"line": 5,
"title": "The cmd/rauc-custom-boot-handler package"
},
{
"file": "cmd/sysotad/cmdrauccustomboothandler/cmdrauccustomboothandler.go",
"description": "The `cmdrauccustomboothandler` - that's a mouthful, is where the command for rauc custom boot handler lives.\n\nAll this package does is to handle the command line arguments, connect to D-Bus, and pass on the baton to `boothandler.Command`.\n\nThe same pattern repeats for all the other RAUC handlers. The command line tool forwards the request, over D-Bus, to SystemOTA. This way the handlers are not privileged, single instate is guaranteed and `sysotad` can implement locking internally in the process.\n\nThis way we also build APIs for other parts of the platform to use, not just Go libraries.",
"file": "cmd/rauc-pre-install-handler/cmd.go",
"description": "The `rauc-pre-install-handler` is the command line handling for RAUC pre-install handler.\n\nAs with the custom boot backend handler, there is very little logic. Just grab the handler context, connect to D-Bus and dispatch the call to handle in SystemOTA service.",
"line": 5,
"title": "The cmd/sysotad/cmdrauccustomboothandler package"
"title": "The cmd/rauc-pre-install-handler package"
},
{
"file": "cmd/sysotad/cmdraucinstallhandler/cmdraucinstallhandler.go",
"description": "The `cmdraucinstallhandler` is another German-sounding word created by the Go package naming scheme.\n\nIn Go package names are lower-case words that are a combination of abbreviations and words joined together into a single symbol. The guiding principle is to have names that are at the same time, specific, descriptive, unique and, crucially, not the word that would clash with a symbol in the places that use the package.\n\nHere the package contains the command line handling for RAUC install handler.\n\nAs with the custom boot backend handler, there is very little logic. Just grab the handler context, connect to D-Bus and dispatch the call to handle in SystemOTA service.",
"file": "cmd/rauc-post-install-handler/cmd.go",
"description": "The `rauc-post-install-handler` is the command line handling for RAUC post-install handler.\n\nAs with the custom boot backend handler, there is very little logic. Just grab the handler context, connect to D-Bus and dispatch the call to handle in SystemOTA service.",
"line": 5,
"title": "The cmd/sysotad/cmdraucinstallhandler package"
"title": "The cmd/rauc-post-install-handler package"
},
{
"file": "cmd/sysotad/cmdsysotad/sysotad.go",
"description": "The `cmdsysotad` package is the last of the `cmd*` packages.\n\nThe name stands for the command for SystemOTA daemon (or service).\n\nMost of the service is implemented in the `service` and related packages. Here we only deal with the start-up and the shut-down of the process. We load configuration and state, connect to the system bus, export all the objects, claim our bus name and work until we are interrupted or until all background activity ceases and the service quits on idle timer. This is also, notably, where we save the state back to the file system.",
"file": "cmd/sysotad/sysotad.go",
"description": "The `sysotad` package is the last of the command packages.\n\nMost of the service is implemented in the `service` and related packages. Here we only deal with the start-up and the shut-down of the process. We load configuration and state, connect to the system bus, export all the objects, claim our bus name and work until we are interrupted or until all background activity ceases and the service quits on idle timer. This is also, notably, where we save the state back to the file system.",
"line": 5,
"title": "The cmd/sysotad/cmdsysotad package"
"title": "The cmd/sysotad package"
},
{
"file": "dbusutil/dbusutil.go",
"file": "pkg/dbusutil/dbusutil.go",
"description": "The `dbusutil` package contains D-Bus utilities.\n\nWe use the `github.com/godbus/dbus/v5` library for all our D-Bus logic but we have a few extras here. There are some constants for well-known interfaces and signal names and there are some constants for D-Bus introspection. We also have a `SystemBus` helper function which is just like `dbus.SystemBus` but it allows the caller to close the connection, because it is not shared.\n\nThis package also holds the `ServiceHost` type, which makes it easier to handle publishing services on the bus, by handling the boiler-plate and by presenting an uniform interface to publish objects and services on top of the vanilla `dbus` package.\n\nSome specific functionality is in two other packages that we are going to look at next.",
"line": 5,
"title": "The dbusutil package"
},
{
"file": "dbusutil/dbustest/dbustest.go",
"file": "pkg/dbusutil/dbustest/dbustest.go",
"description": "The `dbustest` package contains helpers for writing test that involve D-Bus.\n\nTraditionally D-Bus has one system bus for the entire system, where privileged services live, and a session bus which is unique for each user and where unprivileged user services live.\n\nFor testing we don't want to connect to _either_ of those. Instead we want a dedicated bus which has no other users, that we can set up and tear down at will. This is exactly what `TestBus` provides, it starts a new `dbus-daemon` process, with the appropriate configuration and bus policy.\n\nUnit tests are grouped into suites so here we also provide a `dbustest.Suite` type which conveniently replaces the system bus with our test bus. This lets test easily connect to the bus, claim bus name or interact with test services.",
"line": 5,
"title": "The dbusutil/dbustest package"
},
{
"file": "dbusutil/objmgr/objmgr.go",
"file": "pkg/dbusutil/objmgr/objmgr.go",
"description": "The `objmgr` package contains well-known names for the D-Bus Object Manager interface as well as the related D-Bus introspection data.\n\nObject manager is a conceptually powerful but technically simple interface, where a client can enumerate and keep track of arbitrary many D-Bus objects and interfaces provided by a manager object. The SystemOTA service object acts as an object manager, creating individual objects for each potentially-long-running background activity.\n\nRight now there is no implementation of the actual object manager here, it is not generic enough so it lives inside the `service` package. Over time we may make something that is highly re-usable and move it here.",
"line": 8,
"title": "The dbusutil/objmgr package"
},
{
"file": "encoding/ini/ini.go",
"description": "The `encoding/ini` package provides an INI-file encoder/decoder interface, similar to `encoding/json`.\n\nINI files are interesting for several reasons, first of all they are used by both RAUC and Systemd, our two principal dependencies. Second, unlike JSON, they are friendly to be edited by humans, supporting comments and really forgiving (I'm looking at you JSON commas) syntax. Lastly unlike YAML they are inherently simple. There is no way to express cyclic data structures, there are far far fewer syntax elements and the overall surprise factor is very low.\n\nOur package uses structure tags for effortless marshaling and unmarshaling of structure types. It also re-uses the `encoding.TextMarshaler` and `TextUnmarshaler` interface, to extend the basic set of supported field types to arbitrary custom types, as long as they can marshal to and from a text string.",
"line": 7,
"title": "The encoding/ini package"
},
{
"file": "ota/ota.go",
"description": "The `ota` package contains code that us unique to the essence of SystemOTA.\n\nHere we define `Config` - representing the configuration of the service. Here we also define `SystemState` which describes all of the state used by the `sysotad` - for the moment that is literally *one bit* of state we need to keep!\n\nThere are some assorted types here like `BootLoaderType`, `ConfigError`, `LoadStateError` and `SaveStateError`. There are some utility functions related to both configuration and state.\n\nThere are two sub packages relate to how SystemOTA interacts with RAUC. We will look at them now.",
......@@ -75,10 +75,10 @@
"title": "The ota package"
},
{
"file": "ota/raucadapter/raucadapter.go",
"file": "cmd/sysotad/raucadapter/raucadapter.go",
"description": "The `raucadapter` contains one of the most important parts that translate RAUC concepts to SystemOTA concepts.\n\nSpecifically, this is where a `boot.Protocol` becomes usable with a rather different RAUC custom boot handler interface. This is where a RAUC install handler is technically implemented as well - by dispatching the pre/post install handlers to the object providing the `boot.Protocol` interface, if it chooses to implement additional methods.\n\nNote that there is a difference between the glue code that handles the minute details of RAUC boot handler or install handler, the D-Bus bridge for those and the adapter in this package. Everything apart from the adapter is a direct pass through or direct Go implementation of a RAUC interface. This package contains code that may be somewhat tricky or may contain logic bugs due to impedance mismatch.",
"line": 4,
"title": "The ota/raucadapter package"
"title": "The raucadapter package"
},
{
"file": "ota/raucinterface/raucinterface.go",
......@@ -86,18 +86,6 @@
"line": 9,
"title": "The ota/raucinterface package"
},
{
"file": "picfg/picfg.go",
"description": "The `picfg` package contains a model of the Raspberry Pi `config.txt` file.\n\nThis package provides an `Encoder` and `Decoder` types. A `ConfigTxt` type can be marshaled and unmarshaled. Inside there are a number of `Section`s, each with an optional `Filter` and a number of `Parameter`s.\n\nFilters have semantics but it is not captured here. To interpret conditional filters look at the `picfg/condfilter` package.\n\nNone of the code here is specific to System OTA. Eventually it could be moved to a separate library.",
"line": 13,
"title": "The picfg package"
},
{
"file": "picfg/condfilter/condfilter.go",
"description": "The `picfg/condfilter` package contains distinct types for all of the Raspberry Pi bootloader conditional filters.\n\nThere are types for `[all]`, `[nope]`, the per-model filter, the per-serial filter, the EDID and GPIOs. All of this is combined into the `StateTracker` which can be used to traverse a `picfg.ConfigTxt` object and provide the effective conditional filters, resolving combination and overriding rules implemented by the boot loader.",
"line": 13,
"title": "The picfg/condfilter package"
},
{
"file": "rauc/rauc.go",
"description": "The `rauc` package contains APIs for working with RAUC itself.\n\nNone of the code here is specific to SystemOTA. Eventually it could be moved to a separate library.",
......@@ -112,7 +100,7 @@
},
{
"file": "rauc/installhandler/installhandler.go",
"description": "The `installhandler` package provides Go interface to RAUC `pre-install` and `post-install` handlers.\n\nThe `Participant` interface describes types which participate in the install process. The interface contains two functions, each named after the phase of the install process. Both methods take a `HandlerContext` which encapsulates all the information provided by RAUC to the handler in the form of environment variables.\n\nThis type needs some tweaks, as RAUC supports a range of handlers and hooks, and the context type could be split and generalized into several distinct context types, one for each handler or hook.",
"description": "The `installhandler` package provides Go interface to RAUC `pre-install` and `post-install` handlers.\n\nThe `Participant` interface describes types which participate in the install process. The interface contains two functions, each named after the phase of the install process. Both methods take an `Environment` which encapsulates all the information provided by RAUC to the handler in the form of environment variables.\n\nThis type needs some tweaks, as RAUC supports a range of handlers and hooks, and the context type could be split and generalized into several distinct context types, one for each handler or hook.",
"line": 9,
"title": "The rauc/installhandler package"
},
......@@ -123,16 +111,16 @@
"title": "The rauc/rauctest package"
},
{
"file": "service/service.go",
"description": "The `service` package is the penultimate package of SystemOTA. It provides the `Service` type and the `RequestBusName` function.\n\nThe service implements all of the things necessary to create the SystemOTA D-Bus service. The service itself provides one main object, each with several distinct interfaces, and a small collection of objects representing background operations.\n\nThe `Service` contains a number of smaller services that get all published with `dbusutil.ServiceHost`. The `UpdateService` is least develop, containing only stub code for now. The `BootProtocolService` directly exposes a `boot.Protocol` over D-Bus and a yet-unmerged patch provides the `raucinterface.Service` which exposes D-Bus equivalents of the boot and install handlers.",
"file": "cmd/sysotad/service.go",
"description": "The former `service` package is the penultimate package of SystemOTA. It provides the `Service` type and the `RequestBusName` function.\n\nThe service implements all of the things necessary to create the SystemOTA D-Bus service. The service itself provides one main object, each with several distinct interfaces, and a small collection of objects representing background operations.\n\nThe `Service` contains a number of smaller services that get all published with `dbusutil.ServiceHost`. The `UpdateService` is least develop, containing only stub code for now. The `BootProtocolService` directly exposes a `boot.Protocol` over D-Bus and a yet-unmerged patch provides the `raucinterface.Service` which exposes D-Bus equivalents of the boot and install handlers.",
"line": 5,
"title": "The service package"
"title": "The former service package"
},
{
"file": "service/oper/oper.go",
"description": "The `service/oper` package implements individual `Operation` objects.\n\nThis part is mostly underdeveloped. The plan is to wrap any goroutine in an operation and handle enough state marshaling to allow certain operations to work across a reboot boundary. This is how we will handle downloads and certain more complicated update operations.\n\nThis concludes the tour of Go packages in SystemOTA.",
"file": "cmd/sysotad/updatehosted/oper/oper.go",
"description": "The `updatehosted/oper` package implements individual `Operation` objects.\n\nThis part is mostly underdeveloped. The plan is to wrap any goroutine in an operation and handle enough state marshaling to allow certain operations to work across a reboot boundary. This is how we will handle downloads and certain more complicated update operations.\n\nThis concludes the tour of Go packages in SystemOTA.",
"line": 5,
"title": "The service/oper package"
"title": "The updatehosted/oper package"
}
]
}
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Huawei Inc.
Cspell.NpxCmd ?= $(strip $(shell command -v npx 2>/dev/null))
Cspell.CspellCmd ?= $(strip $(shell command -v cspell 2>/dev/null))
Cspell.Options ?=
.PHONY: static-check-npx-cspell-lint
static-check-npx-cspell-lint:
$(strip $(Cspell.NpxCmd) cspell lint $(Cspell.Options))
.PHONY: static-check-cspell-lint
static-check-cspell-lint:
$(if $(ZMK.IsOutOfTreeBuild),cd $(ZMK.SrcDir) && )$(strip $(Cspell.CspellCmd) lint $(Cspell.Options))
# Run "npx cspell" when running static checks, but only when npx is installed.
ifneq (,$(Cspell.NpxCmd))
static-check:: static-check-npx-cspell-lint
# Run "cspell lint" when running static checks, but only when npx is installed.
ifneq (,$(Cspell.CspellCmd))
static-check:: static-check-cspell-lint
else
$(if $(filter check static-check,$(MAKECMDGOALS)),$(warning The npx program is not available, static-check target will not depend on static-check-npx-cspell))
$(if $(filter check static-check,$(MAKECMDGOALS)),$(warning The cspell program is not available, static-check target will not depend on static-check-cspell-lint))
endif
......@@ -10,9 +10,9 @@ $$(foreach v,$$($1.Variables),$$(eval $1.NameOf.$$v ?= $$v))
$1.NameOf.Project.Name = PROJECT_NAME
$1.NameOf.Project.Version = PROJECT_VERSION
$$(if $(ZMK.IsOutOfTreeBuild),$$(eval $$(call ZMK.Expand,Directory,$$(CURDIR)/$$(dir $1))))
$$(if $(ZMK.IsOutOfTreeBuild),$$(CURDIR)/)$1: $$(ZMK.OutOfTreeSourcePath)$1.in | $$(if $(ZMK.IsOutOfTreeBuild),$$(CURDIR)/)$$(dir $1)
$$(if $$(ZMK.IsOutOfTreeBuild),$$(eval $$(call ZMK.Expand,Directory,$$(CURDIR)/$$(dir $1))))
$$(if $$(ZMK.IsOutOfTreeBuild),$$(CURDIR)/$1) $1: $$(ZMK.OutOfTreeSourcePath)$1.in $$(if $$(value Configure.Configured),config.$$(Project.Name).mk) | $$(if $$(ZMK.IsOutOfTreeBuild),$$(CURDIR)/)$$(patsubst %/,%,$$(dir $1))
$$(call Silent.Say,SED,$$@)
$$(Silent.Command)$$(strip sed $$(foreach v,$$($1.Variables), -e 's!@$$($1.NameOf.$$v)@!$$($$v)!g') $$< >$$@)
$$(eval $$(call ZMK.Expand,AllClean,$$(if $(ZMK.IsOutOfTreeBuild),$$(CURDIR)/)$1))
$$(eval $$(call ZMK.Expand,AllClean,$1))
endef
......@@ -10,7 +10,7 @@ Go.GoConst.Options ?=
# from the command below.
.PHONY: static-check-go-goconst
static-check-go-goconst:
$(strip $(Go.GoConst.Cmd) $(Go.GoConst.Options) -set-exit-status ./...)
$(if $(ZMK.IsOutOfTreeBuild),cd $(ZMK.SrcDir) && )$(strip $(Go.GoConst.Cmd) $(Go.GoConst.Options) -set-exit-status ./...)
# Run "goconst" when running static checks, but only when installed.
# You can install this tool by following instructions on https://github.com/jgautheron/goconst
......
......@@ -8,7 +8,7 @@ Go.GoErrCheck.Options ?=
.PHONY: static-check-go-errcheck
static-check-go-errcheck:
$(strip $(Go.GoErrCheck.Cmd) $(Go.GoErrCheck.Options) $(Go.ImportPath)/...)
$(if $(ZMK.IsOutOfTreeBuild),cd $(ZMK.SrcDir) && )$(strip $(Go.GoErrCheck.Cmd) $(Go.GoErrCheck.Options) $(Go.ImportPath)/...)
# Run "errcheck" when running static checks, but only when installed.
# You can install this tool by following instructions on https://github.com/kisielk/errcheck
......
......@@ -8,7 +8,7 @@ Go.GoIneffAssign.Options ?=
.PHONY: static-check-go-ineffassign
static-check-go-ineffassign:
$(strip $(Go.GoIneffAssign.Cmd) $(Go.GoIneffAssign.Options) $(Go.ImportPath)/...)
$(if $(ZMK.IsOutOfTreeBuild),cd $(ZMK.SrcDir) && )$(strip $(Go.GoIneffAssign.Cmd) $(Go.GoIneffAssign.Options) $(Go.ImportPath)/...)
# Run "ineffassign" when running static checks, but only when installed.
# You can install this tool by following instructions on https://github.com/gordonklaus/ineffassign
......
......@@ -8,7 +8,7 @@ Go.GoStaticCheck.Options ?=
.PHONY: static-check-go-staticcheck
static-check-go-staticcheck:
$(strip $(Go.GoStaticCheck.Cmd) $(Go.GoStaticCheck.Options) $(Go.ImportPath)/...)
$(if $(ZMK.IsOutOfTreeBuild),cd $(ZMK.SrcDir) && )$(strip $(Go.GoStaticCheck.Cmd) $(Go.GoStaticCheck.Options) $(Go.ImportPath)/...)
# Run "staticcheck" when running static checks, but only when installed.
# You can install this tool by following instructions on https://staticcheck.io/docs/install
......
......@@ -9,7 +9,7 @@ Go.GoWsl.Options ?=
# Note that wsl doesn't handle full import path, it's therefore omitted from the command below.
.PHONY: static-check-go-wsl
static-check-go-wsl:
$(strip $(Go.GoWsl.Cmd) $(Go.GoWsl.Options) ./...)
$(if $(ZMK.IsOutOfTreeBuild),cd $(ZMK.SrcDir) && )$(strip $(Go.GoWsl.Cmd) $(Go.GoWsl.Options) ./...)
# Run "wsl" when running static checks, but only when installed.
# You can install this tool by following instructions on https://github.com/bombsimon/wsl
......
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Huawei Inc.
Go.Cmd ?= go
Go.TestOptions ?= -race
Go.Sources ?= $(patsubst $(ZMK.SrcDir)/%,%,$(shell find $(ZMK.SrcDir) -name '*.go' -o -name go.mod -o -name go.sum))
Go.ImportPath ?= $(error Define Go.ImportPath to the import path of the project)
Go.Path ?= $(shell go env GOPATH)
Go.Path ?= $(shell $(Go.Cmd) env GOPATH)
# Run "go test" when running checks.
check:: check-go-test
.PHONY: check-go-test
check-go-test:
go test $(Go.ImportPath)/...
$(if $(ZMK.IsOutOfTreeBuild),cd $(ZMK.SrcDir) && )$(Go.Cmd) test $(Go.TestOptions) $(Go.ImportPath)/...
# Run "go vet" when running static checks.
static-check:: static-check-go-vet
.PHONY: static-check-go-vet
static-check-go-vet:
go vet $(Go.ImportPath)/...
$(if $(ZMK.IsOutOfTreeBuild),cd $(ZMK.SrcDir) && )$(Go.Cmd) vet $(Go.ImportPath)/...
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Huawei Inc.
PkgConfig.Cmd ?= $(shell command -v pkg-config 2>/dev/null)
PkgConfig.atLeastPkgConfigVersion = 0.29
ifeq (,$(PkgConfig.Cmd))
$(error pkg-config is not available in PATH, install it or pass PkgConfig.Cmd= to make)
endif
ifeq (,$(shell $(PkgConfig.Cmd) --atleast-pkgconfig-version=$(PkgConfig.atLeastPkgConfigVersion) 2>/dev/null && echo ok))
$(error $(PkgConfig.Cmd) is too old, version $(PkgConfig.atLeastPkgConfigVersion) is required, you have $(shell $(PkgConfig.Cmd) --version))
endif
define PkgConfig.moduleStatusScript
if $(PkgConfig.Cmd) --atleast-version=$2 $1; then
echo "sufficient";
else
if $(PkgConfig.Cmd) --exists $1; then
echo "outdated";
else
echo "missing";
fi;
fi;
endef
PkgConfig.Variables = AtLeastVersion Variables
define PkgConfig.Template
$1.AtLeastVersion ?= $$(error define $1.AtLeastVersion - the required version of the module)
$1.Variables ?=
PkgConfig.Modules.$1.Status ?= $$(shell $$(call PkgConfig.moduleStatusScript,$1,$$($1.AtLeastVersion)))
ifneq (missing,$$(PkgConfig.Modules.$1.Status))
PkgConfig.Modules.$1.Version ?= $$(shell $$(PkgConfig.Cmd) $1 --silence-errors --modversion))
PkgConfig.Modules.$1.Cflags ?= $$(shell $$(PkgConfig.Cmd) $1 --silence-errors --cflags))
PkgConfig.Modules.$1.CflagsOnlyI ?= $$(shell $$(PkgConfig.Cmd) $1 --silence-errors --cflags-only-I))
PkgConfig.Modules.$1.CflagsOnlyOther ?= $$(shell $$(PkgConfig.Cmd) $1 --silence-errors --cflags-only-other))
PkgConfig.Modules.$1.Libs ?= $$(shell $$(PkgConfig.Cmd) $1 --silence-errors --libs))
PkgConfig.Modules.$1.LibsOnlyLowerL ?= $$(shell $$(PkgConfig.Cmd) $1 --silence-errors --libs-only-l))
PkgConfig.Modules.$1.LibsOnlyL ?= $$(shell $$(PkgConfig.Cmd) $1 --silence-errors --libs-only-L))
PkgConfig.Modules.$1.LibsOnlyOther ?= $$(shell $$(PkgConfig.Cmd) $1 --silence-errors --libs-only-other))
$$(foreach v,$$($1.Variables),$$(eval PkgConfig.Modules.$1.Variables.$$(v) ?= $$(shell $$(PkgConfig.Cmd) $1 --variable $$(v) 2>/dev/null)))
endif
endef
......@@ -12,4 +12,4 @@ endif
.PHONY: static-check-reuse
static-check-reuse:
cd $(ZMK.SrcDir) && $(Reuse.Cmd) lint
$(if $(ZMK.IsOutOfTreeBuild),cd $(ZMK.SrcDir) && )$(Reuse.Cmd) lint
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Huawei Inc.
Spread.Cmd ?= $(strip $(shell command -v spread 2>/dev/null))
Spread.Cmd ?= SPREAD_QEMU_KVM=$(if $(wildcard /dev/kvm),1,0) $(strip $(shell command -v spread 2>/dev/null))
Spread.TaskFilter ?= $(if $(value T),$(T))
Spread.Suites ?= $(error Define Spread.SuitesDir to a list of directories containing spread test suites)
Spread.Sources ?= spread.yaml $(patsubst $(ZMK.SrcDir)/%,%,$(foreach suite,$(Spread.Suites),$(shell find $(ZMK.SrcDir)/$(suite) -type f -o -type l)))
......@@ -9,7 +9,7 @@ Spread.Options ?=
.PHONY: check-spread
check-spread:
cd $(ZMK.SrcDir) && $(Spread.Cmd) $(if $(value D),-debug) $(Spread.Options)
$(if $(ZMK.IsOutOfTreeBuild),cd $(ZMK.SrcDir) && )$(Spread.Cmd) $(if $(value D),-debug) $(Spread.Options)
ifneq (,$(Spread.Cmd))
check:: check-spread
......
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Huawei Inc.
systemd.AtLeastVersion = 244
# There are versions of systemd which provide systemd_system_unit_dir and there
# are some that only provide that variable without any _. Use the more
# compatible version.
systemd.Variables = systemdsystemunitdir systemduserunitdir
$(eval $(call ZMK.Expand,PkgConfig,systemd))
ifneq ($(PkgConfig.Modules.systemd.Status),sufficient)
$(error pkg-config package for systemd is $(PkgConfig.Modules.systemd.Status))
endif
SystemdUnit.Variables = IsUser InstallDir
define SystemdUnit.Template
$1.IsUser ?=
$1.systemdUnitVarName = systemd$$(if $$($1.IsUser),user,system)unitdir
$1.InstallDir ?= $$(or $$(PkgConfig.Modules.systemd.Variables.$$($1.systemdUnitVarName)),$$(error pkg-conifg variable $$($1.systemdUnitVarName) for module systemd is undefined or empty))
$$(eval $$(call ZMK.Expand,InstallUninstall,$1))
endef
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
......@@ -8,7 +8,10 @@ Configure.LicenseIdentifier = Apache-2.0
Configure.CopyrightText = Huawei Inc.
include z.mk
$(if $(value ZMK.Version),,$(error The project depends on zmk -- Get it from https://github.com/zyga/zmk;))
$(if $(value ZMK.Version),,$(error The project depends on zmk -- Get it from https://github.com/zyga/zmk or ./get-zmk.sh;))
$(eval $(call ZMK.Import,Directories))
$(eval $(call ZMK.Import,Configure))
# Load hot-fix for issue related to symlinks.
include $(ZMK.SrcDir)/.zmk-hotfixes/zmk-hotfix-80.mk
......@@ -31,11 +34,8 @@ endif
endif
endef
$(eval $(call ZMK.Import,Directories))
$(eval $(call ZMK.Import,Configure))
# Go support.
Go.ImportPath = git.ostc-eu.org/OSTC/OHOS/components/sysota
Go.ImportPath = gitlab.com/zygoon/sysota
$(eval $(call ZMK.Import,Go))
# Go static analysis and code style tools.
......@@ -51,10 +51,12 @@ $(eval $(call ZMK.Import,Cspell))
# Spread system tests.
Spread.Suites = \
boot/piboot/tests \
cmd/sysotad/tests \
man/tests \
rauc/tests
boot/piboot/spread.suite \
boot/grub/spread.suite \
cmd/spread.suite \
man/spread.suite \
ota/statehandler/spread.suite \
rauc/spread.suite
Spread.TaskFilter = qemu:$(if $(value T),$(T))
Spread.Options = -v -reuse -resend $(Spread.TaskFilter)
$(eval $(call ZMK.Import,Spread))
......@@ -67,6 +69,9 @@ $(Project.Name)-$(Project.Version).tar.gz.Files += \
$(Go.Sources) \
$(Reuse.Sources) \
$(Spread.Sources) \
tests/bin/MATCH \
tests/bin/NOMATCH \
tests/lib/rauc.sh \
$(wildcard $(ZMK.SrcDir)/.zmk-hotfixes/*.mk) \
$(wildcard $(ZMK.SrcDir)/.zmk-modules/*.mk) \
$(wildcard $(ZMK.SrcDir)/doc/adr/*.md) \
......@@ -75,50 +80,76 @@ $(Project.Name)-$(Project.Version).tar.gz.Files += \
Makefile \
README.md \
cspell.json \
data/dbus-1/system-services/dev.ostc.sysota1.service \
data/dbus-1/system.d/dev.ostc.sysota1.conf \
data/dbus-1/system-services/org.oniroproject.sysota1.service \
data/dbus-1/system.d/org.oniroproject.sysota1.conf \
data/systemd/system/sysotad.service.in \
man/sysota.state.ini.5.in \
man/sysotad.conf.5.in
$(eval $(call ZMK.Expand,Tarball.Src,$(Project.Name)-$(Project.Version).tar.gz))
# D-Bus configuration
data/dbus-1/system-services/dev.ostc.sysota1.service.InstallDir = $(datadir)/dbus-1/system-services
$(eval $(call ZMK.Expand,InstallUninstall,data/dbus-1/system-services/dev.ostc.sysota1.service))
data/dbus-1/system.d/dev.ostc.sysota1.conf.InstallDir = $(datadir)/dbus-1/system.d
$(eval $(call ZMK.Expand,InstallUninstall,data/dbus-1/system.d/dev.ostc.sysota1.conf))
data/dbus-1/system-services/org.oniroproject.sysota1.service.InstallDir = $(datadir)/dbus-1/system-services
$(eval $(call ZMK.Expand,InstallUninstall,data/dbus-1/system-services/org.oniroproject.sysota1.service))
data/dbus-1/system.d/org.oniroproject.sysota1.conf.InstallDir = $(datadir)/dbus-1/system.d
$(eval $(call ZMK.Expand,InstallUninstall,data/dbus-1/system.d/org.oniroproject.sysota1.conf))
# Systemd configuration
data/systemd/system/sysotad.service.Variables=libexecdir
$(eval $(call ZMK.Expand,DataInOut,data/systemd/system/sysotad.service))
data/systemd/system/sysotad.service.InstallDir = $(libdir)/systemd/system
$(eval $(call ZMK.Expand,InstallUninstall,data/systemd/system/sysotad.service))
# Program: sysotad
cmd/sysotad/sysotad: $(Go.Sources)
go build -o $@ $(Go.ImportPath)/$(dir $@)
$(eval $(call ZMK.Expand,AllClean,cmd/sysotad/sysotad))
cmd/sysotad/sysotad.InstallDir = $(libexecdir)/sysota
cmd/sysotad/sysotad.InstallMode = 755
$(eval $(call ZMK.Expand,InstallUninstall,cmd/sysotad/sysotad))
$(eval $(call ZMK.Expand,SystemdUnit,data/systemd/system/sysotad.service))
# Program: sysota-mux
$(if $(ZMK.IsOutOfTreeBuild),$(eval $(call ZMK.Expand,Directory,$(CURDIR)/$(dir cmd/sysota-mux))))
cmd/sysota-mux/sysota-mux: $(Go.Sources) | $(if $(ZMK.IsOutOfTreeBuild),$(CURDIR)/)$(patsubst %/,%,$(dir cmd/sysota-mux))
$(if $(ZMK.IsOutOfTreeBuild),cd $(ZMK.SrcDir) && )$(Go.Cmd) build -o $(if $(ZMK.IsOutOfTreeBuild),$(CURDIR)/)$@ $(Go.ImportPath)/$(dir $@)
$(eval $(call ZMK.Expand,AllClean,cmd/sysota-mux/sysota-mux))
cmd/sysota-mux/sysota-mux.InstallDir = $(libexecdir)/sysota
cmd/sysota-mux/sysota-mux.InstallMode = 755
$(eval $(call ZMK.Expand,InstallUninstall,cmd/sysota-mux/sysota-mux))
# Program: tests/lib/rauc.sh
tests/lib/rauc.sh.InstallDir = noinst
tests/lib/rauc.sh.Interpreter = sh
$(eval $(call ZMK.Expand,Script,tests/lib/rauc.sh))
# Manual pages.
$(eval $(call ZMK.Expand,DataInOut,man/sysotad.conf.5))
$(eval $(call ZMK.Expand,ManPage,man/sysotad.conf.5))
$(eval $(call ZMK.Expand,DataInOut,man/sysota.state.ini.5))
$(eval $(call ZMK.Expand,ManPage,man/sysota.state.ini.5))
# Symlink: rauc-pre-install-handler -> sysotad
cmd/sysotad/rauc-pre-install-handler.InstallDir = $(cmd/sysotad/sysotad.InstallDir)
cmd/sysotad/rauc-pre-install-handler.SymlinkTarget = sysotad
$(eval $(call ZMK.Expand,Symlink,cmd/sysotad/rauc-pre-install-handler))
# Symlink: rauc-post-install-handler -> sysotad
cmd/sysotad/rauc-post-install-handler.InstallDir = $(cmd/sysotad/sysotad.InstallDir)
cmd/sysotad/rauc-post-install-handler.SymlinkTarget = sysotad
$(eval $(call ZMK.Expand,Symlink,cmd/sysotad/rauc-post-install-handler))
# Symlink: rauc-custom-boot-handler -> sysotad
cmd/sysotad/rauc-custom-boot-handler.InstallDir = $(cmd/sysotad/sysotad.InstallDir)
cmd/sysotad/rauc-custom-boot-handler.SymlinkTarget = sysotad
$(eval $(call ZMK.Expand,Symlink,cmd/sysotad/rauc-custom-boot-handler))
$(eval $(call ZMK.Expand,DataInOut,man/sysota.boot-protocol.7))
$(eval $(call ZMK.Expand,ManPage,man/sysota.boot-protocol.7))
$(eval $(call ZMK.Expand,DataInOut,man/sysota.grub.7))
$(eval $(call ZMK.Expand,ManPage,man/sysota.grub.7))
# Symlink: sysotad -> sysota-mux
cmd/sysota-mux/sysotad.InstallDir = $(cmd/sysota-mux/sysota-mux.InstallDir)
cmd/sysota-mux/sysotad.SymlinkTarget = sysota-mux
$(eval $(call ZMK.Expand,Symlink,cmd/sysota-mux/sysotad))
# Symlink: sysotactl -> sysota-mux
cmd/sysota-mux/sysotactl.InstallDir = $(bindir)
cmd/sysota-mux/sysotactl.SymlinkTarget = $(cmd/sysota-mux/sysota-mux.InstallDir)/sysota-mux
$(eval $(call ZMK.Expand,Symlink,cmd/sysota-mux/sysotactl))
# Symlink: rauc-pre-install-handler -> sysota-mux
cmd/sysota-mux/rauc-pre-install-handler.InstallDir = $(cmd/sysota-mux/sysota-mux.InstallDir)
cmd/sysota-mux/rauc-pre-install-handler.SymlinkTarget = sysota-mux
$(eval $(call ZMK.Expand,Symlink,cmd/sysota-mux/rauc-pre-install-handler))
# Symlink: rauc-post-install-handler -> sysota-mux
cmd/sysota-mux/rauc-post-install-handler.InstallDir = $(cmd/sysota-mux/sysota-mux.InstallDir)
cmd/sysota-mux/rauc-post-install-handler.SymlinkTarget = sysota-mux
$(eval $(call ZMK.Expand,Symlink,cmd/sysota-mux/rauc-post-install-handler))
# Symlink: rauc-custom-boot-handler -> sysota-mux
cmd/sysota-mux/rauc-custom-boot-handler.InstallDir = $(cmd/sysota-mux/sysota-mux.InstallDir)
cmd/sysota-mux/rauc-custom-boot-handler.SymlinkTarget = sysota-mux
$(eval $(call ZMK.Expand,Symlink,cmd/sysota-mux/rauc-custom-boot-handler))
# The entr-check% family of targets runs tests continuously, as the code is
# modified. The set of dependencies is the same as the set of files for the
# project tarball. This is an imperfect but practical simplification.
.PHONY: entr-check%
entr-check-go-test entr-check: entr-check%: $(sort $($(Project.Name)-$(Project.Version).tar.gz.Files))
echo $^ | tr ' ' '\n' | entr -c $(MAKE) check$*
......@@ -7,18 +7,35 @@ SPDX-FileCopyrightText: Huawei Inc.
System OTA is a robust, unattended update system for Linux Gateways, suitable
for home automation gateways and other devices where reliability is paramount.
## OSTC Forum
# Architecture Overview
This component is being designed and discussed on the OSTC Forum
https://forum.ostc-eu.org/t/over-the-air-updates-ota/28/
The update system is comprised of the following elements:
- Immutable file system used as rootfs with:
- Provisions for maintaining state of select files and directories.
- RAUC pre-installed and pre-configured for storage slots.
- SysOTA pre-installed and pre-configured for the boot loader, update server
and package name.
- Shared or dedicated[1] NetOTA server providing update meta-data.
- Shared or dedicated public storage server for storing image blobs.
Shared or dedicated in the sense that either a special purpose installation or
a shared installation used by many different device types, operators and
manufacturers are both allowed by the system.
## Development
This is a standard go project. Use `go get
git.ostc-eu.org/OSTC/OHOS/components/sysota` to get it. Once in the resulting
directory under `$GOPATH`, typically
`~/go/src/git.ostc-eu.org/OSTC/OHOS/components/sysota` run `go test ./...` to
run unit tests. There are no integration tests yet.
This is a somewhat typical Go and `make` project. You can use plain `go` to
build and test most things. For a more complete experience, including to access
the set of integration tests and various static analysis tools, you should
install a few more dependencies:
- `make`
- `zmk`
- `reuse`
- `spread`
Running `make` will build everything. There's a build-time configuration system.
To create the `configure` script run `make configure`.
To try the service out in practice you may want to do this though:
......@@ -48,13 +65,74 @@ Remember that `uninstall` is stateless, if you want to rename a file, first
## Testing
The project has a combination of unit tests, available through the standard go
interface, and integration tests implemented with spread.
interface, and integration tests implemented with spread. To run all kinds of
tests invoke `make check`. This will skip and report tests that depend on tools
you do not have locally.
Please try not to send patches which regress the test suite.
## Go Unit Tests
There's a wide range of standard Go unit tests available. To execute those
simply run:
To execute unit tests run:
``` shell
go test ./...
```
## Go Static Analysis
SystemOTA uses a wide array of Go static analysis tools, including the standard
`go vet` as well as the third-party: `staticcheck`, `goconst`, `errcheck`, `wsl`
and `ineffassign`.
All those checks are integrated into `make check` and `make static-check`. The
precise goals for each individual tool can be discovered by tab-completing `make
static-check-go-`.
The tools are usually not packaged so you should install them directly. Assuming
you are using Go 1.16+ you can do that with with:
``` shell
go install honnef.co/go/tools/cmd/staticcheck@latest
go install github.com/jgautheron/goconst/cmd/goconst@latest
go install github.com/kisielk/errcheck@latest
go install github.com/bombsimon/wsl/v3/...@latest
go install github.com/gordonklaus/ineffassign@latest
```
## REUSE compliance checks
REUSE is a legal compliance toolchain which, among others, ensures that each
file is accompanied by a machine readable copyright and license.
REUSE checks are integrated into `make check` and `make static-check`. The
precise goal is `make static-check-reuse`.
The REUSE toolchain can be installed from the system packager (usually something
like `python3-reuse`) or with `pip` by running:
``` shell
pip install reuse
```
## Spell checker
SystemOTA uses a `cspell` based spell checker. The same spell checker, along
with the exception database, can be used from Visual Studio Code and from
command line. The list of known exceptions is kept in the file `cspell.json`.
The spell checker is integrated into `make check` and `make static-check`. The
precise goals `make static-cspell-lint`.
To install the `cspell` with `npm` by running:
``` shell
npm install --global cspell
```
## Spread system checks
To execute integration tests you will need a working installation of `spread`
and `lxd` or `qemu`. Currently Qemu is preferred, as it allows performing mount
operations inside the virtual machine. GitLab CI also uses `qemu` as LXD cannot
......@@ -80,7 +158,14 @@ or virtual machine, with all the build dependencies and cache, around.
## Packaging
While there is no official packaging yet, the build system does support the
standard `configure --prefix=/usr && make && sudo make install` combo.
If you are looking at packaging, the typical `./configure --prefix=/usr && make
&& make install` trio should do the trick but for a real installation you will
need to configure SystemOTA and RAUC inside your operating system image, at least
to select the boot loader and to describe the partition layout to RAUC.
You may want to enable the `sysotad.service` systemd unit after installation.
### Yocto meta-layers
There's an official meta-layer with SystemOTA in the Oniro repository at
https://booting.oniroproject.org/distro/oniro/ in the `meta-oniro-core` layer.