Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 35 additions & 9 deletions dev-tools/omdb/src/bin/omdb/support_bundle_collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ use nexus_db_queries::context::OpContext;
use nexus_db_queries::db::DataStore;
use nexus_types::fm::ereport::EreportFilters;
use nexus_types::support_bundle::BundleDataSelection;
use nexus_types::support_bundle::BundleTimeRange;
use omicron_uuid_kinds::SupportBundleUuid;
use std::io::Seek;
use std::io::SeekFrom;
use std::sync::Arc;
use std::time::Duration;
use support_bundle_collection::BundleCollection;
use support_bundle_collection::BundleInfo;
use support_bundle_collection::zip::bundle_to_zipfile;
Expand Down Expand Up @@ -89,6 +91,19 @@ struct CollectArgs {
/// Defaults to all categories.
#[clap(long, value_enum)]
include: Vec<BundleCategory>,

/// Collect data newer than this duration ago. Applies to both
/// service logs and ereports. Defaults to 7 days when `--since`
/// is not set.
#[clap(long, value_parser = humantime::parse_duration)]
since: Option<Duration>,

/// Collect data older than this duration ago. Truncates the
/// upper bound of the window. Applies to both service logs and
/// ereports. Defaults to no upper bound (file mtimes can't be
/// in the future, so this effectively means "up to now").
#[clap(long, value_parser = humantime::parse_duration)]
until: Option<Duration>,
}

impl CollectArgs {
Expand All @@ -106,17 +121,28 @@ impl CollectArgs {
BundleCategory::HostInfo => sel.with_all_sleds(),
BundleCategory::SledCubbyInfo => sel.with_sled_cubby_info(),
BundleCategory::SpDumps => sel.with_sp_dumps(),
BundleCategory::Ereports => sel.with_ereports(
EreportFilters::new()
.with_start_time(
omicron_common::now_db_precision()
- chrono::Days::new(7),
)
.expect("no end time set, cannot fail"),
),
BundleCategory::Ereports => {
sel.with_ereports(EreportFilters::new())
}
};
}
sel

// Apply a bundle-wide time range. Each flag's default fires
// independently: `--since` defaults to 7 days, `--until`
// defaults to no upper bound.
let now = omicron_common::now_db_precision();
let range = BundleTimeRange {
start: self
.since
.and_then(|d| chrono::Duration::from_std(d).ok())
.map(|d| now - d)
.or(Some(now - chrono::Days::new(7))),
end: self
.until
.and_then(|d| chrono::Duration::from_std(d).ok())
.map(|d| now - d),
};
sel.with_time_range(range)
}
}

Expand Down
72 changes: 38 additions & 34 deletions dev-tools/omdb/tests/successes.out
Original file line number Diff line number Diff line change
Expand Up @@ -747,23 +747,25 @@ task: "fm_sitrep_gc"
configured period: every <REDACTED_DURATION>s
last completed activation: <REDACTED ITERATIONS>, triggered by <TRIGGERED_BY_REDACTED>
started at <REDACTED_TIMESTAMP> (<REDACTED DURATION>s ago) and ran for <REDACTED DURATION>ms
batch size: 1000
orphaned sitreps deleted: 0
batches: 1
orphaned fm_alert_request rows deleted: 0
batches: 1
orphaned fm_case rows deleted: 0
batches: 1
orphaned fm_ereport_in_case rows deleted: 0
batches: 1
orphaned fm_support_bundle_request rows deleted: 0
batches: 1
orphaned fm_support_bundle_request_data_selection_ereports rows deleted: 0
batches: 1
orphaned fm_support_bundle_request_data_selection_flags rows deleted: 0
batches: 1
orphaned fm_support_bundle_request_data_selection_host_info rows deleted: 0
batches: 1
batch size: 1000
orphaned sitreps deleted: 0
batches: 1
orphaned fm_alert_request rows deleted: 0
batches: 1
orphaned fm_case rows deleted: 0
batches: 1
orphaned fm_ereport_in_case rows deleted: 0
batches: 1
orphaned fm_support_bundle_request rows deleted: 0
batches: 1
orphaned fm_support_bundle_request_data_selection_ereports rows deleted: 0
batches: 1
orphaned fm_support_bundle_request_data_selection_flags rows deleted: 0
batches: 1
orphaned fm_support_bundle_request_data_selection_host_info rows deleted: 0
batches: 1
orphaned fm_support_bundle_request_data_selection_time_range rows deleted: 0
batches: 1

