Skip to content

Commit 5a1abce

Browse files
committed
Use production propolis-server flags in PHD CI builds
We use the dev (e.g. non-release) build of propolis-server in PHD to get debug assertions, which we want, but we should use the `omicron-build` feature to be in line with production binaries. `omicron-build` had also acquired code related to failure injection, which we *also* want in CI so we can test migration failure codepaths. That is moved to a new `failure-injection` feature flag with a bit of ceremony to stop us early if we're ever inadvertently packaging a propolis-server with `omicron-build` and `failure-injection`. Fixes #412.
1 parent cbb33fd commit 5a1abce

File tree

12 files changed

+61
-26
lines changed

12 files changed

+61
-26
lines changed

.github/buildomat/jobs/phd-build.sh

+4-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ rustc --version
3030
# Build the Propolis server binary with 'dev' profile to enable assertions that
3131
# should fire during tests.
3232
banner build-propolis
33-
ptime -m cargo build --verbose -p propolis-server
33+
34+
export PHD_BUILD="true"
35+
ptime -m cargo build --verbose -p propolis-server \
36+
--features omicron-build,failure-injection
3437

3538
# The PHD runner requires unwind-on-panic to catch certain test failures, so
3639
# build it with the 'dev' profile which is so configured.

bin/propolis-server/Cargo.toml

+6
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,9 @@ omicron-build = ["propolis/omicron-build"]
8383

8484
# Falcon builds require corresponding bits turned on in the dependency libs
8585
falcon = ["propolis/falcon"]
86+
87+
# Testing necessitates injecting failures which should hopefully be rare or even
88+
# never occur on real otherwise-unperturbed systems. We conditionally compile
89+
# code supporting failure injection to avoid the risk of somehow injecting
90+
# failures into a real system not under test.
91+
failure-injection = ["propolis/failure-injection"]

bin/propolis-server/src/lib/initializer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ impl MachineInitializer<'_> {
814814
Ok(())
815815
}
816816

