diff --git a/Cargo.lock b/Cargo.lock index c454bdd1652..b3e83726928 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -739,7 +739,7 @@ dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools 0.13.0", + "itertools 0.12.1", "log", "prettyplease", "proc-macro2", @@ -3467,6 +3467,7 @@ version = "0.1.0" dependencies = [ "base64 0.22.1", "chrono", + "daft", "gateway-messages", "omicron-workspace-hack", "progenitor 0.9.1", @@ -7527,6 +7528,7 @@ dependencies = [ "crossterm", "crypto-common", "curve25519-dalek", + "daft", "digest", "dof", "dropshot 0.12.0", @@ -12567,7 +12569,7 @@ dependencies = [ [[package]] name = "tufaceous" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/tufaceous?branch=main#d2387032714f66e31b7e255d89f9bf6eb9b3a010" +source = "git+https://github.com/oxidecomputer/tufaceous?branch=main#bbadc279786d8da5376f61067b42738e2ad6342e" dependencies = [ "anyhow", "camino", @@ -12588,8 +12590,9 @@ dependencies = [ [[package]] name = "tufaceous-artifact" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/tufaceous?branch=main#d2387032714f66e31b7e255d89f9bf6eb9b3a010" +source = "git+https://github.com/oxidecomputer/tufaceous?branch=main#bbadc279786d8da5376f61067b42738e2ad6342e" dependencies = [ + "daft", "parse-display", "proptest", "schemars", @@ -12603,7 +12606,7 @@ dependencies = [ [[package]] name = "tufaceous-brand-metadata" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/tufaceous?branch=main#d2387032714f66e31b7e255d89f9bf6eb9b3a010" +source = "git+https://github.com/oxidecomputer/tufaceous?branch=main#bbadc279786d8da5376f61067b42738e2ad6342e" dependencies = [ "semver 1.0.25", "serde", @@ -12614,7 +12617,7 @@ dependencies = [ [[package]] name = "tufaceous-lib" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/tufaceous?branch=main#d2387032714f66e31b7e255d89f9bf6eb9b3a010" +source = "git+https://github.com/oxidecomputer/tufaceous?branch=main#bbadc279786d8da5376f61067b42738e2ad6342e" dependencies = [ "anyhow", "async-trait", diff --git a/clients/gateway-client/Cargo.toml b/clients/gateway-client/Cargo.toml index 96f6484122c..56ae822a249 100644 --- a/clients/gateway-client/Cargo.toml +++ b/clients/gateway-client/Cargo.toml @@ -10,6 +10,7 @@ workspace = true [dependencies] base64.workspace = true chrono.workspace = true +daft.workspace = true gateway-messages.workspace = true progenitor.workspace = true rand.workspace = true diff --git a/clients/gateway-client/src/lib.rs b/clients/gateway-client/src/lib.rs index a78204d731b..0daa4817c8a 100644 --- a/clients/gateway-client/src/lib.rs +++ b/clients/gateway-client/src/lib.rs @@ -69,6 +69,7 @@ progenitor::generate_api!( SpIgnition = { derives = [PartialEq, Eq, PartialOrd, Ord] }, SpIgnitionSystemType = { derives = [Copy, PartialEq, Eq, PartialOrd, Ord] }, SpState = { derives = [PartialEq, Eq, PartialOrd, Ord] }, + SpType = { derives = [daft::Diffable] }, }, ); diff --git a/common/src/update.rs b/common/src/update.rs index c4d24537614..6201509cdcb 100644 --- a/common/src/update.rs +++ b/common/src/update.rs @@ -4,6 +4,7 @@ use std::{fmt, str::FromStr}; +use daft::Diffable; use hex::FromHexError; use schemars::{ JsonSchema, @@ -64,6 +65,7 @@ impl From<Artifact> for ArtifactId { /// by name and version. This type indicates that. #[derive( Debug, + Diffable, Clone, PartialEq, Eq, @@ -86,6 +88,7 @@ pub struct ArtifactHashId { #[derive( Copy, Clone, + Diffable, Eq, PartialEq, Ord, @@ -95,6 +98,7 @@ pub struct ArtifactHashId { Deserialize, JsonSchema, )] +#[daft(leaf)] #[serde(transparent)] #[cfg_attr(feature = "testing", derive(test_strategy::Arbitrary))] pub struct ArtifactHash( diff --git a/dev-tools/reconfigurator-cli/tests/output/cmd-example-stdout b/dev-tools/reconfigurator-cli/tests/output/cmd-example-stdout index a2639cd2db7..20cc5fee234 100644 --- a/dev-tools/reconfigurator-cli/tests/output/cmd-example-stdout +++ b/dev-tools/reconfigurator-cli/tests/output/cmd-example-stdout @@ -358,6 +358,7 @@ parent: 02697f74-b14a-4418-90f0-c28b2a3a6aa9 internal DNS version: 1 external DNS version: 1 + PENDING MGS-MANAGED UPDATES: 0 > @@ -453,5 +454,6 @@ parent: 02697f74-b14a-4418-90f0-c28b2a3a6aa9 internal DNS version: 1 external DNS version: 1 + PENDING MGS-MANAGED UPDATES: 0 diff --git a/dev-tools/reconfigurator-cli/tests/output/cmd-expunge-newly-added-stdout b/dev-tools/reconfigurator-cli/tests/output/cmd-expunge-newly-added-stdout index d7791c3baa4..3dc26155c76 100644 --- a/dev-tools/reconfigurator-cli/tests/output/cmd-expunge-newly-added-stdout +++ b/dev-tools/reconfigurator-cli/tests/output/cmd-expunge-newly-added-stdout @@ -302,6 +302,7 @@ parent: 06c88262-f435-410e-ba98-101bed41ec27 internal DNS version: 1 external DNS version: 1 + PENDING MGS-MANAGED UPDATES: 0 > blueprint-edit 3f00b694-1b16-4aaa-8f78-e6b3a527b434 expunge-zone 9995de32-dd52-4eb1-b0eb-141eb84bc739 @@ -605,6 +606,7 @@ parent: 3f00b694-1b16-4aaa-8f78-e6b3a527b434 internal DNS version: 1 external DNS version: 1 + PENDING MGS-MANAGED UPDATES: 0 > blueprint-plan 366b0b68-d80e-4bc1-abd3-dc69837847e0 @@ -922,6 +924,7 @@ parent: 366b0b68-d80e-4bc1-abd3-dc69837847e0 internal DNS version: 1 external DNS version: 1 + PENDING MGS-MANAGED UPDATES: 0 > blueprint-edit 9c998c1d-1a7b-440a-ae0c-40f781dea6e2 expunge-zone d786ef4a-5acb-4f5d-a732-a00addf986b5 diff --git a/dev-tools/reconfigurator-cli/tests/output/cmd-set-zone-images-stdout b/dev-tools/reconfigurator-cli/tests/output/cmd-set-zone-images-stdout index bade5023dbf..5d09efd3854 100644 --- a/dev-tools/reconfigurator-cli/tests/output/cmd-set-zone-images-stdout +++ b/dev-tools/reconfigurator-cli/tests/output/cmd-set-zone-images-stdout @@ -94,6 +94,7 @@ parent: 1b013011-2062-4b48-b544-a32b23bce83a internal DNS version: 1 external DNS version: 1 + PENDING MGS-MANAGED UPDATES: 0 > @@ -192,6 +193,7 @@ parent: 971eeb12-1830-4fa0-a699-98ea0164505c internal DNS version: 1 external DNS version: 1 + PENDING MGS-MANAGED UPDATES: 0 > blueprint-diff 971eeb12-1830-4fa0-a699-98ea0164505c 9766ca20-38d4-4380-b005-e7c43c797e7c @@ -455,6 +457,7 @@ parent: 9766ca20-38d4-4380-b005-e7c43c797e7c internal DNS version: 1 external DNS version: 1 + PENDING MGS-MANAGED UPDATES: 0 > blueprint-diff 9766ca20-38d4-4380-b005-e7c43c797e7c f714e6ea-e85a-4d7d-93c2-a018744fe176 diff --git a/nexus/db-queries/src/db/datastore/deployment.rs b/nexus/db-queries/src/db/datastore/deployment.rs index 988628f867a..10297a09199 100644 --- a/nexus/db-queries/src/db/datastore/deployment.rs +++ b/nexus/db-queries/src/db/datastore/deployment.rs @@ -873,6 +873,8 @@ impl DataStore { Ok(Blueprint { id: blueprint_id, + // TODO these need to be serialized to the database. + pending_mgs_updates: BTreeMap::new(), sleds: sled_configs, parent_blueprint_id, internal_dns_version, diff --git a/nexus/db-queries/src/db/datastore/rack.rs b/nexus/db-queries/src/db/datastore/rack.rs index b7b3bc764c8..e1ec30152d8 100644 --- a/nexus/db-queries/src/db/datastore/rack.rs +++ b/nexus/db-queries/src/db/datastore/rack.rs @@ -1054,6 +1054,7 @@ mod test { blueprint: Blueprint { id: BlueprintUuid::new_v4(), sleds: BTreeMap::new(), + pending_mgs_updates: BTreeMap::new(), cockroachdb_setting_preserve_downgrade: CockroachDbPreserveDowngrade::DoNotModify, parent_blueprint_id: None, @@ -1539,6 +1540,7 @@ mod test { let blueprint = Blueprint { id: BlueprintUuid::new_v4(), sleds: make_sled_config_only_zones(blueprint_zones), + pending_mgs_updates: BTreeMap::new(), cockroachdb_setting_preserve_downgrade: CockroachDbPreserveDowngrade::DoNotModify, parent_blueprint_id: None, @@ -1796,6 +1798,7 @@ mod test { let blueprint = Blueprint { id: BlueprintUuid::new_v4(), sleds: make_sled_config_only_zones(blueprint_zones), + pending_mgs_updates: BTreeMap::new(), cockroachdb_setting_preserve_downgrade: CockroachDbPreserveDowngrade::DoNotModify, parent_blueprint_id: None, @@ -2002,6 +2005,7 @@ mod test { let blueprint = Blueprint { id: BlueprintUuid::new_v4(), sleds: make_sled_config_only_zones(blueprint_zones), + pending_mgs_updates: BTreeMap::new(), cockroachdb_setting_preserve_downgrade: CockroachDbPreserveDowngrade::DoNotModify, parent_blueprint_id: None, @@ -2138,6 +2142,7 @@ mod test { let blueprint = Blueprint { id: BlueprintUuid::new_v4(), sleds: make_sled_config_only_zones(blueprint_zones), + pending_mgs_updates: BTreeMap::new(), cockroachdb_setting_preserve_downgrade: CockroachDbPreserveDowngrade::DoNotModify, parent_blueprint_id: None, diff --git a/nexus/reconfigurator/execution/src/dns.rs b/nexus/reconfigurator/execution/src/dns.rs index 84644d0b235..63c361c3235 100644 --- a/nexus/reconfigurator/execution/src/dns.rs +++ b/nexus/reconfigurator/execution/src/dns.rs @@ -678,6 +678,7 @@ mod test { let mut blueprint = Blueprint { id: BlueprintUuid::new_v4(), sleds: blueprint_sleds, + pending_mgs_updates: BTreeMap::new(), cockroachdb_setting_preserve_downgrade: CockroachDbPreserveDowngrade::DoNotModify, parent_blueprint_id: None, diff --git a/nexus/reconfigurator/planning/src/blueprint_builder/builder.rs b/nexus/reconfigurator/planning/src/blueprint_builder/builder.rs index 2c12069d02d..422b495c7b1 100644 --- a/nexus/reconfigurator/planning/src/blueprint_builder/builder.rs +++ b/nexus/reconfigurator/planning/src/blueprint_builder/builder.rs @@ -454,6 +454,7 @@ impl<'a> BlueprintBuilder<'a> { Blueprint { id: rng.next_blueprint(), sleds, + pending_mgs_updates: BTreeMap::new(), parent_blueprint_id: None, internal_dns_version: Generation::new(), external_dns_version: Generation::new(), @@ -710,6 +711,10 @@ impl<'a> BlueprintBuilder<'a> { Blueprint { id: blueprint_id, sleds, + pending_mgs_updates: self + .parent_blueprint + .pending_mgs_updates + .clone(), parent_blueprint_id: Some(self.parent_blueprint.id), internal_dns_version: self.input.internal_dns_version(), external_dns_version: self.input.external_dns_version(), diff --git a/nexus/src/app/background/tasks/blueprint_execution.rs b/nexus/src/app/background/tasks/blueprint_execution.rs index 752a58dd1e9..26471b57250 100644 --- a/nexus/src/app/background/tasks/blueprint_execution.rs +++ b/nexus/src/app/background/tasks/blueprint_execution.rs @@ -247,6 +247,7 @@ mod test { let blueprint = Blueprint { id, sleds: blueprint_sleds, + pending_mgs_updates: BTreeMap::new(), cockroachdb_setting_preserve_downgrade: CockroachDbPreserveDowngrade::DoNotModify, parent_blueprint_id: Some(current_target.target_id), diff --git a/nexus/src/app/background/tasks/blueprint_load.rs b/nexus/src/app/background/tasks/blueprint_load.rs index da2bc6dee2b..31638b00f1d 100644 --- a/nexus/src/app/background/tasks/blueprint_load.rs +++ b/nexus/src/app/background/tasks/blueprint_load.rs @@ -217,6 +217,7 @@ mod test { Blueprint { id, sleds: BTreeMap::new(), + pending_mgs_updates: BTreeMap::new(), cockroachdb_setting_preserve_downgrade: CockroachDbPreserveDowngrade::DoNotModify, parent_blueprint_id: Some(parent_blueprint_id), diff --git a/nexus/test-utils/src/lib.rs b/nexus/test-utils/src/lib.rs index edcf387d172..7adba713579 100644 --- a/nexus/test-utils/src/lib.rs +++ b/nexus/test-utils/src/lib.rs @@ -929,6 +929,7 @@ impl<'a, N: NexusServer> ControlPlaneTestContextBuilder<'a, N> { Blueprint { id: BlueprintUuid::new_v4(), sleds: blueprint_sleds, + pending_mgs_updates: BTreeMap::new(), parent_blueprint_id: None, internal_dns_version: dns_config.generation, external_dns_version: Generation::new(), diff --git a/nexus/types/src/deployment.rs b/nexus/types/src/deployment.rs index f15e74cd688..a0440d2f4cf 100644 --- a/nexus/types/src/deployment.rs +++ b/nexus/types/src/deployment.rs @@ -101,7 +101,11 @@ use blueprint_display::{ }; use id_map::{IdMap, IdMappable}; +use crate::inventory::BaseboardId; pub use blueprint_diff::BlueprintDiffSummary; +use blueprint_display::BpPendingMgsUpdates; +use gateway_client::types::SpType; +use omicron_common::update::ArtifactHashId; /// Describes a complete set of software and configuration for the system // Blueprints are a fundamental part of how the system modifies itself. Each @@ -151,6 +155,9 @@ pub struct Blueprint { /// A map of sled id -> desired configuration of the sled. pub sleds: BTreeMap<SledUuid, BlueprintSledConfig>, + /// List of pending MGS-mediated updates + pub pending_mgs_updates: BTreeMap<BaseboardId, PendingMgsUpdate>, + /// which blueprint this blueprint is based on pub parent_blueprint_id: Option<BlueprintUuid>, @@ -488,6 +495,7 @@ impl fmt::Display for BlueprintDisplay<'_> { let Blueprint { id, sleds, + pending_mgs_updates, parent_blueprint_id, // These two cockroachdb_* fields are handled by // `make_cockroachdb_table()`, called below. @@ -569,6 +577,38 @@ impl fmt::Display for BlueprintDisplay<'_> { writeln!(f, "{}", self.make_cockroachdb_table())?; writeln!(f, "{}", self.make_metadata_table())?; + writeln!( + f, + " PENDING MGS-MANAGED UPDATES: {}", + pending_mgs_updates.len() + )?; + if !pending_mgs_updates.is_empty() { + writeln!( + f, + "{}", + BpTable::new( + BpPendingMgsUpdates {}, + None, + pending_mgs_updates + .values() + .map(|pu| { + BpTableRow::from_strings( + BpDiffState::Unchanged, + vec![ + pu.sp_type.to_string(), + pu.slot_id.to_string(), + pu.baseboard_id.part_number.clone(), + pu.baseboard_id.serial_number.clone(), + pu.artifact_hash_id.kind.to_string(), + pu.artifact_hash_id.hash.to_string(), + ], + ) + }) + .collect() + ) + )?; + } + Ok(()) } } @@ -963,6 +1003,21 @@ impl fmt::Display for BlueprintZoneImageSource { } } +#[derive( + Clone, Debug, Eq, PartialEq, JsonSchema, Deserialize, Serialize, Diffable, +)] +pub struct PendingMgsUpdate { + /// id of the baseboard that we're going to update + baseboard_id: BaseboardId, + /// what type of baseboard this is + sp_type: SpType, + /// last known MGS slot (cubby number) of the baseboard + slot_id: u16, + /// which artifact to apply to this device + /// (implies which component is being updated) + artifact_hash_id: ArtifactHashId, +} + /// The desired state of an Omicron-managed physical disk in a blueprint. #[derive( Debug, diff --git a/nexus/types/src/deployment/blueprint_diff.rs b/nexus/types/src/deployment/blueprint_diff.rs index a0bda212873..3caea50fe53 100644 --- a/nexus/types/src/deployment/blueprint_diff.rs +++ b/nexus/types/src/deployment/blueprint_diff.rs @@ -58,6 +58,9 @@ impl<'a> BlueprintDiffSummary<'a> { let BlueprintDiff { // Fields in which changes are meaningful. sleds, + // TODO Will need to diff these when we can actually create + // blueprints with pending MGS updates. + pending_mgs_updates: _, clickhouse_cluster_config, // Metadata fields for which changes don't reflect semantic // changes from one blueprint to the next. diff --git a/nexus/types/src/deployment/blueprint_display.rs b/nexus/types/src/deployment/blueprint_display.rs index ee11559cb35..bfdcbef98bc 100644 --- a/nexus/types/src/deployment/blueprint_display.rs +++ b/nexus/types/src/deployment/blueprint_display.rs @@ -100,23 +100,23 @@ impl fmt::Display for BpGeneration { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { BpGeneration::Value(generation) => { - write!(f, "at generation {generation}") + write!(f, " at generation {generation}") } BpGeneration::Diff { before: None, after: Some(after) } => { - write!(f, "at generation {after}") + write!(f, " at generation {after}") } BpGeneration::Diff { before: Some(before), after: None } => { - write!(f, "from generation {before}") + write!(f, " from generation {before}") } BpGeneration::Diff { before: Some(before), after: Some(after) } => { if before == after { - write!(f, "at generation {after}") + write!(f, " at generation {after}") } else { - write!(f, "generation {before} -> {after}") + write!(f, " generation {before} -> {after}") } } BpGeneration::Diff { before: None, after: None } => { - write!(f, "unknown generation") + write!(f, " unknown generation") } } } @@ -400,6 +400,25 @@ impl BpTableSchema for BpClickhouseServersTableSchema { } } +/// The [`BpTable`] schema for pending MGS updates +pub struct BpPendingMgsUpdates {} +impl BpTableSchema for BpPendingMgsUpdates { + fn table_name(&self) -> &'static str { + "Pending MGS-managed updates" + } + + fn column_names(&self) -> &'static [&'static str] { + &[ + "sp_type", + "slot", + "part_number", + "serial_number", + "artifact_kind", + "artifact_hash", + ] + } +} + // An entry in a [`KvListWithHeading`] #[derive(Debug)] pub struct KvPair { diff --git a/nexus/types/src/inventory.rs b/nexus/types/src/inventory.rs index 95c4f80e05f..c2aeba993fa 100644 --- a/nexus/types/src/inventory.rs +++ b/nexus/types/src/inventory.rs @@ -14,6 +14,7 @@ use crate::external_api::params::UninitializedSledId; use chrono::DateTime; use chrono::Utc; use clickhouse_admin_types::ClickhouseKeeperClusterMembership; +use daft::Diffable; pub use gateway_client::types::PowerState; pub use gateway_client::types::RotImageError; pub use gateway_client::types::RotSlot; @@ -34,6 +35,7 @@ use omicron_uuid_kinds::CollectionUuid; use omicron_uuid_kinds::DatasetUuid; use omicron_uuid_kinds::SledUuid; use omicron_uuid_kinds::ZpoolUuid; +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_with::serde_as; use std::collections::BTreeMap; @@ -205,7 +207,16 @@ impl Collection { /// the same part number and serial number but a new revision number, we'd want /// to treat that as the same baseboard as one with a different revision number. #[derive( - Clone, Debug, Ord, Eq, PartialOrd, PartialEq, Deserialize, Serialize, + Clone, + Debug, + Diffable, + Ord, + Eq, + PartialOrd, + PartialEq, + Deserialize, + Serialize, + JsonSchema, )] pub struct BaseboardId { /// Oxide Part Number diff --git a/openapi/nexus-internal.json b/openapi/nexus-internal.json index 23b5598a13a..8955f2f169e 100644 --- a/openapi/nexus-internal.json +++ b/openapi/nexus-internal.json @@ -1546,6 +1546,25 @@ } ] }, + "ArtifactHashId": { + "description": "A hash-based identifier for an artifact.\n\nSome places, e.g. the installinator, request artifacts by hash rather than by name and version. This type indicates that.", + "type": "object", + "properties": { + "hash": { + "description": "The hash of the artifact.", + "type": "string", + "format": "hex string (32 bytes)" + }, + "kind": { + "description": "The kind of artifact this is.", + "type": "string" + } + }, + "required": [ + "hash", + "kind" + ] + }, "BackgroundTask": { "description": "Background tasks\n\nThese are currently only intended for observability by developers. We will eventually want to flesh this out into something more observable for end users.", "type": "object", @@ -1629,6 +1648,24 @@ "serial" ] }, + "BaseboardId": { + "description": "A unique baseboard id found during a collection\n\nBaseboard ids are the keys used to link up information from disparate sources (like a service processor and a sled agent).\n\nThese are normalized in the database. Each distinct baseboard id is assigned a uuid and shared across the many possible collections that reference it.\n\nUsually, the part number and serial number are combined with a revision number. We do not include that here. If we ever did find a baseboard with the same part number and serial number but a new revision number, we'd want to treat that as the same baseboard as one with a different revision number.", + "type": "object", + "properties": { + "part_number": { + "description": "Oxide Part Number", + "type": "string" + }, + "serial_number": { + "description": "Serial number (unique for a given part number)", + "type": "string" + } + }, + "required": [ + "part_number", + "serial_number" + ] + }, "BfdMode": { "description": "BFD connection mode.", "type": "string", @@ -1917,6 +1954,13 @@ } ] }, + "pending_mgs_updates": { + "description": "List of pending MGS-mediated updates", + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/PendingMgsUpdate" + } + }, "sleds": { "description": "A map of sled id -> desired configuration of the sled.", "type": "object", @@ -1938,6 +1982,7 @@ "external_dns_version", "id", "internal_dns_version", + "pending_mgs_updates", "sleds", "time_created" ] @@ -4596,6 +4641,47 @@ "collector_id" ] }, + "PendingMgsUpdate": { + "type": "object", + "properties": { + "artifact_hash_id": { + "description": "which artifact to apply to this device (implies which component is being updated)", + "allOf": [ + { + "$ref": "#/components/schemas/ArtifactHashId" + } + ] + }, + "baseboard_id": { + "description": "id of the baseboard that we're going to update", + "allOf": [ + { + "$ref": "#/components/schemas/BaseboardId" + } + ] + }, + "slot_id": { + "description": "last known MGS slot (cubby number) of the baseboard", + "type": "integer", + "format": "uint16", + "minimum": 0 + }, + "sp_type": { + "description": "what type of baseboard this is", + "allOf": [ + { + "$ref": "#/components/schemas/SpType" + } + ] + } + }, + "required": [ + "artifact_hash_id", + "baseboard_id", + "slot_id", + "sp_type" + ] + }, "PhysicalDiskKind": { "description": "Describes the form factor of physical disks.", "type": "string", @@ -5717,6 +5803,15 @@ "last_port" ] }, + "SpType": { + "description": "SpType\n\n<details><summary>JSON schema</summary>\n\n```json { \"type\": \"string\", \"enum\": [ \"sled\", \"power\", \"switch\" ] } ``` </details>", + "type": "string", + "enum": [ + "sled", + "power", + "switch" + ] + }, "Srv": { "type": "object", "properties": { diff --git a/sled-agent/src/rack_setup/service.rs b/sled-agent/src/rack_setup/service.rs index b0ec33d001f..c1de8fe0fe4 100644 --- a/sled-agent/src/rack_setup/service.rs +++ b/sled-agent/src/rack_setup/service.rs @@ -1540,6 +1540,7 @@ pub(crate) fn build_initial_blueprint_from_sled_configs( Ok(Blueprint { id: BlueprintUuid::new_v4(), sleds: blueprint_sleds, + pending_mgs_updates: BTreeMap::new(), parent_blueprint_id: None, internal_dns_version, // We don't configure external DNS during RSS, so set it to an initial diff --git a/workspace-hack/Cargo.toml b/workspace-hack/Cargo.toml index 84feaf9a8b8..6513f6d6b63 100644 --- a/workspace-hack/Cargo.toml +++ b/workspace-hack/Cargo.toml @@ -41,6 +41,7 @@ crossbeam-utils = { version = "0.8.20" } crossterm = { version = "0.28.1", features = ["event-stream", "serde"] } crypto-common = { version = "0.1.6", default-features = false, features = ["getrandom", "std"] } curve25519-dalek = { version = "4.1.3", features = ["digest", "legacy_compatibility", "rand_core"] } +daft = { version = "0.1.2", features = ["derive", "newtype-uuid1", "oxnet01", "uuid1"] } digest = { version = "0.10.7", features = ["mac", "oid", "std"] } dropshot = { version = "0.12.0", default-features = false, features = ["usdt-probes"] } ecdsa = { version = "0.16.9", features = ["pem", "signing", "std", "verifying"] } @@ -70,6 +71,7 @@ idna = { version = "1.0.3" } indexmap = { version = "2.7.1", features = ["serde"] } inout = { version = "0.1.3", default-features = false, features = ["std"] } ipnetwork = { version = "0.21.1", features = ["schemars", "serde"] } +itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12.1" } itertools-93f6ce9d446188ac = { package = "itertools", version = "0.10.5" } lalrpop-util = { version = "0.19.12" } lazy_static = { version = "1.5.0", default-features = false, features = ["spin_no_std"] } @@ -164,6 +166,7 @@ crossbeam-utils = { version = "0.8.20" } crossterm = { version = "0.28.1", features = ["event-stream", "serde"] } crypto-common = { version = "0.1.6", default-features = false, features = ["getrandom", "std"] } curve25519-dalek = { version = "4.1.3", features = ["digest", "legacy_compatibility", "rand_core"] } +daft = { version = "0.1.2", features = ["derive", "newtype-uuid1", "oxnet01", "uuid1"] } digest = { version = "0.10.7", features = ["mac", "oid", "std"] } dropshot = { version = "0.12.0", default-features = false, features = ["usdt-probes"] } ecdsa = { version = "0.16.9", features = ["pem", "signing", "std", "verifying"] } @@ -193,6 +196,7 @@ idna = { version = "1.0.3" } indexmap = { version = "2.7.1", features = ["serde"] } inout = { version = "0.1.3", default-features = false, features = ["std"] } ipnetwork = { version = "0.21.1", features = ["schemars", "serde"] } +itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12.1" } itertools-93f6ce9d446188ac = { package = "itertools", version = "0.10.5" } lalrpop-util = { version = "0.19.12" } lazy_static = { version = "1.5.0", default-features = false, features = ["spin_no_std"] } @@ -337,7 +341,6 @@ getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.1", default hyper-rustls = { version = "0.27.3", default-features = false, features = ["http1", "http2", "ring", "tls12", "webpki-tokio"] } hyper-util = { version = "0.1.10", features = ["full"] } indicatif = { version = "0.17.11", features = ["rayon"] } -itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12.1" } mio = { version = "1.0.2", features = ["net", "os-ext"] } rustix = { version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } tokio-rustls = { version = "0.26.0", default-features = false, features = ["logging", "ring", "tls12"] } @@ -352,7 +355,6 @@ getrandom-468e82937335b1c9 = { package = "getrandom", version = "0.3.1", default hyper-rustls = { version = "0.27.3", default-features = false, features = ["http1", "http2", "ring", "tls12", "webpki-tokio"] } hyper-util = { version = "0.1.10", features = ["full"] } indicatif = { version = "0.17.11", features = ["rayon"] } -itertools-5ef9efb8ec2df382 = { package = "itertools", version = "0.12.1" } mio = { version = "1.0.2", features = ["net", "os-ext"] } rustix = { version = "0.38.37", features = ["event", "fs", "net", "pipe", "process", "stdio", "system", "termios", "time"] } tokio-rustls = { version = "0.26.0", default-features = false, features = ["logging", "ring", "tls12"] }