task: "fm_sitrep_loader"
configured period: every <REDACTED_DURATION>s
Expand Down Expand Up @@ -1428,23 +1430,25 @@ task: "fm_sitrep_gc"
configured period: every <REDACTED_DURATION>s
last completed activation: <REDACTED ITERATIONS>, triggered by <TRIGGERED_BY_REDACTED>
started at <REDACTED_TIMESTAMP> (<REDACTED DURATION>s ago) and ran for <REDACTED DURATION>ms
batch size: 1000
orphaned sitreps deleted: 0
batches: 1
orphaned fm_alert_request rows deleted: 0
batches: 1
orphaned fm_case rows deleted: 0
batches: 1
orphaned fm_ereport_in_case rows deleted: 0
batches: 1
orphaned fm_support_bundle_request rows deleted: 0
batches: 1
orphaned fm_support_bundle_request_data_selection_ereports rows deleted: 0
batches: 1
orphaned fm_support_bundle_request_data_selection_flags rows deleted: 0
batches: 1
orphaned fm_support_bundle_request_data_selection_host_info rows deleted: 0
batches: 1
batch size: 1000
orphaned sitreps deleted: 0
batches: 1
orphaned fm_alert_request rows deleted: 0
batches: 1
orphaned fm_case rows deleted: 0
batches: 1
orphaned fm_ereport_in_case rows deleted: 0
batches: 1
orphaned fm_support_bundle_request rows deleted: 0
batches: 1
orphaned fm_support_bundle_request_data_selection_ereports rows deleted: 0
batches: 1
orphaned fm_support_bundle_request_data_selection_flags rows deleted: 0
batches: 1
orphaned fm_support_bundle_request_data_selection_host_info rows deleted: 0
batches: 1
orphaned fm_support_bundle_request_data_selection_time_range rows deleted: 0
batches: 1

