Skip to content

Commit 19b92d1

Browse files
authored
[installinator] add support for fetching an installinator document (#8733)
Prepare for future work where we're going to transmit other kinds of artifacts over the wire to installinator -- not just host phase 2 and control plane. For compatibility, installinator supports repos both with and without this document. In the future we can clean this up.
1 parent d581075 commit 19b92d1

File tree

17 files changed

+561
-103
lines changed

17 files changed

+561
-103
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,7 @@ opt-level = 3
969969
# tufaceous-artifact = { path = "../tufaceous/artifact" }
970970
# tufaceous-brand-metadata = { path = "../tufaceous/brand-metadata" }
971971
# tufaceous-lib = { path = "../tufaceous/lib" }
972+
# Extra slash here to pretend to be a different source.
972973

973974
# [patch."https://github.com/oxidecomputer/typify"]
974975
# typify = { path = "../typify/typify" }

dev-tools/reconfigurator-cli/tests/output/cmds-mupdate-update-flow-stdout

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ created repo-1.0.0.zip for system version 1.0.0
1717
> set target-release repo-1.0.0.zip
1818
INFO extracting uploaded archive to <EXTRACTING_UPLOADED_ARCHIVE_TO_REDACTED>
1919
INFO created directory to store extracted artifacts, path: <CREATED_DIRECTORY_TO_STORE_EXTRACTED_ARTIFACTS_PATH_REDACTED>
20+
INFO added artifact, name: installinator_document, kind: installinator_document, version: 1.0.0, hash: c6ae866031d1183094c92cde9d9d1fd5f18356abc81a842ce31471b473fd5582, length: 367
2021
INFO added artifact, name: SimGimletSp, kind: gimlet_sp, version: 1.0.0, hash: 7e6667e646ad001b54c8365a3d309c03f89c59102723d38d01697ee8079fe670, length: 747
2122
INFO added artifact, name: fake-gimlet-rot, kind: gimlet_rot_image_a, version: 1.0.0, hash: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a, length: 735
2223
INFO added artifact, name: fake-gimlet-rot, kind: gimlet_rot_image_b, version: 1.0.0, hash: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a, length: 735
@@ -818,6 +819,7 @@ set sled 98e6b7c2-2efa-41ca-b20a-0a4d61102fe6 inventory visibility: visible -> h
818819
> set target-release repo-1.0.0.zip
819820
INFO extracting uploaded archive to <EXTRACTING_UPLOADED_ARCHIVE_TO_REDACTED>
820821
INFO created directory to store extracted artifacts, path: <CREATED_DIRECTORY_TO_STORE_EXTRACTED_ARTIFACTS_PATH_REDACTED>
822+
INFO added artifact, name: installinator_document, kind: installinator_document, version: 1.0.0, hash: c6ae866031d1183094c92cde9d9d1fd5f18356abc81a842ce31471b473fd5582, length: 367
821823
INFO added artifact, name: SimGimletSp, kind: gimlet_sp, version: 1.0.0, hash: 7e6667e646ad001b54c8365a3d309c03f89c59102723d38d01697ee8079fe670, length: 747
822824
INFO added artifact, name: fake-gimlet-rot, kind: gimlet_rot_image_a, version: 1.0.0, hash: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a, length: 735
823825
INFO added artifact, name: fake-gimlet-rot, kind: gimlet_rot_image_b, version: 1.0.0, hash: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a, length: 735
@@ -1018,6 +1020,7 @@ created repo-2.0.0.zip for system version 2.0.0
10181020
> sled-update-install-dataset serial2 --from-repo repo-2.0.0.zip
10191021
INFO extracting uploaded archive to <EXTRACTING_UPLOADED_ARCHIVE_TO_REDACTED>
10201022
INFO created directory to store extracted artifacts, path: <CREATED_DIRECTORY_TO_STORE_EXTRACTED_ARTIFACTS_PATH_REDACTED>
1023+
INFO added artifact, name: installinator_document, kind: installinator_document, version: 2.0.0, hash: 065b2b7cde09474c9a1bcf98a8f9c93129f617e074404c6aa76164f440a5627f, length: 367
10211024
INFO added artifact, name: fake-gimlet-sp, kind: gimlet_sp, version: 2.0.0, hash: ce1e98a8a9ae541654508f101d59a3ddeba3d28177f1d42d5614248eef0b820b, length: 751
10221025
INFO added artifact, name: fake-gimlet-rot, kind: gimlet_rot_image_a, version: 2.0.0, hash: e7047f500a5391e22cd8e6a8d3ae66c9d9de7a8d021e6e9a10e05bb6d554da77, length: 743
10231026
INFO added artifact, name: fake-gimlet-rot, kind: gimlet_rot_image_b, version: 2.0.0, hash: e7047f500a5391e22cd8e6a8d3ae66c9d9de7a8d021e6e9a10e05bb6d554da77, length: 743
@@ -1714,6 +1717,7 @@ external DNS:
17141717
> set target-release repo-2.0.0.zip
17151718
INFO extracting uploaded archive to <EXTRACTING_UPLOADED_ARCHIVE_TO_REDACTED>
17161719
INFO created directory to store extracted artifacts, path: <CREATED_DIRECTORY_TO_STORE_EXTRACTED_ARTIFACTS_PATH_REDACTED>
1720+
INFO added artifact, name: installinator_document, kind: installinator_document, version: 2.0.0, hash: 065b2b7cde09474c9a1bcf98a8f9c93129f617e074404c6aa76164f440a5627f, length: 367
17171721
INFO added artifact, name: fake-gimlet-sp, kind: gimlet_sp, version: 2.0.0, hash: ce1e98a8a9ae541654508f101d59a3ddeba3d28177f1d42d5614248eef0b820b, length: 751
17181722
INFO added artifact, name: fake-gimlet-rot, kind: gimlet_rot_image_a, version: 2.0.0, hash: e7047f500a5391e22cd8e6a8d3ae66c9d9de7a8d021e6e9a10e05bb6d554da77, length: 743
17191723
INFO added artifact, name: fake-gimlet-rot, kind: gimlet_rot_image_b, version: 2.0.0, hash: e7047f500a5391e22cd8e6a8d3ae66c9d9de7a8d021e6e9a10e05bb6d554da77, length: 743

dev-tools/reconfigurator-cli/tests/output/cmds-noop-image-source-stdout

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ created repo-2.0.0.zip for system version 2.0.0
3939
> set target-release repo-1.0.0.zip
4040
INFO extracting uploaded archive to <EXTRACTING_UPLOADED_ARCHIVE_TO_REDACTED>
4141
INFO created directory to store extracted artifacts, path: <CREATED_DIRECTORY_TO_STORE_EXTRACTED_ARTIFACTS_PATH_REDACTED>
42+
INFO added artifact, name: installinator_document, kind: installinator_document, version: 1.0.0, hash: c6ae866031d1183094c92cde9d9d1fd5f18356abc81a842ce31471b473fd5582, length: 367
4243
INFO added artifact, name: SimGimletSp, kind: gimlet_sp, version: 1.0.0, hash: 7e6667e646ad001b54c8365a3d309c03f89c59102723d38d01697ee8079fe670, length: 747
4344
INFO added artifact, name: fake-gimlet-rot, kind: gimlet_rot_image_a, version: 1.0.0, hash: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a, length: 735
4445
INFO added artifact, name: fake-gimlet-rot, kind: gimlet_rot_image_b, version: 1.0.0, hash: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a, length: 735
@@ -103,6 +104,7 @@ sled aff6c093-197d-42c5-ad80-9f10ba051a34: install dataset updated: to target re
103104
> sled-update-install-dataset serial4 --from-repo repo-2.0.0.zip
104105
INFO extracting uploaded archive to <EXTRACTING_UPLOADED_ARCHIVE_TO_REDACTED>
105106
INFO created directory to store extracted artifacts, path: <CREATED_DIRECTORY_TO_STORE_EXTRACTED_ARTIFACTS_PATH_REDACTED>
107+
INFO added artifact, name: installinator_document, kind: installinator_document, version: 2.0.0, hash: 065b2b7cde09474c9a1bcf98a8f9c93129f617e074404c6aa76164f440a5627f, length: 367
106108
INFO added artifact, name: fake-gimlet-sp, kind: gimlet_sp, version: 2.0.0, hash: ce1e98a8a9ae541654508f101d59a3ddeba3d28177f1d42d5614248eef0b820b, length: 751
107109
INFO added artifact, name: fake-gimlet-rot, kind: gimlet_rot_image_a, version: 2.0.0, hash: e7047f500a5391e22cd8e6a8d3ae66c9d9de7a8d021e6e9a10e05bb6d554da77, length: 743
108110
INFO added artifact, name: fake-gimlet-rot, kind: gimlet_rot_image_b, version: 2.0.0, hash: e7047f500a5391e22cd8e6a8d3ae66c9d9de7a8d021e6e9a10e05bb6d554da77, length: 743

dev-tools/reconfigurator-cli/tests/output/cmds-target-release-stdout

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ created repo-1.0.0.zip for system version 1.0.0
3232
> set target-release repo-1.0.0.zip
3333
INFO extracting uploaded archive to <EXTRACTING_UPLOADED_ARCHIVE_TO_REDACTED>
3434
INFO created directory to store extracted artifacts, path: <CREATED_DIRECTORY_TO_STORE_EXTRACTED_ARTIFACTS_PATH_REDACTED>
35+
INFO added artifact, name: installinator_document, kind: installinator_document, version: 1.0.0, hash: c6ae866031d1183094c92cde9d9d1fd5f18356abc81a842ce31471b473fd5582, length: 367
3536
INFO added artifact, name: SimGimletSp, kind: gimlet_sp, version: 1.0.0, hash: 7e6667e646ad001b54c8365a3d309c03f89c59102723d38d01697ee8079fe670, length: 747
3637
INFO added artifact, name: fake-gimlet-rot, kind: gimlet_rot_image_a, version: 1.0.0, hash: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a, length: 735
3738
INFO added artifact, name: fake-gimlet-rot, kind: gimlet_rot_image_b, version: 1.0.0, hash: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a, length: 735
@@ -70,6 +71,7 @@ internal DNS generations: 1
7071
external DNS generations: 1
7172
target number of Nexus instances: default
7273
target release (generation 2): 1.0.0 (system-update-v1.0.0.zip)
74+
artifact: c6ae866031d1183094c92cde9d9d1fd5f18356abc81a842ce31471b473fd5582 installinator_document (installinator_document version 1.0.0)
7375
artifact: 7e6667e646ad001b54c8365a3d309c03f89c59102723d38d01697ee8079fe670 gimlet_sp (SimGimletSp version 1.0.0)
7476
artifact: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a gimlet_rot_image_a (fake-gimlet-rot version 1.0.0)
7577
artifact: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a gimlet_rot_image_b (fake-gimlet-rot version 1.0.0)
@@ -147,6 +149,7 @@ internal DNS generations: 1
147149
external DNS generations: 1
148150
target number of Nexus instances: default
149151
target release (generation 2): 1.0.0 (system-update-v1.0.0.zip)
152+
artifact: c6ae866031d1183094c92cde9d9d1fd5f18356abc81a842ce31471b473fd5582 installinator_document (installinator_document version 1.0.0)
150153
artifact: 7e6667e646ad001b54c8365a3d309c03f89c59102723d38d01697ee8079fe670 gimlet_sp (SimGimletSp version 1.0.0)
151154
artifact: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a gimlet_rot_image_a (fake-gimlet-rot version 1.0.0)
152155
artifact: 04e4a7fdb84acca92c8fd3235e26d64ea61bef8a5f98202589fd346989c5720a gimlet_rot_image_b (fake-gimlet-rot version 1.0.0)

dev-tools/releng/src/tuf.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ pub(crate) async fn build_tuf_repo(
143143
manifest,
144144
keys,
145145
expiry,
146+
true,
146147
output_dir.join("repo.zip"),
147148
)
148149
.build()

installinator-common/src/progress.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ impl StepSpec for InstallinatorSpec {
4343
)]
4444
#[serde(rename_all = "snake_case")]
4545
pub enum InstallinatorComponent {
46+
/// The installinator document.
47+
InstallinatorDocument,
48+
4649
/// The host phase 2 component.
4750
HostPhase2,
4851

installinator/src/artifact.rs

Lines changed: 86 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,19 @@ use installinator_common::EventReport;
1212
use ipcc::{InstallinatorImageId, Ipcc};
1313
use omicron_uuid_kinds::MupdateUuid;
1414
use tokio::sync::mpsc;
15-
use tufaceous_artifact::{ArtifactHash, ArtifactHashId};
15+
use tufaceous_artifact::{
16+
ArtifactHash, ArtifactHashId, ArtifactKind, KnownArtifactKind,
17+
};
1618

1719
use crate::{errors::HttpError, fetch::FetchReceiver};
1820

1921
#[derive(Clone, Debug, Eq, PartialEq, Args)]
2022
pub(crate) struct ArtifactIdOpts {
2123
/// Retrieve artifact ID from IPCC
22-
#[clap(long, required_unless_present_any = ["update_id", "host_phase_2", "control_plane"])]
24+
#[clap(
25+
long,
26+
required_unless_present_any = ["update_id", "host_phase_2", "control_plane", "installinator_doc"]
27+
)]
2328
from_ipcc: bool,
2429

