5
5
//! omdb commands related to update status
6
6
7
7
use anyhow:: Context ;
8
- use nexus_types:: internal_api:: views:: { SpStatus , ZoneStatus } ;
8
+ use gateway_types:: rot:: RotSlot ;
9
+ use nexus_types:: internal_api:: views:: {
10
+ HostPhase1Status , HostPhase2Status , RotBootloaderStatus , RotStatus ,
11
+ SpStatus , ZoneStatus ,
12
+ } ;
13
+ use omicron_common:: disk:: M2Slot ;
9
14
use omicron_uuid_kinds:: SledUuid ;
10
15
use tabled:: Tabled ;
11
16
@@ -19,8 +24,44 @@ pub async fn cmd_nexus_update_status(
19
24
. context ( "retrieving update status" ) ?
20
25
. into_inner ( ) ;
21
26
22
- print_zones ( status. zones . into_iter ( ) ) ;
23
- print_sps ( status. sps . into_iter ( ) ) ;
27
+ print_rot_bootloaders (
28
+ status
29
+ . mgs_driven
30
+ . iter ( )
31
+ . map ( |s| ( s. baseboard_description . clone ( ) , & s. rot_bootloader ) ) ,
32
+ ) ;
33
+ println ! ( ) ;
34
+ print_rots (
35
+ status
36
+ . mgs_driven
37
+ . iter ( )
38
+ . map ( |s| ( s. baseboard_description . clone ( ) , & s. rot ) ) ,
39
+ ) ;
40
+ println ! ( ) ;
41
+ print_sps (
42
+ status
43
+ . mgs_driven
44
+ . iter ( )
45
+ . map ( |s| ( s. baseboard_description . clone ( ) , & s. sp ) ) ,
46
+ ) ;
47
+ println ! ( ) ;
48
+ print_host_phase_1s (
49
+ status
50
+ . mgs_driven
51
+ . iter ( )
52
+ . map ( |s| ( s. baseboard_description . clone ( ) , & s. host_os_phase_1 ) ) ,
53
+ ) ;
54
+ println ! ( ) ;
55
+ print_host_phase_2s (
56
+ status. sleds . iter ( ) . map ( |s| ( s. sled_id , & s. host_phase_2 ) ) ,
57
+ ) ;
58
+ println ! ( ) ;
59
+ print_zones (
60
+ status
61
+ . sleds
62
+ . iter ( )
63
+ . map ( |s| ( s. sled_id , s. zones . iter ( ) . cloned ( ) . collect ( ) ) ) ,
64
+ ) ;
24
65
25
66
Ok ( ( ) )
26
67
}
@@ -59,22 +100,85 @@ fn print_zones(zones: impl Iterator<Item = (SledUuid, Vec<ZoneStatus>)>) {
59
100
println ! ( "{}" , table) ;
60
101
}
61
102
62
- fn print_sps ( sps : impl Iterator < Item = ( String , SpStatus ) > ) {
103
+ fn print_rot_bootloaders < ' a > (
104
+ bootloaders : impl Iterator < Item = ( String , & ' a RotBootloaderStatus ) > ,
105
+ ) {
106
+ #[ derive( Tabled ) ]
107
+ #[ tabled( rename_all = "SCREAMING_SNAKE_CASE" ) ]
108
+ struct BootloaderRow {
109
+ baseboard_id : String ,
110
+ stage0_version : String ,
111
+ stage0_next_version : String ,
112
+ }
113
+
114
+ let mut rows = Vec :: new ( ) ;
115
+ for ( baseboard_id, status) in bootloaders {
116
+ let RotBootloaderStatus { stage0_version, stage0_next_version } =
117
+ status;
118
+ rows. push ( BootloaderRow {
119
+ baseboard_id,
120
+ stage0_version : stage0_version. to_string ( ) ,
121
+ stage0_next_version : stage0_next_version. to_string ( ) ,
122
+ } ) ;
123
+ }
124
+
125
+ let table = tabled:: Table :: new ( rows)
126
+ . with ( tabled:: settings:: Style :: empty ( ) )
127
+ . with ( tabled:: settings:: Padding :: new ( 0 , 1 , 0 , 0 ) )
128
+ . to_string ( ) ;
129
+
130
+ println ! ( "Installed RoT Bootloader Software" ) ;
131
+ println ! ( "{}" , table) ;
132
+ }
133
+
134
+ fn print_rots < ' a > ( rots : impl Iterator < Item = ( String , & ' a RotStatus ) > ) {
135
+ #[ derive( Tabled ) ]
136
+ #[ tabled( rename_all = "SCREAMING_SNAKE_CASE" ) ]
137
+ struct RotRow {
138
+ baseboard_id : String ,
139
+ slot_a_version : String ,
140
+ slot_b_version : String ,
141
+ }
142
+
143
+ let mut rows = Vec :: new ( ) ;
144
+ for ( baseboard_id, status) in rots {
145
+ let RotStatus { active_slot, slot_a_version, slot_b_version } = status;
146
+ let ( slot_a_suffix, slot_b_suffix) = match active_slot {
147
+ Some ( RotSlot :: A ) => ( " (active)" , "" ) ,
148
+ Some ( RotSlot :: B ) => ( "" , " (active)" ) ,
149
+ // This is not expected! Be louder.
150
+ None => ( "" , " (ACTIVE SLOT UNKNOWN)" ) ,
151
+ } ;
152
+ rows. push ( RotRow {
153
+ baseboard_id,
154
+ slot_a_version : format ! ( "{slot_a_version}{slot_a_suffix}" ) ,
155
+ slot_b_version : format ! ( "{slot_b_version}{slot_b_suffix}" ) ,
156
+ } ) ;
157
+ }
158
+
159
+ let table = tabled:: Table :: new ( rows)
160
+ . with ( tabled:: settings:: Style :: empty ( ) )
161
+ . with ( tabled:: settings:: Padding :: new ( 0 , 1 , 0 , 0 ) )
162
+ . to_string ( ) ;
163
+
164
+ println ! ( "Installed RoT Software" ) ;
165
+ println ! ( "{}" , table) ;
166
+ }
167
+
168
+ fn print_sps < ' a > ( sps : impl Iterator < Item = ( String , & ' a SpStatus ) > ) {
63
169
#[ derive( Tabled ) ]
64
170
#[ tabled( rename_all = "SCREAMING_SNAKE_CASE" ) ]
65
171
struct SpRow {
66
172
baseboard_id : String ,
67
- sled_id : String ,
68
173
slot0_version : String ,
69
174
slot1_version : String ,
70
175
}
71
176
72
177
let mut rows = Vec :: new ( ) ;
73
178
for ( baseboard_id, status) in sps {
74
- let SpStatus { sled_id , slot0_version, slot1_version } = status;
179
+ let SpStatus { slot0_version, slot1_version } = status;
75
180
rows. push ( SpRow {
76
181
baseboard_id,
77
- sled_id : sled_id. map_or ( "" . to_string ( ) , |id| id. to_string ( ) ) ,
78
182
slot0_version : slot0_version. to_string ( ) ,
79
183
slot1_version : slot1_version. to_string ( ) ,
80
184
} ) ;
@@ -88,3 +192,88 @@ fn print_sps(sps: impl Iterator<Item = (String, SpStatus)>) {
88
192
println ! ( "Installed SP Software" ) ;
89
193
println ! ( "{}" , table) ;
90
194
}
195
+
196
+ fn print_host_phase_1s < ' a > (
197
+ phase_1s : impl Iterator < Item = ( String , & ' a HostPhase1Status ) > ,
198
+ ) {
199
+ #[ derive( Tabled ) ]
200
+ #[ tabled( rename_all = "SCREAMING_SNAKE_CASE" ) ]
201
+ struct HostPhase1Row {
202
+ baseboard_id : String ,
203
+ sled_id : String ,
204
+ slot_a_version : String ,
205
+ slot_b_version : String ,
206
+ }
207
+
208
+ let mut rows = Vec :: new ( ) ;
209
+ for ( baseboard_id, status) in phase_1s {
210
+ match status {
211
+ HostPhase1Status :: NotASled => continue ,
212
+ HostPhase1Status :: Sled {
213
+ sled_id,
214
+ active_slot,
215
+ slot_a_version,
216
+ slot_b_version,
217
+ } => {
218
+ let ( slot_a_suffix, slot_b_suffix) = match active_slot {
219
+ Some ( M2Slot :: A ) => ( " (active)" , "" ) ,
220
+ Some ( M2Slot :: B ) => ( "" , " (active)" ) ,
221
+ // This is not expected! Be louder.
222
+ None => ( "" , " (ACTIVE SLOT UNKNOWN)" ) ,
223
+ } ;
224
+ rows. push ( HostPhase1Row {
225
+ baseboard_id,
226
+ sled_id : sled_id
227
+ . map_or ( "" . to_string ( ) , |id| id. to_string ( ) ) ,
228
+ slot_a_version : format ! ( "{slot_a_version}{slot_a_suffix}" ) ,
229
+ slot_b_version : format ! ( "{slot_b_version}{slot_b_suffix}" ) ,
230
+ } ) ;
231
+ }
232
+ }
233
+ }
234
+
235
+ let table = tabled:: Table :: new ( rows)
236
+ . with ( tabled:: settings:: Style :: empty ( ) )
237
+ . with ( tabled:: settings:: Padding :: new ( 0 , 1 , 0 , 0 ) )
238
+ . to_string ( ) ;
239
+
240
+ println ! ( "Installed Host Phase 1 Software" ) ;
241
+ println ! ( "{}" , table) ;
242
+ }
243
+
244
+ fn print_host_phase_2s < ' a > (
245
+ sleds : impl Iterator < Item = ( SledUuid , & ' a HostPhase2Status ) > ,
246
+ ) {
247
+ #[ derive( Tabled ) ]
248
+ #[ tabled( rename_all = "SCREAMING_SNAKE_CASE" ) ]
249
+ struct HostPhase2Row {
250
+ sled_id : String ,
251
+ slot_a_version : String ,
252
+ slot_b_version : String ,
253
+ }
254
+
255
+ let mut rows = Vec :: new ( ) ;
256
+ for ( sled_id, status) in sleds {
257
+ let HostPhase2Status { boot_disk, slot_a_version, slot_b_version } =
258
+ status;
259
+ let ( slot_a_suffix, slot_b_suffix) = match boot_disk {
260
+ Ok ( M2Slot :: A ) => ( " (boot disk)" , "" . to_string ( ) ) ,
261
+ Ok ( M2Slot :: B ) => ( "" , " (boot disk)" . to_string ( ) ) ,
262
+ // This is not expected! Be louder.
263
+ Err ( err) => ( "" , format ! ( " (BOOT DISK UNKNOWN: {err})" ) ) ,
264
+ } ;
265
+ rows. push ( HostPhase2Row {
266
+ sled_id : sled_id. to_string ( ) ,
267
+ slot_a_version : format ! ( "{slot_a_version}{slot_a_suffix}" ) ,
268
+ slot_b_version : format ! ( "{slot_b_version}{slot_b_suffix}" ) ,
269
+ } ) ;
270
+ }
271
+
272
+ let table = tabled:: Table :: new ( rows)
273
+ . with ( tabled:: settings:: Style :: empty ( ) )
274
+ . with ( tabled:: settings:: Padding :: new ( 0 , 1 , 0 , 0 ) )
275
+ . to_string ( ) ;
276
+
277
+ println ! ( "Installed Host Phase 2 Software" ) ;
278
+ println ! ( "{}" , table) ;
279
+ }
0 commit comments