Skip to content
Commits on Source (32)
......@@ -31,7 +31,7 @@ variables:
# - CI_SSHFS_PRIVATE_KEY
.build:
stage: build
image: quay.io/os-forge/rpm-ostree-engine:0.6.0
image: quay.io/os-forge/rpm-ostree-engine:0.6.5
before_script:
- if [ -z "$CI_SSHFS_TARGET" ]; then rose-ci-prepare sshfs --sshfs-target="$CI_SSHFS_TARGET" --sshfs-auth="$CI_SSHFS_AUTH" --sshfs-path="$CI_SSHFS_PATH" --sshfs-key="$CI_SSHFS_PRIVATE_KEY"; fi
script:
......@@ -61,7 +61,7 @@ variables:
# - CI_IMAGE_BUILD_OPTIONS
.image:
stage: image
image: quay.io/os-forge/rpm-ostree-engine:0.6.0
image: quay.io/os-forge/rpm-ostree-engine:0.6.5
before_script:
# Prepare loop devices for image build
- for i in `seq 0 7`; do mknod /dev/loop$i b 7 $i || :; done
......@@ -84,27 +84,27 @@ variables:
.check:
stage: check
variables:
SSH_TIMEOUT_SEC: 300
SSH_RETRIES_NUM: 10
image: quay.io/os-forge/rpm-ostree-engine:0.6.0
ROSE_SPAWN_OFF_TIMEOUT_SEC: 300
ROSE_GUEST_SSH_TIMEOUT_SEC: 300
ROSE_GUEST_SSH_RETRIES_NUM: 10
image: quay.io/os-forge/rpm-ostree-engine:0.6.5
artifacts:
expire_in: 28 days
when: always
paths:
- varfiles.tar
- logs/*
- ./varfiles.tar
- ./logs/*
.check-install:
extends: .check
before_script:
- for i in `seq 0 7`; do mknod /dev/loop$i b 7 $i || :; done
- rose-shell --image="$IMAGE_NAME" -- /rpm-ostree-engine/step-scripts/prepare.sh
- rose-shell --image="$IMAGE_NAME" -- /rpm-ostree-engine/image-scripts/prepare
script:
- rose-check --image="$IMAGE_NAME" --memory=512 --arch="$CI_OSTREE_REF_ARCH" --workdir=./logs/running/
-- /rpm-ostree-engine/test-scripts/test.sh running
- rose-check --image="$IMAGE_NAME" --memory=512 --arch="$CI_OSTREE_REF_ARCH" -- /rpm-ostree-engine/guest-scripts/running
after_script:
- rose-shell --image="$IMAGE_NAME" -- /rpm-ostree-engine/step-scripts/collect.sh
- for logs in ./logs/*; do echo "${logs}:"; cat "${logs}/summary.txt"; done
- rose-shell --image="$IMAGE_NAME" -- /rpm-ostree-engine/image-scripts/collect
- cat ./logs/history.txt
cache:
- key: "image-latest-$CI_COMMIT_REF_SLUG-$CI_OSTREE_REF_ARCH"
policy: pull
......@@ -116,17 +116,15 @@ variables:
before_script:
- test -f "$IMAGE_NAME" || exit 99
- for i in `seq 0 7`; do mknod /dev/loop$i b 7 $i || :; done
- rose-shell --image="$IMAGE_NAME" -- /rpm-ostree-engine/step-scripts/prepare.sh
- rose-shell --image="$IMAGE_NAME" -- /rpm-ostree-engine/step-scripts/implant.sh ./.intermediate-repo
- rose-shell --image="$IMAGE_NAME" -- /rpm-ostree-engine/image-scripts/prepare
- rose-shell --image="$IMAGE_NAME" -- /rpm-ostree-engine/image-scripts/implant ./.intermediate-repo
script:
- rose-check --image="$IMAGE_NAME" --memory=512 --arch="$CI_OSTREE_REF_ARCH" --workdir=./logs/upgrade/
-- /rpm-ostree-engine/test-scripts/test.sh upgrade
- rose-check --image="$IMAGE_NAME" --memory=512 --arch="$CI_OSTREE_REF_ARCH" --workdir=./logs/running/
-- /rpm-ostree-engine/test-scripts/test.sh running
- rose-check --image="$IMAGE_NAME" --memory=512 --arch="$CI_OSTREE_REF_ARCH" -- /rpm-ostree-engine/guest-scripts/upgrade
- rose-check --image="$IMAGE_NAME" --memory=512 --arch="$CI_OSTREE_REF_ARCH" -- /rpm-ostree-engine/guest-scripts/running
after_script:
- test -f "$IMAGE_NAME" || exit 99
- rose-shell --image="$IMAGE_NAME" -- /rpm-ostree-engine/step-scripts/collect.sh
- for logs in ./logs/*; do echo "${logs}:"; cat "${logs}/summary.txt"; done
- rose-shell --image="$IMAGE_NAME" -- /rpm-ostree-engine/image-scripts/collect
- cat ./logs/history.txt
allow_failure:
exit_codes: 99
cache:
......@@ -148,7 +146,7 @@ variables:
# - CI_SSHFS_PRIVATE_KEY
.yield:
stage: yield
image: quay.io/os-forge/rpm-ostree-engine:0.6.0
image: quay.io/os-forge/rpm-ostree-engine:0.6.5
before_script:
- rose-ci-prepare sshfs --sshfs-target="$CI_SSHFS_TARGET" --sshfs-auth="$CI_SSHFS_AUTH" --sshfs-path="$CI_SSHFS_PATH" --sshfs-key="$CI_SSHFS_PRIVATE_KEY"
script:
......@@ -194,7 +192,7 @@ variables:
# - CI_GPG_KEY_ID
.deltas:
stage: deltas
image: quay.io/os-forge/rpm-ostree-engine:0.6.0
image: quay.io/os-forge/rpm-ostree-engine:0.6.5
before_script:
- rose-ci-prepare sshfs --sshfs-target="$CI_SSHFS_TARGET" --sshfs-auth="$CI_SSHFS_AUTH" --sshfs-path="$CI_SSHFS_PATH" --sshfs-key="$CI_SSHFS_PRIVATE_KEY"
script:
......
......@@ -13,8 +13,18 @@ stages:
- tag
- release
workflow:
rules:
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
when: never
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
when: never
- if: '$CI_COMMIT_BRANCH'
- if: '$CI_COMMIT_TAG'
variables:
CI_REGISTRY_IMAGE_VERSION: "0.6.0"
CI_REGISTRY_IMAGE_VERSION: "0.6.5"
CI_ADD_TEST: "1"
CI_CONTAINER_BUILD: ""
......@@ -181,7 +191,6 @@ test-check-upgrade-x86_64:
- .test-local
needs:
- test-build-x86_64
- test-image-x86_64
##
# Expire the test artifacts fast, we'll be building a lot of them
......@@ -252,7 +261,6 @@ test-check-upgrade-aarch64:
- .test-local
needs:
- test-build-aarch64
- test-image-aarch64
##
# Expire the test artifacts fast, we'll be building a lot of them
......@@ -304,5 +312,3 @@ gitlab-release:
--tag-name "v${RELEASE_VERSION}" --ref $CI_COMMIT_SHA
rules:
- if: $CI_COMMIT_TAG
needs:
- container-manifest
FROM docker.io/library/fedora:34
ENV RELEASE_VERSION=0.6.5
RUN dnf -y upgrade && \
dnf -y install ostree rpm-ostree \
selinux-policy selinux-policy-targeted policycoreutils unzip \
qemu-kvm qemu-kvm-core qemu-system-aarch64 qemu-system-x86 openssh-clients sshpass \
qemu-kvm qemu-kvm-core qemu-system-aarch64 qemu-system-x86 openssh-clients sshpass nc \
dosfstools e2fsprogs parted \
gnupg ykclient ykpers \
iputils \
......
# Tooling
## Console and guest script or command modes of guest machines
The `rose-spawn` and `rose-check` scripts provide a way to spawn a guest virtual machine with custom OS image.
Generally there are two modes of invocation:
- Console mode -- attach directly to a serial console of spawned virtual machine
- Guest execute mode -- spawns a virtual machine in background and execute arbitrary user script or command in foreground
There are slight changes in invocation of those two modes:
Instead of passing (or not) `--console` option to `rose-check` the mode to use
is now auto-detected by the presense of extra command line to execute, i.e.:
Run in console mode:
```
$ rose-check
$ rose-check --
```
Run in guest execute mode:
```
$ rose-check -- sleep inf
$ rose-check -- ssh -p 2222 localhost -- sleep inf
```
The `--console` option is kept for compatibility and let to forcibly run in console mode even if extra command line passed:
```
$ rose-check --console
$ rose-check --console -- /doesnt/make/sense
```
In previous releases `rose-spawn` was just a wrapper of `rose-check` to forcibly run `--console` mode without an option.
Now both of `rose-spawn` and `rose-check` act the same in terms of console and guest execute modes.
However there are still a bit difference between them.
The `rose-spawn` doesn't perform any logging by default whereas `rose-check` does.
### Unification of logging for console and execute modes
Most aspects of console and guest execute modes were unified with recent changes.
Such as collecting serial console messages to a logfile and suppressing serial console output.
In order to spawn a virtual machine and attach to it directly but suppress any output from serial console run:
```
rose-spawn --no-tty
```
It could helpful to run guest machine in background independently of guest scripts with optional logging enabled.
Note however that suppressing serial console output doesn't affect collecting of serial console messages to a logfile.
## Command to run scripts in qemu guests
The primary scenario for the guest execute mode of `rose-spawn`/`rose-check`
is to run a sequence of commands on a guest side employing SSH connection.
A sequence of commands alternatively could be expressed as a script to be copied to a guest and then executed.
Some constructs for the scenario were introduced in previous releases as a part of custom test scripts,
notably `test.sh` executable, `testlib.sh` source file and pair of helpers -- to ensure guest is alive and to shutdown guest.
The functionality has been reworked to be a part of tooling scripts and most of it is now provided by the `rose-guest` script.
The script awaits for guest machine to be alive and then connects to it via SSH protocol to execute custom commands.
Optionally the script copies local files to the guest machine and cleans up them after the executed of custom command, i.e.:
Run `echo test` on a guest side:
```
$ rose-guest -- echo test
```
Run custom script on a guest side:
```
$ rose-guest --files=/path/to/my-script -- ./my-script
```
All of the files specified via `--files=` option are copied to a temporary directory on a guest system using `scp` protocol.
The `--files` option could be specified multiple times if additional files could be required for a script execution, i.e.:
```
$ rose-guest --files=/path/to/my-script --files=/path/to/other-files -- ./my-script ./other-files
```
Without extra command line the `rose-guest` command runs interactive shell on a guest side:
```
$ rose-guest
```
The `rose-guest` script relies on environment variables -- `ROSE_GUEST_SSH_HOST`/`ROSE_GUEST_SSH_PORT`/`ROSE_GUEST_SSH_USER`.
Defaults are set to `root@localhost:2222` which are the configuration used by `rose-check`/`rose-spawn` by default.
The functionality of `isalive` helper is now also handled by `rose-guest` script.
Running arbitrary guest script or command should employ isalive checks and awaiting.
But it's possible to use isalive check and awaiting in standalone mode using either trivial command or `--alive` option:
```
$ rose-guest -- :
$ rose-guest --alive
```
The environment variables to manage ssh connection timeout and connection retries
are renamed accordingly to `ROSE_GUEST_SSH_TIMEOUT_SEC` and `ROSE_GUEST_SSH_RETRIES_NUM`.
As compared to previously used `test.sh`/`testlib.sh` approach the current command could not be used as a shell source file.
Also there is no currently standalone command/function to permanently copy files to a guest machine. The workaround is:
```
$ rose-guest --files=/path/to/my-files -- mv -f ./my-files /permanent/guest/location/
```
## Renaming of helper script directories
The directories for `test-script` and `step-scripts` were renamed to better suit their usage and be more intuitve.
Scripts used over mounted sysroot with `rose-shell` command previously named `step-script` now renamed to `image-scripts`.
Scripts user over spawned vm guest with `rose-check` command previously named `test-scripts` now renamed to `guest-scripts`.
The latter also changes a usage semantics a bit to rely on `rose-guest` instead of `test.sh`/`testlib.sh`.
Indeed the `test.sh`/`testlib.sh` based scripts still could be used with `rose-spawn`/`rose-check`
but it could be required to manually set `ROSE_GUEST_WORK_DIR` option to specify resulting testcase logs location.
Given primary scenario to use with `rose-guest` to copy script to a guest and execute it on a guest side.
Usually the guest-script is a wrapper around `rose-guest` which specifies files to copy and command to execute.
Several standard scripts in `guest-scripts` directory effectively use same code.
I.e. consider wrapper name to be `.../running` and script to be copied and executed on guest-side: `.../running.guest`:
```
#/bin/bash --posix
. rose-default.sh
this="$0"
that="./$(basename "$0")"
rose-guest --files="$this.guest" -- "$that.guest" "$@"
```
## Guest cleanup and monitor based commands
### Handling guest shutdown by `rose-spawn`/`rose-check` scripts
In previous releases guest scripts were responsible to shutdown guest machines if needed passing shutdown commands over SSH.
Usually shutdowns were handled by `stopped` helper provided with `test.sh`/`testlib.sh` scripts.
However such a shutdown commands were still relying onto the QEMU functionality to detect if the system is really stopped.
With the recent changes shutdown logic is now incorporated into the `rose-spawn`/`rose-check` scripts.
Once the guest script or command terminated it's execution the guest machine started being spammed with ACPI shutdown events.
The `rose-spawn`/`rose-check` scripts then continiously check if the system has been stopped.
If the guest system hasn't been stopped for a specified amount of time the system is then halted unconditionally.
In case of unconditional halt take place the exit code of `rose-spawn`/`rose-check` should be set to `255`.
The clean shutdown timeout value is specified with `--timeout=...` command line option to `rose-spawn`/`rose-guest` scripts.
It specifies values in seconds. If zero value is passed there is no timeout and scripts should wait for system stop forever.
Alternatively timeout value could be specified with environment variable named `ROSE_SPAWN_OFF_TIMEOUT_SEC`.
It's still okay to invoke reboot or shutdown commands from a guest-side scripts but it's no longer recommended.
### Examine and control state options for QEMU guests
In order to manage the state of a spawned guest machine the `rose-spawn`/`rose-check` scripts provide a bunch of options.
All of those options operate using QEMU monitor socket residing in the directory where `rose-spawn`/`rose-check` were invoked:
- `--examine` -- tests if the guest machine was spawned. Returns zero if machine is running, non-zero otherwise.
- `--destroy` -- unconditionally halts he guest machine. Returns zero if machine was halted, non-zero otherwise.
- `--shutdown` -- perform a clean shutdown with timeout. Returns zero if machine was cleanly shut down, non-zero otherwise.
The behavior of `--shutdown` command resembles the shutdown procedure for guest execute mode with respect to timeout.
But it doesn't halt the system unconditionally. In order to do this `--destroy` option should be used.
The primary usage for those command is the examine/control of guest machine running in console mode,
i.e. in background or in a separate shell session. Given support for `--no-tty` option the user session could look like:
```
$ rose-spawn --console --no-tty &
$ rose-guest -- /path/to/command
$ rose-spawn --examine
$ rose-guest -- /path/to/command
$ rose-spawn --shutdown || rose-spawn --destroy
```
### Using direct qemu monitor connection
The `rose-spawn`/`rose-check` scripts provide `--monitor` option to connect to QEMU monitor directry.
The option is provided for a convenience and the same result could be achived by connecting to a UNIX socket `qemu.mon`
residing in invocation directory.
Same monitor socket is also used by cleanup code and examine/control modes of `rose-spawn`/`rose-check` scripts.
It should be noted that due to QEMU constraints monitor socket allows only one connection at a time and blocks others.
Thus long-lasting connection to a monitor should block all other monitor connections.
As a result cleanup code and examine/control modes of `rose-spawn`/`rose-check` scripts could suffer from such a connection.
Otherwise monitor connection is provided mostly for developer purposes and should be used with caution.
### Handling if vm is gone in guest scripts
For arbitrary user commands invoked as a guest script or command via `rose-spawn`/`rose-check` scripts
a guest script or command doesn't always get notified when VM is gone (i.e. shutdown or destroyed).
It's not an issue if a guest script or command uses ssh connection to run a script on a guest-side
or interacting with the guest machine via network using other means/protocols.
Usually in this case network disconnection causes guest script or command to interrupt it's exection.
I.e. invocation of scripts via `rose-guest` always leads to ssh connection and execute commands on a guest-side:
```
$ rose-spawn -- rose-guest
$ rose-spawn -- rose-guest -- sleep inf
```
Stopping the guest machine causes ssh connection to interrupt with exit code `255` produced by SSH client.
However if guest script or command doesn't effectively connect to a guest machine they could continue running,
i.e. following commands are executed on a host-side and are not interrupted if guest machine is gone:
```
$ rose-spawn -- /bin/sh
$ rose-spawn -- sleep inf
```
There is no change in behavior of `rose-spawn`/`rose-check` as compared to previous releases.
But introduced `--shutdown` and `--destroy` options provide a standard way of stopping guest machine
independently of guest script or command being in progress. It could be compared to power button pressed on a real machine.
Thus it's considered to be a resposibility of guest script or command to track the presence of guest machine if needed.
As a fallback the `rose-spawn`/`rose-check` commands provides `--exitsig[=SIG]` option disabled by default.
Once enabled `rose-spawn` should notify guest command or script process group with the signal (`INT` if not specified).
## Collecting logs from console and executed script or command
### Logging consolidation at `rose-spawn`/`rose-check` scripts
All the console and executed script or command logging is now consolidated at `rose-spawn`/`rose-check` scripts
as opposed to executed logs handled by `test.sh`/`testlib.sh` in previous releases.
There are no longer separate per-testcase logs as were collected by `test.sh`/`testlib.sh`.
Because usually the sequence was -- `isalive` helper testcase, general testcase, `stopped` helper testcase.
And now helpers functionality is handled by tooling, either on `rose-spawn` or `rose-guest` part.
As in previous releases the name of a logfile to collect messages from serial console is `bootlog.txt`.
Whereas the name of a logfile to collect messages from executed guest script or command is now `execlog.txt`.
It's not named like `testlog.txt` in order to denote that custom script or command is not always a test.
### Using `--logroot=` and `--logname=` option to sort out logs
Previous releases introduced the `upgrade` scenario which were implemented as two distinct `rose-check` invocations.
As a result in order to store logfiles for distinct `rose-check` invocations the `--workdir=...` option was introduced.
Also showing summary of both `rose-check` invocations required iteration over log directories to `cat ./summary.txt`.
In the current release the structure of logs has been reworked. As previously noted there is no per-testcase logs anymore.
But distinct `rose-check` invocation could be considered as a single testcase.
Recent changes introduce a term `logroot` and `logname`. Logroot is a toplevel directory to collect all the logs.
Logname is a subdirectory for a particular `rose-spawn`/`rose-check` invocation.
Summary log is now collected automatically by tooling and resides on logroot directory.
Same time the format of summary has been changed to provide more details and thus file is now named `history.txt`.
So if previously `upgrade` scenario was implemented as:
```
$ rose-check --workdir=./logs/upgrade -- .../rpm-ostree-engine/test-scripts/test.sh upgrade
$ rose-check --workdir=./logs/running -- .../rpm-ostree-engine/test-scripts/test.sh running
```
The resulting log structure was like:
```
logs/
upgrade/
summary.txt
bootlog.txt
test-isalive.txt
test-upgrade.txt
test-stopped.txt
running/
summary.txt
bootlog.txt
test-isalive.txt
test-running.txt
test-stopped.txt
```
and the consolidated contents of summaries were like:
```
$ for logs in ./logs/*; do echo "${logs}:"; cat "${logs}/summary.txt"; done
./logs/running:
test-isalive success 0
test-running success 0
test-stopped success 0
./logs/upgrade:
test-isalive success 0
test-upgrade success 0
test-stopped success 0
```
It should be noted that showing consolidated summary required a compound shell command with no order of summaries guaranteed.
With the recent changes `upgrade` scenario could be implemented as:
```
rose-check --logroot=./logs --logname=upgrade -- .../rpm-ostree-engine/guest-scripts/upgrade
rose-check --logroot=./logs --logname=running -- .../rpm-ostree-engine/guest-scripts/running
```
The resulting log structure would be like:
```
logs/
history.txt
upgrade/
bootlog.txt
execlog.txt
running/
bootlog.txt
execlog.txt
```
and content of `history.txt`:
```
$ cat ./logs/history.txt
COMMAND=".../rpm-ostree-engine/guest-scripts/upgrade " EXIT_CODE="0" STARTED="..." STOPPED="..." LOGNAME="upgrade"
COMMAND=".../rpm-ostree-engine/guest-scripts/running " EXIT_CODE="0" STARTED="..." STOPPED="..." LOGNAME="running"
```
The consolidated content of `history.txt` is now generated by `rose-spawn`/`rose-check` scripts with ordering preserved.
### Dynamic generation of logname entries
In previous releases without `--workdir=...` option all the logs to be kept in the current directory.
Thus leading to a partial override of logs from previous invocations and possibly causing a confusion.
With recent changes it's possible to dynamically generate unique logname entry for each `rose-spawn`/`rose-check` invocation.
There are two step processing of a `--logname=...` option.
Firstly the name is processed using datetime formatting to assign lognames based on a format of execution timestamp.
Secondly sequences of more than 3 uppercase 'X' letters (such as 'XXX') in the passed logname
causes `rose-spawn`/`rose-check` to use `mktemp` utility to generate unique logname.
In this case `--logname=...` becomes a template for a actual name to be generated, i.e.:
$ rose-check --logroot=./logs --logname=fixed-name -- ...
$ rose-check --logroot=./logs --logname=timestamp-%s -- ...
$ rose-check --logroot=./logs --logname=%Y-%m-%d-%H-%M-%s -- ...
$ rose-check --logroot=./logs --logname=unique.XXXXXX -- ...
$ rose-check --logroot=./logs --logname=%s.XXX -- ...
It could be unobvious to recognize the order of invocations which lognames are belong to.
That's where the `history.txt` could be helpful with executed command line and lognames logged into.
Additionally since `--logroot=...` and `--logname=...` options become the same values for different invocations
it could be convenient to define them via environment variables than via command line parameters.
Such environment variables are introdced and named `ROSE_SPAWN_LOGROOT_DIR` and `ROSE_SPAWN_LOGNAME_FMT` respectively.
As a result the `upgrade` scenario could be written as:
```
$ export ROSE_SPAWN_LOGROOT_DIR="${PWD}/logs"
$ export ROSE_SPAWN_LOGNAME_FMT="XXXXXX.%s"
$ rose-check -- .../rpm-ostree-engine/guest-scripts/upgrade
$ rose-check -- .../rpm-ostree-engine/guest-scripts/running
```
The resulting log structure is like:
```
logs/
history.txt
JpZkzk.1631537061/
bootlog.txt
execlog.txt
lHOKmG.1631537416/
bootlog.txt
execlog.txt
```
and content of `history.txt`:
```
$ cat ./logs/history.txt
COMMAND=".../rpm-ostree-engine/guest-scripts/upgrade " EXIT_CODE="0" STARTED="..." STOPPED="..." LOGNAME="JpZkzk.1631537061"
COMMAND=".../rpm-ostree-engine/guest-scripts/running " EXIT_CODE="0" STARTED="..." STOPPED="..." LOGNAME="lHOKmG.1631537416"
```
Finally it should be noted that `rose-check` would generate exactly such a log directory structure as shown above by default.
Whereas `rose-spawn` script doesn't generate any logs by default (implies logname is set to empty value).
So the `upgrade` scenario could be implemented as simple as:
```
rose-check -- .../rpm-ostree-engine/guest-scripts/upgrade
rose-check -- .../rpm-ostree-engine/guest-scripts/running
```
### Logging rework without background jobs
Logging is now performed by the standard tools without background jobs running `tail -f` to dump contents onto the screen.
This approach simplifies cleanup a lot whereas previous versions could leave unreaped `tail -f` processes in some cases.
Also this approach provides a way to invoke `rose-spawn`/`rose-check` without logfiles (`rose-spawn` does this by default).
Finally it's now possible to run arbitrary interactive command (i.e. just a shell) in execute mode, i.e.:
Spawn a machine, run a shell on a host side:
```
rose-spawn -- /bin/sh
```
Spawn a machine, run a shell on a guest side:
```
rose-spawn -- rose-guest
```
......@@ -81,7 +81,7 @@ An example `.gitlab-ci.yml`:
```yaml
include:
- project: 'os-forge/rpm-ostree-engine'
ref: 'v0.6.0'
ref: 'v0.6.5'
file: 'gitlab-ci-template.yml'
variables:
......
include:
# - remote: https://git.shivering-isles.com/os-forge/rpm-ostree-engine/-/raw/v0.6.0/.gitlab-ci-template.yml
# - remote: https://git.shivering-isles.com/os-forge/rpm-ostree-engine/-/raw/v0.6.5/.gitlab-ci-template.yml
- project: 'os-forge/rpm-ostree-engine'
ref: v0.6.0
ref: v0.6.5
file: '/.gitlab-ci-template.yml'
variables:
......
include:
# - remote: https://git.shivering-isles.com/os-forge/rpm-ostree-engine/-/raw/v0.6.0/.gitlab-ci-template-subpipeline.yml
# - remote: https://git.shivering-isles.com/os-forge/rpm-ostree-engine/-/raw/v0.6.5/.gitlab-ci-template-subpipeline.yml
- project: 'os-forge/rpm-ostree-engine'
ref: v0.6.0
ref: v0.6.5
file: '/.gitlab-ci-template-subpipeline.yml'
variables:
......
include:
# - remote: https://git.shivering-isles.com/os-forge/rpm-ostree-engine/-/raw/v0.6.0/.gitlab-ci-template-subpipeline.yml
# - remote: https://git.shivering-isles.com/os-forge/rpm-ostree-engine/-/raw/v0.6.5/.gitlab-ci-template-subpipeline.yml
- project: 'os-forge/rpm-ostree-engine'
ref: v0.6.0
ref: v0.6.5
file: '/.gitlab-ci-template-subpipeline.yml'
variables:
......
......@@ -6,8 +6,7 @@ _shellcheck() {
dir=$1
shift
# shellcheck disable=SC2046
shellcheck $(find "$dir" ! -type d "$@") --source-path="$dir"
find "$dir" ! -type d -print0 | xargs -0trx shellcheck --check-sourced --source-path="$dir" "$@"
}
_shellcheck './shellcheck.sh'
......@@ -16,6 +15,6 @@ _shellcheck './src/bin/'
_shellcheck './src/install.sh'
_shellcheck './src/share/rpm-ostree-engine/step-scripts/'
_shellcheck './src/share/rpm-ostree-engine/image-scripts/' --source-path='./src/bin/' './src/bin/rose-defaults.sh'
_shellcheck './src/share/rpm-ostree-engine/test-scripts/'
_shellcheck './src/share/rpm-ostree-engine/guest-scripts/' --source-path='./src/bin/' './src/bin/rose-defaults.sh'
#!/bin/bash --posix
printUsage() {
cat <<- EOF
cat <<- EOF
rpm-ostree-engine or ROSE
Commands to work with RPM-OSTree operating systems, specifically Fedora IoT Remixes.
......@@ -23,21 +23,21 @@ printUsage() {
$0-build
$0-image
EOF
exit 1
exit 1
}
for i in "$@"
do
case $i in
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
esac
done
......
#!/bin/bash --posix
printUsage() {
cat <<- EOF
cat <<- EOF
rpm-ostree-engine build
Usage of $0:
......@@ -29,7 +29,7 @@ printUsage() {
$0 --gpg-key-id=ABCDEF1234 --gpg-key-passphrase=super-secret
$0 --ostree-files=ostree-files --spec=ostree.json --treecompose=treecomose-post.sh --branch=OSTreeBeard/develop/x86_64
EOF
exit 1
exit 1
}
CLEAN="no"
......@@ -46,61 +46,61 @@ OSTREE_BRANCH="OSTreeBeard/develop/$(rpm --eval "%{_arch}")"
for i in "$@"
do
case $i in
-c|--clean)
CLEAN="yes"
shift
;;
--gpg-key-id=*)
GPG_KEYID="${i#*=}"
shift
;;
--gpg-key-passphrase=*)
GPG_PASSPHRASE="${i#*=}"
shift
;;
--ostree-files=*)
OSTREE_FILES_DIR="${i#*=}"
shift
;;
--treecompose=*)
OSTREE_FILES_TREECOMPOSE="${i#*=}"
shift
;;
--spec=*)
OSTREE_FILE="${i#*=}"
shift
;;
--branch=*)
OSTREE_BRANCH="${i#*=}"
shift
;;
--source-branch=*)
SOURCE_BRANCH="${i#*=}"
shift
;;
--source-url=*)
SOURCE_URL="${i#*=}"
shift
;;
-n|--no-deploy)
DEPLOY="no"
shift
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
-c|--clean)
CLEAN="yes"
shift
;;
--gpg-key-id=*)
GPG_KEYID="${i#*=}"
shift
;;
--gpg-key-passphrase=*)
GPG_PASSPHRASE="${i#*=}"
shift
;;
--ostree-files=*)
OSTREE_FILES_DIR="${i#*=}"
shift
;;
--treecompose=*)
OSTREE_FILES_TREECOMPOSE="${i#*=}"
shift
;;
--spec=*)
OSTREE_FILE="${i#*=}"
shift
;;
--branch=*)
OSTREE_BRANCH="${i#*=}"
shift
;;
--source-branch=*)
SOURCE_BRANCH="${i#*=}"
shift
;;
--source-url=*)
SOURCE_URL="${i#*=}"
shift
;;
-n|--no-deploy)
DEPLOY="no"
shift
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
esac
done
if [ "$(id -u)" != "0" ]; then
echo "Please run build with sudo"
exit
echo "Please run build with sudo"
exit
fi
set -e
......@@ -115,35 +115,35 @@ WK_DIR="$BASE_DIR/.tmp"
COMMIT_FILE="$(mktemp)"
if [ "${CLEAN}" = "yes" ]; then
echo "Running fresh build"
rm -rf "${CACHE_DIR:?}"/
rm -rf "${INTERMEDIATE_REPO:?}"/
rm -rf "${SOURCE_REPO:?}"/
rm -rf "${WK_DIR:?}"/
echo "Running fresh build"
rm -rf "${CACHE_DIR:?}"/
rm -rf "${INTERMEDIATE_REPO:?}"/
rm -rf "${SOURCE_REPO:?}"/
rm -rf "${WK_DIR:?}"/
fi
mkdir -p "$CACHE_DIR" "$WK_DIR"
if [ -e "$BUILD_REPO" ]; then
rm -rf "${BUILD_REPO:?}"/
rm -rf "${BUILD_REPO:?}"/
fi
ostree --repo="$BUILD_REPO" init --mode=bare-user
if [ ! -e "$DEPLOY_REPO" ]; then
ostree --repo="$DEPLOY_REPO" init --mode=archive
ostree --repo="$DEPLOY_REPO" init --mode=archive
else
ostree --repo="$BUILD_REPO" pull-local --depth=2 "$DEPLOY_REPO" "$OSTREE_BRANCH" || true
ostree --repo="$BUILD_REPO" pull-local --depth=2 "$DEPLOY_REPO" "$OSTREE_BRANCH" || true
fi
if [ ! -e "$INTERMEDIATE_REPO" ]; then
ostree --repo="$INTERMEDIATE_REPO" init --mode=archive
ostree --repo="$INTERMEDIATE_REPO" init --mode=archive
else
ostree --repo="$BUILD_REPO" pull-local --depth=-1 "$INTERMEDIATE_REPO" "$OSTREE_BRANCH" || true
ostree --repo="$BUILD_REPO" pull-local --depth=-1 "$INTERMEDIATE_REPO" "$OSTREE_BRANCH" || true
fi
if [ ! -e "$SOURCE_REPO" ]; then
git clone -b "$SOURCE_BRANCH" "$SOURCE_URL" "$SOURCE_REPO"
git clone -b "$SOURCE_BRANCH" "$SOURCE_URL" "$SOURCE_REPO"
fi
# Evaluate all scripts in hooks.d
......@@ -164,24 +164,24 @@ sed -i "s,OSTREE_BRANCH,$OSTREE_BRANCH," "$WK_DIR/$OSTREE_FILE"
COMMIT_SUBJECT="MBuilt | Builddate $(date --rfc-3339=seconds)"
if [ "$CI_JOB_ID" != "" ]; then
COMMIT_SUBJECT="ABuilt | Job: $CI_JOB_ID | Builddate $(date --rfc-3339=seconds)"
COMMIT_SUBJECT="ABuilt | Job: $CI_JOB_ID | Builddate $(date --rfc-3339=seconds)"
fi
rpm-ostree compose tree --unified-core --cachedir="$CACHE_DIR" --repo="$BUILD_REPO" --write-commitid-to="$COMMIT_FILE" "$WK_DIR/$OSTREE_FILE"
if [ "$GPG_KEYID" != "" ]; then
if [ "$GPG_PASSPHRASE" != "" ]; then
echo "$GPG_PASSPHRASE" | gpg --batch --always-trust --yes --passphrase-fd 0 --pinentry-mode=loopback -s "$(mktemp)"
fi
ostree --repo="$BUILD_REPO" commit --gpg-sign="$GPG_KEYID" -b "$OSTREE_BRANCH" -s "$COMMIT_SUBJECT" --tree=ref="$(cat "$COMMIT_FILE")" | tee "./.COMMIT_FILE"
else
ostree --repo="$BUILD_REPO" commit -b "$OSTREE_BRANCH" -s "$COMMIT_SUBJECT" --tree=ref="$(cat "$COMMIT_FILE")" | tee "./.COMMIT_FILE"
if [ "$GPG_PASSPHRASE" != "" ]; then
echo "$GPG_PASSPHRASE" | gpg --batch --always-trust --yes --passphrase-fd 0 --pinentry-mode=loopback -s "$(mktemp)"
fi
ostree --repo="$BUILD_REPO" commit --gpg-sign="$GPG_KEYID" -b "$OSTREE_BRANCH" -s "$COMMIT_SUBJECT" --tree=ref="$(cat "$COMMIT_FILE")" | tee "./.COMMIT_FILE"
else
ostree --repo="$BUILD_REPO" commit -b "$OSTREE_BRANCH" -s "$COMMIT_SUBJECT" --tree=ref="$(cat "$COMMIT_FILE")" | tee "./.COMMIT_FILE"
fi
ostree --repo="$INTERMEDIATE_REPO" pull-local "$BUILD_REPO" "$OSTREE_BRANCH"
if [ "$DEPLOY" = "yes" ]; then
"$BIN_DIR"/deploy.sh || "$BIN_DIR"/rose-deploy
"$BIN_DIR"/deploy.sh || "$BIN_DIR"/rose-deploy
fi
rm "${COMMIT_FILE:?}"
......@@ -2,192 +2,7 @@
. rose-defaults.sh
printUsage() {
cat <<- EOF
rpm-ostree-engine check
export ROSE_SPAWN_LOGROOT_DIR="${ROSE_SPAWN_LOGROOT_DIR:-${PWD}/logs/}"
export ROSE_SPAWN_LOGNAME_FMT="${ROSE_SPAWN_LOGNAME_FMT:-XXXXXX.%s}"
Usage of $0:
$0 [<option>=<value>, ...] --image=os-iot.raw
Run test scripts on an image within a QEMU VM instance.
Options:
--image=FILE File name of created image
--memory=INT Memory size of VM in MB
-k --no-kvm Don't use KVM acceleration
-s --no-smp Don't use SMP
--boot=bios|uefi Bootloader technology to use
--arch=x86_64|aarch64 Architecture to emulate in VM
-v --keep-vm Don't destroy the VM after checks are done
-c --console Attach a console to the VM
-t --no-tty Don't attach a TTY to the VM
--workdir=PATH Use this working directory for VM initialization
-h --help Show this message.
Examples:
$0
$0 --image=os-iot.raw --memory=512 --boot=uefi --arch=aarch64
$0 --keep-vm
EOF
exit 1
}
usearch="$(uname -m)"
useboot='uefi'
withkvm='true'
withsmp='true'
withtty='true'
cleanup='true'
console='false'
workdir="${PWD}"
for i in "$@"; do
case $i in
--image=*)
osimage="${i#*=}"
shift
;;
--memory=*)
memsize="${i#*=}"
shift
;;
-k|--no-kvm)
withkvm='false'
shift
;;
-s|--no-smp)
withsmp='false'
shift
;;
--boot=*)
useboot="${i#*=}"
shift
;;
--arch=*)
usearch="${i#*=}"
shift
;;
-v|--keep-vm)
cleanup='false'
shift
;;
-c|--console)
console='true'
shift
;;
-t|--no-tty)
withtty='false'
shift
;;
--workdir=*)
workdir="${i#*=}"
shift
;;
--)
shift
break
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
esac
done
emulate="$usearch:$useboot"
case "$emulate" in
x86_64:bios)
cputype='qemu64'
bootbin='/usr/share/seabios/bios.bin'
machine='q35'
;;
x86_64:uefi)
cputype='qemu64'
bootbin='/usr/share/edk2/ovmf/OVMF_CODE.fd'
machine='q35'
;;
aarch64:uefi)
cputype='cortex-a72'
bootbin='/usr/share/edk2/aarch64/QEMU_EFI.fd'
machine='virt'
;;
*)
echo "Unsupported configuration: $emulate"
exit 1
esac
if test "$usearch" != "$(uname -m)"; then
withkvm='false'
elif ! test -e '/dev/kvm'; then
withkvm='false'
fi
cpuopts=()
if "$withkvm"; then
cpuopts+=('--enable-kvm')
cputype='host'
fi
if "$withsmp"; then
cpuopts+=('-smp' "$(nproc)")
fi
mkdir -p "${workdir}"
bootlog="${workdir}/bootlog.txt"
ttyopts=()
if "$console"; then
ttyopts+=('-nographic')
ttyopts+=('-serial' 'mon:stdio')
else
ttyopts+=('-daemonize')
ttyopts+=('-display' 'none')
ttyopts+=('-chardev' "null,id=stdio0,logfile=${bootlog},mux=on")
ttyopts+=('-serial' 'chardev:stdio0')
ttyopts+=('-monitor' 'chardev:stdio0')
fi
memsize="${memsize:-1024}"
osimage="${osimage:-${PWD}/os-iot.raw}"
_exit() {
if "$cleanup" && pkill -F "$PWD/qemu.pid" 2>/dev/null; then sleep 3; fi
jobs -p | xargs -r kill --
}
trap '_exit' EXIT
if "$console"; then
:
elif "$withtty"; then
rm -f "${bootlog}"
touch "${bootlog}"
tail -f "${bootlog}" &
fi
"qemu-system-${usearch}" "${cpuopts[@]}" -cpu "${cputype}" \
-m "${memsize}" -machine "${machine}" -bios "${bootbin}" \
-drive file="${osimage}",format=raw,if=virtio \
-nic user,id=net0,hostname=ostree,hostfwd=tcp::2222-:22,model=virtio \
"${ttyopts[@]}" -pidfile "$PWD/qemu.pid"
if "$console"; then
:
else
export ROSE_GUEST_SSH_HOST='localhost'
export ROSE_GUEST_SSH_PORT='2222'
export ROSE_GUEST_WORK_DIR="${workdir}"
env sh -c 'exec "$@"' sh "$@"
fi
exec "${0//-check/-spawn}" "$@"
......@@ -3,7 +3,7 @@
set -e
printUsage() {
cat <<- EOF
cat <<- EOF
rpm-ostree-engine CI helper
Usage of $0:
......@@ -30,7 +30,7 @@ printUsage() {
OSTreeBeard/develop/x86_64
OSTreeBeard/your-ci-branch/aarch64
EOF
exit 1
exit 1
}
OSTREE_REF_NAME=""
......@@ -40,48 +40,48 @@ OSTREE_REF_ARCH=""
for i in "$@"
do
case $i in
--name=*)
OSTREE_REF_NAME="${i#*=}"
shift
;;
--branch=*)
OSTREE_REF_BRANCH="${i#*=}"
shift
;;
--arch=*)
OSTREE_REF_ARCH="${i#*=}"
shift
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
--name=*)
OSTREE_REF_NAME="${i#*=}"
shift
;;
--branch=*)
OSTREE_REF_BRANCH="${i#*=}"
shift
;;
--arch=*)
OSTREE_REF_ARCH="${i#*=}"
shift
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
esac
done
if [ "$OSTREE_REF_NAME" = "" ]; then
echo "Error: please specify a name for your ostree ref"
printUsage
echo "Error: please specify a name for your ostree ref"
printUsage
fi
# Set proper branch
if [ "$OSTREE_REF_BRANCH" = "" ]; then
if [ "$CI_COMMIT_BRANCH" = "$CI_DEFAULT_BRANCH" ] && [ "$CI_COMMIT_BRANCH" != "" ]; then
OSTREE_REF_BRANCH=stable
elif [ "$CI_COMMIT_BRANCH" != "" ]; then
OSTREE_REF_BRANCH="$CI_COMMIT_REF_SLUG"
else
OSTREE_REF_BRANCH="develop"
fi
if [ "$CI_COMMIT_BRANCH" = "$CI_DEFAULT_BRANCH" ] && [ "$CI_COMMIT_BRANCH" != "" ]; then
OSTREE_REF_BRANCH=stable
elif [ "$CI_COMMIT_BRANCH" != "" ]; then
OSTREE_REF_BRANCH="$CI_COMMIT_REF_SLUG"
else
OSTREE_REF_BRANCH="develop"
fi
fi
if [ "$OSTREE_REF_ARCH" = "" ]; then
OSTREE_REF_ARCH="$(rpm --eval "%{_arch}")"
OSTREE_REF_ARCH="$(rpm --eval "%{_arch}")"
fi
echo "$OSTREE_REF_NAME/$OSTREE_REF_BRANCH/$OSTREE_REF_ARCH"
......@@ -3,7 +3,7 @@
set -e
printUsage() {
cat <<- EOF
cat <<- EOF
rpm-ostree-engine ci-prepare
Usage of $0:
......@@ -26,98 +26,98 @@ printUsage() {
$0
$0 sshfs --sshfs-target=example.com --sshfs-auth=user:pass --sshfs-path=/some/dir --sshfs-key=/tmp/mykey
EOF
exit 1
exit 1
}
mount_sshfs() {
for i in "$@"
do
case $i in
--sshfs-target=*)
SSHFS_TARGET="${i#*=}"
shift
;;
--sshfs-auth=*)
SSHFS_AUTH="${i#*=}"
shift
;;
--sshfs-path=*)
SSHFS_PATH="${i#*=}"
shift
;;
--sshfs-key=*)
SSHFS_KEY="${i#*=}"
shift
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
esac
done
if [ -z "$SSHFS_TARGET" ] || [ -z "$SSHFS_AUTH" ] || [ -z "$SSHFS_PATH" ] || [ -z "$SSHFS_KEY" ]; then
echo "Not all required options provided!" >&2
printUsage
fi
if [ ! -e "$SSHFS_KEY" ]; then
echo "Provided ssh key file does not exist!" >&2
exit 1
else
chmod 0600 "$SSHFS_KEY"
fi
# Mount file system of repository to /remote-storage
if [ ! -d /remote-storage ]; then
mkdir /remote-storage
fi
## SSH key for file system access
eval "$(ssh-agent -s)"
ssh-add "$SSHFS_KEY"
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keyscan "$SSHFS_TARGET" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
# Workaround for hosts which can't connect immediately (like some runner on AWS)
ping -c5 "$CI_SSHFS_TARGET"
for i in 1 2 3 4 5; do
# shellcheck disable=SC2015
sshfs -o allow_other "$SSHFS_AUTH"@"$SSHFS_TARGET":"$SSHFS_PATH" /remote-storage && \
break || \
sleep 15
done
# The remote is expected to have a /repo directory
if [ ! -d /remote-storage/repo ]; then
echo "No repository found. Creating empty repo..."
mkdir -p /remote-storage/repo
ostree --repo=/remote-storage/repo init --mode=archive
fi
if [ ! -d ./.deploy-repo ]; then
ln -s /remote-storage/repo ./.deploy-repo
fi
for i in "$@"
do
case $i in
--sshfs-target=*)
SSHFS_TARGET="${i#*=}"
shift
;;
--sshfs-auth=*)
SSHFS_AUTH="${i#*=}"
shift
;;
--sshfs-path=*)
SSHFS_PATH="${i#*=}"
shift
;;
--sshfs-key=*)
SSHFS_KEY="${i#*=}"
shift
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
esac
done
if [ -z "$SSHFS_TARGET" ] || [ -z "$SSHFS_AUTH" ] || [ -z "$SSHFS_PATH" ] || [ -z "$SSHFS_KEY" ]; then
echo "Not all required options provided!" >&2
printUsage
fi
if [ ! -e "$SSHFS_KEY" ]; then
echo "Provided ssh key file does not exist!" >&2
exit 1
else
chmod 0600 "$SSHFS_KEY"
fi
# Mount file system of repository to /remote-storage
if [ ! -d /remote-storage ]; then
mkdir /remote-storage
fi
## SSH key for file system access
eval "$(ssh-agent -s)"
ssh-add "$SSHFS_KEY"
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keyscan "$SSHFS_TARGET" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
# Workaround for hosts which can't connect immediately (like some runner on AWS)
ping -c5 "$CI_SSHFS_TARGET"
for i in 1 2 3 4 5; do
# shellcheck disable=SC2015
sshfs -o allow_other "$SSHFS_AUTH"@"$SSHFS_TARGET":"$SSHFS_PATH" /remote-storage && \
break || \
sleep 15
done
# The remote is expected to have a /repo directory
if [ ! -d /remote-storage/repo ]; then
echo "No repository found. Creating empty repo..."
mkdir -p /remote-storage/repo
ostree --repo=/remote-storage/repo init --mode=archive
fi
if [ ! -d ./.deploy-repo ]; then
ln -s /remote-storage/repo ./.deploy-repo
fi
}
case $1 in
test)
# just skip sub-program execution for now
;;
sshfs)
shift
mount_sshfs "$@"
;;
*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
test)
# just skip sub-program execution for now
;;
sshfs)
shift
mount_sshfs "$@"
;;
*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
esac
......@@ -3,7 +3,7 @@
. rose-defaults.sh
printUsage() {
cat <<- EOF
cat <<- EOF
rpm-ostree-engine clone
Usage of $0:
......@@ -22,41 +22,41 @@ printUsage() {
Examples:
$0
EOF
exit 1
exit 1
}
depth=0
for i in "$@"; do
case $i in
--remote=*)
remote="${i#*=}"
shift
;;
--branch=*)
branch="${i#*=}"
shift
;;
--origin=*)
origin="${i#*=}"
shift
;;
--mirror=*)
mirror="${i#*=}"
shift
;;
--depth=*)
depth="${i#*=}"
shift
;;
-h|--help)
printUsage
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
--remote=*)
remote="${i#*=}"
shift
;;
--branch=*)
branch="${i#*=}"
shift
;;
--origin=*)
origin="${i#*=}"
shift
;;
--mirror=*)
mirror="${i#*=}"
shift
;;
--depth=*)
depth="${i#*=}"
shift
;;
-h|--help)
printUsage
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
esac
done
......
......@@ -4,12 +4,12 @@ set -e
ROSE_DEBUG="${ROSE_DEBUG:-1}"
if test "$ROSE_DEBUG" -gt 0; then
# shellcheck disable=SC2034
if (( "$ROSE_DEBUG" )); then
_ROSE_DEBUG=_
set -x
else
# shellcheck disable=SC2034
_ROSE_DEBUG=
set +x
fi
: "${_ROSE_DEBUG?}"
#!/bin/bash
printUsage() {
cat <<- EOF
cat <<- EOF
rpm-ostree-engine delta
Usage of $0:
......@@ -23,16 +23,16 @@ printUsage() {
$0 --branch=OSTreeBeard/develop/x86_64 --gpg-key-id=ABCDEF1234 --gpg-key-passphrase=super-secret
$0 --branch=OSTreeBeard/develop/x86_64 --repo=/path/to/repo
EOF
exit 1
exit 1
}
unlockGPG() {
if [ "$GPG_KEYID" != "" ]; then
EXTRA_OPTIONS+=("--gpg-sign=$GPG_KEYID")
if [ "$GPG_PASSPHRASE" != "" ]; then
echo "$GPG_PASSPHRASE" | gpg --batch --always-trust --yes --passphrase-fd 0 --pinentry-mode=loopback -s "$(mktemp)"
fi
fi
if [ "$GPG_KEYID" != "" ]; then
EXTRA_OPTIONS+=("--gpg-sign=$GPG_KEYID")
if [ "$GPG_PASSPHRASE" != "" ]; then
echo "$GPG_PASSPHRASE" | gpg --batch --always-trust --yes --passphrase-fd 0 --pinentry-mode=loopback -s "$(mktemp)"
fi
fi
}
BASE_DIR=$(pwd)
......@@ -43,31 +43,31 @@ OSTREE_BRANCH="OSTreeBeard/develop/$(rpm --eval "%{_arch}")"
for i in "$@"
do
case $i in
--gpg-key-id=*)
GPG_KEYID="${i#*=}"
shift
;;
--gpg-key-passphrase=*)
GPG_PASSPHRASE="${i#*=}"
shift
;;
--branch=*)
OSTREE_BRANCH="${i#*=}"
shift
;;
--repo=*)
REPO="${i#*=}"
shift
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
--gpg-key-id=*)
GPG_KEYID="${i#*=}"
shift
;;
--gpg-key-passphrase=*)
GPG_PASSPHRASE="${i#*=}"
shift
;;
--branch=*)
OSTREE_BRANCH="${i#*=}"
shift
;;
--repo=*)
REPO="${i#*=}"
shift
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
esac
done
......@@ -80,17 +80,17 @@ set -e
set -x
if ostree --repo="$REPO" show "$OSTREE_BRANCH" | grep "Parent"; then
unlockGPG
ostree --repo="$REPO" static-delta generate "$OSTREE_BRANCH"
unlockGPG
ostree --repo="$REPO" static-delta generate "$OSTREE_BRANCH"
else
echo "Main ref has no parent. No deltas generated."
echo "Main ref has no parent. No deltas generated."
fi
if ostree --repo="$REPO" show "$OSTREE_BRANCH"^^ | grep "Parent"; then
unlockGPG
ostree --repo="$REPO" static-delta generate --from="$OSTREE_BRANCH"^^ --to="$OSTREE_BRANCH"
unlockGPG
ostree --repo="$REPO" static-delta generate --from="$OSTREE_BRANCH"^^ --to="$OSTREE_BRANCH"
else
echo "Main ref\'s parent has no parent. No deltas generated."
echo "Main ref\'s parent has no parent. No deltas generated."
fi
ostree --repo="$REPO" "${EXTRA_OPTIONS[@]}" summary -u
#!/bin/bash --posix
printUsage() {
cat <<- EOF
cat <<- EOF
rpm-ostree-engine deploy
Usage of $0:
......@@ -17,7 +17,7 @@ printUsage() {
$0
$0 --branch=OSTreeBeard/develop/x86_64
EOF
exit 1
exit 1
}
BASE_DIR=$(pwd)
......@@ -28,19 +28,19 @@ OSTREE_BRANCH="OSTreeBeard/develop/$(rpm --eval "%{_arch}")"
for i in "$@"
do
case $i in
--branch=*)
OSTREE_BRANCH="${i#*=}"
shift
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
--branch=*)
OSTREE_BRANCH="${i#*=}"
shift
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
esac
done
......@@ -52,28 +52,28 @@ fi
set -e
if [ -d "$INTERMEDIATE_REPO" ]; then
echo "Deploying commits from intermediate repo"
echo "Summary:"
echo "------------------------"
ostree --repo="$INTERMEDIATE_REPO" summary -u
ostree --repo="$INTERMEDIATE_REPO" summary -v
echo "------------------------"
echo "Contents:"
ostree --repo="$INTERMEDIATE_REPO" log "$OSTREE_BRANCH"
echo "Deploying commits from intermediate repo"
echo "Summary:"
echo "------------------------"
ostree --repo="$INTERMEDIATE_REPO" summary -u
ostree --repo="$INTERMEDIATE_REPO" summary -v
echo "------------------------"
echo "Contents:"
ostree --repo="$INTERMEDIATE_REPO" log "$OSTREE_BRANCH"
else
echo "Nothing to deploy"
exit 0
echo "Nothing to deploy"
exit 0
fi
if ostree --repo="$DEPLOY_REPO" pull-local --depth=-1 "$INTERMEDIATE_REPO" "$OSTREE_BRANCH"; then
echo "Intermediate commits deployed! Removing intermediate repo..."
rm -r "${INTERMEDIATE_REPO:?}"/
echo "Done"
echo "Intermediate commits deployed! Removing intermediate repo..."
rm -r "${INTERMEDIATE_REPO:?}"/
echo "Done"
if [ -e "$DEPLOY_REPO/summary" ]; then
ostree --repo="$DEPLOY_REPO" summary -u
fi
if [ -e "$DEPLOY_REPO/summary" ]; then
ostree --repo="$DEPLOY_REPO" summary -u
fi
else
echo "Error deploying commits!"
exit 1
echo "Error deploying commits!"
exit 1
fi
#!/bin/bash --posix
. rose-defaults.sh
printUsage() {
cat <<- EOF
rpm-ostree-engine guest
Usage of $0:
$0 [<option>=<value>, ...]
Execute arbitrary shell commands on a guest-side using SSH session.
Options:
--files=[PATH] Copy files specified by PATH from local system to a guest
--alive Just perform is alive check and awaiting without command
-h --help Show this message.
Examples:
$0
$0 -- /guest/path/to/command args...
$0 --files=/local/path/to/executable -- ./executable args...
EOF
exit 1
}
ROSE_GUEST_SSH_HOST="${ROSE_GUEST_SSH_HOST:-localhost}"
ROSE_GUEST_SSH_PORT="${ROSE_GUEST_SSH_PORT:-2222}"
ROSE_GUEST_SSH_USER="${ROSE_GUEST_SSH_USER:-root}"
ROSE_GUEST_SSH_TIMEOUT_SEC="${ROSE_GUEST_SSH_TIMEOUT_SEC:-60}"
ROSE_GUEST_SSH_RETRIES_NUM="${ROSE_GUEST_SSH_RETRIES_NUM:-5}"
await='false'
files=()
for i in "$@"; do
case $i in
--files=*)
files+=("${i#*=}")
shift
;;
--await)
await='true'
shift
;;
--)
shift
break
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
esac
done
_ssh() {
sshpass -p "" \
ssh -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \
-p "$ROSE_GUEST_SSH_PORT" "$ROSE_GUEST_SSH_USER@$ROSE_GUEST_SSH_HOST" "$@"
}
_scp() {
sshpass -p "" \
scp -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -p -r \
-P "$ROSE_GUEST_SSH_PORT" "${@:1:$#-1}" "$ROSE_GUEST_SSH_USER@$ROSE_GUEST_SSH_HOST:${*:$#:1}"
}
alive='false'
_int() {
trap - INT
kill -INT 0
}
trap '_int' INT
for _ in $(seq 1 "${ROSE_GUEST_SSH_RETRIES_NUM}"); do
if _ssh -o "ConnectTimeout=${ROSE_GUEST_SSH_TIMEOUT_SEC}" -- :; then
alive='true'
break
fi
done
if "${await}" || ! "${alive}"; then
exec "${alive}"
fi
tmpdir=
_exit() {
if test "${tmpdir}"; then
_ssh -- rm -rf "${tmpdir}/" || :
fi
}
trap '_exit' EXIT
if (( "${#files[@]}" )); then
tmpdir="$(_ssh -- mktemp -d -p .)"
_scp -- "${files[@]}" "${tmpdir}"
fi
if ! (( $# )); then
_ssh --
else
_ssh -- "cd \"${tmpdir}\"; $(printf '%q ' "$@");"
fi
......@@ -5,7 +5,7 @@
. rose-mountlib.sh
printUsage() {
cat <<- EOF
cat <<- EOF
rpm-ostree-engine image
Usage of $0:
......@@ -16,7 +16,7 @@ printUsage() {
Options:
--image=FILE File name of created image
--sysroot=PATH Mount path / working directory used to create the image
-f --force Force usage of sysroot as working directory. Defaults to yes
-f --force Force usage of sysroot as working directory. Defaults to yes
--remote=STRING Name of the OSTree remote used in the OS
--branch=STRING OSTree branch name to use from the repo to build the image
--origin=URL OSTree repository URL to store as the upstream remote
......@@ -32,12 +32,12 @@ printUsage() {
$0 [--image=os-iot.raw] [--remote=origin] --origin=https://host/repo/ --branch=branch/custom
$0 [--image=os-iot.raw] [--remote=origin] --origin=https://host/repo/ --branch=branch/custom --mirror=/path/to/mirror
EOF
exit 1
exit 1
}
if [ "$(id -u)" != "0" ]; then
echo "Please run script with sudo"
exit
echo "Please run script with sudo"
exit
fi
force='false'
......@@ -49,62 +49,62 @@ kargs=()
for i in "$@"
do
case $i in
--image=*)
image="${i#*=}"
shift
;;
--sysroot=*)
sysroot="${i#*=}"
shift
;;
-f|--force)
force='true'
shift
;;
--remote=*)
remote="${i#*=}"
shift
;;
--branch=*)
branch="${i#*=}"
shift
;;
--origin=*)
origin="${i#*=}"
shift
;;
--mirror=*)
mirror="${i#*=}"
shift
;;
--commit=*)
commit="${i#*=}"
shift
;;
--gpg-import=*)
gpgkey="${i#*=}"
shift
;;
--karg=*)
kargs+=("--karg=${i#*=}")
shift
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
--image=*)
image="${i#*=}"
shift
;;
--sysroot=*)
sysroot="${i#*=}"
shift
;;
-f|--force)
force='true'
shift
;;
--remote=*)
remote="${i#*=}"
shift
;;
--branch=*)
branch="${i#*=}"
shift
;;
--origin=*)
origin="${i#*=}"
shift
;;
--mirror=*)
mirror="${i#*=}"
shift
;;
--commit=*)
commit="${i#*=}"
shift
;;
--gpg-import=*)
gpgkey="${i#*=}"
shift
;;
--karg=*)
kargs+=("--karg=${i#*=}")
shift
;;
-h|--help)
printUsage
shift
;;
--*)
echo "Error: unknown option ${i#*=}"
printUsage
shift
;;
esac
done
image="${image:-"${PWD}/os-iot.raw"}"
if ! test "${mirror}" && ! test "${origin}"; then
printUsage
printUsage
fi
remote="${remote:-fedora-iot}"
......@@ -125,31 +125,32 @@ ostree admin init-fs --verbose --sysroot="${sysroot}" "${sysroot}"
ostree admin os-init --verbose --sysroot="${sysroot}" "${osname}"
if test "${gpgkey}"; then
ostree --verbose --repo="${sysroot}/ostree/repo/" remote add "${remote}" "${origin}" --gpg-import="${gpgkey}"
ostree --verbose --repo="${sysroot}/ostree/repo/" remote add "${remote}" "${origin}" --gpg-import="${gpgkey}"
else
ostree --verbose --repo="${sysroot}/ostree/repo/" remote add "${remote}" "${origin}" --no-gpg-verify
ostree --verbose --repo="${sysroot}/ostree/repo/" remote add "${remote}" "${origin}" --no-gpg-verify
fi
if test "${commit}"; then
treeid="${commit}"
treeid="${commit}"
else
treeid="${branch}"
treeid="${branch}"
fi
if ! test "${mirror}"; then
ostree --verbose --repo="${sysroot}/ostree/repo/" pull "${remote}" "${treeid}"
ostree --verbose --repo="${sysroot}/ostree/repo/" pull "${remote}" "${treeid}"
elif test "${gpgkey}"; then
ostree --verbose --repo="${sysroot}/ostree/repo/" pull-local --remote="${remote}" "${mirror}" "${treeid}" --gpg-verify
ostree --verbose --repo="${sysroot}/ostree/repo/" pull-local --remote="${remote}" "${mirror}" "${treeid}" --gpg-verify
else
ostree --verbose --repo="${sysroot}/ostree/repo/" pull-local --remote="${remote}" "${mirror}" "${treeid}"
ostree --verbose --repo="${sysroot}/ostree/repo/" pull-local --remote="${remote}" "${mirror}" "${treeid}"
fi
if test "${commit}"; then
ostree --verbose --repo="${sysroot}/ostree/repo/" refs --create="${remote}:${branch}" "${commit}"
ostree --verbose --repo="${sysroot}/ostree/repo/" refs --create="${remote}:${branch}" "${commit}"
fi
deployFstab "${sysroot}" "${PWD}/fstab"
idroot="$(< "${PWD}/fstab" grep -w '/' | cut -f1)"
fstabtmp="$(mktemp)"
deployFstab "${sysroot}" "${fstabtmp}"
idroot="$(< "${fstabtmp}" grep -w '/' | cut -f1)"
ostree --verbose --repo="${sysroot}/ostree/repo/" config --group=sysroot set bootloader none
......@@ -178,7 +179,7 @@ mkdir -p "${osroot}/var/spool/mail"
ln -sf '../../usr/share/rpm' "${osroot}/var/lib/rpm"
cp -f "${PWD}/fstab" "${deploy}/etc/fstab"
mv -f "${fstabtmp}" "${deploy}/etc/fstab"
setfiles -F -r "${sysroot}" "${deploy}/etc/selinux/targeted/contexts/files/file_contexts" "${sysroot}/boot/"
setfiles -F -r "${sysroot}" "${deploy}/etc/selinux/targeted/contexts/files/file_contexts" "${sysroot}/dev/"
......@@ -203,12 +204,12 @@ cp -r "${deploy}/${osboot}/grub2/" "${sysroot}/boot/"
uboot3=${deploy}/usr/share/uboot/rpi_3/u-boot.bin
if test -r "${uboot3}"; then
cp -r "${uboot3}" "${sysroot}/boot/efi/rpi3-u-boot.bin"
cp -r "${uboot3}" "${sysroot}/boot/efi/rpi3-u-boot.bin"
fi
uboot4=${deploy}/usr/share/uboot/rpi_4/u-boot.bin
if test -r "${uboot4}"; then
cp -r "${uboot4}" "${sysroot}/boot/efi/rpi4-u-boot.bin"
cp -r "${uboot4}" "${sysroot}/boot/efi/rpi4-u-boot.bin"
fi
dir="$(dirname "$(readlink -f "$0")")"
......