Skip to content
Merged
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
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions clients/wicketd-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ workspace = true
[dependencies]
bootstrap-agent-lockstep-types.workspace = true
chrono.workspace = true
iddqd.workspace = true
installinator-common.workspace = true
omicron-common.workspace = true
omicron-uuid-kinds.workspace = true
Expand Down
2 changes: 2 additions & 0 deletions clients/wicketd-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ progenitor::generate_api!(
UplinkConfig = { derives = [PartialEq, Eq, PartialOrd, Ord] },
},
crates = {
"iddqd" = "*",
"omicron-uuid-kinds" = "*",
"oxide-update-engine-types" = "*",
},
Expand Down Expand Up @@ -71,6 +72,7 @@ progenitor::generate_api!(
RssStep = bootstrap_agent_lockstep_types::RssStep,
SpComponentCaboose = wicket_common::inventory::SpComponentCaboose,
SpComponentInfo = wicket_common::inventory::SpComponentInfo,
SpEventReport = wicket_common::update_events::SpEventReport,
SpIdentifier = wicket_common::inventory::SpIdentifier,
SpIgnition = wicket_common::inventory::SpIgnition,
SpIgnitionSystemType = wicket_common::inventory::SpIgnitionSystemType,
Expand Down
39 changes: 32 additions & 7 deletions openapi/wicketd.json
Original file line number Diff line number Diff line change
Expand Up @@ -1602,13 +1602,22 @@
}
},
"event_reports": {
"type": "object",
"additionalProperties": {
"type": "object",
"additionalProperties": {
"$ref": "#/components/schemas/EventReportForWicketdEngineSpec"
}
}
"title": "IdOrdMap",
"x-rust-type": {
"crate": "iddqd",
"parameters": [
{
"$ref": "#/components/schemas/SpEventReport"
}
],
"path": "iddqd::IdOrdMap",
"version": "*"
},
"type": "array",
"items": {
"$ref": "#/components/schemas/SpEventReport"
},
"uniqueItems": true
},
"system_version": {
"nullable": true,
Expand Down Expand Up @@ -4157,6 +4166,22 @@
}
]
},
"SpEventReport": {
"description": "An event report for a single SP.",
"type": "object",
"properties": {
"event_report": {
"$ref": "#/components/schemas/EventReportForWicketdEngineSpec"
},
"sp": {
"$ref": "#/components/schemas/SpIdentifier"
}
},
"required": [
"event_report",
"sp"
]
},
"SpIdentifier": {
"type": "object",
"properties": {
Expand Down
20 changes: 20 additions & 0 deletions wicket-common/src/update_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use gateway_client::types::PowerState;
use iddqd::IdOrdItem;
use iddqd::id_upcast;
use oxide_update_engine_types::errors::NestedEngineError;
use oxide_update_engine_types::spec::EngineSpec;
use schemars::JsonSchema;
Expand All @@ -14,6 +16,7 @@ use thiserror::Error;
use tufaceous_artifact::DisplayTags;

use crate::artifact::ArtifactId;
use crate::inventory::SpIdentifier;

#[derive(JsonSchema)]
pub enum WicketdEngineSpec {}
Expand Down Expand Up @@ -77,6 +80,23 @@ oxide_update_engine_types::define_update_engine_types!(pub WicketdEngineSpec);
pub type StepStatus<S = WicketdEngineSpec> =
oxide_update_engine_types::buffer::StepStatus<S>;

/// An event report for a single SP.
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
pub struct SpEventReport {
pub sp: SpIdentifier,
pub event_report: EventReport,
}

impl IdOrdItem for SpEventReport {
type Key<'a> = SpIdentifier;

fn key(&self) -> Self::Key<'_> {
self.sp
}

id_upcast!();
}

#[derive(JsonSchema)]
pub enum TestStepSpec {}

Expand Down
6 changes: 3 additions & 3 deletions wicket/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@
use crate::{State, keymap::Cmd, state::ComponentId};
use camino::Utf8PathBuf;
use humantime::format_rfc3339;
use iddqd::IdOrdMap;
use semver::Version;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs::File;
use std::time::SystemTime;
use wicket_common::artifact::ArtifactId;
use wicket_common::inventory::RackV1Inventory;
use wicket_common::update_events::EventReport;
use wicket_common::update_events::SpEventReport;
use wicketd_client::types::{
CurrentRssUserConfig, IgnitionCommand, RackOperationStatus,
};
use wicketd_commission_types::inventory::LocationInfo;

/// Event report type returned by the get_artifacts_and_event_reports API call.
pub type EventReportMap = HashMap<String, HashMap<String, EventReport>>;
pub type EventReportMap = IdOrdMap<SpEventReport>;

/// An event that will update state
///
Expand Down
18 changes: 0 additions & 18 deletions wicket/src/state/inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,24 +312,6 @@ impl Display for ComponentId {
}
}

