Skip to content

Commit f0808c1

Browse files
committed
Add cosmo to ignition
1 parent 0a3e169 commit f0808c1

File tree

13 files changed

+4487
-115
lines changed

13 files changed

+4487
-115
lines changed

Cargo.lock

Lines changed: 109 additions & 82 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -457,9 +457,9 @@ gateway-client = { path = "clients/gateway-client" }
457457
# compatibility, but will mean that faux-mgs might be missing new
458458
# functionality.)
459459
#
460-
gateway-ereport-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "77e316c812aa057b9714d0d99c4a7bdd36d45be2", default-features = false, features = ["debug-impls"] }
461-
gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "77e316c812aa057b9714d0d99c4a7bdd36d45be2", default-features = false, features = ["std"] }
462-
gateway-sp-comms = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "77e316c812aa057b9714d0d99c4a7bdd36d45be2" }
460+
gateway-ereport-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "ad5f86ce59029dbc9154d1ec65e2e988ed50628a", default-features = false, features = ["debug-impls"] }
461+
gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "ad5f86ce59029dbc9154d1ec65e2e988ed50628a", default-features = false, features = ["std"] }
462+
gateway-sp-comms = { git = "https://github.com/oxidecomputer/management-gateway-service", rev = "ad5f86ce59029dbc9154d1ec65e2e988ed50628a" }
463463
gateway-test-utils = { path = "gateway-test-utils" }
464464
gateway-types = { path = "gateway-types" }
465465
gethostname = "0.5.0"

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@ fn show_sps_from_ignition(
236236
id: SpIgnitionSystemType::Gimlet,
237237
..
238238
} => "Gimlet".to_string(),
239+
SpIgnition::Yes {
240+
id: SpIgnitionSystemType::Cosmo,
241+
..
242+
} => "Cosmo".to_string(),
239243
SpIgnition::Yes {
240244
id: SpIgnitionSystemType::Sidecar,
241245
..

gateway-api/src/lib.rs

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ use gateway_types::{
1717
},
1818
component_details::SpComponentDetails,
1919
host::{ComponentFirmwareHashStatus, HostStartupOptions},
20-
ignition::{IgnitionCommand, SpIgnitionInfo},
20+
ignition,
21+
//ignition::{IgnitionCommand, SpIgnitionInfo},
2122
rot::{RotCfpa, RotCfpaSlot, RotCmpa, RotState},
2223
sensor::SpSensorReading,
2324
task_dump::TaskDump,
@@ -45,6 +46,7 @@ api_versions!([
4546
// | example for the next person.
4647
// v
4748
// (next_int, IDENT),
49+
(2, COSMO),
4850
(1, INITIAL),
4951
]);
5052

@@ -407,10 +409,43 @@ pub trait GatewayApi {
407409
#[endpoint {
408410
method = GET,
409411
path = "/ignition",
412+
operation_id = "ignition_list",
413+
versions = VERSION_INITIAL..VERSION_COSMO
410414
}]
411-
async fn ignition_list(
415+
async fn ignition_list_v1(
412416
rqctx: RequestContext<Self::Context>,
413-
) -> Result<HttpResponseOk<Vec<SpIgnitionInfo>>, HttpError>;
417+
) -> Result<HttpResponseOk<Vec<ignition::v1::SpIgnitionInfo>>, HttpError>;
418+
419+
/// List SPs via Ignition
420+
///
421+
/// Retreive information for all SPs via the Ignition controller. This is
422+
/// lower latency and has fewer possible failure modes than querying the SP
423+
/// over the management network.
424+
#[endpoint {
425+
method = GET,
426+
path = "/ignition",
427+
operation_id = "ignition_list",
428+
versions = VERSION_COSMO..
429+
}]
430+
async fn ignition_list_v2(
431+
rqctx: RequestContext<Self::Context>,
432+
) -> Result<HttpResponseOk<Vec<ignition::v2::SpIgnitionInfo>>, HttpError>;
433+
434+
/// Get SP info via Ignition
435+
///
436+
/// Retreive information for an SP via the Ignition controller. This is
437+
/// lower latency and has fewer possible failure modes than querying the SP
438+
/// over the management network.
439+
#[endpoint {
440+
method = GET,
441+
path = "/ignition/{type}/{slot}",
442+
operation_id = "ignition_get",
443+
versions = VERSION_INITIAL..VERSION_COSMO
444+
}]
445+
async fn ignition_get_v1(
446+
rqctx: RequestContext<Self::Context>,
447+
path: Path<PathSp>,
448+
) -> Result<HttpResponseOk<ignition::v1::SpIgnitionInfo>, HttpError>;
414449

