@@ -42,16 +42,16 @@ use omicron_common::api::external::Name;
42
42
use omicron_common:: policy:: NEXUS_REDUNDANCY ;
43
43
use omicron_repl_utils:: run_repl_from_file;
44
44
use omicron_repl_utils:: run_repl_on_stdin;
45
- use omicron_uuid_kinds:: BlueprintUuid ;
46
45
use omicron_uuid_kinds:: CollectionUuid ;
47
46
use omicron_uuid_kinds:: GenericUuid ;
48
47
use omicron_uuid_kinds:: OmicronZoneUuid ;
49
48
use omicron_uuid_kinds:: ReconfiguratorSimUuid ;
50
49
use omicron_uuid_kinds:: SledUuid ;
51
50
use omicron_uuid_kinds:: VnicUuid ;
51
+ use omicron_uuid_kinds:: { BlueprintUuid , MupdateOverrideUuid } ;
52
52
use std:: borrow:: Cow ;
53
53
use std:: collections:: BTreeMap ;
54
- use std:: fmt:: Write ;
54
+ use std:: fmt:: { self , Write } ;
55
55
use std:: io:: IsTerminal ;
56
56
use std:: str:: FromStr ;
57
57
use swrite:: { SWrite , swriteln} ;
@@ -204,7 +204,9 @@ fn process_command(
204
204
let cmd_result = match command {
205
205
Commands :: SledList => cmd_sled_list ( sim) ,
206
206
Commands :: SledAdd ( args) => cmd_sled_add ( sim, args) ,
207
+ Commands :: SledRemove ( args) => cmd_sled_remove ( sim, args) ,
207
208
Commands :: SledShow ( args) => cmd_sled_show ( sim, args) ,
209
+ Commands :: SledSetPolicy ( args) => cmd_sled_set_policy ( sim, args) ,
208
210
Commands :: SiloList => cmd_silo_list ( sim) ,
209
211
Commands :: SiloAdd ( args) => cmd_silo_add ( sim, args) ,
210
212
Commands :: SiloRemove ( args) => cmd_silo_remove ( sim, args) ,
@@ -252,8 +254,12 @@ enum Commands {
252
254
SledList ,
253
255
/// add a new sled
254
256
SledAdd ( SledAddArgs ) ,
257
+ /// remove a sled from the system
258
+ SledRemove ( SledRemoveArgs ) ,
255
259
/// show details about one sled
256
260
SledShow ( SledArgs ) ,
261
+ /// set a sled's policy
262
+ SledSetPolicy ( SledSetPolicyArgs ) ,
257
263
258
264
/// list silos
259
265
SiloList ,
@@ -308,6 +314,10 @@ enum Commands {
308
314
struct SledAddArgs {
309
315
/// id of the new sled
310
316
sled_id : Option < SledUuid > ,
317
+
318
+ /// number of disks or pools
319
+ #[ clap( short = 'd' , long, visible_alias = "npools" , default_value_t = SledBuilder :: DEFAULT_NPOOLS ) ]
320
+ ndisks : u8 ,
311
321
}
312
322
313
323
#[ derive( Debug , Args ) ]
@@ -320,6 +330,53 @@ struct SledArgs {
320
330
filter : SledFilter ,
321
331
}
322
332
333
+ #[ derive( Debug , Args ) ]
334
+ struct SledSetPolicyArgs {
335
+ /// id of the sled
336
+ sled_id : SledUuid ,
337
+
338
+ /// The policy to set for the sled
339
+ #[ clap( value_enum) ]
340
+ policy : SledPolicyOpt ,
341
+ }
342
+
343
+ #[ derive( Clone , Copy , Debug , ValueEnum ) ]
344
+ enum SledPolicyOpt {
345
+ InService ,
346
+ NonProvisionable ,
347
+ Expunged ,
348
+ }
349
+
350
+ impl fmt:: Display for SledPolicyOpt {
351
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
352
+ match self {
353
+ SledPolicyOpt :: InService => write ! ( f, "in-service" ) ,
354
+ SledPolicyOpt :: NonProvisionable => write ! ( f, "non-provisionable" ) ,
355
+ SledPolicyOpt :: Expunged => write ! ( f, "expunged" ) ,
356
+ }
357
+ }
358
+ }
359
+
360
+ impl From < SledPolicyOpt > for SledPolicy {
361
+ fn from ( value : SledPolicyOpt ) -> Self {
362
+ match value {
363
+ SledPolicyOpt :: InService => SledPolicy :: InService {
364
+ provision_policy : SledProvisionPolicy :: Provisionable ,
365
+ } ,
366
+ SledPolicyOpt :: NonProvisionable => SledPolicy :: InService {
367
+ provision_policy : SledProvisionPolicy :: NonProvisionable ,
368
+ } ,
369
+ SledPolicyOpt :: Expunged => SledPolicy :: Expunged ,
370
+ }
371
+ }
372
+ }
373
+
374
+ #[ derive( Debug , Args ) ]
375
+ struct SledRemoveArgs {
376
+ /// id of the sled
377
+ sled_id : SledUuid ,
378
+ }
379
+
323
380
#[ derive( Debug , Args ) ]
324
381
struct SiloAddRemoveArgs {
325
382
/// name of the silo
@@ -374,6 +431,14 @@ enum BlueprintEditCommands {
374
431
#[ command( subcommand) ]
375
432
image_source : ImageSourceArgs ,
376
433
} ,
434
+ /// set the remove_mupdate_override field for a sled
435
+ SetRemoveMupdateOverride {
436
+ /// sled to set the field on
437
+ sled_id : SledUuid ,
438
+
439
+ /// the UUID to set the field to, or "unset"
440
+ value : MupdateOverrideUuidOpt ,
441
+ } ,
377
442
/// expunge a zone
378
443
ExpungeZone { zone_id : OmicronZoneUuid } ,
379
444
/// configure an SP update
@@ -393,6 +458,34 @@ enum BlueprintEditCommands {
393
458
/// baseboard serial number whose update to delete
394
459
serial : String ,
395
460
} ,
461
+ /// debug commands that bypass normal checks
462
+ ///
463
+ /// These commands mutate the blueprint directly, bypassing higher-level
464
+ /// planner checks. They're meant for getting into weird states to test
465
+ /// against.
466
+ Debug {
467
+ #[ command( subcommand) ]
468
+ command : BlueprintEditDebugCommands ,
469
+ } ,
470
+ }
471
+
472
+ #[ derive( Debug , Subcommand ) ]
473
+ enum BlueprintEditDebugCommands {
474
+ /// remove a sled from the blueprint
475
+ ///
476
+ /// This bypasses expungement and decommissioning checks, and simply drops
477
+ /// the sled from the blueprint.
478
+ RemoveSled {
479
+ /// the sled to remove
480
+ sled : SledUuid ,
481
+ } ,
482
+
483
+ /// Bump a sled's generation number, even if nothing else about the sled has
484
+ /// changed.
485
+ ForceSledGenerationBump {
486
+ /// the sled to bump the sled-agent generation number of
487
+ sled : SledUuid ,
488
+ } ,
396
489
}
397
490
398
491
#[ derive( Clone , Debug ) ]
@@ -430,6 +523,42 @@ impl From<BlueprintIdOpt> for BlueprintId {
430
523
}
431
524
}
432
525
526
+ /// Clap field for an optional mupdate override UUID.
527
+ ///
528
+ /// This structure is similar to `Option`, but is specified separately to:
529
+ ///
530
+ /// 1. Disable clap's magic around `Option`.
531
+ /// 2. Provide a custom parser.
532
+ ///
533
+ /// There are other ways to do both 1 and 2 (e.g. specify the type as
534
+ /// `std::option::Option`), but when combined they're uglier than this.
535
+ #[ derive( Clone , Copy , Debug ) ]
536
+ enum MupdateOverrideUuidOpt {
537
+ Unset ,
538
+ Set ( MupdateOverrideUuid ) ,
539
+ }
540
+
541
+ impl FromStr for MupdateOverrideUuidOpt {
542
+ type Err = newtype_uuid:: ParseError ;
543
+
544
+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
545
+ if s == "unset" || s == "none" {
546
+ Ok ( MupdateOverrideUuidOpt :: Unset )
547
+ } else {
548
+ Ok ( MupdateOverrideUuidOpt :: Set ( s. parse :: < MupdateOverrideUuid > ( ) ?) )
549
+ }
550
+ }
551
+ }
552
+
553
+ impl From < MupdateOverrideUuidOpt > for Option < MupdateOverrideUuid > {
554
+ fn from ( value : MupdateOverrideUuidOpt ) -> Self {
555
+ match value {
556
+ MupdateOverrideUuidOpt :: Unset => None ,
557
+ MupdateOverrideUuidOpt :: Set ( uuid) => Some ( uuid) ,
558
+ }
559
+ }
560
+ }
561
+
433
562
#[ derive( Clone , Debug , Subcommand ) ]
434
563
enum SpUpdateComponent {
435
564
/// update the SP itself
@@ -673,7 +802,7 @@ fn cmd_sled_add(
673
802
) -> anyhow:: Result < Option < String > > {
674
803
let mut state = sim. current_state ( ) . to_mut ( ) ;
675
804
let sled_id = add. sled_id . unwrap_or_else ( || state. rng_mut ( ) . next_sled_id ( ) ) ;
676
- let new_sled = SledBuilder :: new ( ) . id ( sled_id) ;
805
+ let new_sled = SledBuilder :: new ( ) . id ( sled_id) . npools ( add . ndisks ) ;
677
806
state. system_mut ( ) . description_mut ( ) . sled ( new_sled) ?;
678
807
sim. commit_and_bump (
679
808
format ! ( "reconfigurator-cli sled-add: {sled_id}" ) ,
@@ -683,6 +812,24 @@ fn cmd_sled_add(
683
812
Ok ( Some ( format ! ( "added sled {}" , sled_id) ) )
684
813
}
685
814
815
+ fn cmd_sled_remove (
816
+ sim : & mut ReconfiguratorSim ,
817
+ args : SledRemoveArgs ,
818
+ ) -> anyhow:: Result < Option < String > > {
819
+ let mut state = sim. current_state ( ) . to_mut ( ) ;
820
+ let sled_id = args. sled_id ;
821
+ state
822
+ . system_mut ( )
823
+ . description_mut ( )
824
+ . sled_remove ( sled_id)
825
+ . context ( "failed to remove sled" ) ?;
826
+ sim. commit_and_bump (
827
+ format ! ( "reconfigurator-cli sled-remove: {sled_id}" ) ,
828
+ state,
829
+ ) ;
830
+ Ok ( Some ( format ! ( "removed sled {} from system" , sled_id) ) )
831
+ }
832
+
686
833
fn cmd_sled_show (
687
834
sim : & mut ReconfiguratorSim ,
688
835
args : SledArgs ,
@@ -708,6 +855,25 @@ fn cmd_sled_show(
708
855
Ok ( Some ( s) )
709
856
}
710
857
858
+ fn cmd_sled_set_policy (
859
+ sim : & mut ReconfiguratorSim ,
860
+ args : SledSetPolicyArgs ,
861
+ ) -> anyhow:: Result < Option < String > > {
862
+ let mut state = sim. current_state ( ) . to_mut ( ) ;
863
+ state
864
+ . system_mut ( )
865
+ . description_mut ( )
866
+ . sled_set_policy ( args. sled_id , args. policy . into ( ) ) ?;
867
+ sim. commit_and_bump (
868
+ format ! (
869
+ "reconfigurator-cli sled-set-policy: {} to {}" ,
870
+ args. sled_id, args. policy,
871
+ ) ,
872
+ state,
873
+ ) ;
874
+ Ok ( Some ( format ! ( "set sled {} policy to {}" , args. sled_id, args. policy) ) )
875
+ }
876
+
711
877
fn cmd_inventory_list (
712
878
sim : & mut ReconfiguratorSim ,
713
879
) -> anyhow:: Result < Option < String > > {
@@ -925,6 +1091,19 @@ fn cmd_blueprint_edit(
925
1091
. context ( "failed to add CockroachDB zone" ) ?;
926
1092
format ! ( "added CockroachDB zone to sled {}" , sled_id)
927
1093
}
1094
+ BlueprintEditCommands :: SetRemoveMupdateOverride { sled_id, value } => {
1095
+ builder
1096
+ . sled_set_remove_mupdate_override ( sled_id, value. into ( ) )
1097
+ . context ( "failed to set remove_mupdate_override" ) ?;
1098
+ match value {
1099
+ MupdateOverrideUuidOpt :: Unset => {
1100
+ "unset remove_mupdate_override" . to_owned ( )
1101
+ }
1102
+ MupdateOverrideUuidOpt :: Set ( uuid) => {
1103
+ format ! ( "set remove_mupdate_override to {uuid}" )
1104
+ }
1105
+ }
1106
+ }
928
1107
BlueprintEditCommands :: SetZoneImage { zone_id, image_source } => {
929
1108
let sled_id = sled_with_zone ( & builder, & zone_id) ?;
930
1109
let source = BlueprintZoneImageSource :: from ( image_source) ;
@@ -998,6 +1177,19 @@ fn cmd_blueprint_edit(
998
1177
builder. pending_mgs_update_delete ( baseboard_id) ;
999
1178
format ! ( "deleted configured update for serial {serial}" )
1000
1179
}
1180
+ BlueprintEditCommands :: Debug {
1181
+ command : BlueprintEditDebugCommands :: RemoveSled { sled } ,
1182
+ } => {
1183
+ builder. debug_sled_remove ( sled) ?;
1184
+ format ! ( "debug: removed sled {sled} from blueprint" )
1185
+ }
1186
+ BlueprintEditCommands :: Debug {
1187
+ command :
1188
+ BlueprintEditDebugCommands :: ForceSledGenerationBump { sled } ,
1189
+ } => {
1190
+ builder. debug_sled_force_generation_bump ( sled) ?;
1191
+ format ! ( "debug: forced sled {sled} generation bump" )
1192
+ }
1001
1193
} ;
1002
1194
1003
1195
let mut new_blueprint = builder. build ( ) ;
0 commit comments