-
Notifications
You must be signed in to change notification settings - Fork 184
Expand file tree
/
Copy pathfile.rs
More file actions
4170 lines (3776 loc) · 159 KB
/
Copy pathfile.rs
File metadata and controls
4170 lines (3776 loc) · 159 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use std::collections::HashMap;
use std::fmt;
use std::net::{Ipv4Addr, SocketAddr};
use std::path::PathBuf;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use bmc_vendor::BMCVendor;
use carbide_authn::config::{AllowedCertCriteria, TrustConfig};
use carbide_firmware::FirmwareConfig;
use carbide_ib_fabric::config::{IBFabricConfig, IbFabricDefinition};
use carbide_nvlink_manager::config::NvLinkConfig;
use carbide_preingestion_manager::PreingestionManagerConfig;
use carbide_site_explorer::config::SiteExplorerConfig;
use carbide_utils::config::{
as_duration, as_std_duration, deserialize_arc_atomic_bool, serialize_arc_atomic_bool,
};
use chrono::Duration;
use duration_str::{deserialize_duration, deserialize_duration_chrono};
use figment::Figment;
use ipnetwork::{IpNetwork, Ipv4Network};
use itertools::Itertools;
use libmlx::firmware::config::FirmwareFlasherProfile;
use libmlx::profile::profile::MlxConfigProfile;
use libmlx::profile::serialization::{
deserialize_option_profile_map, serialize_option_profile_map,
};
use model::firmware::{
AgentUpgradePolicyChoice, Firmware, FirmwareComponent, FirmwareComponentType, FirmwareEntry,
};
use model::machine::HostHealthConfig;
use model::network_security_group::NetworkSecurityGroupRule;
use model::network_segment::NetworkDefinition;
use model::resource_pool::define::ResourcePoolDef;
use model::tenant::identity_config::SigningAlgorithm;
use regex::Regex;
use serde::{Deserialize, Deserializer, Serialize};
use crate::state_controller::config::IterationConfig;
use crate::state_controller::rack::config::{RackValidationConfig, RmsConfig};
static BF2_NIC: &str = "24.47.2682";
static BF2_BMC: &str = "BF-25.10-20";
static BF2_CEC: &str = "4-15";
static BF2_UEFI: &str = "4.13.2-12-g943a91640d";
static BF3_NIC: &str = "32.47.2682";
static BF3_BMC: &str = "BF-25.10-20";
static BF3_CEC: &str = "00.02.0195.0000_n02";
static BF3_UEFI: &str = "4.13.2-12-g943a91640d";
pub(crate) const DEFAULT_DPU_NUM_OF_VFS: u32 = 16;
pub(crate) const MAX_DPU_NUM_OF_VFS: u32 = 126;
/// nico-api configuration file content
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CarbideConfig {
/// Socket address for the gRPC API server, used by
/// clients and nico-admin-cli to connect.
/// Default is `[::]:1079`.
#[serde(default = "default_listen")]
pub listen: SocketAddr,
/// Run this instance passively: no background services,
/// just listen for RPC/web connections. Used in dev mode
/// when running a second nico instance against a
/// cluster that already has a "full" instance.
#[serde(default)]
pub listen_only: bool,
/// Socket address for the HTTP server that serves
/// Prometheus metrics under `/metrics`.
pub metrics_endpoint: Option<SocketAddr>,
/// Alternative metric prefix emitted alongside `carbide_`,
/// used for dual-emitting while migrating dashboards and
/// alerts. Increases observability system load.
pub alt_metric_prefix: Option<String>,
/// Postgres connection string used by the API server
/// for all persistent state.
pub database_url: String,
/// Maximum size of the database connection pool.
/// Default is 1000.
#[serde(default = "default_max_database_connections")]
pub max_database_connections: u32,
/// InfiniBand fabric configuration, used by the IB
/// fabric manager for partition and UFM management.
pub ib_config: Option<IBFabricConfig>,
/// Autonomous System Number, fixed per environment.
/// Used by nico-dpu-agent to write `frr.conf` for
/// BGP routing.
pub asn: u32,
/// DHCP server addresses announced to DPUs during
/// network provisioning.
#[serde(default)]
pub dhcp_servers: Vec<String>,
/// Route server IP addresses for L2VPN (Ethernet
/// Virtual) network support on DPUs.
#[serde(default)]
pub route_servers: Vec<String>,
/// Enables route server injection into DPU FRR
/// configs for L2VPN Ethernet Virtual networks.
#[serde(default)]
pub enable_route_servers: bool,
/// List of IPv4 prefixes (in CIDR notation) that tenant instances are not allowed to talk to.
//
// TODO(chet): For now, this remains `Vec<Ipv4Network>`, because the dpu-agent consumers
// that process deny prefixes are IPv4-only (and I'll do it in another PR):
// - `crates/agent/src/acl_rules.rs` parses rules into `Ipv4Network` and generates
// iptables DROP rules via `make_deny_prefix_rules(&[Ipv4Network], ...)`
// - nvue templates (in `nvue_startup_fnn.conf` and `nvue_startup_etv.conf`) render these
// prefixes under a "p0000_deny_prefixes_ipv4" ACL policy with `type: ipv4`.
//
// Updating to support `Vec<IpNetwork>` requires the agent to generate parallel IPv6 deny
// rules (I think via ip6tables / `type: ipv6` ACL policy), similar to how NSG rules already
// handle the `ipv6: bool` split.
#[serde(default)]
pub deny_prefixes: Vec<Ipv4Network>,
/// List of IP prefixes (in CIDR notation) that are assigned for tenant
/// use within this site. Supports both IPv4 and IPv6 prefixes.
#[serde(default)]
pub site_fabric_prefixes: Vec<IpNetwork>,
/// List of aggregate IPv4 prefixes (in CIDR notation) that contain prefixes assigned
/// to tenants so that they themselves can announce to the DPU. E.g., BYOIP
#[serde(default)]
pub anycast_site_prefixes: Vec<Ipv4Network>,
/// An ASN allocated for tenants to use
/// when they peer with the DPU.
/// If configured, the DPU will expect the host
/// to peer with this ASN. If left unset
/// remote-as external will be used, allowing
/// any ASN.
pub common_tenant_host_asn: Option<u32>,
/// VPC isolation policy enforced on tenant traffic.
/// Controls whether VPCs are mutually isolated or open.
#[serde(default)]
pub vpc_isolation_behavior: VpcIsolationBehaviorType,
/// Pinger implementation type (e.g., "OobNetBind") used
/// by the DPU network monitor to health-check DPU links.
#[serde(default)]
pub dpu_network_monitor_pinger_type: Option<String>,
/// TLS certificate and key paths for securing gRPC and
/// HTTP connections.
pub tls: Option<TlsConfig>,
/// Transport mode for the gRPC API server.
/// Default is `Tls`.
#[serde(default)]
pub listen_mode: ListenMode,
/// Authentication and authorization configuration
/// including Casbin policies and client certificate
/// trust settings.
pub auth: Option<AuthConfig>,
/// Resource pools that allocate IPs, VNIs, etc.
/// Required, but wrapped in `Option` so partial configs
/// can be deserialized and merged.
pub pools: Option<HashMap<String, ResourcePoolDef>>,
/// Networks to create at startup. Use the
/// `CreateNetworkSegment` gRPC to create them later
/// instead.
pub networks: Option<HashMap<String, NetworkDefinition>>,
/// IPMI tool implementation for DPU power control
/// (e.g., "prod" or "fake").
pub dpu_ipmi_tool_impl: Option<String>,
/// Number of retries when IPMI returns an error during
/// DPU reboot.
pub dpu_ipmi_reboot_attempts: Option<u32>,
/// Number of consecutive HTTP 401/403 responses from a BMC before the
/// session-token path stops attempting to log in to that BMC, to avoid
/// exhausting the BMC root account's retry budget.
/// Default is 3.
#[serde(default = "default_bmc_session_lockout_threshold")]
pub bmc_session_lockout_threshold: u32,
/// Infiniband fabrics managed by the site
/// Note: At the moment, only a single fabric is supported
#[serde(default)]
pub ib_fabrics: HashMap<String, IbFabricDefinition>,
/// Domain to create if there are no domains.
///
/// Most sites use a single domain for their lifetime. This is that domain.
/// The alternative is to create it via `CreateDomain` grpc endpoint.
pub initial_domain_name: Option<String>,
/// The policy we use to decide whether a specific nico-dpu-agent
/// should be upgraded.
///
/// Also settable via a `nico-admin-cli` command.
pub initial_dpu_agent_upgrade_policy: Option<AgentUpgradePolicyChoice>,
/// Deprecated, use machine_updater
pub max_concurrent_machine_updates: Option<i32>,
/// The interval at which the machine update manager checks for machine updates in seconds.
pub machine_update_run_interval: Option<u64>,
/// SiteExplorer related configuration
#[serde(default)]
pub site_explorer: SiteExplorerConfig,
/// The policy to decide whether two VPCs are allowed to peer with each other based on their
/// network virtualization type during creation
pub vpc_peering_policy: Option<VpcPeeringPolicy>,
/// The policy to decide whether a VPC peering should be active
pub vpc_peering_policy_on_existing: Option<VpcPeeringPolicy>,
/// Controls whether or not machine attestion is required before a machine
/// can go from Discovered -> Ready (and, when enabled, introduces the new
/// `Measuring` state to the flow).
///
/// This control exists so we can roll it out on a site-by-site basis,
/// which includes making sure the latest Scout image for the site has
/// been deployed with attestation support (and knows Action::MEASURE).
#[serde(default)]
pub attestation_enabled: bool,
/// *** This mode is for testing purposes and is not widely supported right now ***
/// Controls if machines allowed to be registered without TPM module,
/// in this case for stable machine identifier api will use chasis serial.
/// Set `true` by default
#[serde(default = "default_to_true")]
pub tpm_required: bool,
/// MachineStateController related configuration parameter
#[serde(default)]
pub machine_state_controller: MachineStateControllerConfig,
/// NetworkSegmentController related configuration parameter
#[serde(default)]
pub network_segment_state_controller: NetworkSegmentStateControllerConfig,
/// IbPartitionStateController related configuration parameter
#[serde(default)]
pub ib_partition_state_controller: IbPartitionStateControllerConfig,
/// DpaInterfaceStateController related configuration parameter
#[serde(default)]
pub dpa_interface_state_controller: DpaInterfaceStateControllerConfig,
/// RackStateController related configuration parameter
#[serde(default)]
pub rack_state_controller: RackStateControllerConfig,
/// PowerShelfStateController related configuration parameter
#[serde(default)]
pub power_shelf_state_controller: PowerShelfStateControllerConfig,
/// SwitchStateController related configuration parameter
#[serde(default)]
pub switch_state_controller: SwitchStateControllerConfig,
/// SpdmStateController related configuration parameter
#[serde(default)]
pub spdm_state_controller: SpdmStateControllerConfig,
/// Maps host model identifiers to firmware definitions,
/// used by the firmware manager to determine BMC, UEFI,
/// and NIC upgrade targets for each host type.
#[serde(default)]
pub host_models: HashMap<String, Firmware>,
/// Global firmware update settings: upload concurrency,
/// retry intervals, autoupdate policies, and firmware
/// binary storage paths.
#[serde(default)]
pub firmware_global: FirmwareGlobal,
/// Machine update policies: auto-reboot windows and
/// concurrent update limits used by the machine update
/// manager.
#[serde(default)]
pub machine_updater: MachineUpdater,
/// Maximum number of IDs accepted by
/// `find_*_by_ids` APIs to prevent oversized queries.
/// Default is 100.
#[serde(default = "default_max_find_by_ids")]
pub max_find_by_ids: u32,
/// Network security group settings: max expanded rule
/// count, stateful ACL enforcement, and policy overrides
/// injected before user-defined rules.
#[serde(default)]
pub network_security_group: NetworkSecurityGroupConfig,
/// Minimum functioning DPU links required for the DPU
/// to be considered healthy. If unset, all links must
/// be functional.
#[serde(default)]
pub min_dpu_functioning_links: Option<u32>,
/// Host health monitoring thresholds, used by the
/// machine state controller to determine hardware health
/// and DPU agent version compliance.
#[serde(default)]
pub host_health: HostHealthConfig,
/// Network infrastructure-provided L3 VNI for FNN VPC Internet
/// connectivity. Combined with `datacenter_asn` to form
/// a route-target. If unset, VPCs cannot reach the
/// Internet.
/// Default is 100001.
//
// TODO(chet): This might be interesting to toggle on
// a per-VPC basis (e.g. a VPC guaranteed not to access
// the Internet).
#[serde(default = "default_internet_l3_vni")]
pub internet_l3_vni: u32,
/// Measured boot metrics collector configuration.
/// Exports TPM-based boot measurement data as
/// Prometheus metrics for attestation monitoring.
#[serde(default)]
pub measured_boot_collector: MeasuredBootMetricsCollectorConfig,
/// Machine validation test configuration. Runs
/// hardware tests (memory latency, SSD I/O, etc.)
/// after ingestion to verify machine health.
#[serde(default)]
pub machine_validation_config: MachineValidationConfig,
/// Rack-level validation configuration. Runs
/// multi-node partition tests after firmware upgrade
/// and maintenance to verify rack health.
#[serde(default)]
pub rack_validation_config: RackValidationConfig,
/// Machine identity (SPIFFE JWT-SVID) settings,
/// used by `SignMachineIdentity` to issue short-lived
/// identity tokens to tenant workloads.
/// Section `[machine_identity]`.
#[serde(default)]
pub machine_identity: MachineIdentityConfig,
/// Disables role-based access control enforcement.
/// Intended for testing and development only.
#[serde(default)]
pub bypass_rbac: bool,
/// DPU-specific firmware and provisioning config,
/// including DPU model definitions, NIC firmware
/// versions, and secure boot settings.
#[serde(default)]
pub dpu_config: DpuConfig,
/// Fabric Nearest Neighbor (FNN) configuration for
/// L3 VNI-based overlay networking, including routing
/// profiles and route target import/export policies.
#[serde(default)]
pub fnn: Option<FnnConfig>,
/// Bill-of-materials (BOM) validation settings.
/// Ensures machines match expected SKU configurations
/// before being marked as Ready.
#[serde(default)]
pub bom_validation: BomValidationConfig,
/// BIOS profile definitions organized by vendor and
/// model, used by SiteExplorer to apply Redfish BIOS
/// settings during ingestion.
#[serde(default)]
pub bios_profiles: libredfish::BiosProfileVendor,
/// Default BIOS profile type (e.g., Performance,
/// PowerEfficiency) applied to machines when no
/// per-model override exists.
#[serde(default)]
pub selected_profile: libredfish::BiosProfileType,
/// Vendor-specific iDRAC/BMC manager attributes applied during machine_setup,
/// before BMC lockdown. Keyed by vendor → model → profile → attribute name.
///
/// These target the manager OEM attributes endpoint (e.g.
/// `Managers/{id}/Oem/Dell/DellAttributes/{id}` on Dell), as opposed to
/// `bios_profiles` which targets BIOS settings.
///
/// Model names are normalized to lowercase with spaces replaced by underscores
/// (e.g. `"PowerEdge R760"` → `"poweredge_r760"`).
///
/// Example (carbide.toml):
/// ```toml
/// # Disable PSU Hot Spare on Dell R760 to prevent fan spin-up (nvbugs-5834644)
/// [oem_manager_profiles.Dell.poweredge_r760.performance]
/// "ServerPwr.1.PSRapidOn" = "Disabled"
/// ```
#[serde(default)]
pub oem_manager_profiles: libredfish::BiosProfileVendor,
/// DpaConfig refers to East West Ethernet (aka
/// Cluster Interconnect Network) configuration
#[serde(default)]
pub dpa_config: Option<DpaConfig>,
/// DSX Exchange Event Bus configuration. Publishes
/// `ManagedHostState` transitions, BMS rack leak/isolation
/// values, and heartbeat timestamps over MQTT, and subscribes
/// to BMS metadata topics used to route those values.
#[serde(default)]
pub dsx_exchange_event_bus: Option<DsxExchangeEventBusConfig>,
/// Datacenter ASN used by FNN to build DC-specific
/// route targets for VRF import and export.
/// Default is 11414.
#[serde(default = "default_datacenter_asn")]
pub datacenter_asn: u32,
/// NvLink partitioning configuration, used by the
/// NvLink monitor to manage GPU mesh partitions
/// via NMX-C.
#[serde(default)]
pub nvlink_config: Option<NvLinkConfig>,
/// Power management settings: retry intervals after
/// success/failure and host reboot wait time.
#[serde(default = "default_power_options")]
pub power_manager_options: PowerManagerOptions,
/// Human-readable site name, exposed to customers
/// running tenant OS via the FMDS endpoint.
pub sitename: Option<String>,
/// Auto machine repair plugin. When enabled,
/// automatically transitions failed machines into
/// repair workflows.
#[serde(default)]
pub auto_machine_repair_plugin: AutoMachineRepairPluginConfig,
/// VMaaS (VM-as-a-Service) configuration for using
/// NICo with a VM system, including VF settings and
/// traffic-intercept bridging.
pub vmaas_config: Option<VmaasConfig>,
/// Named Mellanox NIC firmware configuration profiles,
/// used by superNIC firmware flashing to apply
/// device-specific register settings.
#[serde(
default,
rename = "mlx-config-profiles",
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_option_profile_map",
serialize_with = "serialize_option_profile_map"
)]
pub mlxconfig_profiles: Option<HashMap<String, MlxConfigProfile>>,
/// The intent of this config option is to use the NICo site controller as a standalone
/// (disconnected / air-gapped) infrastructure manager for racks of GB200/GB300/VR144.
/// Only set this if using NICo site controller with Rack Manager to manage GB200/300/VR144.
/// It will change site controller behavior significantly in the following ways, etc.:
/// 1. skip dpu management and use dpus in nic mode (optional, can set force_dpu_nic_mode=false)
/// a. no dpu bfb upgrade and host power cycle
/// b. no firmware upgrade and host power cycle
/// c. no hbn deployment (no ecmp, etc)
/// d. no dpu agent deployment
/// e. no restricted mode configuration
/// f. no tenant overlay network via L2 vxlan/evpn or L3 vni (fnn)
/// 2. support any other nic interface on the compute nodes including the onboard 3p nic
/// 3. require expected machines table rows to have other/all mac addresses for each machine
/// 4. restrict dhcp service to only provide ip address to known mac addresses
/// a. for additional mac addresses, use HostInband network segment when dpu is in nic mode
/// 5. disable compute host individual firmware upgrades
/// a. only rack level firmware upgrades are allowed
/// 6. enable nvlink switch and power shelf discovery and ingestion
/// a. site explorer changes to explore switch and power shelf bmc
/// b. state machine for ingestion workflow
/// c. nvlink switch nvos deployment/upgrade via onie
/// d. nvlink switch default configuration and machine validation
/// 7. enable rack state machine and calls to rack manager
/// a. depend on rack manager for firmware upgrades of the rack
/// b. depend on rack manager for all power sequencing of the rack and components
/// c. override/suspend component level state machine state transitions as needed
/// 8. enable nvlink control plane integration with nmx-c
/// a. export nmx-c apis via site controller
/// b. hardware health daemon polling of switch telemetry and collection into site controller
/// prometheus instance
/// 9. enable domain power service integration
#[serde(default)]
pub rack_management_enabled: bool,
/// Rack Manager Service configuration for rack-level firmware upgrades,
/// power sequencing, and mTLS connectivity.
#[serde(default)]
pub rms: RmsConfig,
/// rack_profiles contains the rack profile definitions. When expected racks
/// are created, they are given a rack_profile_id to reference. This maps
/// those names to the actual RackProfileConfig. This may eventually change,
/// and/or co-exist with a DCIM providing us an entire config as part of
/// the ingestion call.
#[serde(default)]
pub rack_profiles: model::rack_type::RackProfileConfig,
/// Treat any dpu found as a regular NIC and skip configuring it as a managed dpu.
/// This is specifically for dev labs to allow using GB200/300 and VR compute
/// trays with bluefield dpus as NICs.
#[serde(
default = "SiteExplorerConfig::default_force_dpu_nic_mode",
deserialize_with = "deserialize_arc_atomic_bool",
serialize_with = "serialize_arc_atomic_bool"
)]
pub force_dpu_nic_mode: Arc<AtomicBool>,
/// SPDM (Security Protocol and Data Model) configuration for hardware attestation.
#[serde(default)]
pub spdm: SpdmConfig,
/// Due to limitations in Cumulus Linux route-leaking,
/// some sites may require all VRFs to use the same VNI.
/// Isolation is still possible via ACLs, and route-imports
/// will still use the dynamically allocated VNI for deriving
/// route-targets.
/// This will limit the number of VRFs supported on the
/// DPU to a single VRF.
pub site_global_vpc_vni: Option<u32>,
/// DPF (DPU Platform Framework) configuration for DPU fabric deployment as a Kubernetes service.
#[serde(default)]
pub dpf: DpfConfig,
/// The URL to use for overriding the PXE boot url on X86 machines.
#[serde(default)]
pub x86_pxe_boot_url_override: Option<String>,
/// The URL to use for overriding the PXE boot url on ARM machines.
#[serde(default)]
pub arm_pxe_boot_url_override: Option<String>,
/// Vendors for which the state controller should pin the UEFI HTTP boot
/// URL on the BMC (via Redfish `HttpBootUri`) in addition to the existing
/// DHCP option 67 path. Machines whose BMC vendor is NOT in this list
/// continue to rely on carbide-dhcp's option 67 for the URL.
///
/// Empty by default — no machines get the BMC-pinned URL until vendors
/// are explicitly added here (typically after per-vendor verification on
/// real hardware). Adding a vendor that libredfish doesn't yet implement
/// (e.g., `Dell` / `Lenovo` until their libredfish impls land) will
/// surface a runtime `NotSupported` error; carbide-dhcp option 67 is the
/// fallback URL source.
#[serde(default)]
pub set_http_boot_uri_for_vendors: Vec<BMCVendor>,
/// Alternate API URL for external hosts that cannot resolve
/// https://carbide-pxe.forge. This be an IP (e.g., "https://10.0.0.1:1079"),
/// or an externally resolvable hostname (e.g.,
/// "https://carbide-stack-api.corp.example.com"). This is the URL
/// that gets handed back to interfaces assigned ot the static-assignments
/// subnet. If not set, external hosts will just get the "internal"
/// variant of api_url.
#[serde(default)]
pub external_api_url: Option<String>,
/// Alternate PXE URL for external hosts (e.g., "http://10.0.0.1:8080"
/// or "http://carbide-stack-pxe.corp.example.com"). Used for cloud-init and
/// root CA retrieval for interfaces on the static-assignments segment,
/// and follows the same rules as external_api_url above.
#[serde(default)]
pub external_pxe_url: Option<String>,
/// Alternate static PXE URL for external hosts (e.g.,
/// "http://10.0.0.1:8081" or "http://carbide-stack-static.corp.example.com").
/// Used for kernel/blob downloads on the static-assignments segment.
/// If not set, falls back to `external_pxe_url`.
#[serde(default)]
pub external_static_pxe_url: Option<String>,
/// Controls enforcement of compute allocations when a new instance is
/// requested.
#[serde(default)]
pub compute_allocation_enforcement: ComputeAllocationEnforcement,
/// supernic_firmware_profiles is a nested map of FirmwareFlasherProfiles
/// keyed by part_number and PSID. Each profile specifies the firmware to
/// flash and optional lifecycle flags (reset, verify_image, verify_version).
///
/// Configured in `nico-api-config.toml`:
///
/// ```toml
/// [supernic_firmware_profiles.900-9D3B4-00CV-TA0.MT_0000000884]
/// part_number = "900-9D3B4-00CV-TA0"
/// psid = "MT_0000000884"
/// version = "32.43.1014"
/// firmware_url = "https://firmware.example.com/fw-32.43.1014.bin"
/// reset = true
///
/// [supernic_firmware_profiles.900-9D3B4-00CV-TB0.MT_0000000885]
/// part_number = "900-9D3B4-00CV-TB0"
/// psid = "MT_0000000885"
/// version = "32.43.1014"
/// firmware_url = "ssh://firmwarehost/path/to/fw-32.43.1014.bin"
/// ```
#[serde(default)]
pub supernic_firmware_profiles: HashMap<String, HashMap<String, FirmwareFlasherProfile>>,
/// Component manager configuration for managing
/// NvLink switches and power shelves via rack
/// manager integration.
#[serde(default)]
pub component_manager: Option<component_manager::config::ComponentManagerConfig>,
/// The password source to use for sites where the LEAF TOR
/// requires session passwords.
#[serde(default)]
pub bgp_leaf_session_password: Option<BgpLeafSessionPassword>,
/// The default routing-profile to use when a tenant is created.
#[serde(default = "default_tenant_routing_profile")]
pub default_tenant_routing_profile_type: String,
/// The initial_objects.toml file for seeding the database
#[serde(default)]
pub initial_objects_file: Option<PathBuf>,
/// The Figment that produced this config, when one was used. Kept after
/// extraction so runtime code can attribute individual keys back to their
/// source files via `Figment::find_metadata`
///
/// `None` for `CarbideConfig` values that didn't come from `parse_carbide_config`
/// (test fixtures, programmatic construction).
#[serde(skip)]
pub config_ctx: Option<Figment>,
/// External tool links surfaced in the admin web UI's "Tools"
/// sidebar. Each entry's `name` must be unique. The section is
/// hidden when the list is empty.
#[serde(default)]
pub web_ui_sidebar_tools: Vec<ToolLink>,
}
/// One external tool link rendered in the admin web UI's "Tools"
/// sidebar.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ToolLink {
/// Stable identifier, must be unique within `tools`. Used
/// to look up well-known integrations.
pub name: String,
/// Label rendered in the sidebar.
pub display_name: String,
/// Absolute URL the link points to.
pub url: String,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq)]
pub enum BgpLeafSessionPassword {
/// Use a defined site-wide password.
/// The password should already exist in the credentials
/// store.
#[default]
SiteWide,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "snake_case")]
pub enum ComputeAllocationEnforcement {
#[default]
/// If an allocation exists, don't enforce, but log what would have happened.
WarnOnly,
/// Only enforce if allocations exist.
EnforceIfPresent,
/// Always enforce, and zero allocations for the tenant means
/// the new instance request will be rejected.
Always,
}
/// DPF (DPU Platform Framework) configuration for
/// deploying DPU fabric as a Kubernetes service.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DpfConfig {
/// Enables DPF deployment.
#[serde(default)]
pub enabled: bool,
/// Kubernetes deployment name for the DPF service.
#[serde(default = "default_dpf_deployment_name")]
pub deployment_name: String,
/// Kubernetes DPUFlavor CR name.
#[serde(default = "default_dpf_flavor_name")]
pub flavor_name: String,
/// Label key applied to DPUNode CRs for deployment matching.
#[serde(default = "default_dpf_node_label_key")]
pub node_label_key: String,
/// URL to the BlueField firmware bundle (BFB) for
/// DPU provisioning.
#[serde(default = "default_dpf_bfb_url")]
pub bfb_url: String,
/// Additional Helm services to deploy alongside DPF.
#[serde(default)]
pub services: Box<DpfMandatoryServicesConfig>,
}
impl Default for DpfConfig {
fn default() -> Self {
Self {
enabled: false,
deployment_name: default_dpf_deployment_name(),
flavor_name: default_dpf_flavor_name(),
node_label_key: default_dpf_node_label_key(),
bfb_url: String::new(),
services: Box::default(),
}
}
}
fn default_dpf_bfb_url() -> String {
"https://content.mellanox.com/BlueField/BFBs/Ubuntu24.04/bf-bundle-3.2.2-125_26.02_ubuntu-24.04_64k_prod.bfb".to_string()
}
fn default_dpf_deployment_name() -> String {
"nico-deployment-v2".to_string()
}
fn default_dpf_flavor_name() -> String {
"carbide-dpu-flavor".to_string()
}
fn default_dpf_node_label_key() -> String {
"carbide.nvidia.com/controlled.node.v2".to_string()
}
/// Configuration for a mandatory Helm-based DPF service.
/// Making it configurable means, a user can provide the link for his version of the service (for
/// testing/dev purpose).
/// There are following mandatory services:
/// dpu-agent, fmds, dhcp-server, doca-hbn, dts and otel.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DpfMandatoryServicesConfig {
#[serde(default = "crate::dpf_services::default_dts_service")]
pub dts: DpfServiceConfig,
#[serde(default = "crate::dpf_services::default_doca_hbn_service")]
pub doca_hbn: DpfServiceConfig,
#[serde(default = "crate::dpf_services::default_dpu_agent_service")]
pub dpu_agent: DpfServiceConfig,
#[serde(default = "crate::dpf_services::default_dhcp_server_service")]
pub dhcp_server: DpfServiceConfig,
#[serde(default = "crate::dpf_services::default_fmds_service")]
pub fmds: DpfServiceConfig,
#[serde(default = "crate::dpf_services::default_otelcol_service")]
pub otel: DpfServiceConfig,
}
impl Default for DpfMandatoryServicesConfig {
fn default() -> Self {
Self {
dts: crate::dpf_services::default_dts_service(),
doca_hbn: crate::dpf_services::default_doca_hbn_service(),
dpu_agent: crate::dpf_services::default_dpu_agent_service(),
dhcp_server: crate::dpf_services::default_dhcp_server_service(),
fmds: crate::dpf_services::default_fmds_service(),
otel: crate::dpf_services::default_otelcol_service(),
}
}
}
/// Default name for the Kubernetes `imagePullSecrets` entry used by DPF workload charts.
pub(crate) const DEFAULT_DPF_IMAGE_PULL_SECRET: &str = "dpf-pull-secret";
fn default_dpf_image_pull_secret() -> String {
DEFAULT_DPF_IMAGE_PULL_SECRET.to_string()
}
/// Configuration for a single Helm-based DPF service.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct DpfServiceConfig {
/// Name of the Helm service.
pub name: String,
/// URL of the Helm chart repository.
pub helm_repo_url: String,
/// Name of the Helm chart.
pub helm_chart: String,
/// Version of the Helm chart.
pub helm_version: String,
/// Url for docker image
pub docker_repo_url: String,
/// Version of docker image
pub docker_image_tag: String,
/// Secret to use to pull the docker images.
#[serde(default = "default_dpf_image_pull_secret")]
pub docker_image_pull_secret: String,
}
/// Machine identity (SPIFFE JWT-SVID) configuration.
/// Loaded from `[machine_identity]` section in config.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MachineIdentityConfig {
/// Master switch. If false, SetTenantIdentityConfiguration and SignMachineIdentity return 503.
#[serde(default = "machine_identity_default_enabled")]
pub enabled: bool,
/// Signing algorithm for per-org keys (e.g. ES256).
#[serde(default = "machine_identity_default_algorithm")]
pub algorithm: SigningAlgorithm,
/// Min token TTL permitted in seconds.
#[serde(default = "machine_identity_default_token_ttl_min_sec")]
pub token_ttl_min_sec: u32,
/// Max token TTL permitted in seconds.
#[serde(default = "machine_identity_default_token_ttl_max_sec")]
pub token_ttl_max_sec: u32,
/// Optional HTTP proxy for token endpoint calls (SSRF mitigation).
#[serde(default)]
pub token_endpoint_http_proxy: Option<String>,
/// Key-id for encryption/decryption of signing keys (selects from secrets `machine_identity.encryption_keys`).
#[serde(default)]
pub current_encryption_key_id: Option<String>,
/// Trust domains allowed for tenant JWT `iss` (normalized host). Empty = allow any.
/// Patterns: exact hostname, `*.suffix` (one label under suffix), `**.suffix` (suffix or any subdomain).
#[serde(default)]
pub trust_domain_allowlist: Vec<String>,
/// Allowed DNS names for the `token_endpoint` URL host (`http://` / `https://` only). Empty = allow any.
/// Same pattern syntax as [`Self::trust_domain_allowlist`].
#[serde(default)]
pub token_endpoint_domain_allowlist: Vec<String>,
/// Upper bound for `signing_key_overlap_sec` on `SetTenantIdentityConfiguration` when `rotate_key` is true (seconds).
#[serde(default = "machine_identity_default_signing_key_overlap_max_sec")]
pub signing_key_overlap_max_sec: u32,
}
fn machine_identity_default_enabled() -> bool {
false
}
fn machine_identity_default_algorithm() -> SigningAlgorithm {
SigningAlgorithm::Es256
}
fn machine_identity_default_token_ttl_min_sec() -> u32 {
60
}
fn machine_identity_default_token_ttl_max_sec() -> u32 {
86400
}
fn machine_identity_default_signing_key_overlap_max_sec() -> u32 {
604800
}
impl Default for MachineIdentityConfig {
fn default() -> Self {
Self {
enabled: machine_identity_default_enabled(),
algorithm: machine_identity_default_algorithm(),
token_ttl_min_sec: machine_identity_default_token_ttl_min_sec(),
token_ttl_max_sec: machine_identity_default_token_ttl_max_sec(),
token_endpoint_http_proxy: None,
current_encryption_key_id: None,
trust_domain_allowlist: Vec::new(),
token_endpoint_domain_allowlist: Vec::new(),
signing_key_overlap_max_sec: machine_identity_default_signing_key_overlap_max_sec(),
}
}
}
impl From<MachineIdentityConfig> for model::tenant::IdentityConfigValidationBounds {
fn from(mi: MachineIdentityConfig) -> Self {
Self {
token_ttl_min_sec: mi.token_ttl_min_sec,
token_ttl_max_sec: mi.token_ttl_max_sec,
algorithm: mi.algorithm,
encryption_key_id: mi
.current_encryption_key_id
.expect(
"current_encryption_key_id is required when machine identity is enabled; \
startup validation in parse_carbide_config failed",
)
.try_into()
.expect(
"current_encryption_key_id must be non-empty when machine identity is enabled",
),
trust_domain_allowlist: mi.trust_domain_allowlist,
signing_key_overlap_max_sec: mi.signing_key_overlap_max_sec,
}
}
}
impl From<MachineIdentityConfig> for model::tenant::TokenDelegationValidationBounds {
fn from(mi: MachineIdentityConfig) -> Self {
Self {
token_endpoint_domain_allowlist: mi.token_endpoint_domain_allowlist,
}
}
}
/// SPDM (Security Protocol and Data Model) configuration
/// for hardware attestation of DPU components.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct SpdmConfig {
/// Enables SPDM-based hardware attestation.
#[serde(default)]
pub enabled: bool,
/// NRAS (Network Root of trust for Attestation
/// Service) configuration for secure boot
/// verification.
#[serde(default)]
pub nras_config: Option<nras::Config>,
}
/// Power management configuration controlling retry
/// intervals and reboot timing.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct PowerManagerOptions {
/// Master switch to enable or disable power
/// management.
#[serde(default)]
pub enabled: bool,
/// Interval before retrying power operations after
/// a successful attempt.
/// Default is 5 minutes.
#[serde(
default = "default_next_duration_success",
deserialize_with = "deserialize_duration_chrono",
serialize_with = "as_duration"
)]
pub next_try_duration_on_success: chrono::TimeDelta,
/// Interval before retrying power operations after
/// a failed attempt.
/// Default is 2 minutes.
#[serde(
default = "default_next_duration_failure",
deserialize_with = "deserialize_duration_chrono",
serialize_with = "as_duration"
)]
pub next_try_duration_on_failure: chrono::TimeDelta,
/// Time to wait after power-down before powering on
/// the host.
/// Default is 15 minutes.
#[serde(
default = "default_wait_duration_next_reboot",
deserialize_with = "deserialize_duration_chrono",
serialize_with = "as_duration"
)]
pub wait_duration_until_host_reboot: chrono::TimeDelta,
}
/// A BGP route target used in FNN VRF import/export policies.
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct RouteTargetConfig {
/// Autonomous System Number component of the route target.
#[serde(default)]
pub asn: u32,
/// Virtual Network Identifier component of the route target.
#[serde(default)]
pub vni: u32,
}
/// Fabric Nearest Neighbor (FNN) configuration for L3 VNI-based overlay networking.
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct FnnConfig {
/// Optional FNN configuration for the admin network VPC.
#[serde(default)]
pub admin_vpc: Option<AdminFnnConfig>,
/// We'll double-tag our internal tenant routes with this tag.
/// Original consumer is a Network Infrastructure team, who will
/// import a common route-target for internal tenant routes,
/// reducing the coordination needed between NICo and the Network
/// Infrastructure, but who knows what the future holds.
#[serde(default)]
pub common_internal_route_target: Option<RouteTargetConfig>,
/// Additional route targets to import on DPU VRFs beyond the per-VPC defaults.
#[serde(default)]
pub additional_route_target_imports: Vec<RouteTargetConfig>,
/// Named routing profiles that define per-VPC route target import/export policies.
#[serde(default)]
pub routing_profiles: HashMap<String, FnnRoutingProfileConfig>,
/// Whether IPs should be allocated for VPC loopbacks.
/// The VPC loopback pool will not be used if this false and
/// no VPC/VRF loopback IP will be sent to the DPU.
#[serde(default)]
pub use_vpc_vrf_loopback: bool,