Skip to content

Commit b26bca7

Browse files
committed
test_external_dns_external_ips_specified_by_rack_setup()
1 parent 2e567af commit b26bca7

File tree

1 file changed

+117
-106
lines changed

1 file changed

+117
-106
lines changed

nexus/db-queries/src/db/datastore/deployment/external_networking.rs

Lines changed: 117 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,11 @@ mod tests {
513513
use nexus_config::NUM_INITIAL_RESERVED_IP_ADDRESSES;
514514
use nexus_db_model::SqlU16;
515515
use nexus_reconfigurator_planning::blueprint_builder::BlueprintBuilder;
516+
use nexus_reconfigurator_planning::blueprint_editor::ExternalNetworkingAllocator;
517+
use nexus_reconfigurator_planning::example::ExampleSystemBuilder;
518+
use nexus_reconfigurator_planning::planner::PlannerRng;
516519
use nexus_sled_agent_shared::inventory::OmicronZoneDataset;
520+
use nexus_types::deployment::BlueprintSource;
517521
use nexus_types::deployment::BlueprintTarget;
518522
use nexus_types::deployment::BlueprintZoneConfig;
519523
use nexus_types::deployment::BlueprintZoneImageSource;
@@ -527,6 +531,7 @@ mod tests {
527531
use omicron_common::address::DNS_OPTE_IPV4_SUBNET;
528532
use omicron_common::address::IpRange;
529533
use omicron_common::address::IpRangeIter;
534+
use omicron_common::address::Ipv4Range;
530535
use omicron_common::address::NEXUS_OPTE_IPV4_SUBNET;
531536
use omicron_common::address::NTP_OPTE_IPV4_SUBNET;
532537
use omicron_common::address::NUM_SOURCE_NAT_PORTS;
@@ -535,10 +540,7 @@ mod tests {
535540
use omicron_common::api::external::Vni;
536541
use omicron_common::zpool_name::ZpoolName;
537542
use omicron_test_utils::dev;
538-
use omicron_uuid_kinds::BlueprintUuid;
539543
use omicron_uuid_kinds::ExternalIpUuid;
540-
use omicron_uuid_kinds::ExternalZpoolUuid;
541-
use omicron_uuid_kinds::SledUuid;
542544
use omicron_uuid_kinds::ZpoolUuid;
543545
use oxnet::IpNet;
544546
use std::net::IpAddr;
@@ -1352,149 +1354,158 @@ mod tests {
13521354
const TEST_NAME: &str =
13531355
"test_external_dns_external_ips_specified_by_rack_setup";
13541356

1355-
// Helper closures to reduce boilerplate below.
1357+
// Helper closure to reduce boilerplate below.
13561358
let make_bp_target = |blueprint_id| BlueprintTarget {
13571359
target_id: blueprint_id,
13581360
enabled: false,
13591361
time_made_target: Utc::now(),
13601362
};
1361-
let mut opte_ip_iter = DNS_OPTE_IPV4_SUBNET.addr_iter();
1362-
let mut mac_iter = MacAddr::iter_system();
1363-
let mut make_external_dns_zone = |ip, disposition| {
1364-
let zone_id = OmicronZoneUuid::new_v4();
1365-
let pool = ZpoolName::External(ExternalZpoolUuid::new_v4());
1366-
BlueprintZoneConfig {
1367-
disposition,
1368-
id: zone_id,
1369-
filesystem_pool: pool,
1370-
zone_type: BlueprintZoneType::ExternalDns(
1371-
blueprint_zone_type::ExternalDns {
1372-
dataset: OmicronZoneDataset { pool_name: pool },
1373-
http_address: "[::1]:0".parse().unwrap(),
1374-
dns_address: OmicronZoneExternalFloatingAddr {
1375-
id: ExternalIpUuid::new_v4(),
1376-
addr: SocketAddr::new(ip, 0),
1377-
},
1378-
nic: NetworkInterface {
1379-
id: Uuid::new_v4(),
1380-
kind: NetworkInterfaceKind::Service {
1381-
id: zone_id.into_untyped_uuid(),
1382-
},
1383-
name: "test-external-dns".parse().unwrap(),
1384-
ip: opte_ip_iter.next().unwrap().into(),
1385-
mac: mac_iter.next().unwrap(),
1386-
subnet: IpNet::from(*DNS_OPTE_IPV4_SUBNET),
1387-
vni: Vni::SERVICES_VNI,
1388-
primary: true,
1389-
slot: 0,
1390-
transit_ips: vec![],
1391-
},
1392-
},
1393-
),
1394-
image_source: BlueprintZoneImageSource::InstallDataset,
1395-
}
1396-
};
13971363

13981364
// Set up.
13991365
let logctx = dev::test_setup_log(TEST_NAME);
14001366
let db = TestDatabase::new_with_datastore(&logctx.log).await;
14011367
let (opctx, datastore) = (db.opctx(), db.datastore());
14021368

1403-
// Create a blueprint with one sled and no zones. Insert it and make it
1404-
// the target.
1405-
let sled_id = SledUuid::new_v4();
1406-
let bp0 = BlueprintBuilder::build_empty_with_sleds(
1407-
std::iter::once(sled_id),
1408-
TEST_NAME,
1409-
);
1410-
datastore.blueprint_insert(opctx, &bp0).await.expect("inserted bp0");
1411-
datastore
1412-
.blueprint_target_set_current(opctx, make_bp_target(bp0.id))
1413-
.await
1414-
.expect("made bp0 the target");
1369+
// Create a blueprint with no external DNS zones.
1370+
let (example_system, bp1) =
1371+
ExampleSystemBuilder::new(&opctx.log, TEST_NAME)
1372+
.external_dns_count(0)
1373+
.expect("external DNS count can be 0")
1374+
.build();
1375+
1376+
// Insert the example system's initial empty blueprint and the one we
1377+
// want to test. Advance the target to point to `blueprint`.
1378+
let bp0 = &example_system.initial_blueprint;
1379+
for bp in [bp0, &bp1] {
1380+
datastore.blueprint_insert(opctx, bp).await.expect("inserted bp");
1381+
datastore
1382+
.blueprint_target_set_current(opctx, make_bp_target(bp.id))
1383+
.await
1384+
.expect("made bp the target");
1385+
}
14151386

14161387
// No external DNS zones => no external DNS IPs.
1388+
assert!(
1389+
example_system
1390+
.input
1391+
.external_ip_policy()
1392+
.external_dns_ips()
1393+
.is_empty()
1394+
);
14171395
let external_dns_ips = datastore
14181396
.external_dns_external_ips_specified_by_rack_setup(opctx)
14191397
.await
14201398
.expect("got external DNS IPs");
14211399
assert_eq!(external_dns_ips, BTreeSet::new());
14221400

1423-
// Create a blueprint with three in-service external DNS zones. We
1424-
// should get their IPs back.
1425-
let expected_ips = ["192.168.1.1", "192.168.1.2", "192.168.1.3"]
1426-
.into_iter()
1427-
.map(|ip| ip.parse::<IpAddr>().unwrap())
1428-
.collect::<BTreeSet<_>>();
1429-
let mut bp1 = bp0.clone();
1430-
bp1.id = BlueprintUuid::new_v4();
1431-
bp1.parent_blueprint_id = Some(bp0.id);
1432-
for &ip in &expected_ips {
1433-
bp1.sleds
1434-
.get_mut(&sled_id)
1435-
.unwrap()
1436-
.zones
1437-
.insert_unique(make_external_dns_zone(
1438-
ip,
1439-
BlueprintZoneDisposition::InService,
1440-
))
1441-
.expect("freshly generated zone IDs are unique");
1401+
// Extend the external IP policy to allow for external DNS.
1402+
let all_external_dns_ips = IpRange::V4(Ipv4Range {
1403+
first: "192.168.1.1".parse().unwrap(),
1404+
last: "192.168.1.5".parse().unwrap(),
1405+
});
1406+
let input = {
1407+
let mut policy_builder = example_system
1408+
.input
1409+
.external_ip_policy()
1410+
.clone()
1411+
.into_builder();
1412+
policy_builder
1413+
.push_service_pool_range(all_external_dns_ips)
1414+
.expect("valid range");
1415+
for ip in all_external_dns_ips.iter() {
1416+
policy_builder.add_external_dns_ip(ip).expect("valid IP");
1417+
}
1418+
1419+
let mut input_builder = example_system.input.into_builder();
1420+
input_builder.policy_mut().external_ips = policy_builder.build();
1421+
input_builder.build()
1422+
};
1423+
1424+
// Add an in-service external DNS zone for each IP.
1425+
let mut builder = BlueprintBuilder::new_based_on(
1426+
&opctx.log,
1427+
&bp1,
1428+
&input,
1429+
TEST_NAME,
1430+
PlannerRng::from_entropy(),
1431+
)
1432+
.expect("created builder");
1433+
1434+
let mut external_networking_alloc =
1435+
ExternalNetworkingAllocator::from_current_zones(
1436+
&builder,
1437+
input.external_ip_policy(),
1438+
)
1439+
.expect("created allocator");
1440+
1441+
let sled_id = bp1.sleds().next().expect("at least 1 sled exists");
1442+
for _ in all_external_dns_ips.iter() {
1443+
builder
1444+
.sled_add_zone_external_dns(
1445+
sled_id,
1446+
BlueprintZoneImageSource::InstallDataset,
1447+
external_networking_alloc
1448+
.for_new_external_dns()
1449+
.expect("got IP for external DNS"),
1450+
)
1451+
.expect("added external DNS");
14421452
}
14431453

1444-
// Insert bp1 and make it the target. Confirm we get back the expected
1454+
// Insert bp2 and make it the target. Confirm we get back the expected
14451455
// external DNS IPs.
1446-
datastore.blueprint_insert(opctx, &bp1).await.expect("inserted bp1");
1456+
let bp2 = builder.build(BlueprintSource::Test);
1457+
let expected_ips = all_external_dns_ips.iter().collect::<BTreeSet<_>>();
1458+
datastore.blueprint_insert(opctx, &bp2).await.expect("inserted bp2");
14471459
datastore
1448-
.blueprint_target_set_current(opctx, make_bp_target(bp1.id))
1460+
.blueprint_target_set_current(opctx, make_bp_target(bp2.id))
14491461
.await
1450-
.expect("made bp1 the target");
1462+
.expect("made bp2 the target");
14511463
let external_dns_ips = datastore
14521464
.external_dns_external_ips_specified_by_rack_setup(opctx)
14531465
.await
14541466
.expect("got external DNS IPs");
14551467
assert_eq!(external_dns_ips, expected_ips);
14561468

1457-
// Create a third blueprint with multiple expunged external DNS zones
1458-
// covering a couple additional IPs. Those should also be returned.
1459-
let extra_ips = ["192.168.1.4", "192.168.1.5"]
1460-
.into_iter()
1461-
.map(|ip| ip.parse::<IpAddr>().unwrap())
1469+
// Create a new blueprint that expunges two of those zones.
1470+
let mut builder = BlueprintBuilder::new_based_on(
1471+
&opctx.log,
1472+
&bp2,
1473+
&input,
1474+
TEST_NAME,
1475+
PlannerRng::from_entropy(),
1476+
)
1477+
.expect("created builder");
1478+
1479+
let to_expunge = builder
1480+
.current_zones(BlueprintZoneDisposition::is_in_service)
1481+
.filter_map(|(sled_id, zone)| {
1482+
if zone.zone_type.is_external_dns() {
1483+
Some((sled_id, zone.id))
1484+
} else {
1485+
None
1486+
}
1487+
})
1488+
.take(2)
14621489
.collect::<BTreeSet<_>>();
1463-
assert_eq!(expected_ips.intersection(&extra_ips).count(), 0);
1464-
1465-
let mut bp2 = bp1.clone();
1466-
bp2.id = BlueprintUuid::new_v4();
1467-
bp2.parent_blueprint_id = Some(bp1.id);
1468-
for &ip in &extra_ips {
1469-
for i in 0..4 {
1470-
bp2.sleds
1471-
.get_mut(&sled_id)
1472-
.unwrap()
1473-
.zones
1474-
.insert_unique(make_external_dns_zone(
1475-
ip,
1476-
BlueprintZoneDisposition::Expunged {
1477-
as_of_generation: Generation::new(),
1478-
ready_for_cleanup: i % 2 == 0,
1479-
},
1480-
))
1481-
.expect("freshly generated zone IDs are unique");
1482-
}
1490+
assert_eq!(to_expunge.len(), 2);
1491+
1492+
for (sled_id, zone_id) in to_expunge {
1493+
builder.sled_expunge_zone(sled_id, zone_id).expect("expunged zone");
14831494
}
14841495

1485-
// Insert bp1 and make it the target. Confirm we get back the expected
1496+
// Insert bp3 and make it the target. Confirm we still get back all five
14861497
// external DNS IPs.
1487-
datastore.blueprint_insert(opctx, &bp2).await.expect("inserted bp2");
1498+
let bp3 = builder.build(BlueprintSource::Test);
1499+
let expected_ips = all_external_dns_ips.iter().collect::<BTreeSet<_>>();
1500+
datastore.blueprint_insert(opctx, &bp3).await.expect("inserted bp3");
14881501
datastore
1489-
.blueprint_target_set_current(opctx, make_bp_target(bp2.id))
1502+
.blueprint_target_set_current(opctx, make_bp_target(bp3.id))
14901503
.await
1491-
.expect("made bp2 the target");
1504+
.expect("made bp3 the target");
14921505
let external_dns_ips = datastore
14931506
.external_dns_external_ips_specified_by_rack_setup(opctx)
14941507
.await
14951508
.expect("got external DNS IPs");
1496-
let expected_ips =
1497-
expected_ips.union(&extra_ips).copied().collect::<BTreeSet<_>>();
14981509
assert_eq!(external_dns_ips, expected_ips);
14991510

15001511
// Clean up.

0 commit comments

Comments
 (0)