pub struct ParsableComponentId<'a> {
pub sp_type: &'a str,
pub i: &'a str,
}

impl<'a> TryFrom<ParsableComponentId<'a>> for ComponentId {
type Error = ();
fn try_from(value: ParsableComponentId<'a>) -> Result<Self, Self::Error> {
let i: u8 = value.i.parse().map_err(|_| ())?;
match (value.sp_type, i) {
("sled", 0..=31) => Ok(ComponentId::Sled(i)),
("switch", 0..=1) => Ok(ComponentId::Switch(i)),
("power", 0..=1) => Ok(ComponentId::Psc(i)),
_ => Err(()),
}
}
}

#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub enum PowerState {
/// Working
Expand Down
4 changes: 1 addition & 3 deletions wicket/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ mod status;
mod update;

pub use force_update::ForceUpdateState;
pub use inventory::{
ALL_COMPONENT_IDS, Component, ComponentId, Inventory, ParsableComponentId,
};
pub use inventory::{ALL_COMPONENT_IDS, Component, ComponentId, Inventory};
pub use rack::{KnightRiderMode, RackState};
pub use status::ServiceStatus;
pub use update::{
Expand Down
30 changes: 13 additions & 17 deletions wicket/src/state/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use wicket_common::update_events::{
use crate::helpers::{get_update_simulated_result, get_update_test_error};
use crate::{events::EventReportMap, ui::defaults::style};

use super::{ALL_COMPONENT_IDS, ComponentId, ParsableComponentId};
use super::{ALL_COMPONENT_IDS, ComponentId};
use semver::Version;
use serde::{Deserialize, Serialize};
use slog::Logger;
Expand Down Expand Up @@ -510,22 +510,18 @@ pub fn parse_event_report_map(
reports: EventReportMap,
) -> BTreeMap<ComponentId, EventReport> {
let mut component_id_map = BTreeMap::new();
for (sp_type, logs) in reports {
for (i, event_report) in logs {
let Ok(id) = ComponentId::try_from(ParsableComponentId {
sp_type: &sp_type,
i: &i,
}) else {
slog::warn!(
log,
"Invalid ComponentId in EventReportMap: {} {}",
&sp_type,
&i
);
continue;
};
component_id_map.insert(id, event_report);
}
for report in reports {
let Ok(id) =
ComponentId::from_sp_type_and_slot(report.sp.typ, report.sp.slot)
else {
slog::warn!(
log,
"Invalid ComponentId in EventReportMap: {:?}",
report.sp,
);
continue;
};
component_id_map.insert(id, report.event_report);
}

component_id_map
Expand Down
1 change: 1 addition & 0 deletions wicketd-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ workspace = true
bootstrap-agent-lockstep-types.workspace = true
dropshot.workspace = true
gateway-client.workspace = true
iddqd.workspace = true
omicron-uuid-kinds.workspace = true
omicron-workspace-hack.workspace = true
schemars.workspace = true
Expand Down
5 changes: 3 additions & 2 deletions wicketd-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ use dropshot::Path;
use dropshot::RequestContext;
use dropshot::TypedBody;
use gateway_client::types::IgnitionCommand;
use iddqd::IdOrdMap;
use schemars::JsonSchema;
use semver::Version;
use serde::Deserialize;
use serde::Serialize;
use sled_hardware_types::BaseboardId;
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::net::Ipv6Addr;
use wicket_common::artifact::ArtifactId;
Expand All @@ -31,6 +31,7 @@ use wicket_common::rack_update::AbortUpdateOptions;
use wicket_common::rack_update::ClearUpdateStateOptions;
use wicket_common::rack_update::StartUpdateOptions;
use wicket_common::update_events::EventReport;
use wicket_common::update_events::SpEventReport;
use wicketd_commission_types::rack_setup::BgpAuthKeyId;
use wicketd_commission_types::update::ClearUpdateStateResponse;
use wicketd_commission_types::update::UpdateTargets;
Expand Down Expand Up @@ -323,7 +324,7 @@ pub struct GetArtifactsAndEventReportsResponse {
/// repository.
pub artifacts: Vec<ArtifactId>,

pub event_reports: BTreeMap<SpType, BTreeMap<u16, EventReport>>,
pub event_reports: IdOrdMap<SpEventReport>,
}

#[derive(Clone, Debug, JsonSchema, Deserialize)]
Expand Down
24 changes: 7 additions & 17 deletions wicketd/src/commission/http_entrypoints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use wicketd_commission_api::{
};
use wicketd_commission_types::inventory::{
BaseboardId, GetBootstrapSledsResponse, Inventory, InventoryParams,
LocationInfo, SpIdentifier, SpType, SwitchSlot,
LocationInfo, SpType, SwitchSlot,
};
use wicketd_commission_types::rack_setup::{
BgpAuthKey, BgpAuthKeyPath, CertificatePem, CertificateUploadResponse,
Expand Down Expand Up @@ -246,23 +246,13 @@ impl WicketdCommissionApi for WicketdCommissionApiImpl {
let ctx = rqctx.context();
let event_reports = ctx.update_tracker.event_reports().await;

// event_reports is keyed by (sp_type, slot), so the derived
// SpIdentifiers are unique by construction.
//
// TODO: once rkdeploy is on the published API, we can make
// `event_reports` be an IdOrdMap and make this much simpler.
let mut sps = IdOrdMap::new();
for (sp_type, slots) in event_reports {
for (slot, report) in slots {
sps.insert_unique(progress::sp_update_progress(
SpIdentifier { typ: sp_type, slot },
report,
))
.expect(
"event_reports is keyed by (sp_type, slot), so SP ids \
are unique",
);
}
for report in event_reports {
sps.insert_unique(progress::sp_update_progress(
report.sp,
report.event_report,
))
.expect("event_reports is keyed by SpIdentifier");
}

Ok(HttpResponseOk(GetUpdateProgressResponse { sps }))
Expand Down
19 changes: 8 additions & 11 deletions wicketd/src/update_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use gateway_messages::ROT_PAGE_SIZE;
use gateway_messages::SpComponent;
use gateway_types::rot::RotImageError;
use gateway_types::rot::RotState;
use iddqd::IdOrdMap;
use installinator_common::InstallinatorCompletionMetadata;
use installinator_common::WriteOutput;
use lpc55_areas::CMPAPage;
Expand Down Expand Up @@ -89,6 +90,7 @@ use wicket_common::update_events::SpComponentUpdateSpec;
use wicket_common::update_events::SpComponentUpdateStage;
use wicket_common::update_events::SpComponentUpdateStepId;
use wicket_common::update_events::SpComponentUpdateTerminalError;
use wicket_common::update_events::SpEventReport;
use wicket_common::update_events::StepContext;
use wicket_common::update_events::StepHandle;
use wicket_common::update_events::StepProgress;
Expand Down Expand Up @@ -436,9 +438,7 @@ impl UpdateTracker {
self.sp_update_data.lock().await.artifact_store.system_version()
}

pub(crate) async fn event_reports(
&self,
) -> BTreeMap<SpType, BTreeMap<u16, EventReport>> {
pub(crate) async fn event_reports(&self) -> IdOrdMap<SpEventReport> {
self.sp_update_data.lock().await.event_reports()
}

Expand Down Expand Up @@ -719,17 +719,14 @@ impl UpdateTrackerData {
Self { artifact_store, sp_update_data: BTreeMap::new() }
}

// TODO: once rkdeploy is on the published API, change the return type here
// and elsewhere to be an `IdOrdMap<SpEventReport>` where `SpEventReport`'s
// key is an `SpIdentifier`.
fn event_reports(&self) -> BTreeMap<SpType, BTreeMap<u16, EventReport>> {
let mut event_reports = BTreeMap::new();
fn event_reports(&self) -> IdOrdMap<SpEventReport> {
let mut event_reports = IdOrdMap::new();
for (sp, update_data) in &self.sp_update_data {
let event_report =
update_data.event_buffer.lock().unwrap().generate_report();
let inner: &mut BTreeMap<_, _> =
event_reports.entry(sp.typ).or_default();
inner.insert(sp.slot, event_report);
event_reports
.insert_unique(SpEventReport { sp: *sp, event_report })
.expect("sp_update_data is keyed by SpIdentifier");
}
event_reports
}
Expand Down
Loading