415450
/// Get SP info via Ignition
416451
///
@@ -420,11 +455,14 @@ pub trait GatewayApi {
420455
#[endpoint {
421456
method = GET,
422457
path = "/ignition/{type}/{slot}",
458+
operation_id = "ignition_get",
459+
versions = VERSION_COSMO..
423460
}]
424-
async fn ignition_get(
461+
async fn ignition_get_v2(
425462
rqctx: RequestContext<Self::Context>,
426463
path: Path<PathSp>,
427-
) -> Result<HttpResponseOk<SpIgnitionInfo>, HttpError>;
464+
) -> Result<HttpResponseOk<ignition::v2::SpIgnitionInfo>, HttpError>;
465+
428466

429467
/// Send an ignition command targeting a specific SP.
430468
///
@@ -437,12 +475,35 @@ pub trait GatewayApi {
437475
#[endpoint {
438476
method = POST,
439477
path = "/ignition/{type}/{slot}/{command}",
478+
operation_id = "ignition_command",
479+
versions = VERSION_INITIAL..VERSION_COSMO
440480
}]
441-
async fn ignition_command(
481+
async fn ignition_command_v1(
442482
rqctx: RequestContext<Self::Context>,
443-
path: Path<PathSpIgnitionCommand>,
483+
path: Path<ignition::v1::PathSpIgnitionCommand>,
444484
) -> Result<HttpResponseUpdatedNoContent, HttpError>;
445485

486+
/// Send an ignition command targeting a specific SP.
487+
///
488+
/// This endpoint can be used to transition a target between A2 and A3 (via
489+
/// power-on / power-off) or reset it.
490+
///
491+
/// The management network traffic caused by requests to this endpoint is
492+
/// between this MGS instance and its local ignition controller, _not_ the
493+
/// SP targeted by the command.
494+
#[endpoint {
495+
method = POST,
496+
path = "/ignition/{type}/{slot}/{command}",
497+
operation_id = "ignition_command",
498+
versions = VERSION_COSMO..
499+
}]
500+
async fn ignition_command_v2(
501+
rqctx: RequestContext<Self::Context>,
502+
path: Path<ignition::v2::PathSpIgnitionCommand>,
503+
) -> Result<HttpResponseUpdatedNoContent, HttpError>;
504+
505+
506+
446507
/// Get the current power state of a sled via its SP.
447508
///
448509
/// Note that if the sled is in A3, the SP is powered off and will not be able
@@ -684,12 +745,3 @@ pub struct GetRotBootInfoParams {
684745
pub version: u8,
685746
}
686747

687-
#[derive(Deserialize, JsonSchema)]
688-
pub struct PathSpIgnitionCommand {
689-
/// ID for the SP that the gateway service translates into the appropriate
690-
/// port for communicating with the given SP.
691-
#[serde(flatten)]
692-
pub sp: SpIdentifier,
693-
/// Ignition command to perform on the targeted SP.
694-
pub command: IgnitionCommand,
695-
}

gateway-test-utils/src/sim_state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub async fn current_simulator_state(simrack: &SimRack) -> Vec<SpInfo> {
3636
};
3737
let typ = match target_state.system_type {
3838
SystemType::Sidecar => SpType::Switch,
39-
SystemType::Gimlet => SpType::Sled,
39+
SystemType::Gimlet | SystemType::Cosmo => SpType::Sled,
4040
SystemType::Psc => {
4141
todo!("testing simulated PSC not yet implemented")
4242
}

gateway-types/src/ignition/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
pub mod v1;
6+
pub mod v2;
7+
8+
pub use v2::*;

gateway-types/src/ignition.rs renamed to gateway-types/src/ignition/v1.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ use serde::{Deserialize, Serialize};
77

88
use crate::component::SpIdentifier;
99

10+
#[derive(Deserialize, JsonSchema)]
11+
pub struct PathSpIgnitionCommand {
12+
/// ID for the SP that the gateway service translates into the appropriate
13+
/// port for communicating with the given SP.
14+
#[serde(flatten)]
15+
pub sp: SpIdentifier,
16+
/// Ignition command to perform on the targeted SP.
17+
pub command: IgnitionCommand,
18+
}
19+
1020
#[derive(
1121
Debug,
1222
Clone,
@@ -135,6 +145,8 @@ impl From<gateway_messages::ignition::SystemType> for SpIgnitionSystemType {
135145
SystemType::Sidecar => Self::Sidecar,
136146
SystemType::Psc => Self::Psc,
137147
SystemType::Unknown(id) => Self::Unknown { id },
148+
SystemType::Cosmo => Self::Unknown { id: 0x4 },
138149
}
139150
}
140151
}
152+

