Skip to content

Commit 390ac60

Browse files
authored
[4/n] [omicron-package] add and use target presets (#7288)
The overall goal of this change is to ensure that all release-related configuration is present in `package-manifest.toml`. This will allow linting and SBOM generation based on this config, rather than the knowledge being scattered across omicron-package and the releng tool.
1 parent 12b65a3 commit 390ac60

File tree

12 files changed

+531
-176
lines changed

12 files changed

+531
-176
lines changed

.github/buildomat/jobs/package.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ ptime -m cargo xtask download softnpu
2828
# Build the test target
2929
export CARGO_INCREMENTAL=0
3030
ptime -m cargo run --locked --release --bin omicron-package -- \
31-
-t test target create -i standard -m non-gimlet -s softnpu -r single-sled
31+
-t test target create -p dev
3232
ptime -m cargo run --locked --release --bin omicron-package -- \
3333
-t test package
3434
mapfile -t packages \

.github/workflows/rust.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ jobs:
5353
- name: Install Pre-Requisites
5454
run: ./tools/install_builder_prerequisites.sh -y
5555
- name: Set default target
56-
run: cargo run --bin omicron-package -- -t default target create -r single-sled
56+
run: cargo run --bin omicron-package -- -t default target create --preset dev
5757
- name: Check build of deployed Omicron packages
5858
run: cargo run --bin omicron-package -- -t default check
5959

Cargo.lock

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

dev-tools/releng/src/main.rs

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -454,8 +454,13 @@ async fn main() -> Result<()> {
454454
artifacts_path.as_str(),
455455
"target",
456456
"create",
457+
"--preset",
458+
target.as_str(),
457459
])
458-
.args(target.target_args())
460+
// Note: Do not override the preset by adding arguments like
461+
// `-m`/`--machine` here, or anywhere else in the releng
462+
// tooling! All release targets must be configured entirely via
463+
// the `target.preset` table in `package-manifest.toml`.
459464
.env_remove("CARGO_MANIFEST_DIR"),
460465
)
461466
.after("omicron-package");
@@ -639,22 +644,6 @@ impl Target {
639644
}
640645
}
641646