2530
#[clap(
@@ -31,31 +36,100 @@ pub(crate) struct ArtifactIdOpts {
3136

3237
#[clap(
3338
long,
34-
conflicts_with = "from_ipcc",
35-
required_unless_present = "from_ipcc"
39+
conflicts_with_all = ["from_ipcc", "installinator_doc"],
40+
required_unless_present_any = ["from_ipcc", "installinator_doc"],
3641
)]
3742
host_phase_2: Option<ArtifactHash>,
3843

3944
#[clap(
4045
long,
41-
conflicts_with = "from_ipcc",
42-
required_unless_present = "from_ipcc"
46+
conflicts_with_all = ["from_ipcc", "installinator_doc"],
47+
required_unless_present_any = ["from_ipcc", "installinator_doc"],
4348
)]
4449
control_plane: Option<ArtifactHash>,
50+
51+
#[clap(
52+
long,
53+
conflicts_with_all = ["from_ipcc", "host_phase_2", "control_plane"],
54+
required_unless_present_any = ["from_ipcc", "host_phase_2", "control_plane"],
55+
)]
56+
installinator_doc: Option<ArtifactHash>,
4557
}
4658

4759
impl ArtifactIdOpts {
48-
pub(crate) fn resolve(&self) -> Result<InstallinatorImageId> {
60+
pub(crate) fn resolve(&self) -> Result<LookupId> {
4961
if self.from_ipcc {
5062
let ipcc = Ipcc::new().context("error opening IPCC")?;
51-
ipcc.installinator_image_id()
52-
.context("error retrieving installinator image ID")
63+
let image_id = ipcc
64+
.installinator_image_id()
65+
.context("error retrieving installinator image ID")?;
66+
Ok(LookupId::from_image_id(&image_id))
5367
} else {
5468
let update_id = self.update_id.unwrap();
55-
let host_phase_2 = self.host_phase_2.unwrap();
56-
let control_plane = self.control_plane.unwrap();
69+
let kind =
70+
if let Some(installinator_doc_hash) = self.installinator_doc {
71+
LookupIdKind::Document(installinator_doc_hash)
72+
} else {
73+
LookupIdKind::Hashes {
74+
host_phase_2: self.host_phase_2.unwrap(),
75+
control_plane: self.control_plane.unwrap(),
76+
}
77+
};
78+
79+
Ok(LookupId { update_id, kind })
80+
}
81+
}
82+
}
83+
84+
/// Identifiers used by installinator to retrieve artifacts.
85+
pub(crate) struct LookupId {
86+
pub(crate) update_id: MupdateUuid,
87+
pub(crate) kind: LookupIdKind,
88+
}
89+
90+
impl LookupId {
91+
fn from_image_id(image_id: &InstallinatorImageId) -> Self {
92+
// This sentinel hash is used to indicate that the host phase 2 hash is
93+
// actually the hash to the installinator document.
94+
let kind = if image_id.control_plane == ArtifactHash([0; 32]) {
95+
LookupIdKind::Document(image_id.host_phase_2)
96+
} else {
97+
LookupIdKind::Hashes {
98+
host_phase_2: image_id.host_phase_2,
99+
control_plane: image_id.control_plane,
100+
}
101+
};
102+
103+
Self { update_id: image_id.update_id, kind }
104+
}
105+
}
106+
107+
/// Either an installinator document hash, or host phase 2 and control plane
108+
/// hashes.
109+
pub(crate) enum LookupIdKind {
110+
Document(ArtifactHash),
111+
Hashes { host_phase_2: ArtifactHash, control_plane: ArtifactHash },
112+
}
113+
114+
/// The host phase 2 and control plane hashes to download.
115+
#[derive(Clone, Debug)]
116+
pub(crate) struct ArtifactsToDownload {
117+
pub(crate) host_phase_2: ArtifactHash,
118+
pub(crate) control_plane: ArtifactHash,
119+
}
120+
121+
impl ArtifactsToDownload {
122+
pub(crate) fn host_phase_2_id(&self) -> ArtifactHashId {
123+
ArtifactHashId {
124+
kind: ArtifactKind::HOST_PHASE_2,
125+
hash: self.host_phase_2,
126+
}
127+
}
57128

58-
Ok(InstallinatorImageId { update_id, host_phase_2, control_plane })
129+
pub(crate) fn control_plane_id(&self) -> ArtifactHashId {
130+
ArtifactHashId {
131+
kind: KnownArtifactKind::ControlPlane.into(),
132+
hash: self.control_plane,
59133
}
60134
}
61135
}

0 commit comments

Comments
 (0)