Skip to content

Commit 5f46981

Browse files
committed
[fm] Guard support bundle creation with SitrepGuardedInsert.
The support-bundle mirror of the preceding alert change: `impl SitrepGuardedResource for SupportBundle`, the `support_bundle_generation` column and `rendezvous_support_bundle_created` marker table (migration fm-bundle-resource-deletion), `support_bundle_create`'s FM path routed through the combinator inside its transaction, support-bundle generation tracking and carry-forward, the fm_rendezvous bundle loop, the fm_analysis bundle-marker lookup, and the omdb display. `support_bundle_generation` and `alert_generation` are tracked and guarded independently, so a stale generation for one resource aborts only that resource's rendezvous loop.
1 parent 70d100f commit 5f46981

27 files changed

Lines changed: 1394 additions & 142 deletions

File tree

dev-tools/omdb/src/bin/omdb/db/sitrep.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ async fn cmd_db_sitrep_show(
248248
comment,
249249
next_inv_min_time_started,
250250
alert_generation,
251+
support_bundle_generation,
251252
} = metadata;
252253

253254
const ID: &'static str = "ID";
@@ -264,6 +265,7 @@ async fn cmd_db_sitrep_show(
264265
const NEXT_INV_MIN_START: &'static str =
265266
" next inventory minimum start time";
266267
const ALERT_GEN: &'static str = "alert generation";
268+
const SUPPORT_BUNDLE_GEN: &'static str = "support bundle generation";
267269
const TOTAL_EREPORTS: &'static str = "ereports in this sitrep";
268270

269271
const WIDTH: usize = const_max_len(&[
@@ -280,6 +282,7 @@ async fn cmd_db_sitrep_show(
280282
INV_FINISHED_AT,
281283
NEXT_INV_MIN_START,
282284
ALERT_GEN,
285+
SUPPORT_BUNDLE_GEN,
283286
TOTAL_EREPORTS,
284287
]);
285288

@@ -355,6 +358,7 @@ async fn cmd_db_sitrep_show(
355358
}
356359
println!(" {NEXT_INV_MIN_START:>WIDTH$}: {next_inv_min_time_started}");
357360
println!(" {ALERT_GEN:>WIDTH$}: {alert_generation}");
361+
println!(" {SUPPORT_BUNDLE_GEN:>WIDTH$}: {support_bundle_generation}");
358362
println!(" ");
359363
println!(" {TOTAL_EREPORTS}: {}", ereports_by_id.len());
360364
// TODO(eliza): perhaps display a table summarizing those ereports? possibly

dev-tools/omdb/src/bin/omdb/nexus.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3838,23 +3838,26 @@ fn print_task_fm_rendezvous(details: &serde_json::Value) {
38383838
total_bundles_requested,
38393839
current_sitrep_bundles_requested,
38403840
bundles_created,
3841+
bundles_already_existed,
3842+
stale_sitrep,
38413843
errors,
38423844
}| {
3843-
let already_created =
3844-
total_bundles_requested - bundles_created - errors.len();
38453845
const REQUESTED: &str = "support bundles requested:";
38463846
const REQUESTED_THIS_SITREP: &str = " requested in this sitrep:";
38473847
const CREATED: &str = " created in this activation:";
3848-
const ALREADY_CREATED: &str = " already created:";
3848+
const ALREADY_EXISTED: &str = " already existed:";
38493849
const ERRORS: &str = " errors:";
38503850
const WIDTH: usize = const_max_len(&[
38513851
REQUESTED,
38523852
REQUESTED_THIS_SITREP,
38533853
CREATED,
3854-
ALREADY_CREATED,
3854+
ALREADY_EXISTED,
38553855
ERRORS,
38563856
]) + 1;
38573857
pub const NUM_WIDTH: usize = 4;
3858+
if *stale_sitrep {
3859+
println!("{ERRICON} sitrep was stale");
3860+
}
38583861
println!(
38593862
" {REQUESTED:<WIDTH$}{total_bundles_requested:>NUM_WIDTH$}"
38603863
);
@@ -3864,7 +3867,7 @@ fn print_task_fm_rendezvous(details: &serde_json::Value) {
38643867
);
38653868
println!(" {CREATED:<WIDTH$}{bundles_created:>NUM_WIDTH$}");
38663869
println!(
3867-
" {ALREADY_CREATED:<WIDTH$}{already_created:>NUM_WIDTH$}"
3870+
" {ALREADY_EXISTED:<WIDTH$}{bundles_already_existed:>NUM_WIDTH$}"
38683871
);
38693872
println!(
38703873
"{} {ERRORS:<WIDTH$}{:>NUM_WIDTH$}",

dev-tools/omdb/tests/successes.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,7 @@ task: "fm_rendezvous"
737737
support bundles requested: 0
738738
requested in this sitrep: 0
739739
created in this activation: 0
740-
already created: 0
740+
already existed: 0
741741
errors: 0
742742
marking ereports as seen:
743743
(i) note: this operation was not executed
@@ -1428,7 +1428,7 @@ task: "fm_rendezvous"
14281428
support bundles requested: 0
14291429
requested in this sitrep: 0
14301430
created in this activation: 0
1431-
already created: 0
1431+
already existed: 0
14321432
errors: 0
14331433
marking ereports as seen:
14341434
(i) note: this operation was not executed

nexus/db-model/src/fm.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub struct SitrepMetadata {
4343
pub comment: String,
4444
pub next_inv_min_time_started: DateTime<Utc>,
4545
pub alert_generation: Generation,
46+
pub support_bundle_generation: Generation,
4647
}
4748

4849
impl From<SitrepMetadata> for nexus_types::fm::SitrepMetadata {
@@ -56,6 +57,7 @@ impl From<SitrepMetadata> for nexus_types::fm::SitrepMetadata {
5657
time_created,
5758
next_inv_min_time_started,
5859
alert_generation,
60+
support_bundle_generation,
5961
} = db_meta;
6062
Self {
6163
id: id.into(),
@@ -66,6 +68,7 @@ impl From<SitrepMetadata> for nexus_types::fm::SitrepMetadata {
6668
comment,
6769
time_created,
6870
alert_generation: alert_generation.into(),
71+
support_bundle_generation: support_bundle_generation.into(),
6972
}
7073
}
7174
}
@@ -81,6 +84,7 @@ impl From<nexus_types::fm::SitrepMetadata> for SitrepMetadata {
8184
time_created,
8285
next_inv_min_time_started,
8386
alert_generation,
87+
support_bundle_generation,
8488
} = db_meta;
8589
Self {
8690
id: id.into(),
@@ -91,6 +95,7 @@ impl From<nexus_types::fm::SitrepMetadata> for SitrepMetadata {
9195
time_created,
9296
next_inv_min_time_started,
9397
alert_generation: alert_generation.into(),
98+
support_bundle_generation: support_bundle_generation.into(),
9499
}
95100
}
96101
}

nexus/db-model/src/fm/rendezvous_created.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
44

5-
//! Marker rows recording that FM rendezvous has successfully created an alert.
6-
//! See the corresponding table comments in `schema/crdb/dbinit.sql` for the
7-
//! tombstone-and-idempotency semantics that motivate these tables.
5+
//! Marker rows recording that FM rendezvous has successfully created an alert
6+
//! or support bundle. See the corresponding table comments in
7+
//! `schema/crdb/dbinit.sql` for the tombstone-and-idempotency semantics that
8+
//! motivate these tables.
89
910
use crate::Generation;
1011
use crate::typed_uuid::DbTypedUuid;
1112
use nexus_db_schema::schema::rendezvous_alert_created;
13+
use nexus_db_schema::schema::rendezvous_support_bundle_created;
1214
use omicron_uuid_kinds::{AlertKind, AlertUuid};
15+
use omicron_uuid_kinds::{SupportBundleKind, SupportBundleUuid};
1316

1417
#[derive(Queryable, Insertable, Debug, Clone, Selectable, PartialEq)]
1518
#[diesel(table_name = rendezvous_alert_created)]
@@ -27,3 +30,26 @@ impl RendezvousAlertCreated {
2730
self.alert_id.into()
2831
}
2932
}
33+
34+
#[derive(Queryable, Insertable, Debug, Clone, Selectable, PartialEq)]
35+
#[diesel(table_name = rendezvous_support_bundle_created)]
36+
pub struct RendezvousSupportBundleCreated {
37+
support_bundle_id: DbTypedUuid<SupportBundleKind>,
38+
pub created_at_generation: Generation,
39+
}
40+
41+
impl RendezvousSupportBundleCreated {
42+
pub fn new(
43+
support_bundle_id: SupportBundleUuid,
44+
generation: Generation,
45+
) -> Self {
46+
Self {
47+
support_bundle_id: support_bundle_id.into(),
48+
created_at_generation: generation,
49+
}
50+
}
51+
52+
pub fn support_bundle_id(&self) -> SupportBundleUuid {
53+
self.support_bundle_id.into()
54+
}
55+
}

nexus/db-model/src/schema_versions.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use std::{collections::BTreeMap, sync::LazyLock};
1616
///
1717
/// This must be updated when you change the database schema. Refer to
1818
/// schema/crdb/README.adoc in the root of this repository for details.
19-
pub const SCHEMA_VERSION: Version = Version::new(264, 0, 0);
19+
pub const SCHEMA_VERSION: Version = Version::new(265, 0, 0);
2020

2121
/// List of all past database schema versions, in *reverse* order
2222
///
@@ -28,6 +28,7 @@ pub static KNOWN_VERSIONS: LazyLock<Vec<KnownVersion>> = LazyLock::new(|| {
2828
// | leaving the first copy as an example for the next person.
2929
// v
3030
// KnownVersion::new(next_int, "unique-dirname-with-the-sql-files"),
31+
KnownVersion::new(265, "fm-bundle-resource-deletion"),
3132
KnownVersion::new(264, "fm-alert-resource-deletion"),
3233
KnownVersion::new(263, "external-jumbo-frames"),
3334
KnownVersion::new(262, "rename-ip-pool-reservation-type"),

nexus/db-queries/src/db/datastore/alert.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ mod tests {
235235
parent_sitrep_id: None,
236236
next_inv_min_time_started: Utc::now(),
237237
alert_generation,
238+
support_bundle_generation: Generation::new(),
238239
},
239240
cases: Default::default(),
240241
ereports_by_id: Default::default(),

nexus/db-queries/src/db/datastore/fm.rs

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1782,7 +1782,8 @@ mod tests {
17821782
time_created: Utc::now(),
17831783
parent_sitrep_id: None,
17841784
next_inv_min_time_started: Utc::now(),
1785-
alert_generation: Generation::from_u32(0),
1785+
alert_generation: Generation::new(),
1786+
support_bundle_generation: Generation::new(),
17861787
},
17871788
cases: Default::default(),
17881789
ereports_by_id: Default::default(),
@@ -1834,7 +1835,8 @@ mod tests {
18341835
time_created: Utc::now(),
18351836
parent_sitrep_id: None,
18361837
next_inv_min_time_started: Utc::now(),
1837-
alert_generation: Generation::from_u32(0),
1838+
alert_generation: Generation::new(),
1839+
support_bundle_generation: Generation::new(),
18381840
},
18391841
cases: Default::default(),
18401842
ereports_by_id: Default::default(),
@@ -1851,7 +1853,8 @@ mod tests {
18511853
time_created: Utc::now(),
18521854
parent_sitrep_id: Some(sitrep1.id()),
18531855
next_inv_min_time_started: Utc::now(),
1854-
alert_generation: Generation::from_u32(0),
1856+
alert_generation: Generation::new(),
1857+
support_bundle_generation: Generation::new(),
18551858
},
18561859
cases: Default::default(),
18571860
ereports_by_id: Default::default(),
@@ -1895,7 +1898,8 @@ mod tests {
18951898
time_created: Utc::now(),
18961899
parent_sitrep_id: None,
18971900
next_inv_min_time_started: Utc::now(),
1898-
alert_generation: Generation::from_u32(0),
1901+
alert_generation: Generation::new(),
1902+
support_bundle_generation: Generation::new(),
18991903
},
19001904
cases: Default::default(),
19011905
ereports_by_id: Default::default(),
@@ -1913,7 +1917,8 @@ mod tests {
19131917
time_created: Utc::now(),
19141918
parent_sitrep_id: Some(nonexistent_id),
19151919
next_inv_min_time_started: Utc::now(),
1916-
alert_generation: Generation::from_u32(0),
1920+
alert_generation: Generation::new(),
1921+
support_bundle_generation: Generation::new(),
19171922
},
19181923
cases: Default::default(),
19191924
ereports_by_id: Default::default(),
@@ -1951,7 +1956,8 @@ mod tests {
19511956
time_created: Utc::now(),
19521957
parent_sitrep_id: None,
19531958
next_inv_min_time_started: Utc::now(),
1954-
alert_generation: Generation::from_u32(0),
1959+
alert_generation: Generation::new(),
1960+
support_bundle_generation: Generation::new(),
19551961
},
19561962
cases: Default::default(),
19571963
ereports_by_id: Default::default(),
@@ -1968,7 +1974,8 @@ mod tests {
19681974
time_created: Utc::now(),
19691975
parent_sitrep_id: Some(sitrep1.id()),
19701976
next_inv_min_time_started: Utc::now(),
1971-
alert_generation: Generation::from_u32(0),
1977+
alert_generation: Generation::new(),
1978+
support_bundle_generation: Generation::new(),
19721979
},
19731980
cases: Default::default(),
19741981
ereports_by_id: Default::default(),
@@ -1986,7 +1993,8 @@ mod tests {
19861993
time_created: Utc::now(),
19871994
parent_sitrep_id: Some(sitrep1.id()),
19881995
next_inv_min_time_started: Utc::now(),
1989-
alert_generation: Generation::from_u32(0),
1996+
alert_generation: Generation::new(),
1997+
support_bundle_generation: Generation::new(),
19901998
},
19911999
cases: Default::default(),
19922000
ereports_by_id: Default::default(),
@@ -2318,7 +2326,8 @@ mod tests {
23182326
time_created: Utc::now(),
23192327
parent_sitrep_id: None,
23202328
next_inv_min_time_started: Utc::now(),
2321-
alert_generation: Generation::from_u32(0),
2329+
alert_generation: Generation::new(),
2330+
support_bundle_generation: Generation::new(),
23222331
},
23232332
cases,
23242333
ereports_by_id,
@@ -2429,7 +2438,8 @@ mod tests {
24292438
time_created: Utc::now(),
24302439
parent_sitrep_id: None,
24312440
next_inv_min_time_started: Utc::now(),
2432-
alert_generation: Generation::from_u32(0),
2441+
alert_generation: Generation::new(),
2442+
support_bundle_generation: Generation::new(),
24332443
},
24342444
cases,
24352445
ereports_by_id: Default::default(),
@@ -2482,7 +2492,8 @@ mod tests {
24822492
comment: "my cool sitrep".to_string(),
24832493
inv_collection_id: CollectionUuid::new_v4(),
24842494
next_inv_min_time_started: Utc::now(),
2485-
alert_generation: Generation::from_u32(0),
2495+
alert_generation: Generation::new(),
2496+
support_bundle_generation: Generation::new(),
24862497
},
24872498
cases: Default::default(),
24882499
ereports_by_id: Default::default(),
@@ -2640,7 +2651,8 @@ mod tests {
26402651
comment: "my cool sitrep".to_string(),
26412652
inv_collection_id: CollectionUuid::new_v4(),
26422653
next_inv_min_time_started: Utc::now(),
2643-
alert_generation: Generation::from_u32(0),
2654+
alert_generation: Generation::new(),
2655+
support_bundle_generation: Generation::new(),
26442656
},
26452657
cases: Default::default(),
26462658
ereports_by_id: Default::default(),
@@ -2775,7 +2787,8 @@ mod tests {
27752787
time_created: Utc::now(),
27762788
parent_sitrep_id: None,
27772789
next_inv_min_time_started: Utc::now(),
2778-
alert_generation: Generation::from_u32(0),
2790+
alert_generation: Generation::new(),
2791+
support_bundle_generation: Generation::new(),
27792792
},
27802793
cases: Default::default(),
27812794
ereports_by_id: Default::default(),
@@ -3013,7 +3026,8 @@ mod tests {
30133026
time_created: Utc::now(),
30143027
parent_sitrep_id: None,
30153028
next_inv_min_time_started: Utc::now(),
3016-
alert_generation: Generation::from_u32(0),
3029+
alert_generation: Generation::new(),
3030+
support_bundle_generation: Generation::new(),
30173031
},
30183032
cases: Default::default(),
30193033
ereports_by_id: Default::default(),
@@ -3141,7 +3155,8 @@ mod tests {
31413155
time_created: Utc::now(),
31423156
parent_sitrep_id: None,
31433157
next_inv_min_time_started: Utc::now(),
3144-
alert_generation: Generation::from_u32(0),
3158+
alert_generation: Generation::new(),
3159+
support_bundle_generation: Generation::new(),
31453160
},
31463161
cases: Default::default(),
31473162
ereports_by_id: Default::default(),
@@ -3437,7 +3452,8 @@ mod tests {
34373452
comment: "child sitrep".to_string(),
34383453
inv_collection_id: CollectionUuid::new_v4(),
34393454
next_inv_min_time_started: Utc::now(),
3440-
alert_generation: Generation::from_u32(0),
3455+
alert_generation: Generation::new(),
3456+
support_bundle_generation: Generation::new(),
34413457
},
34423458
cases: Default::default(),
34433459
ereports_by_id: Default::default(),
@@ -3748,18 +3764,20 @@ mod tests {
37483764
parent_sitrep_id: None,
37493765
next_inv_min_time_started: Utc::now(),
37503766
alert_generation: Generation::from_u32(5),
3767+
support_bundle_generation: Generation::from_u32(7),
37513768
},
37523769
cases: Default::default(),
37533770
ereports_by_id: Default::default(),
37543771
};
37553772

37563773
datastore.fm_sitrep_insert(&opctx, sitrep.clone()).await.unwrap();
37573774

3758-
// Read the persisted metadata back and assert the generation value
3775+
// Read the persisted metadata back and assert both generation values
37593776
// roundtripped correctly through the INSERT and SELECT.
37603777
let loaded =
37613778
datastore.fm_sitrep_metadata_read(&opctx, sitrep_id).await.unwrap();
37623779
assert_eq!(loaded.alert_generation, Generation::from_u32(5));
3780+
assert_eq!(loaded.support_bundle_generation, Generation::from_u32(7));
37633781

37643782
db.terminate().await;
37653783
logctx.cleanup_successful();

0 commit comments

Comments
 (0)