gateway-types/src/ignition/v2.rs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
// This Source Code Form is subject to the terms of the Mozilla Public
2+
// License, v. 2.0. If a copy of the MPL was not distributed with this
3+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4+
5+
use schemars::JsonSchema;
6+
use serde::{Deserialize, Serialize};
7+
8+
use crate::component::SpIdentifier;
9+
10+
#[derive(Deserialize, JsonSchema)]
11+
pub struct PathSpIgnitionCommand {
12+
/// ID for the SP that the gateway service translates into the appropriate
13+
/// port for communicating with the given SP.
14+
#[serde(flatten)]
15+
pub sp: SpIdentifier,
16+
/// Ignition command to perform on the targeted SP.
17+
pub command: IgnitionCommand,
18+
}
19+
20+
#[derive(
21+
Debug,
22+
Clone,
23+
PartialEq,
24+
Eq,
25+
PartialOrd,
26+
Ord,
27+
Deserialize,
28+
Serialize,
29+
JsonSchema,
30+
)]
31+
pub struct SpIgnitionInfo {
32+
pub id: SpIdentifier,
33+
pub details: SpIgnition,
34+
}
35+
36+
/// Ignition command.
37+
#[derive(
38+
Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, JsonSchema,
39+
)]
40+
#[serde(rename_all = "snake_case")]
41+
pub enum IgnitionCommand {
42+
PowerOn,
43+
PowerOff,
44+
PowerReset,
45+
}
46+
47+
impl From<IgnitionCommand> for gateway_messages::IgnitionCommand {
48+
fn from(cmd: IgnitionCommand) -> Self {
49+
match cmd {
50+
IgnitionCommand::PowerOn => {
51+
gateway_messages::IgnitionCommand::PowerOn
52+
}
53+
IgnitionCommand::PowerOff => {
54+
gateway_messages::IgnitionCommand::PowerOff
55+
}
56+
IgnitionCommand::PowerReset => {
57+
gateway_messages::IgnitionCommand::PowerReset
58+
}
59+
}
60+
}
61+
}
62+
63+
/// State of an ignition target.
64+
///
65+
/// TODO: Ignition returns much more information than we're reporting here: do
66+
/// we want to expand this?
67+
#[derive(
68+
Debug,
69+
Clone,
70+
PartialEq,
71+
Eq,
72+
PartialOrd,
73+
Ord,
74+
Deserialize,
75+
Serialize,
76+
JsonSchema,
77+
)]
78+
#[serde(tag = "present")]
79+
pub enum SpIgnition {
80+
#[serde(rename = "no")]
81+
Absent,
82+
#[serde(rename = "yes")]
83+
Present {
84+
id: SpIgnitionSystemType,
85+
power: bool,
86+
ctrl_detect_0: bool,
87+
ctrl_detect_1: bool,
88+
flt_a3: bool,
89+
flt_a2: bool,
90+
flt_rot: bool,
91+
flt_sp: bool,
92+
},
93+
}
94+
95+
impl From<gateway_messages::IgnitionState> for SpIgnition {
96+
fn from(state: gateway_messages::IgnitionState) -> Self {
97+
use gateway_messages::ignition::SystemPowerState;
98+
99+
if let Some(target_state) = state.target {
100+
Self::Present {
101+
id: target_state.system_type.into(),
102+
power: matches!(
103+
target_state.power_state,
104+
SystemPowerState::On | SystemPowerState::PoweringOn
105+
),
106+
ctrl_detect_0: target_state.controller0_present,
107+
ctrl_detect_1: target_state.controller1_present,
108+
flt_a3: target_state.faults.power_a3,
109+
flt_a2: target_state.faults.power_a2,
110+
flt_rot: target_state.faults.rot,
111+
flt_sp: target_state.faults.sp,
112+
}
113+
} else {
114+
Self::Absent
115+
}
116+
}
117+
}
118+
119+
#[derive(
120+
Debug,
121+
Clone,
122+
Copy,
123+
PartialEq,
124+
Eq,
125+
PartialOrd,
126+
Ord,
127+
Deserialize,
128+
Serialize,
129+
JsonSchema,
130+
)]
131+
#[serde(tag = "system_type", rename_all = "snake_case")]
132+
pub enum SpIgnitionSystemType {
133+
Gimlet,
134+
Sidecar,
135+
Psc,
136+
Unknown { id: u16 },
137+
Cosmo,
138+
}
139+
140+
impl From<gateway_messages::ignition::SystemType> for SpIgnitionSystemType {
141+
fn from(st: gateway_messages::ignition::SystemType) -> Self {
142+
use gateway_messages::ignition::SystemType;
143+
match st {
144+
SystemType::Gimlet => Self::Gimlet,
145+
SystemType::Sidecar => Self::Sidecar,
146+
SystemType::Psc => Self::Psc,
147+
SystemType::Unknown(id) => Self::Unknown { id },
148+
SystemType::Cosmo => Self::Cosmo,
149+
}
150+
}
151+
}

0 commit comments

Comments
 (0)