Skip to content

Commit fd54c92

Browse files
committed
Add Measurement Corpus artifact
This will be installed for wicket via the installinator document. Skip installing anything for the moment.
1 parent 61ad056 commit fd54c92

File tree

16 files changed

+523
-136
lines changed

16 files changed

+523
-136
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,7 @@ rand_distr = "0.4.3"
647647
rand_seeder = "0.3.0"
648648
range-requests = { path = "range-requests" }
649649
ratatui = "0.29.0"
650+
rats-corim = { git = "https://github.com/oxidecomputer/rats-corim.git", branch = "main" }
650651
rayon = "1.10"
651652
rcgen = "0.12.1"
652653
reconfigurator-cli = { path = "dev-tools/reconfigurator-cli" }
@@ -747,10 +748,10 @@ toml_edit = "0.22.27"
747748
tough = { version = "0.20.0", features = [ "http" ] }
748749
transceiver-controller = { git = "https://github.com/oxidecomputer/transceiver-control", features = [ "api-traits" ] }
749750
trybuild = "1.0.106"
750-
tufaceous = { git = "https://github.com/oxidecomputer/tufaceous", branch = "main" }
751-
tufaceous-artifact = { git = "https://github.com/oxidecomputer/tufaceous", branch = "main", features = ["proptest", "schemars"] }
752-
tufaceous-brand-metadata = { git = "https://github.com/oxidecomputer/tufaceous", branch = "main" }
753-
tufaceous-lib = { git = "https://github.com/oxidecomputer/tufaceous", branch = "main" }
751+
tufaceous = { git = "https://github.com/oxidecomputer/tufaceous", branch = "measurement_corpus_take_2" }
752+
tufaceous-artifact = { git = "https://github.com/oxidecomputer/tufaceous", branch = "measurement_corpus_take_2", features = ["proptest", "schemars"] }
753+
tufaceous-brand-metadata = { git = "https://github.com/oxidecomputer/tufaceous", branch = "measurement_corpus_take_2" }
754+
tufaceous-lib = { git = "https://github.com/oxidecomputer/tufaceous", branch = "measurement_corpus_take_2" }
754755
tui-tree-widget = "0.23.1"
755756
typed-rng = { path = "typed-rng" }
756757
typify = "0.3.0"

dev-tools/releng/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ hex.workspace = true
1717
omicron-pins.workspace = true
1818
omicron-workspace-hack.workspace = true
1919
omicron-zone-package.workspace = true
20+
rats-corim.workspace = true
2021
reqwest.workspace = true
2122
semver.workspace = true
2223
serde.workspace = true

dev-tools/releng/src/hubris.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,19 @@ pub(crate) async fn fetch_hubris_artifacts(
3838

3939
fs::create_dir_all(&output_dir).await?;
4040

41+
// We need to remove our old downloaded corpus to make sure nothing else
42+
// gets added to the repo unexpectedly. This should only really be a
43+
// issue with local builds
44+
if std::fs::exists(&output_dir.join("measurement_corpus"))
45+
.context("failed to check `measurement_corpus`")?
46+
{
47+
std::fs::remove_dir_all(&output_dir.join("measurement_corpus"))
48+
.context("failed to remove `measurement_corpus")?;
49+
}
50+
fs::create_dir_all(&output_dir.join("measurement_corpus"))
51+
.await
52+
.context("Failed to create `measurement_corpus`")?;
53+
4154
// This could be parallelized with FuturesUnordered but in practice this
4255
// takes less time than OS builds.
4356

@@ -106,6 +119,22 @@ pub(crate) async fn fetch_hubris_artifacts(
106119
}
107120
}
108121
}
122+
if let Some(corpus) = hash_manifest.corpus {
123+
let hash = match corpus {
124+
Source::File(file) => file.hash,
125+
_ => anyhow::bail!(
126+
"Unexpected file type: should be a single file, not an RoT"
127+
),
128+
};
129+
let data =
130+
fetch_hash(&logger, base_url, &client, &hash).await?;
131+
fs::write(
132+
output_dir.join("measurement_corpus").join(hash),
133+
data,
134+
)
135+
.await
136+
.context("failed to write file {hash}")?;
137+
}
109138
}
110139
}
111140

@@ -160,6 +189,9 @@ async fn fetch_hash(
160189
struct Manifest {
161190
#[serde(rename = "artifact")]
162191
artifacts: HashMap<KnownArtifactKind, Vec<Artifact>>,
192+
// Add a default for backwards compatibility
193+
#[serde(rename = "measurement_corpus")]
194+
corpus: Option<Source>,
163195
}
164196

165197
#[derive(Deserialize)]

dev-tools/releng/src/tuf.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,46 @@ pub(crate) async fn build_tuf_repo(
7676
}
7777
}
7878