642-
fn target_args(self) -> &'static [&'static str] {
643-
match self {
644-
Target::Host => &[
645-
"--image",
646-
"standard",
647-
"--machine",
648-
"gimlet",
649-
"--switch",
650-
"asic",
651-
"--rack-topology",
652-
"multi-sled",
653-
],
654-
Target::Recovery => &["--image", "trampoline"],
655-
}
656-
}
657-
658647
fn proto_packages(
659648
self,
660649
) -> &'static [(&'static PackageName, InstallMethod)] {

docs/how-to-run.adoc

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -332,57 +332,88 @@ In some configurations (not the one described here), it may be necessary to upda
332332

333333
The `omicron-package` tool builds Omicron and bundles all required files into _packages_ that can be copied to another system (if necessary) and installed there. This tool acts on `package-manifest.toml`, which describes the contents of the packages.
334334

335-
Packages have a notion of "build targets", which are used to select between different variants of certain components. A build target is composed of an image type, a machine type, and a switch type:
335+
Packages have a notion of "build targets", which are used to select between different variants of certain components. For example, the Sled Agent can be built for a real Oxide system, for a standalone Gimlet, or for a non-Gimlet system. This choice is represented by the `--machine` setting here:
336336

337337
[source,console]
338338
----
339-
$ cargo run --release --bin omicron-package -- target create -h
340-
Finished release [optimized] target(s) in 0.70s
341-
Running `target/release/omicron-package target create -h`
339+
$ cargo run --release --bin omicron-package -- target create --help
340+
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.55s
341+
Running `target/release/omicron-package target create --help`
342342
Error: Creates a new build target, and sets it as "active"
343343
344-
Usage: omicron-package target create [OPTIONS]
344+
Usage: omicron-package target create [OPTIONS] --preset <PRESET>
345345
346346
Options:
347+
-p, --preset <PRESET>
348+
The preset to use as part of the build (use `dev` for development).
349+
350+
Presets are defined in the `target.preset` section of the config. The other configurations are layered on top of
351+
the preset.
352+
347353
-i, --image <IMAGE>
348-
[default: standard]
354+
The image to use for the target.
355+
356+
If specified, this configuration is layered on top of the preset.
349357
350358
Possible values:
351359
- standard: A typical host OS image
352360
- trampoline: A recovery host OS image, intended to bootstrap a Standard image
353361
354362
-m, --machine <MACHINE>
363+
The kind of machine to build for
364+
355365
Possible values:
356366
- gimlet: Use sled agent configuration for a Gimlet
357367
- gimlet-standalone: Use sled agent configuration for a Gimlet running in isolation
358368
- non-gimlet: Use sled agent configuration for a device emulating a Gimlet
359369
360370
-s, --switch <SWITCH>
371+
The switch to use for the target
372+
361373
Possible values:
362374
- asic: Use the "real" Dendrite, that attempts to interact with the Tofino
363375
- stub: Use a "stub" Dendrite that does not require any real hardware
364376
- softnpu: Use a "softnpu" Dendrite that uses the SoftNPU asic emulator
365377
366378
-r, --rack-topology <RACK_TOPOLOGY>
379+
Specify whether nexus will run in a single-sled or multi-sled environment.
380+
381+
Set single-sled for dev purposes when you're running a single sled-agent. Set multi-sled if you're running with
382+
multiple sleds. Currently this only affects the crucible disk allocation strategy- VM disks will require 3
383+
distinct sleds with `multi-sled`, which will fail in a single-sled environment. `single-sled` relaxes this
384+
requirement.
385+
367386
Possible values:
368387
- multi-sled: Use configurations suitable for a multi-sled deployment, such as dogfood and production racks
369388
- single-sled: Use configurations suitable for a single-sled deployment, such as CI and dev machines
370389
390+
-c, --clickhouse-topology <CLICKHOUSE_TOPOLOGY>
391+
Specify whether clickhouse will be deployed as a replicated cluster or single-node configuration.
392+
393+
Replicated cluster configuration is an experimental feature to be used only for testing.
394+
395+
Possible values:
396+
- replicated-cluster: Use configurations suitable for a replicated ClickHouse cluster deployment
397+
- single-node: Use configurations suitable for a single-node ClickHouse deployment
398+
371399
-h, --help
372400
Print help (see a summary with '-h')
373-
374401
----
375402

376-
To set up a build target for a non-Gimlet machine with simulated (but fully functional) external networking, you would run:
403+
Setting up a target is typically done by selecting a **preset**. Presets are defined in `package-manifest.toml` under `[target.preset]`.
404+
405+
For development purposes, the recommended preset is `dev`. This preset sets up a build target for a non-Gimlet machine with simulated (but fully functional) external networking:
377406

378407
[source,console]
379408
----
380-
$ cargo run --release --bin omicron-package -- -t default target create -i standard -m non-gimlet -s softnpu -r single-sled
409+
$ cargo run --release --bin omicron-package -- -t default target create -p dev
381410
Finished release [optimized] target(s) in 0.66s
382-
Running `target/release/omicron-package -t default target create -i standard -m non-gimlet -s softnpu -r single-sled`
411+
Running `target/release/omicron-package -t default target create -p dev`
383412
Created new build target 'default' and set it as active
384413
----
385414

415+
To customize the target beyond the preset, use the other options (for example, `--image`). These options will override the settings in the preset.
416+
386417
NOTE: The `target create` command will set the new target as active and thus let you omit the `-t` flag in subsequent commands.
387418

388419
To kick off the build and package everything up, you can run:

package-manifest.toml

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -797,7 +797,7 @@ output.intermediate_only = true
797797

798798
# To package and install the asic variant of the switch, do:
799799
#
800-
# $ cargo run --release --bin omicron-package -- -t default target create -i standard -m gimlet -s asic
800+
# $ cargo run --release --bin omicron-package -- -t default target create -p dev -m gimlet -s asic
801801
# $ cargo run --release --bin omicron-package -- package
802802
# $ pfexec ./target/release/omicron-package install
803803
[package.switch-asic]
@@ -825,7 +825,7 @@ output.type = "zone"
825825

826826
# To package and install the stub variant of the switch, do the following:
827827
#
828-
# $ cargo run --release --bin omicron-package -- -t default target create -i standard -m <gimlet|gimlet-standalone|non-gimlet> -s stub
828+
# $ cargo run --release --bin omicron-package -- -t default target create -p dev -m <gimlet|gimlet-standalone|non-gimlet> -s stub
829829
# $ cargo run --release --bin omicron-package -- package
830830
# $ pfexec ./target/release/omicron-package install
831831
[package.switch-stub]
@@ -851,7 +851,7 @@ output.type = "zone"
851851

852852
# To package and install the softnpu variant of the switch, do the following:
853853
#
854-
# $ cargo run --release --bin omicron-package -- -t default target create -i standard -m <gimlet|gimlet-standalone|non-gimlet> -s softnpu
854+
# $ cargo run --release --bin omicron-package -- -t default target create -p dev -m <gimlet|gimlet-standalone|non-gimlet>
855855
# $ cargo run --release --bin omicron-package -- package
856856
# $ pfexec ./target/release/omicron-package install
857857
[package.switch-softnpu]
@@ -934,4 +934,38 @@ source.type = "local"
934934
source.rust.binary_names = ["clickana"]
935935
source.rust.release = true
936936
output.type = "zone"
937-
output.intermediate_only = true
937+
output.intermediate_only = true
938+
939+
# Target configuration
940+
# --------------------
941+
#
942+
# This section defines "targets" built by Omicron. A target is a map of keys and
943+
# values that are used to filter out packages (via `only_for_targets`) and for
944+
# other purposes.
945+
#
946+
# For what the individual keys mean, see the definition for `TargetCommand` in
947+
# `package/src/lib.rs`.
948+
949+
# A preset for the host image built during release.
950+
[target.preset.host]
951+
image = "standard"
952+
machine = "gimlet"
953+
switch = "asic"
954+
rack-topology = "multi-sled"
955+
clickhouse-topology = "single-node"
956+
957+
# A preset for the recovery image built during release.
958+
[target.preset.recovery]
959+
image = "trampoline"
960+
# The trampoline image doesn't execute sled-agent and doesn't contain the switch
961+
# zone, so neither "machine" nor "switch" are defined.
962+
rack-topology = "single-sled"
963+
clickhouse-topology = "single-node"
964+
965+
# A preset for development.
966+
[target.preset.dev]
967+
image = "standard"
968+
machine = "non-gimlet"
969+
switch = "softnpu"
970+
rack-topology = "single-sled"
971+
clickhouse-topology = "single-node"

package/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ clap.workspace = true
1616
futures.workspace = true
1717
hex.workspace = true
1818
illumos-utils.workspace = true
19+
indent_write.workspace = true
1920
indicatif.workspace = true
2021
omicron-workspace-hack.workspace = true
2122
omicron-zone-package.workspace = true

package/src/bin/omicron-package.rs

Lines changed: 28 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@ use clap::{Parser, Subcommand};
1010
use futures::stream::{self, StreamExt, TryStreamExt};
1111
use illumos_utils::{zfs, zone};
1212
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
13-
use omicron_package::cargo_plan::build_cargo_plan;
14-
use omicron_package::config::{Config, ConfigArgs};
15-
use omicron_package::target::{target_command_help, KnownTarget};
16-
use omicron_package::{parse, BuildCommand, DeployCommand, TargetCommand};
17-
use omicron_zone_package::config::{Config as PackageConfig, PackageName};
13+
use omicron_package::cargo_plan::{
14+
build_cargo_plan, do_show_cargo_commands_for_config,
15+
do_show_cargo_commands_for_presets,
16+
};
17+
use omicron_package::config::{BaseConfig, Config, ConfigArgs};
18+
use omicron_package::target::target_command_help;
19+
use omicron_package::{BuildCommand, DeployCommand, TargetCommand};
20+
use omicron_zone_package::config::PackageName;
1821
use omicron_zone_package::package::{Package, PackageOutput, PackageSource};
1922
use omicron_zone_package::progress::Progress;
2023
use omicron_zone_package::target::TargetMap;
@@ -30,7 +33,6 @@ use std::fs::create_dir_all;
3033
use std::sync::{Arc, OnceLock};
3134
use std::time::Duration;
3235
use tokio::io::{AsyncReadExt, AsyncWriteExt, BufReader};
33-
use tokio::process::Command;
3436

3537
const OMICRON_SLED_AGENT: PackageName =
3638
PackageName::new_const("omicron-sled-agent");
@@ -70,49 +72,6 @@ struct Args {
7072
subcommand: SubCommand,
7173
}
7274

73-
async fn do_show_cargo_commands(config: &Config) -> Result<()> {
74-
let metadata = cargo_metadata::MetadataCommand::new().no_deps().exec()?;
75-
let features = config.cargo_features();
76-
let cargo_plan =
77-
build_cargo_plan(&metadata, config.packages_to_build(), &features)?;
78-
79-
let release_command = cargo_plan.release.build_command("build");
80-
let debug_command = cargo_plan.debug.build_command("build");
81-
82-
print!("release command: ");
83-
if let Some(command) = release_command {
84-
println!("{}", command_to_string(&command));
85-
} else {
86-
println!("(none)");
87-
}
88-
89-
print!("debug command: ");
90-
if let Some(command) = debug_command {
91-
println!("{}", command_to_string(&command));
92-
} else {
93-
println!("(none)");
94-
}
95-
96-
Ok(())
97-
}
98-
99-
fn command_to_string(command: &Command) -> String {
100-
// Use shell-words to join the command and arguments into a single string.
101-
let mut v = vec![command
102-
.as_std()
103-
.get_program()
104-
.to_str()
105-
.expect("program is valid UTF-8")];
106-
v.extend(
107-
command
108-
.as_std()
109-
.get_args()
110-
.map(|arg| arg.to_str().expect("argument is valid UTF-8")),
111-
);
112-
113-
shell_words::join(&v)
114-
}
115-
11675
async fn do_for_all_rust_packages(
11776
config: &Config,
11877
command: &str,
@@ -159,6 +118,7 @@ async fn do_list_outputs(
159118
}
160119

161120
async fn do_target(
121+
base_config: &BaseConfig,
162122
artifact_dir: &Utf8Path,
163123
name: Option<&str>,
164124
subcommand: &TargetCommand,
@@ -169,13 +129,15 @@ async fn do_target(
169129
})?;
170130
match subcommand {
171131
TargetCommand::Create {
132+
preset,
172133
image,
173134
machine,
174135
switch,
175136
rack_topology,
176137
clickhouse_topology,
177138
} => {
178-
let target = KnownTarget::new(
139+
let preset_target = base_config.get_preset(preset)?;
140+
let target = preset_target.with_overrides(
179141
image.clone(),
180142
machine.clone(),
181143
switch.clone(),
@@ -269,7 +231,7 @@ async fn replace_active_link(
269231

270232
let dst = target_dir.join(Config::ACTIVE);
271233
if !target_dir.join(src).exists() {
272-
bail!("TargetMap file {} does not exist", src);
234+
bail!("Target file {} does not exist", src);
273235
}
274236
let _ = tokio::fs::remove_file(&dst).await;
275237
tokio::fs::symlink(src, &dst).await.with_context(|| {
@@ -869,7 +831,9 @@ impl Progress for PackageProgress {
869831
#[tokio::main]
870832
async fn main() -> Result<()> {
871833
let args = Args::try_parse()?;
872-
let package_config = parse::<_, PackageConfig>(&args.manifest)?;
834+
let base_config = BaseConfig::load(&args.manifest).with_context(|| {
835+
format!("failed to load base config from {:?}", args.manifest)
836+
})?;
873837

874838
let mut open_options = std::fs::OpenOptions::new();
875839
open_options.write(true).create(true).truncate(true);
@@ -883,9 +847,9 @@ async fn main() -> Result<()> {
883847
let log = Logger::root(drain, o!());
884848

885849
let get_config = || -> Result<Config> {
886-
Config::get_config(
850+
Config::load(
887851
&log,
888-
package_config,
852+
base_config.package_config(),
889853
&args.config_args,
890854
&args.artifact_dir,
891855
)
@@ -903,6 +867,7 @@ async fn main() -> Result<()> {
903867
match args.subcommand {
904868
SubCommand::Build(BuildCommand::Target { subcommand }) => {
905869
do_target(
870+
&base_config,
906871
&args.artifact_dir,
907872
args.config_args.target.as_deref(),
908873
&subcommand,
@@ -930,8 +895,15 @@ async fn main() -> Result<()> {
930895
)
931896
.await?;
932897
}
933-
SubCommand::Build(BuildCommand::ShowCargoCommands) => {
934-
do_show_cargo_commands(&get_config()?).await?;
898+
SubCommand::Build(BuildCommand::ShowCargoCommands { presets }) => {
899+
// If presets is empty, show the commands from the
900+
// default configuration, otherwise show the commands
901+
// for the specified presets.
902+
if let Some(presets) = presets {
903+
do_show_cargo_commands_for_presets(&base_config, &presets)?;
904+
} else {
905+
do_show_cargo_commands_for_config(&get_config()?)?;
906+
}
935907
}
936908
SubCommand::Build(BuildCommand::Check) => {
937909
do_check(&get_config()?).await?

0 commit comments

Comments
 (0)