task: "fm_sitrep_loader"
configured period: every <REDACTED_DURATION>s
Expand Down
83 changes: 54 additions & 29 deletions nexus/db-model/src/fm/support_bundle_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ use nexus_db_schema::schema::{
fm_support_bundle_request_data_selection_ereports,
fm_support_bundle_request_data_selection_flags,
fm_support_bundle_request_data_selection_host_info,
fm_support_bundle_request_data_selection_time_range,
};
use nexus_types::fm;
use nexus_types::fm::ereport::{EreportFilters, EreportFiltersParams};
use nexus_types::support_bundle::{BundleData, SledSelection};
use nexus_types::fm::ereport::EreportFilters;
use nexus_types::support_bundle::{BundleData, BundleTimeRange, SledSelection};
use omicron_uuid_kinds::{
CaseKind, GenericUuid, SitrepKind, SledUuid, SupportBundleKind,
};
Expand Down Expand Up @@ -120,14 +121,14 @@ impl HostInfo {
impl From<HostInfo> for BundleData {
fn from(row: HostInfo) -> Self {
let HostInfo { sitrep_id: _, request_id: _, all_sleds, sled_ids } = row;
let selection = if all_sleds {
let sleds = if all_sleds {
SledSelection::All
} else {
SledSelection::Specific(
sled_ids.into_iter().map(SledUuid::from_untyped_uuid).collect(),
)
};
BundleData::HostInfo(selection)
BundleData::HostInfo(sleds)
}
}

Expand All @@ -136,8 +137,6 @@ impl From<HostInfo> for BundleData {
pub struct Ereports {
pub sitrep_id: DbTypedUuid<SitrepKind>,
pub request_id: DbTypedUuid<SupportBundleKind>,
pub start_time: Option<DateTime<Utc>>,
pub end_time: Option<DateTime<Utc>>,
pub only_serials: Vec<String>,
pub only_classes: Vec<String>,
}
Expand All @@ -151,39 +150,64 @@ impl Ereports {
Ereports {
sitrep_id: sitrep_id.into(),
request_id: request_id.into(),
start_time: filters.start_time(),
end_time: filters.end_time(),
only_serials: filters.only_serials().to_vec(),
only_classes: filters.only_classes().to_vec(),
}
}
}

impl TryFrom<Ereports> for BundleData {
type Error = omicron_common::api::external::Error;

fn try_from(row: Ereports) -> Result<Self, Self::Error> {
impl From<Ereports> for BundleData {
fn from(row: Ereports) -> Self {
let Ereports {
sitrep_id: _,
request_id: _,
start_time,
end_time,
only_serials,
only_classes,
} = row;
EreportFiltersParams {
start_time,
end_time,
only_serials,
only_classes,
BundleData::Ereports(
EreportFilters::new()
.with_serials(only_serials)
.with_classes(only_classes),
)
}
}

/// Bundle-wide time bound persisted alongside the per-category data
/// selection rows. Reads are merged into
/// [`nexus_types::support_bundle::BundleDataSelection::time_range`].
#[derive(Queryable, Insertable, Clone, Debug, Selectable)]
#[diesel(table_name = fm_support_bundle_request_data_selection_time_range)]
pub struct TimeRange {
pub sitrep_id: DbTypedUuid<SitrepKind>,
pub request_id: DbTypedUuid<SupportBundleKind>,
pub start_time: Option<DateTime<Utc>>,
pub end_time: Option<DateTime<Utc>>,
}

impl TimeRange {
pub fn from_sitrep(
sitrep_id: impl Into<DbTypedUuid<SitrepKind>>,
request_id: impl Into<DbTypedUuid<SupportBundleKind>>,
range: &BundleTimeRange,
) -> Self {
TimeRange {
sitrep_id: sitrep_id.into(),
request_id: request_id.into(),
start_time: range.start,
end_time: range.end,
}
.try_into()
.map(BundleData::Ereports)
}
}

/// Joined query result: flags + optional host_info + optional ereports.
/// All fields use `#[diesel(embed)]` so no `table_name` is needed.
impl From<TimeRange> for BundleTimeRange {
fn from(row: TimeRange) -> Self {
BundleTimeRange { start: row.start_time, end: row.end_time }
}
}

/// Joined query result: flags + optional host_info + optional ereports +
/// optional bundle-wide time range. All fields use `#[diesel(embed)]` so
/// no `table_name` is needed.
#[derive(Queryable, Selectable)]
pub struct BundleDataSelection {
#[diesel(embed)]
Expand All @@ -192,14 +216,14 @@ pub struct BundleDataSelection {
pub host_info: Option<HostInfo>,
#[diesel(embed)]
pub ereports: Option<Ereports>,
#[diesel(embed)]
pub time_range: Option<TimeRange>,
}

impl TryFrom<BundleDataSelection>
impl From<BundleDataSelection>
for nexus_types::support_bundle::BundleDataSelection
{
type Error = omicron_common::api::external::Error;

fn try_from(row: BundleDataSelection) -> Result<Self, Self::Error> {
fn from(row: BundleDataSelection) -> Self {
let mut selection =
nexus_types::support_bundle::BundleDataSelection::new();
if row.flags.include_reconfigurator {
Expand All @@ -215,8 +239,9 @@ impl TryFrom<BundleDataSelection>
selection.insert(host_info.into());
}
if let Some(ereports) = row.ereports {
selection.insert(ereports.try_into()?);
selection.insert(ereports.into());
}
Ok(selection)
selection.set_time_range(row.time_range.map(BundleTimeRange::from));
selection
}
}
3 changes: 2 additions & 1 deletion nexus/db-model/src/schema_versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(256, 0, 0);
pub const SCHEMA_VERSION: Version = Version::new(257, 0, 0);

/// List of all past database schema versions, in *reverse* order
///
Expand All @@ -28,6 +28,7 @@ pub static KNOWN_VERSIONS: LazyLock<Vec<KnownVersion>> = 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(257, "support-bundle-time-range"),
KnownVersion::new(256, "bgp-unnumbered-peer-cleanup"),
KnownVersion::new(255, "blueprint-add-external-networking-generation"),
KnownVersion::new(
Expand Down
Loading
Loading