79+
let mut measurement_corpus = vec![];
80+
81+
for entry in std::fs::read_dir(
82+
output_dir.join("hubris-staging").join("measurement_corpus"),
83+
)
84+
.context("failed to read `hubris-staging/measurement_corpus")?
85+
{
86+
let entry = entry?;
87+
88+
let corim = rats_corim::Corim::from_file(entry.path())?;
89+
90+
measurement_corpus.push(DeserializedArtifactData {
91+
name: format!("staging-{}", corim.id),
92+
version: ArtifactVersion::new(corim.get_version()?.clone())?,
93+
source: DeserializedArtifactSource::File {
94+
path: Utf8PathBuf::from_path_buf(entry.path()).unwrap(),
95+
},
96+
});
97+
}
98+
99+
for entry in std::fs::read_dir(
100+
output_dir.join("hubris-production").join("measurement_corpus"),
101+
)
102+
.context("failed to read `hubris-production/measurement_corpus")?
103+
{
104+
let entry = entry?;
105+
let corim = rats_corim::Corim::from_file(entry.path())?;
106+
measurement_corpus.push(DeserializedArtifactData {
107+
name: format!("production-{}", corim.id),
108+
version: ArtifactVersion::new(corim.get_version()?.clone())?,
109+
source: DeserializedArtifactSource::File {
110+
path: Utf8PathBuf::from_path_buf(entry.path()).unwrap(),
111+
},
112+
});
113+
}
114+
115+
manifest
116+
.artifacts
117+
.insert(KnownArtifactKind::MeasurementCorpus, measurement_corpus);
118+
79119
// Add the OS images.
80120
manifest.artifacts.insert(
81121
KnownArtifactKind::Host,
@@ -115,6 +155,7 @@ pub(crate) async fn build_tuf_repo(
115155
.join(format!("{}.tar.gz", package)),
116156
});
117157
}
158+
118159
manifest.artifacts.insert(
119160
KnownArtifactKind::ControlPlane,
120161
vec![DeserializedArtifactData {

installinator-common/src/progress.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,13 @@ pub enum InstallinatorComponent {
5252
/// The control plane component.
5353
ControlPlane,
5454

55-
/// A component that means "both the host and the control plane", used for
56-
/// writes for now. It is possible that this component will go away in the
57-
/// future.
58-
Both,
55+
/// The measurement corpus component
56+
MeasurementCorpus,
57+
58+
/// A component that means "all possible components (host phase 2, control
59+
/// plane, and measurements)", used for writes for now. It is possible
60+
/// that this component will go away in the future.
61+
All,
5962

6063
/// Future variants that might be unknown.
6164
#[serde(other, deserialize_with = "deserialize_ignore_any")]
@@ -194,6 +197,9 @@ pub enum WriteComponent {
194197
/// The control plane component.
195198
ControlPlane,
196199

200+
/// The measurement corpus
201+
MeasurementCorpus,
202+
197203
/// Future variants that might be unknown.
198204
#[serde(other, deserialize_with = "deserialize_ignore_any")]
199205
Unknown,
@@ -205,6 +211,7 @@ impl fmt::Display for WriteComponent {
205211
Self::HostPhase2 => f.write_str("host phase 2"),
206212
Self::ControlPlane => f.write_str("control plane"),
207213
Self::Unknown => f.write_str("unknown"),
214+
Self::MeasurementCorpus => f.write_str("measurement corpus"),
208215
}
209216
}
210217
}
@@ -254,6 +261,8 @@ pub enum WriteError {
254261
#[source]
255262
error: Box<NestedEngineError<ControlPlaneZonesSpec>>,
256263
},
264+
#[error("error creating directory: {error}")]
265+
CreateDirError { error: std::io::Error },
257266
}
258267

259268
impl From<NestedEngineError<ControlPlaneZonesSpec>> for WriteError {
@@ -303,6 +312,12 @@ pub enum ControlPlaneZonesStepId {
303312
/// Writing the zone manifest.
304313
ZoneManifest,
305314

315+
/// Writing the measurement corpus.
316+
Measurement { name: String },
317+
318+
/// Ensure the measurement directory exists
319+
CreateMeasurementDir,
320+
306321
/// Syncing writes to disk.
307322
Fsync,
308323

installinator/src/artifact.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,23 @@ pub(crate) enum LookupIdKind {
111111
Hashes { host_phase_2: ArtifactHash, control_plane: ArtifactHash },
112112
}
113113

114+
#[derive(Clone, Debug)]
115+
pub(crate) struct MeasurementArtifact {
116+
pub(crate) hash: ArtifactHash,
117+
pub(crate) name: String,
118+
}
119+
120+
pub(crate) struct MeasurementArtifactHashId {
121+
pub(crate) hash: ArtifactHashId,
122+
pub(crate) name: String,
123+
}
124+
114125
/// The host phase 2 and control plane hashes to download.
115126
#[derive(Clone, Debug)]
116127
pub(crate) struct ArtifactsToDownload {
117128
pub(crate) host_phase_2: ArtifactHash,
118129
pub(crate) control_plane: ArtifactHash,
130+
pub(crate) measurement_corpus: Vec<MeasurementArtifact>,
119131
}
120132

121133
impl ArtifactsToDownload {
@@ -132,6 +144,20 @@ impl ArtifactsToDownload {
132144
hash: self.control_plane,
133145
}
134146
}
147+
148+
pub(crate) fn measurement_corpus(&self) -> Vec<MeasurementArtifactHashId> {
149+
self.measurement_corpus
150+
.clone()
151+
.into_iter()
152+
.map(|x| MeasurementArtifactHashId {
153+
name: x.name,
154+
hash: ArtifactHashId {
155+
kind: KnownArtifactKind::MeasurementCorpus.into(),
156+
hash: x.hash,
157+
},
158+
})
159+
.collect()
160+
}
135161
}
136162

137163
#[derive(Debug)]

0 commit comments

Comments
 (0)