diff --git a/nexus/db-model/src/schema.rs b/nexus/db-model/src/schema.rs index 89ae6c18c5e..7f29c707282 100644 --- a/nexus/db-model/src/schema.rs +++ b/nexus/db-model/src/schema.rs @@ -1432,6 +1432,20 @@ table! { } } +table! { + inv_nvme_disk_firmware (inv_collection_id, sled_id, slot) { + inv_collection_id -> Uuid, + sled_id -> Uuid, + slot -> Int8, + + number_of_slots -> Int8, + active_slot -> Int8, + next_active_slot -> Nullable, + slot1_is_read_only -> Bool, + slot_fw_versions -> Array>, + } +} + table! { inv_zpool (inv_collection_id, sled_id, id) { inv_collection_id -> Uuid, @@ -1816,6 +1830,7 @@ allow_tables_to_appear_in_same_query!( network_interface, instance_network_interface, inv_physical_disk, + inv_nvme_disk_firmware, service_network_interface, oximeter, physical_disk, diff --git a/nexus/db-queries/src/db/datastore/physical_disk.rs b/nexus/db-queries/src/db/datastore/physical_disk.rs index 7005bc6d506..42ffe360a8d 100644 --- a/nexus/db-queries/src/db/datastore/physical_disk.rs +++ b/nexus/db-queries/src/db/datastore/physical_disk.rs @@ -719,6 +719,7 @@ mod test { active_firmware_slot: 1, next_active_firmware_slot: None, number_of_firmware_slots: 1, + slot1_is_read_only: true, slot_firmware_versions: vec![Some("TEST1".to_string())], } } diff --git a/nexus/inventory/src/examples.rs b/nexus/inventory/src/examples.rs index 90b4ab86f89..9a511dd3d42 100644 --- a/nexus/inventory/src/examples.rs +++ b/nexus/inventory/src/examples.rs @@ -288,6 +288,7 @@ pub fn representative() -> Representative { active_firmware_slot: 1, next_active_firmware_slot: None, number_of_firmware_slots: 1, + slot1_is_read_only: true, slot_firmware_versions: vec![Some("EXAMP1".to_string())], }, // ... and a couple different vendors for our U.2s @@ -302,6 +303,7 @@ pub fn representative() -> Representative { active_firmware_slot: 1, next_active_firmware_slot: None, number_of_firmware_slots: 1, + slot1_is_read_only: true, slot_firmware_versions: vec![Some("EXAMP1".to_string())], }, sled_agent_client::types::InventoryDisk { @@ -315,6 +317,7 @@ pub fn representative() -> Representative { active_firmware_slot: 1, next_active_firmware_slot: None, number_of_firmware_slots: 1, + slot1_is_read_only: true, slot_firmware_versions: vec![Some("EXAMP1".to_string())], }, sled_agent_client::types::InventoryDisk { @@ -328,6 +331,7 @@ pub fn representative() -> Representative { active_firmware_slot: 1, next_active_firmware_slot: None, number_of_firmware_slots: 1, + slot1_is_read_only: true, slot_firmware_versions: vec![Some("EXAMP1".to_string())], }, ]; diff --git a/nexus/reconfigurator/planning/src/system.rs b/nexus/reconfigurator/planning/src/system.rs index 9a5a3cadca3..ae75a93e95c 100644 --- a/nexus/reconfigurator/planning/src/system.rs +++ b/nexus/reconfigurator/planning/src/system.rs @@ -552,6 +552,7 @@ impl Sled { active_firmware_slot: 1, next_active_firmware_slot: None, number_of_firmware_slots: 1, + slot1_is_read_only: true, slot_firmware_versions: vec![Some( "SIMUL1".to_string(), )], diff --git a/nexus/types/src/inventory.rs b/nexus/types/src/inventory.rs index 661c4c088d7..fbf81d750d0 100644 --- a/nexus/types/src/inventory.rs +++ b/nexus/types/src/inventory.rs @@ -367,6 +367,7 @@ pub struct PhysicalDisk { pub identity: omicron_common::disk::DiskIdentity, pub variant: PhysicalDiskKind, pub slot: i64, + pub active_firmware_slot: u8, } impl From for PhysicalDisk { @@ -375,6 +376,7 @@ impl From for PhysicalDisk { identity: disk.identity, variant: disk.variant.into(), slot: disk.slot, + active_firmware_slot: disk.active_firmware_slot, } } } diff --git a/openapi/sled-agent.json b/openapi/sled-agent.json index 4c47c461411..5ad399f6a82 100644 --- a/openapi/sled-agent.json +++ b/openapi/sled-agent.json @@ -3368,6 +3368,9 @@ "type": "integer", "format": "int64" }, + "slot1_is_read_only": { + "type": "boolean" + }, "slot_firmware_versions": { "type": "array", "items": { @@ -3384,6 +3387,7 @@ "identity", "number_of_firmware_slots", "slot", + "slot1_is_read_only", "slot_firmware_versions", "variant" ] diff --git a/schema/crdb/dbinit.sql b/schema/crdb/dbinit.sql index 4db467bfdae..17db28509a3 100644 --- a/schema/crdb/dbinit.sql +++ b/schema/crdb/dbinit.sql @@ -3149,6 +3149,8 @@ CREATE TABLE IF NOT EXISTS omicron.public.inv_nvme_disk_firmware ( active_slot INT8 CHECK (number_of_slots BETWEEN 1 AND 7) NOT NULL, -- staged firmware slot to be active on reset next_active_slot INT8 CHECK (number_of_slots BETWEEN 1 AND 7), + -- slot1 is distinct in the NVMe spec in the sense that it can be read only + slot1_is_read_only BOOLEAN, -- the firmware version string for each NVMe slot (0 indexed), a NULL means the -- slot exists but is empty slot_fw_versions STRING(8)[] CHECK (array_length(slot_fw_versions) BETWEEN 1 AND 7), diff --git a/sled-agent/src/params.rs b/sled-agent/src/params.rs index 21dc70d460a..3bd02ea1dc0 100644 --- a/sled-agent/src/params.rs +++ b/sled-agent/src/params.rs @@ -758,9 +758,10 @@ pub struct InventoryDisk { // Today we only have NVMe disks so we embedded the firmware metadata here. // In the future we can track firmware metadata in a unique type if we // support more than one disk format. + pub number_of_firmware_slots: u8, pub active_firmware_slot: u8, pub next_active_firmware_slot: Option, - pub number_of_firmware_slots: u8, + pub slot1_is_read_only: bool, pub slot_firmware_versions: Vec>, } diff --git a/sled-agent/src/rack_setup/service.rs b/sled-agent/src/rack_setup/service.rs index f3ec309c3bb..771baf854c4 100644 --- a/sled-agent/src/rack_setup/service.rs +++ b/sled-agent/src/rack_setup/service.rs @@ -1588,6 +1588,7 @@ mod test { active_firmware_slot: 1, next_active_firmware_slot: None, number_of_firmware_slots: 1, + slot1_is_read_only: true, slot_firmware_versions: vec![Some("TEST1".to_string())], }) .collect(), diff --git a/sled-agent/src/sim/sled_agent.rs b/sled-agent/src/sim/sled_agent.rs index 0a04b6ba81a..857e212d2ca 100644 --- a/sled-agent/src/sim/sled_agent.rs +++ b/sled-agent/src/sim/sled_agent.rs @@ -857,6 +857,7 @@ impl SledAgent { active_firmware_slot: 1, next_active_firmware_slot: None, number_of_firmware_slots: 1, + slot1_is_read_only: true, slot_firmware_versions: vec![Some("SIMUL1".to_string())], }) .collect(), diff --git a/sled-agent/src/sled_agent.rs b/sled-agent/src/sled_agent.rs index 807454268be..2f5a0fddace 100644 --- a/sled-agent/src/sled_agent.rs +++ b/sled-agent/src/sled_agent.rs @@ -1216,6 +1216,7 @@ impl SledAgent { active_firmware_slot: firmware.active_slot(), next_active_firmware_slot: firmware.next_active_slot(), number_of_firmware_slots: firmware.number_of_slots(), + slot1_is_read_only: firmware.slot1_read_only(), slot_firmware_versions: firmware.slots().to_vec(), }); }