Skip to content

Commit 7c3ee87

Browse files
frankdavidIDX GitHub Automation
andauthored
test: Extend bare metal deployment (#7661)
This PR adds many improvements to the reload_host.sh script and adds a library for redeploying HostOS and GuestOS. A CLI tool is coming in a follow-up PR. Notable changes: - Create deploy_to_bare_metal function for deploying HostOS and/or GuestOS from a URL or a file - Make all input images optional in reload_hostos.sh - Support loading images from a local file in reload_hostos.sh reload_hostos will be renamed in the future, for now it's still called reload_hostos to preserve git history. --------- Co-authored-by: IDX GitHub Automation <[email protected]>
1 parent 3c79383 commit 7c3ee87

File tree

8 files changed

+367
-123
lines changed

8 files changed

+367
-123
lines changed

Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ic-os/testing/BUILD.bazel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
load("//ic-os/components:setupos.bzl", "component_files")
22

3-
package(default_visibility = ["//rs/tests:__subpackages__"])
3+
package(default_visibility = ["//rs:ic-os-pkg"])
44

55
# Components required by the reload_hostos script to reload HostOS
66
all_component_files = component_files | {

ic-os/testing/reload_hostos.sh

Lines changed: 86 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ TARGET_BOOT_PARTITION_MOUNT=/tmp/target_boot_partition
1111
GUESTOS_EXTRACT_DIR=/tmp/guestos_img
1212

1313
# Temporary download paths
14-
HOSTOS_UPGRADE_TAR=/tmp/hostos-upgrade-img.tar.zst
15-
GUESTOS_TAR=/tmp/guestos.tar.zst
14+
SETUPOS_CONFIG_IMG_PATH=/tmp/setupos-config.img
15+
HOSTOS_UPGRADE_IMG_TAR_PATH=/tmp/hostos-upgrade-img.tar.zst
16+
GUESTOS_IMG_TAR_PATH=/tmp/guestos.tar.zst
1617

1718
usage() {
18-
echo "Usage: $0 --setupos-config-img=<path-to-setupos-config-image> --hostos-upgrade-img=<path-to-hostos-upgrade-image> --guestos-img=<path-to-guestos-image>" >&2
19+
echo "Usage: $0 [--setupos-config-img=<path-to-setupos-config-image>] [--hostos-upgrade-img=<path-to-hostos-upgrade-image>] [--guestos-img=<path-to-guestos-image>]" >&2
20+
echo "At least one of --hostos-upgrade-img or --guestos-img must be provided." >&2
1921
}
2022

2123
cleanup() {
@@ -27,18 +29,42 @@ cleanup() {
2729
umount /media 2>/dev/null || true
2830
umount "$SETUPOS_CONFIG_MOUNT" 2>/dev/null || true
2931
umount "$TARGET_BOOT_PARTITION_MOUNT" 2>/dev/null || true
30-
rm -rf "$TARGET_BOOT_PARTITION_MOUNT" 2>/dev/null || true
31-
rm -rf "$GUESTOS_EXTRACT_DIR" 2>/dev/null || true
32-
rm -f "$HOSTOS_UPGRADE_TAR" "$GUESTOS_TAR" 2>/dev/null || true
32+
rm -rf "$TARGET_BOOT_PARTITION_MOUNT" "$GUESTOS_EXTRACT_DIR" 2>/dev/null || true
33+
rm -f "$SETUPOS_CONFIG_IMG_PATH" "$HOSTOS_UPGRADE_IMG_TAR_PATH" "$GUESTOS_IMG_TAR_PATH" 2>/dev/null || true
3334
}
3435

35-
download_images() {
36-
echo "Downloading HostOS upgrade image..."
37-
curl "$HOSTOS_UPGRADE_IMG" -o "$HOSTOS_UPGRADE_TAR" --fail --silent --show-error --clobber
36+
fetch_file() {
37+
# Fetch a file from a URL or local filesystem and store it at the specified path.
38+
local source="$1"
39+
local dest="$2"
40+
local name="$3"
41+
42+
if echo "$source" | grep -q "://"; then
43+
echo "Downloading $name from $source..."
44+
curl "$source" -o "$dest" --fail --silent --show-error --clobber
45+
else
46+
if [ ! -f "$source" ]; then
47+
echo "Local file $source does not exist!" >&2
48+
exit 1
49+
fi
50+
echo "Using local $name from $source..."
51+
if [[ "$source" != "$dest" ]]; then
52+
mv "$source" "$dest"
53+
fi
54+
fi
55+
}
56+
57+
fetch_images() {
58+
if [ -n "$SETUPOS_CONFIG_IMG_SRC" ]; then
59+
fetch_file "$SETUPOS_CONFIG_IMG_SRC" "$SETUPOS_CONFIG_IMG_PATH" "SetupOS config image"
60+
fi
61+
62+
if [ -n "$HOSTOS_UPGRADE_IMG_TAR_SRC" ]; then
63+
fetch_file "$HOSTOS_UPGRADE_IMG_TAR_SRC" "$HOSTOS_UPGRADE_IMG_TAR_PATH" "HostOS upgrade image"
64+
fi
3865

39-
if [ -n "$GUESTOS_IMG" ]; then
40-
echo "Downloading GuestOS image..."
41-
curl "$GUESTOS_IMG" -o "$GUESTOS_TAR" --fail --silent --show-error --clobber
66+
if [ -n "$GUESTOS_IMG_TAR_SRC" ]; then
67+
fetch_file "$GUESTOS_IMG_TAR_SRC" "$GUESTOS_IMG_TAR_PATH" "GuestOS image"
4268
fi
4369
}
4470

@@ -50,19 +76,24 @@ setup_temp_mounts() {
5076
}
5177

5278
install_new_hostos() {
79+
if [ -z "$HOSTOS_UPGRADE_IMG_TAR_SRC" ]; then
80+
echo "No HostOS upgrade image specified, skipping HostOS upgrade."
81+
return
82+
fi
83+
5384
echo "Invoking HostOS upgrade..."
54-
/opt/ic/bin/manageboot.sh hostos upgrade-install "$HOSTOS_UPGRADE_TAR"
85+
/opt/ic/bin/manageboot.sh hostos upgrade-install "$HOSTOS_UPGRADE_IMG_TAR_PATH"
5586
}
5687

5788
install_new_guestos() {
58-
if [ -z "$GUESTOS_IMG" ]; then
89+
if [ -z "$GUESTOS_IMG_TAR_SRC" ]; then
5990
echo "No GuestOS image specified, skipping GuestOS upgrade."
6091
return
6192
fi
6293

6394
echo "Installing GuestOS image..."
6495
mkdir -p "$GUESTOS_EXTRACT_DIR"
65-
tar -xavf "$GUESTOS_TAR" -C "$GUESTOS_EXTRACT_DIR"
96+
tar -xavf "$GUESTOS_IMG_TAR_PATH" -C "$GUESTOS_EXTRACT_DIR"
6697

6798
echo "Stopping GuestOS service..."
6899
systemctl stop guestos.service || true
@@ -83,6 +114,11 @@ mount_target_boot_partition() {
83114
}
84115

85116
setup_config() {
117+
if [ -z "$SETUPOS_CONFIG_IMG_SRC" ]; then
118+
echo "No SetupOS config image provided, skipping configuration setup..."
119+
return
120+
fi
121+
86122
echo "Setting up configuration environment..."
87123

88124
# Mount over existing script dir and use the shipped scripts instead of the ones already deployed on the node
@@ -94,7 +130,7 @@ setup_config() {
94130

95131
# Mount SetupOS config image
96132
mkdir -p "$SETUPOS_CONFIG_MOUNT"
97-
mount "$SETUPOS_CONFIG_IMG" "$SETUPOS_CONFIG_MOUNT"
133+
mount "$SETUPOS_CONFIG_IMG_PATH" "$SETUPOS_CONFIG_MOUNT"
98134

99135
# Preload and create config
100136
/opt/ic/bin/preload-config.sh
@@ -119,25 +155,25 @@ commit_and_reboot() {
119155
--command-line="$boot_args"
120156

121157
echo "Scheduling reboot via kexec..."
122-
nohup bash -c 'sleep 5; systemctl start kexec.target' >/dev/null 2>&1 &
158+
nohup bash -c 'sleep 2; systemctl start kexec.target' >/dev/null 2>&1 &
123159
}
124160

125-
SETUPOS_CONFIG_IMG=""
126-
HOSTOS_UPGRADE_IMG=""
127-
GUESTOS_IMG=""
161+
SETUPOS_CONFIG_IMG_SRC=""
162+
HOSTOS_UPGRADE_IMG_TAR_SRC=""
163+
GUESTOS_IMG_TAR_SRC=""
128164

129165
while [ "$#" -gt 0 ]; do
130166
case "$1" in
131167
--setupos-config-img=*)
132-
SETUPOS_CONFIG_IMG="${1#*=}"
168+
SETUPOS_CONFIG_IMG_SRC="${1#*=}"
133169
shift
134170
;;
135171
--hostos-upgrade-img=*)
136-
HOSTOS_UPGRADE_IMG="${1#*=}"
172+
HOSTOS_UPGRADE_IMG_TAR_SRC="${1#*=}"
137173
shift
138174
;;
139175
--guestos-img=*)
140-
GUESTOS_IMG="${1#*=}"
176+
GUESTOS_IMG_TAR_SRC="${1#*=}"
141177
shift
142178
;;
143179
--)
@@ -147,40 +183,46 @@ while [ "$#" -gt 0 ]; do
147183
*)
148184
echo "Unknown option: $1" >&2
149185
usage
150-
exit 2
186+
exit 1
151187
;;
152188
esac
153189
done
154190

155-
if [ -z "$SETUPOS_CONFIG_IMG" ]; then
156-
echo "Missing required --setupos-config-img argument" >&2
191+
if [ -z "$HOSTOS_UPGRADE_IMG_TAR_SRC" ] && [ -z "$GUESTOS_IMG_TAR_SRC" ] && [ -z "$SETUPOS_CONFIG_IMG_SRC" ]; then
192+
echo "At least one of --hostos-upgrade-img or --guestos-img or --setupos-config-img must be provided" >&2
157193
usage
158-
exit 2
159-
fi
160-
if [ -z "$HOSTOS_UPGRADE_IMG" ]; then
161-
echo "Missing required --hostos-upgrade-img argument" >&2
162-
usage
163-
exit 2
194+
exit 1
164195
fi
165196

166197
trap cleanup EXIT
167198

168199
mount -o remount,rw /
169200
cleanup
170201

171-
download_images
202+
fetch_images
172203
setup_temp_mounts
173204
install_new_hostos
174205
install_new_guestos
175-
176-
# Determine target alternative and mount its boot partition
177-
target_alternative="$(/opt/ic/bin/manageboot.sh hostos target)"
178-
echo "Will update HostOS into: $target_alternative"
179-
mount_target_boot_partition "$target_alternative"
180-
181-
# Read boot arguments from new HostOS
182-
eval "$(cat "$TARGET_BOOT_PARTITION_MOUNT/boot_args")"
183-
boot_args_var=BOOT_ARGS_${target_alternative}
184-
185206
setup_config
186-
commit_and_reboot "${!boot_args_var}"
207+
208+
if [ -n "$HOSTOS_UPGRADE_IMG_TAR_SRC" ]; then
209+
# Determine target alternative and mount its boot partition
210+
target_alternative="$(/opt/ic/bin/manageboot.sh hostos target)"
211+
echo "Will update HostOS into: $target_alternative"
212+
mount_target_boot_partition "$target_alternative"
213+
214+
# Read boot arguments from new HostOS
215+
eval "$(cat "$TARGET_BOOT_PARTITION_MOUNT/boot_args")"
216+
boot_args_var=BOOT_ARGS_${target_alternative}
217+
218+
commit_and_reboot "${!boot_args_var}"
219+
elif [ -n "$SETUPOS_CONFIG_IMG_SRC" ]; then
220+
# Config-only update: reboot with current kernel
221+
echo "Preparing kexec reboot with current kernel..."
222+
kexec -l /boot/vmlinuz --initrd=/boot/initrd.img --reuse-cmdline
223+
nohup bash -c 'sleep 2; systemctl start kexec.target' >/dev/null 2>&1 &
224+
elif [ -n "$GUESTOS_IMG_TAR_SRC" ]; then
225+
echo "Only GuestOS was updated."
226+
echo "Starting GuestOS..."
227+
systemctl start guestos.service
228+
fi
Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,35 @@
1+
load("@rules_rust//cargo:defs.bzl", "cargo_build_script")
12
load("@rules_rust//rust:defs.bzl", "rust_library")
23

34
package(default_visibility = ["//rs:ic-os-pkg"])
45

56
rust_library(
67
name = "bare_metal_deployment",
7-
srcs = ["src/lib.rs"],
8+
srcs = [
9+
"src/deploy.rs",
10+
"src/lib.rs",
11+
],
12+
compile_data = ["//ic-os/testing:reload_hostos_cmd"],
13+
rustc_env = {
14+
"RELOAD_HOSTOS_CMD": "$(execpath //ic-os/testing:reload_hostos_cmd)",
15+
},
16+
target_compatible_with = ["@platforms//os:linux"], # requires Linux-specific dependencies
817
visibility = [
918
"//rs:ic-os-pkg",
1019
"//rs:system-tests-pkg",
1120
],
1221
deps = [
22+
":build_script",
1323
"@crate_index//:anyhow",
24+
"@crate_index//:http",
25+
"@crate_index//:rand",
1426
"@crate_index//:rexpect",
27+
"@crate_index//:slog",
28+
"@crate_index//:ssh2",
1529
],
1630
)
31+
32+
cargo_build_script(
33+
name = "build_script",
34+
srcs = ["build.rs"],
35+
)

rs/ic_os/dev_test_tools/bare_metal_deployment/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,8 @@ name = "bare_metal_deployment"
33
edition = "2021"
44

55
[dependencies]
6-
anyhow = "1.0"
6+
anyhow = { workspace = true }
7+
http = { workspace = true }
8+
rand = { workspace = true }
79
rexpect = { workspace = true }
10+
ssh2 = { workspace = true }
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use std::env;
2+
use std::fs;
3+
use std::path::PathBuf;
4+
5+
fn main() {
6+
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
7+
let dest_path = out_dir.join("reload_hostos_cmd.rs");
8+
9+
if let Ok(path) = env::var("RELOAD_HOSTOS_CMD") {
10+
// Bazel build: include the actual file
11+
let code = format!(
12+
r#"const RELOAD_HOSTOS_CMD: &[u8] = include_bytes!("{}");"#,
13+
path
14+
);
15+
fs::write(&dest_path, code).unwrap();
16+
} else {
17+
// Cargo build: use empty bytes
18+
fs::write(&dest_path, r#"const RELOAD_HOSTOS_CMD: &[u8] = b"";"#).unwrap();
19+
}
20+
}

0 commit comments

Comments
 (0)