817-
#[cfg(not(feature = "omicron-build"))]
817+
#[cfg(feature = "failure-injection")]
818818
pub fn initialize_test_devices(&mut self) {
819819
use propolis::hw::testdev::{
820820
MigrationFailureDevice, MigrationFailures,

bin/propolis-server/src/lib/migrate/preamble.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ impl Preamble {
5252
};
5353

5454
match comp {
55-
#[cfg(feature = "omicron-build")]
55+
#[cfg(not(feature = "failure-injection"))]
5656
ReplacementComponent::MigrationFailureInjector(_) => {
5757
return Err(MigrateError::InstanceSpecsIncompatible(
5858
format!(
@@ -62,7 +62,7 @@ impl Preamble {
6262
));
6363
}
6464

65-
#[cfg(not(feature = "omicron-build"))]
65+
#[cfg(feature = "failure-injection")]
6666
ReplacementComponent::MigrationFailureInjector(comp) => {
6767
let ComponentV0::MigrationFailureInjector(src) = to_amend
6868
else {

bin/propolis-server/src/lib/spec/api_spec_v0.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use super::{
2727
StorageDevice,
2828
};
2929

30-
#[cfg(not(feature = "omicron-build"))]
30+
#[cfg(feature = "failure-injection")]
3131
use super::MigrationFailure;
3232

3333
#[cfg(feature = "falcon")]
@@ -65,7 +65,7 @@ impl From<Spec> for InstanceSpecV0 {
6565
serial,
6666
pci_pci_bridges,
6767
pvpanic,
68-
#[cfg(not(feature = "omicron-build"))]
68+
#[cfg(feature = "failure-injection")]
6969
migration_failure,
7070
#[cfg(feature = "falcon")]
7171
softnpu,
@@ -157,7 +157,7 @@ impl From<Spec> for InstanceSpecV0 {
157157
);
158158
}
159159

160-
#[cfg(not(feature = "omicron-build"))]
160+
#[cfg(feature = "failure-injection")]
161161
if let Some(mig) = migration_failure {
162162
insert_component(
163163
&mut spec,
@@ -310,14 +310,14 @@ impl TryFrom<InstanceSpecV0> for Spec {
310310
// apply it to the builder later.
311311
boot_settings = Some((device_id, settings));
312312
}
313-
#[cfg(feature = "omicron-build")]
313+
#[cfg(not(feature = "failure-injection"))]
314314
ComponentV0::MigrationFailureInjector(_) => {
315315
return Err(ApiSpecError::FeatureCompiledOut {
316316
component: device_id,
317-
feature: "omicron-build",
317+
feature: "failure-injection",
318318
});
319319
}
320-
#[cfg(not(feature = "omicron-build"))]
320+
#[cfg(feature = "failure-injection")]
321321
ComponentV0::MigrationFailureInjector(mig) => {
322322
builder.add_migration_failure_device(MigrationFailure {
323323
id: device_id,

bin/propolis-server/src/lib/spec/builder.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use super::{
2626
Board, BootOrderEntry, BootSettings, Disk, Nic, QemuPvpanic, SerialPort,
2727
};
2828

29-
#[cfg(not(feature = "omicron-build"))]
29+
#[cfg(feature = "failure-injection")]
3030
use super::MigrationFailure;
3131

3232
#[cfg(feature = "falcon")]
@@ -50,7 +50,7 @@ pub(crate) enum SpecBuilderError {
5050
#[error("pvpanic device already specified")]
5151
PvpanicInUse,
5252

53-
#[cfg(not(feature = "omicron-build"))]
53+
#[cfg(feature = "failure-injection")]
5454
#[error("migration failure injection already enabled")]
5555
MigrationFailureInjectionInUse,
5656

@@ -269,7 +269,7 @@ impl SpecBuilder {
269269
Ok(self)
270270
}
271271

272-
#[cfg(not(feature = "omicron-build"))]
272+
#[cfg(feature = "failure-injection")]
273273
pub fn add_migration_failure_device(
274274
&mut self,
275275
mig: MigrationFailure,

bin/propolis-server/src/lib/spec/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use propolis_api_types::instance_spec::{
3434
};
3535
use thiserror::Error;
3636

37-
#[cfg(not(feature = "omicron-build"))]
37+
#[cfg(feature = "failure-injection")]
3838
use propolis_api_types::instance_spec::components::devices::MigrationFailureInjector;
3939

4040
#[cfg(feature = "falcon")]
@@ -73,7 +73,7 @@ pub(crate) struct Spec {
7373
pub pci_pci_bridges: BTreeMap<SpecKey, PciPciBridge>,
7474
pub pvpanic: Option<QemuPvpanic>,
7575

76-
#[cfg(not(feature = "omicron-build"))]
76+
#[cfg(feature = "failure-injection")]
7777
pub migration_failure: Option<MigrationFailure>,
7878

7979
#[cfg(feature = "falcon")]
@@ -285,7 +285,7 @@ pub struct QemuPvpanic {
285285
pub spec: QemuPvpanicDesc,
286286
}
287287

288-
#[cfg(not(feature = "omicron-build"))]
288+
#[cfg(feature = "failure-injection")]
289289
#[derive(Clone, Debug)]
290290
pub struct MigrationFailure {
291291
pub id: SpecKey,

bin/propolis-server/src/lib/vm/ensure.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -564,10 +564,8 @@ async fn initialize_vm_objects(
564564
))?;
565565
init.initialize_network_devices(&chipset).await?;
566566

567-
#[cfg(not(feature = "omicron-build"))]
567+
#[cfg(feature = "failure-injection")]
568568
init.initialize_test_devices();
569-
#[cfg(feature = "omicron-build")]
570-
info!(log, "`omicron-build` feature enabled, ignoring any test devices");
571569

572570
#[cfg(feature = "falcon")]
573571
{

bin/propolis-server/src/main.rs

+13
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,19 @@ fn main() -> anyhow::Result<()> {
278278
// Ensure proper setup of USDT probes
279279
register_probes().unwrap();
280280

281+
#[cfg(all(
282+
feature = "omicron-build",
283+
any(feature = "failure-injection", feature = "falcon")
284+
))]
285+
if option_env!("PHD_BUILD") != Some("true") {
286+
panic!(
287+
"`omicron-build` is enabled alongside development features, \
288+
this build is NOT SUITABLE for production. Set PHD_BUILD=true in \
289+
the environment and rebuild propolis-server if you really need \
290+
this to work."
291+
);
292+
}
293+
281294
// Command line arguments.
282295
let args = Args::parse();
283296

crates/propolis-api-types/src/instance_spec/components/devices.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,8 @@ pub struct P9fs {
193193
/// Describes a synthetic device that registers for VM lifecycle notifications
194194
/// and returns errors during attempts to migrate.
195195
///
196-
/// This is only supported by Propolis servers compiled without the
197-
/// `omicron-build` feature.
196+
/// This is only supported by Propolis servers compiled with the
197+
/// `failure-injection` feature.
198198
#[derive(Clone, Deserialize, Serialize, Debug, JsonSchema)]
199199
#[serde(deny_unknown_fields)]
200200
pub struct MigrationFailureInjector {

lib/propolis/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,5 @@ falcon = ["libloading", "p9ds", "dlpi", "ispf", "rand", "softnpu", "viona_api/fa
6161
# TODO until crucible#1280 is addressed, enabling Nexus notifications is done
6262
# through a feature flag.
6363
omicron-build = ["crucible/notify-nexus"]
64+
65+
failure-injection = []

xtask/src/task_phd.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use anyhow::Context;
66
use camino::{Utf8Path, Utf8PathBuf};
7-
use std::{fs, process::Command, time};
7+
use std::{collections::HashMap, fs, process::Command, time};
88

99
macro_rules! cargo_log {
1010
($tag:literal, $($arg:tt)*) => {
@@ -270,15 +270,15 @@ impl Cmd {
270270
return Ok(());
271271
}
272272
Self::List { phd_args } => {
273-
let phd_runner = build_bin("phd-runner", false)?;
273+
let phd_runner = build_bin("phd-runner", false, None)?;
274274
let status = run_exit_code(
275275
phd_runner.command().arg("list").args(phd_args),
276276
)?;
277277
std::process::exit(status);
278278
}
279279

280280
Self::RunnerHelp { phd_args } => {
281-
let phd_runner = build_bin("phd-runner", false)?;
281+
let phd_runner = build_bin("phd-runner", false, None)?;
282282
let status = run_exit_code(
283283
phd_runner.command().arg("help").args(phd_args),
284284
)?;
@@ -292,7 +292,14 @@ impl Cmd {
292292
cmd
293293
}
294294
None => {
295-
let bin = build_bin("propolis-server", propolis_args.release)?;
295+
let mut server_build_env = HashMap::new();
296+
server_build_env
297+
.insert("PHD_BUILD".to_string(), "true".to_string());
298+
let bin = build_bin(
299+
"propolis-server",
300+
propolis_args.release,
301+
Some(server_build_env),
302+
)?;
296303
let path = bin
297304
.path()
298305
.try_into()
@@ -345,7 +352,7 @@ impl Cmd {
345352
anyhow::bail!("Missing artifacts config `{artifacts_toml}`!");
346353
}
347354

348-
let phd_runner = build_bin("phd-runner", false)?;
355+
let phd_runner = build_bin("phd-runner", false, None)?;
349356
let mut cmd = if cfg!(target_os = "illumos") {
350357
let mut cmd = Command::new("pfexec");
351358
cmd.arg(phd_runner.path());
@@ -421,12 +428,18 @@ impl BasePropolisArgs {
421428
fn build_bin(
422429
name: impl AsRef<str>,
423430
release: bool,
431+
build_env: Option<HashMap<String, String>>,
424432
) -> anyhow::Result<escargot::CargoRun> {
425433
let name = name.as_ref();
426434
cargo_log!("Compiling", "{name}");
427435

428436
let mut cmd =
429437
escargot::CargoBuild::new().package(name).bin(name).current_target();
438+
if let Some(env) = build_env {
439+
for (k, v) in env {
440+
cmd = cmd.env(k, v);
441+
}
442+
}
430443
let profile = if release {
431444
cmd = cmd.release();
432445
"release [optimized]"

0 commit comments

Comments
 (0)