@@ -10,6 +10,9 @@ use nexus_types::deployment::Blueprint;
1010use nexus_types:: deployment:: BlueprintArtifactVersion ;
1111use nexus_types:: deployment:: BlueprintDatasetConfig ;
1212use nexus_types:: deployment:: BlueprintZoneConfig ;
13+ use nexus_types:: deployment:: OmicronZoneExternalIp ;
14+ use nexus_types:: deployment:: OmicronZoneNicEntry ;
15+ use nexus_types:: deployment:: PlanningInput ;
1316use nexus_types:: inventory:: ZpoolName ;
1417use omicron_common:: address:: DnsSubnet ;
1518use omicron_common:: address:: Ipv6Subnet ;
@@ -55,48 +58,55 @@ impl fmt::Display for Severity {
5558pub enum Kind {
5659 Blueprint ( BlueprintKind ) ,
5760 Sled { sled_id : SledUuid , kind : Box < SledKind > } ,
61+ PlanningInput ( PlanningInputKind ) ,
5862}
5963
6064impl Kind {
6165 pub fn display_component ( & self ) -> impl fmt:: Display + ' _ {
6266 enum Component < ' a > {
6367 Blueprint ,
6468 Sled ( & ' a SledUuid ) ,
69+ PlanningInput ,
6570 }
6671
6772 impl fmt:: Display for Component < ' _ > {
6873 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
6974 match self {
7075 Component :: Blueprint => write ! ( f, "blueprint" ) ,
7176 Component :: Sled ( id) => write ! ( f, "sled {id}" ) ,
77+ Component :: PlanningInput => write ! ( f, "planning input" ) ,
7278 }
7379 }
7480 }
7581
7682 match self {
77- Kind :: Blueprint { .. } => Component :: Blueprint ,
83+ Kind :: Blueprint ( _ ) => Component :: Blueprint ,
7884 Kind :: Sled { sled_id, .. } => Component :: Sled ( sled_id) ,
85+ Kind :: PlanningInput ( _) => Component :: PlanningInput ,
7986 }
8087 }
8188
8289 pub fn display_subkind ( & self ) -> impl fmt:: Display + ' _ {
8390 enum Subkind < ' a > {
8491 Blueprint ( & ' a BlueprintKind ) ,
8592 Sled ( & ' a SledKind ) ,
93+ PlanningInput ( & ' a PlanningInputKind ) ,
8694 }
8795
8896 impl fmt:: Display for Subkind < ' _ > {
8997 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
9098 match self {
9199 Subkind :: Blueprint ( kind) => write ! ( f, "{kind}" ) ,
92100 Subkind :: Sled ( kind) => write ! ( f, "{kind}" ) ,
101+ Subkind :: PlanningInput ( kind) => write ! ( f, "{kind}" ) ,
93102 }
94103 }
95104 }
96105
97106 match self {
98107 Kind :: Blueprint ( kind) => Subkind :: Blueprint ( kind) ,
99108 Kind :: Sled { kind, .. } => Subkind :: Sled ( kind) ,
109+ Kind :: PlanningInput ( kind) => Subkind :: PlanningInput ( kind) ,
100110 }
101111 }
102112}
@@ -488,6 +498,54 @@ impl fmt::Display for SledKind {
488498 }
489499}
490500
501+ #[ derive( Debug , Clone , PartialEq , Eq , PartialOrd , Ord ) ]
502+ pub enum PlanningInputKind {
503+ IpNotInBlueprint ( OmicronZoneExternalIp ) ,
504+ NicMacNotInBluperint ( OmicronZoneNicEntry ) ,
505+ NicIpNotInBlueprint ( OmicronZoneNicEntry ) ,
506+ NicWithUnknownOpteSubnet ( OmicronZoneNicEntry ) ,
507+ }
508+
509+ impl fmt:: Display for PlanningInputKind {
510+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
511+ match self {
512+ PlanningInputKind :: IpNotInBlueprint ( ip) => {
513+ write ! (
514+ f,
515+ "planning input contains an external IP \
516+ not described by the blueprint: {} ({})",
517+ ip. ip( ) ,
518+ ip. id( )
519+ )
520+ }
521+ PlanningInputKind :: NicMacNotInBluperint ( nic) => {
522+ write ! (
523+ f,
524+ "planning input contains a NIC with a MAC address \
525+ not described by the blueprint: {} (NIC {} in zone {})",
526+ nic. nic. mac, nic. nic. id, nic. zone_id,
527+ )
528+ }
529+ PlanningInputKind :: NicIpNotInBlueprint ( nic) => {
530+ write ! (
531+ f,
532+ "planning input contains a NIC with an IP address \
533+ not described by the blueprint: {} (NIC {} in zone {})",
534+ nic. nic. ip, nic. nic. id, nic. zone_id,
535+ )
536+ }
537+ PlanningInputKind :: NicWithUnknownOpteSubnet ( nic) => {
538+ write ! (
539+ f,
540+ "planning input contains a NIC with an IP not in a known
541+ OPTE subnet: {} (NIC {} in zone {})" ,
542+ nic. nic. ip, nic. nic. id, nic. zone_id,
543+ )
544+ }
545+ }
546+ }
547+ }
548+
491549impl Note {
492550 pub fn display ( & self , sort_key : BlippyReportSortKey ) -> NoteDisplay < ' _ > {
493551 NoteDisplay { note : self , sort_key }
@@ -532,7 +590,20 @@ pub struct Blippy<'a> {
532590}
533591
534592impl < ' a > Blippy < ' a > {
535- pub fn new ( blueprint : & ' a Blueprint ) -> Self {
593+ /// Check `blueprint` for internal inconsistencies and check for
594+ /// inconsistencies between `blueprint` and `planning_input`.
595+ pub fn new (
596+ blueprint : & ' a Blueprint ,
597+ planning_input : & PlanningInput ,
598+ ) -> Self {
599+ let mut slf = Self { blueprint, notes : Vec :: new ( ) } ;
600+ checks:: perform_all_blueprint_only_checks ( & mut slf) ;
601+ checks:: perform_planning_input_checks ( & mut slf, planning_input) ;
602+ slf
603+ }
604+
605+ /// Check `blueprint` for internal inconsistencies.
606+ pub fn new_blueprint_only ( blueprint : & ' a Blueprint ) -> Self {
536607 let mut slf = Self { blueprint, notes : Vec :: new ( ) } ;
537608 checks:: perform_all_blueprint_only_checks ( & mut slf) ;
538609 slf
@@ -562,6 +633,14 @@ impl<'a> Blippy<'a> {
562633 } ) ;
563634 }
564635
636+ pub ( crate ) fn push_planning_input_note (
637+ & mut self ,
638+ severity : Severity ,
639+ kind : PlanningInputKind ,
640+ ) {
641+ self . notes . push ( Note { severity, kind : Kind :: PlanningInput ( kind) } ) ;
642+ }
643+
565644 pub fn into_report (
566645 self ,
567646 sort_key : BlippyReportSortKey ,
0 commit comments