diff --git a/Cargo.lock b/Cargo.lock index 4a4684ef72..acd1d7ec7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12645,7 +12645,7 @@ dependencies = [ [[package]] name = "tufaceous" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/tufaceous?branch=main#0ae289102f0fe2605781afcb4c5395652a9c842b" +source = "git+https://github.com/oxidecomputer/tufaceous?branch=measurement_corpus#8d8b48dc57cd47703a328c00a3abcf31f366987a" dependencies = [ "anyhow", "camino", @@ -12666,7 +12666,7 @@ dependencies = [ [[package]] name = "tufaceous-artifact" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/tufaceous?branch=main#0ae289102f0fe2605781afcb4c5395652a9c842b" +source = "git+https://github.com/oxidecomputer/tufaceous?branch=measurement_corpus#8d8b48dc57cd47703a328c00a3abcf31f366987a" dependencies = [ "daft", "parse-display", @@ -12683,7 +12683,7 @@ dependencies = [ [[package]] name = "tufaceous-brand-metadata" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/tufaceous?branch=main#0ae289102f0fe2605781afcb4c5395652a9c842b" +source = "git+https://github.com/oxidecomputer/tufaceous?branch=measurement_corpus#8d8b48dc57cd47703a328c00a3abcf31f366987a" dependencies = [ "semver 1.0.25", "serde", @@ -12695,7 +12695,7 @@ dependencies = [ [[package]] name = "tufaceous-lib" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/tufaceous?branch=main#0ae289102f0fe2605781afcb4c5395652a9c842b" +source = "git+https://github.com/oxidecomputer/tufaceous?branch=measurement_corpus#8d8b48dc57cd47703a328c00a3abcf31f366987a" dependencies = [ "anyhow", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index fa68313586..32bf7d0837 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -684,10 +684,10 @@ toml_edit = "0.22.24" tough = { version = "0.20.0", features = [ "http" ] } transceiver-controller = { git = "https://github.com/oxidecomputer/transceiver-control", features = [ "api-traits" ] } trybuild = "1.0.103" -tufaceous = { git = "https://github.com/oxidecomputer/tufaceous", branch = "main" } -tufaceous-artifact = { git = "https://github.com/oxidecomputer/tufaceous", branch = "main", features = ["proptest", "schemars"] } -tufaceous-brand-metadata = { git = "https://github.com/oxidecomputer/tufaceous", branch = "main" } -tufaceous-lib = { git = "https://github.com/oxidecomputer/tufaceous", branch = "main" } +tufaceous = { git = "https://github.com/oxidecomputer/tufaceous", branch = "measurement_corpus" } +tufaceous-artifact = { git = "https://github.com/oxidecomputer/tufaceous", branch = "measurement_corpus", features = ["proptest", "schemars"] } +tufaceous-brand-metadata = { git = "https://github.com/oxidecomputer/tufaceous", branch = "measurement_corpus" } +tufaceous-lib = { git = "https://github.com/oxidecomputer/tufaceous", branch = "measurement_corpus" } tui-tree-widget = "0.23.0" typed-rng = { path = "typed-rng" } typify = "0.3.0" diff --git a/dev-tools/releng/src/tuf.rs b/dev-tools/releng/src/tuf.rs index 499f91e8af..05692376ba 100644 --- a/dev-tools/releng/src/tuf.rs +++ b/dev-tools/releng/src/tuf.rs @@ -111,12 +111,23 @@ pub(crate) async fn build_tuf_repo( .join(format!("{}.tar.gz", package)), }); } + + // XXX fixme + let measurement_corpus = vec![ + DeserailzedControlPlanZoneSource::File { + file_name: "test_manifest.cbor", + path: format!("/home/labbott/omicron/Cargo.toml"), + } + ]; manifest.artifacts.insert( KnownArtifactKind::ControlPlane, vec![DeserializedArtifactData { name: "control-plane".to_string(), version: artifact_version.clone(), - source: DeserializedArtifactSource::CompositeControlPlane { zones }, + source: DeserializedArtifactSource::CompositeControlPlane { + zones, + measurement_corpus, + }, }], ); diff --git a/installinator-common/src/progress.rs b/installinator-common/src/progress.rs index cafed7a7f4..62bc67995d 100644 --- a/installinator-common/src/progress.rs +++ b/installinator-common/src/progress.rs @@ -294,6 +294,9 @@ pub enum ControlPlaneZonesStepId { /// Writing a zone. Zone { name: String }, + /// Writing a measurement corpus + MeasurementCorpus { name: String }, + /// Syncing writes to disk. Fsync, diff --git a/installinator/src/write.rs b/installinator/src/write.rs index 506fc33b0e..a4d23fc75f 100644 --- a/installinator/src/write.rs +++ b/installinator/src/write.rs @@ -667,6 +667,34 @@ impl ControlPlaneZoneWriteContext<'_> { .register(); } + for (name, data) in &self.zones.measurement_corpus { + let out_path = self.output_directory.join(name); + transport = engine + .new_step( + WriteComponent::ControlPlane, + ControlPlaneZonesStepId::MeasurementCorpus { name: name.clone() }, + format!("Writing measurement corpus {name}"), + async move |cx| { + let transport = transport.into_value(cx.token()).await; + write_artifact_impl( + WriteComponent::ControlPlane, + slot, + data.clone().into(), + &out_path, + transport, + &cx, + ) + .await?; + + StepSuccess::new(transport).into() + }, + ) + .register(); + } + + + + // XXX here is where we can write the corpus // `fsync()` the directory to ensure the directory entries for all the // files we just created are written to disk. let output_directory = self.output_directory.to_path_buf(); @@ -1106,6 +1134,7 @@ mod tests { destination_control_plane.file_name().unwrap().to_string(), artifact_control_plane.iter().flatten().copied().collect(), )], + measurement_corpus: vec![], }; let mut writer = ArtifactWriter::new( diff --git a/update-common/src/artifacts/update_plan.rs b/update-common/src/artifacts/update_plan.rs index 6db6f10f7c..cc2d5f26a9 100644 --- a/update-common/src/artifacts/update_plan.rs +++ b/update-common/src/artifacts/update_plan.rs @@ -38,6 +38,7 @@ use tokio::runtime::Handle; use tufaceous_artifact::ArtifactKind; use tufaceous_artifact::ArtifactVersion; use tufaceous_artifact::KnownArtifactKind; +use tufaceous_lib::ControlPlaneEntry; use tufaceous_lib::ControlPlaneZoneImages; use tufaceous_lib::HostPhaseImages; use tufaceous_lib::RotArchives; @@ -256,9 +257,9 @@ impl<'a> UpdatePlanBuilder<'a> { ) .await } - KnownArtifactKind::Zone => { + KnownArtifactKind::Zone | KnownArtifactKind::MeasurementCorpus => { // We don't currently support repos with already split-out - // zones. + // zones and manifest. self.add_unknown_artifact(artifact_id, artifact_hash, stream) .await } @@ -286,7 +287,8 @@ impl<'a> UpdatePlanBuilder<'a> { | KnownArtifactKind::SwitchRot | KnownArtifactKind::GimletRotBootloader | KnownArtifactKind::PscRotBootloader - | KnownArtifactKind::SwitchRotBootloader => unreachable!(), + | KnownArtifactKind::SwitchRotBootloader + | KnownArtifactKind::MeasurementCorpus => unreachable!(), }; let mut stream = std::pin::pin!(stream); @@ -379,7 +381,8 @@ impl<'a> UpdatePlanBuilder<'a> { | KnownArtifactKind::SwitchRot | KnownArtifactKind::GimletSp | KnownArtifactKind::PscSp - | KnownArtifactKind::SwitchSp => unreachable!(), + | KnownArtifactKind::SwitchSp + | KnownArtifactKind::MeasurementCorpus => unreachable!(), }; let mut stream = std::pin::pin!(stream); @@ -474,7 +477,8 @@ impl<'a> UpdatePlanBuilder<'a> { | KnownArtifactKind::SwitchSp | KnownArtifactKind::GimletRotBootloader | KnownArtifactKind::SwitchRotBootloader - | KnownArtifactKind::PscRotBootloader => unreachable!(), + | KnownArtifactKind::PscRotBootloader + | KnownArtifactKind::MeasurementCorpus => unreachable!(), }; let (rot_a_data, rot_b_data) = Self::extract_nested_artifact_pair( @@ -913,12 +917,18 @@ impl<'a> UpdatePlanBuilder<'a> { &mut self, reader: impl io::Read, ) -> Result<(), RepositoryError> { - ControlPlaneZoneImages::extract_into(reader, |_, reader| { + ControlPlaneZoneImages::extract_into(reader, |_, kind, reader| { + let known_kind = match kind { + ControlPlaneEntry::Zone => KnownArtifactKind::Zone, + ControlPlaneEntry::MeasurementCorpus => { + KnownArtifactKind::MeasurementCorpus + } + }; let mut out = self.extracted_artifacts.new_tempfile()?; io::copy(reader, &mut out)?; let data = self .extracted_artifacts - .store_tempfile(KnownArtifactKind::Zone.into(), out)?; + .store_tempfile(known_kind.into(), out)?; // Read the zone name and version from the `oxide.json` at the root // of the zone. @@ -934,12 +944,12 @@ impl<'a> UpdatePlanBuilder<'a> { let artifact_id = ArtifactId { name: info.pkg.clone(), version: ArtifactVersion::new(info.version.to_string())?, - kind: KnownArtifactKind::Zone.into(), + kind: known_kind.into(), }; self.record_extracted_artifact( artifact_id, data, - KnownArtifactKind::Zone.into(), + known_kind.into(), self.log, )?; Ok(())