From 26045768fa3cc74efaf672c41d358737eca7a199 Mon Sep 17 00:00:00 2001 From: Dan Rosen Date: Wed, 18 Mar 2026 13:32:35 -0400 Subject: [PATCH] schema: add fm_support_bundle_request table, per-variant data selection tables, and fm_case_id on support_bundle Add migration SQL for fm_support_bundle_request and five per-variant data selection tables (reconfigurator, sled_cubby_info, sp_dumps, host_info, ereports). Add fm_case_id column to support_bundle. Update dbinit.sql, Diesel schema, and schema version. --- nexus/db-model/src/schema_versions.rs | 3 +- nexus/db-schema/src/schema.rs | 75 +++++++++++++++++++ schema/crdb/dbinit.sql | 71 +++++++++++++++++- schema/crdb/fm-support-bundle-request/up1.sql | 13 ++++ schema/crdb/fm-support-bundle-request/up2.sql | 3 + .../fm-support-bundle-request/up2.verify.sql | 2 + schema/crdb/fm-support-bundle-request/up3.sql | 6 ++ schema/crdb/fm-support-bundle-request/up4.sql | 6 ++ schema/crdb/fm-support-bundle-request/up5.sql | 6 ++ schema/crdb/fm-support-bundle-request/up6.sql | 8 ++ schema/crdb/fm-support-bundle-request/up7.sql | 10 +++ schema/crdb/fm-support-bundle-request/up8.sql | 2 + 12 files changed, 202 insertions(+), 3 deletions(-) create mode 100644 schema/crdb/fm-support-bundle-request/up1.sql create mode 100644 schema/crdb/fm-support-bundle-request/up2.sql create mode 100644 schema/crdb/fm-support-bundle-request/up2.verify.sql create mode 100644 schema/crdb/fm-support-bundle-request/up3.sql create mode 100644 schema/crdb/fm-support-bundle-request/up4.sql create mode 100644 schema/crdb/fm-support-bundle-request/up5.sql create mode 100644 schema/crdb/fm-support-bundle-request/up6.sql create mode 100644 schema/crdb/fm-support-bundle-request/up7.sql create mode 100644 schema/crdb/fm-support-bundle-request/up8.sql diff --git a/nexus/db-model/src/schema_versions.rs b/nexus/db-model/src/schema_versions.rs index 5e0fdd10b09..d80d50e35bd 100644 --- a/nexus/db-model/src/schema_versions.rs +++ b/nexus/db-model/src/schema_versions.rs @@ -16,7 +16,7 @@ use std::{collections::BTreeMap, sync::LazyLock}; /// /// This must be updated when you change the database schema. Refer to /// schema/crdb/README.adoc in the root of this repository for details. -pub const SCHEMA_VERSION: Version = Version::new(240, 0, 0); +pub const SCHEMA_VERSION: Version = Version::new(241, 0, 0); /// List of all past database schema versions, in *reverse* order /// @@ -28,6 +28,7 @@ static KNOWN_VERSIONS: LazyLock> = LazyLock::new(|| { // | leaving the first copy as an example for the next person. // v // KnownVersion::new(next_int, "unique-dirname-with-the-sql-files"), + KnownVersion::new(241, "fm-support-bundle-request"), KnownVersion::new(240, "multicast-drop-mvlan"), KnownVersion::new(239, "fm-alert-request"), KnownVersion::new(238, "fewer-nullable-columns"), diff --git a/nexus/db-schema/src/schema.rs b/nexus/db-schema/src/schema.rs index d108372694b..fb162694fdf 100644 --- a/nexus/db-schema/src/schema.rs +++ b/nexus/db-schema/src/schema.rs @@ -1590,6 +1590,7 @@ table! { assigned_nexus -> Nullable, user_comment -> Nullable, + fm_case_id -> Nullable, } } @@ -3183,6 +3184,80 @@ table! { } } +// FM support bundle requests, stored per-sitrep like alert requests. +table! { + fm_support_bundle_request (sitrep_id, id) { + id -> Uuid, + sitrep_id -> Uuid, + requested_sitrep_id -> Uuid, + case_id -> Uuid, + } +} + +// Per-variant data selection tables for fm_support_bundle_request. +// Each table corresponds to a BundleData variant. Row existence means +// "include this category in the bundle." No rows across any variant +// table means "collect everything." + +// BundleData::Reconfigurator (unit variant, no filter columns) +table! { + fm_sb_req_reconfigurator (sitrep_id, request_id) { + sitrep_id -> Uuid, + request_id -> Uuid, + } +} + +// BundleData::SledCubbyInfo (unit variant, no filter columns) +table! { + fm_sb_req_sled_cubby_info (sitrep_id, request_id) { + sitrep_id -> Uuid, + request_id -> Uuid, + } +} + +// BundleData::SpDumps (unit variant, no filter columns) +table! { + fm_sb_req_sp_dumps (sitrep_id, request_id) { + sitrep_id -> Uuid, + request_id -> Uuid, + } +} + +// BundleData::HostInfo(HashSet) +table! { + fm_sb_req_host_info (sitrep_id, request_id) { + sitrep_id -> Uuid, + request_id -> Uuid, + all_sleds -> Bool, + sled_ids -> Array, + } +} + +// BundleData::Ereports(EreportFilters) +table! { + fm_sb_req_ereports (sitrep_id, request_id) { + sitrep_id -> Uuid, + request_id -> Uuid, + start_time -> Nullable, + end_time -> Nullable, + only_serials -> Array, + only_classes -> Array, + } +} + +// The per-variant tables use composite keys (sitrep_id, request_id) +// matching fm_support_bundle_request's (sitrep_id, id), so joinable! +// cannot be used (it requires single-column FKs). Queries must use +// explicit .on() clauses instead. +allow_tables_to_appear_in_same_query!( + fm_support_bundle_request, + fm_sb_req_reconfigurator, + fm_sb_req_sled_cubby_info, + fm_sb_req_sp_dumps, + fm_sb_req_host_info, + fm_sb_req_ereports, +); + table! { trust_quorum_configuration (rack_id, epoch) { rack_id -> Uuid, diff --git a/schema/crdb/dbinit.sql b/schema/crdb/dbinit.sql index ae61055b071..566bbf82702 100644 --- a/schema/crdb/dbinit.sql +++ b/schema/crdb/dbinit.sql @@ -3156,7 +3156,10 @@ CREATE TABLE IF NOT EXISTS omicron.public.support_bundle ( -- and later managing its storage. assigned_nexus UUID, - user_comment TEXT + user_comment TEXT, + + -- If this bundle was requested by an FM case, the case UUID. + fm_case_id UUID ); @@ -7440,6 +7443,70 @@ CREATE INDEX IF NOT EXISTS lookup_fm_alert_requests_for_case ON omicron.public.fm_alert_request (sitrep_id, case_id); +CREATE TABLE IF NOT EXISTS omicron.public.fm_support_bundle_request ( + -- Requested support bundle UUID. + id UUID NOT NULL, + -- UUID of the current sitrep that this request record is part of. + -- + -- Note that this is *not* the sitrep in which the bundle was requested. + sitrep_id UUID NOT NULL, + -- UUID of the original sitrep in which the bundle was first requested. + requested_sitrep_id UUID NOT NULL, + -- UUID of the case to which this request belongs. + case_id UUID NOT NULL, + + PRIMARY KEY (sitrep_id, id) +); + +CREATE INDEX IF NOT EXISTS + lookup_fm_support_bundle_requests_for_case +ON omicron.public.fm_support_bundle_request (sitrep_id, case_id); + +-- Per-variant data selection tables for fm_support_bundle_request. +-- Row existence = "include this category in the bundle." +-- No rows in any variant table = "collect everything." + +CREATE TABLE IF NOT EXISTS omicron.public.fm_sb_req_reconfigurator ( + sitrep_id UUID NOT NULL, + request_id UUID NOT NULL, + + PRIMARY KEY (sitrep_id, request_id) +); + +CREATE TABLE IF NOT EXISTS omicron.public.fm_sb_req_sled_cubby_info ( + sitrep_id UUID NOT NULL, + request_id UUID NOT NULL, + + PRIMARY KEY (sitrep_id, request_id) +); + +CREATE TABLE IF NOT EXISTS omicron.public.fm_sb_req_sp_dumps ( + sitrep_id UUID NOT NULL, + request_id UUID NOT NULL, + + PRIMARY KEY (sitrep_id, request_id) +); + +CREATE TABLE IF NOT EXISTS omicron.public.fm_sb_req_host_info ( + sitrep_id UUID NOT NULL, + request_id UUID NOT NULL, + all_sleds BOOL NOT NULL, + sled_ids UUID[] NOT NULL DEFAULT ARRAY[], + + PRIMARY KEY (sitrep_id, request_id) +); + +CREATE TABLE IF NOT EXISTS omicron.public.fm_sb_req_ereports ( + sitrep_id UUID NOT NULL, + request_id UUID NOT NULL, + start_time TIMESTAMPTZ, + end_time TIMESTAMPTZ, + only_serials TEXT[] NOT NULL DEFAULT ARRAY[], + only_classes TEXT[] NOT NULL DEFAULT ARRAY[], + + PRIMARY KEY (sitrep_id, request_id) +); + /* * List of datasets available to be sliced up and passed to VMMs for encrypted * instance local storage. @@ -8270,7 +8337,7 @@ INSERT INTO omicron.public.db_metadata ( version, target_version ) VALUES - (TRUE, NOW(), NOW(), '240.0.0', NULL) + (TRUE, NOW(), NOW(), '241.0.0', NULL) ON CONFLICT DO NOTHING; COMMIT; diff --git a/schema/crdb/fm-support-bundle-request/up1.sql b/schema/crdb/fm-support-bundle-request/up1.sql new file mode 100644 index 00000000000..4ab9fdda7f9 --- /dev/null +++ b/schema/crdb/fm-support-bundle-request/up1.sql @@ -0,0 +1,13 @@ +CREATE TABLE IF NOT EXISTS omicron.public.fm_support_bundle_request ( + -- Requested support bundle UUID. + id UUID NOT NULL, + -- UUID of the current sitrep that this request record is part of. + -- + -- Note that this is *not* the sitrep in which the bundle was requested. + sitrep_id UUID NOT NULL, + -- UUID of the original sitrep in which the bundle was first requested. + requested_sitrep_id UUID NOT NULL, + -- UUID of the case to which this request belongs. + case_id UUID NOT NULL, + PRIMARY KEY (sitrep_id, id) +); diff --git a/schema/crdb/fm-support-bundle-request/up2.sql b/schema/crdb/fm-support-bundle-request/up2.sql new file mode 100644 index 00000000000..2742178f61a --- /dev/null +++ b/schema/crdb/fm-support-bundle-request/up2.sql @@ -0,0 +1,3 @@ +CREATE INDEX IF NOT EXISTS + lookup_fm_support_bundle_requests_for_case +ON omicron.public.fm_support_bundle_request (sitrep_id, case_id); diff --git a/schema/crdb/fm-support-bundle-request/up2.verify.sql b/schema/crdb/fm-support-bundle-request/up2.verify.sql new file mode 100644 index 00000000000..aa1319640d3 --- /dev/null +++ b/schema/crdb/fm-support-bundle-request/up2.verify.sql @@ -0,0 +1,2 @@ +-- DO NOT EDIT. Generated by test_migration_verification_files. +SELECT CAST(IF((SELECT true WHERE EXISTS (SELECT index_name FROM omicron.crdb_internal.table_indexes WHERE descriptor_name = 'fm_support_bundle_request' AND index_name = 'lookup_fm_support_bundle_requests_for_case')),'true','Schema change verification failed: index lookup_fm_support_bundle_requests_for_case on table fm_support_bundle_request does not exist') AS BOOL); diff --git a/schema/crdb/fm-support-bundle-request/up3.sql b/schema/crdb/fm-support-bundle-request/up3.sql new file mode 100644 index 00000000000..0699362b195 --- /dev/null +++ b/schema/crdb/fm-support-bundle-request/up3.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS omicron.public.fm_sb_req_reconfigurator ( + sitrep_id UUID NOT NULL, + request_id UUID NOT NULL, + + PRIMARY KEY (sitrep_id, request_id) +); diff --git a/schema/crdb/fm-support-bundle-request/up4.sql b/schema/crdb/fm-support-bundle-request/up4.sql new file mode 100644 index 00000000000..565f4943625 --- /dev/null +++ b/schema/crdb/fm-support-bundle-request/up4.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS omicron.public.fm_sb_req_sled_cubby_info ( + sitrep_id UUID NOT NULL, + request_id UUID NOT NULL, + + PRIMARY KEY (sitrep_id, request_id) +); diff --git a/schema/crdb/fm-support-bundle-request/up5.sql b/schema/crdb/fm-support-bundle-request/up5.sql new file mode 100644 index 00000000000..f30f40caaf6 --- /dev/null +++ b/schema/crdb/fm-support-bundle-request/up5.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS omicron.public.fm_sb_req_sp_dumps ( + sitrep_id UUID NOT NULL, + request_id UUID NOT NULL, + + PRIMARY KEY (sitrep_id, request_id) +); diff --git a/schema/crdb/fm-support-bundle-request/up6.sql b/schema/crdb/fm-support-bundle-request/up6.sql new file mode 100644 index 00000000000..6cce61c17c2 --- /dev/null +++ b/schema/crdb/fm-support-bundle-request/up6.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS omicron.public.fm_sb_req_host_info ( + sitrep_id UUID NOT NULL, + request_id UUID NOT NULL, + all_sleds BOOL NOT NULL, + sled_ids UUID[] NOT NULL DEFAULT ARRAY[], + + PRIMARY KEY (sitrep_id, request_id) +); diff --git a/schema/crdb/fm-support-bundle-request/up7.sql b/schema/crdb/fm-support-bundle-request/up7.sql new file mode 100644 index 00000000000..d64e8010792 --- /dev/null +++ b/schema/crdb/fm-support-bundle-request/up7.sql @@ -0,0 +1,10 @@ +CREATE TABLE IF NOT EXISTS omicron.public.fm_sb_req_ereports ( + sitrep_id UUID NOT NULL, + request_id UUID NOT NULL, + start_time TIMESTAMPTZ, + end_time TIMESTAMPTZ, + only_serials TEXT[] NOT NULL DEFAULT ARRAY[], + only_classes TEXT[] NOT NULL DEFAULT ARRAY[], + + PRIMARY KEY (sitrep_id, request_id) +); diff --git a/schema/crdb/fm-support-bundle-request/up8.sql b/schema/crdb/fm-support-bundle-request/up8.sql new file mode 100644 index 00000000000..199098c0ccb --- /dev/null +++ b/schema/crdb/fm-support-bundle-request/up8.sql @@ -0,0 +1,2 @@ +ALTER TABLE omicron.public.support_bundle + ADD COLUMN IF NOT EXISTS fm_case_id UUID;