Skip to content

Commit ae3aec5

Browse files
committed
test v6 routes reach mgd, hard coded ports -> dns
1 parent 1a57038 commit ae3aec5

File tree

6 files changed

+107
-11
lines changed

6 files changed

+107
-11
lines changed

nexus/src/app/background/tasks/bfd.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ impl BackgroundTask for BfdManager {
132132
},
133133
};
134134

135-
let mgd_clients = build_mgd_clients(mappings, log);
135+
let mgd_clients = build_mgd_clients(mappings, log, &self.resolver).await;
136136

137137
for (location, c) in &mgd_clients {
138138
let client_current = match c.get_bfd_peers().await {

nexus/src/app/background/tasks/networking.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,37 @@ use db::datastore::SwitchPortSettingsCombinedResult;
66
use dpd_client::types::{
77
LinkCreate, LinkId, LinkSettings, PortFec, PortSettings, PortSpeed, TxEq,
88
};
9+
use internal_dns_types::names::ServiceName;
910
use nexus_db_model::{SwitchLinkFec, SwitchLinkSpeed};
1011
use nexus_db_queries::db;
1112
use omicron_common::{address::MGD_PORT, api::external::SwitchLocation};
12-
use std::{collections::HashMap, net::SocketAddrV6};
13+
use std::{
14+
collections::HashMap,
15+
net::{Ipv6Addr, SocketAddrV6},
16+
};
1317

14-
pub(crate) fn build_mgd_clients(
18+
pub(crate) async fn build_mgd_clients(
1519
mappings: HashMap<SwitchLocation, std::net::Ipv6Addr>,
1620
log: &slog::Logger,
21+
resolver: &internal_dns_resolver::Resolver,
1722
) -> HashMap<SwitchLocation, mg_admin_client::Client> {
1823
let mut clients: Vec<(SwitchLocation, mg_admin_client::Client)> = vec![];
1924
for (location, addr) in &mappings {
20-
let port = MGD_PORT;
25+
let port = match resolver.lookup_all_socket_v6(ServiceName::Mgd).await {
26+
Ok(addrs) => {
27+
let port_map: HashMap<Ipv6Addr, u16> = addrs
28+
.into_iter()
29+
.map(|sockaddr| (*sockaddr.ip(), sockaddr.port()))
30+
.collect();
31+
32+
*port_map.get(&addr).unwrap_or(&MGD_PORT)
33+
}
34+
Err(e) => {
35+
error!(log, "failed to addresses"; "error" => %e);
36+
MGD_PORT
37+
}
38+
};
39+
2140
let socketaddr =
2241
std::net::SocketAddr::V6(SocketAddrV6::new(*addr, port, 0, 0));
2342
let client = mg_admin_client::Client::new(

nexus/src/app/background/tasks/sync_switch_configuration.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,8 @@ impl BackgroundTask for SwitchPortSettingsManager {
335335
async move {
336336
let log = opctx.log.clone();
337337

338+
info!(log, "running switch port settings manager RPW");
339+
338340
let racks = match self.datastore.rack_list_initialized(opctx, &DataPageParams::max_page()).await {
339341
Ok(racks) => racks,
340342
Err(e) => {
@@ -394,7 +396,7 @@ impl BackgroundTask for SwitchPortSettingsManager {
394396

395397
// TODO https://github.com/oxidecomputer/omicron/issues/5201
396398
// build mgd clients
397-
let mgd_clients = build_mgd_clients(mappings, &log);
399+
let mgd_clients = build_mgd_clients(mappings, &log, &self.resolver).await;
398400

399401
let port_list = match self.switch_ports(opctx, &log).await {
400402
Ok(value) => value,

nexus/src/app/mod.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,7 +1320,7 @@ async fn switch_zone_address_mappings(
13201320
return Err(e.to_string());
13211321
}
13221322
};
1323-
Ok(map_switch_zone_addrs(&log, switch_zone_addresses).await)
1323+
Ok(map_switch_zone_addrs(&log, switch_zone_addresses, resolver).await)
13241324
}
13251325

13261326
// TODO: #3596 Allow updating of Nexus from `handoff_to_nexus()`
@@ -1344,14 +1344,33 @@ async fn switch_zone_address_mappings(
13441344
async fn map_switch_zone_addrs(
13451345
log: &Logger,
13461346
switch_zone_addresses: Vec<Ipv6Addr>,
1347+
resolver: &internal_dns_resolver::Resolver,
13471348
) -> HashMap<SwitchLocation, Ipv6Addr> {
13481349
use gateway_client::Client as MgsClient;
13491350
info!(log, "Determining switch slots managed by switch zones");
13501351
let mut switch_zone_addrs = HashMap::new();
13511352

13521353
for addr in switch_zone_addresses {
1354+
let port = match resolver
1355+
.lookup_all_socket_v6(ServiceName::ManagementGatewayService)
1356+
.await
1357+
{
1358+
Ok(addrs) => {
1359+
let port_map: HashMap<Ipv6Addr, u16> = addrs
1360+
.into_iter()
1361+
.map(|sockaddr| (*sockaddr.ip(), sockaddr.port()))
1362+
.collect();
1363+
1364+
*port_map.get(&addr).unwrap_or(&MGS_PORT)
1365+
}
1366+
Err(e) => {
1367+
error!(log, "failed to resolve MGS addresses"; "error" => %e);
1368+
MGS_PORT
1369+
}
1370+
};
1371+
13531372
let mgs_client = MgsClient::new(
1354-
&format!("http://[{}]:{}", addr, MGS_PORT),
1373+
&format!("http://[{}]:{}", addr, port),
13551374
log.new(o!("component" => "MgsClient")),
13561375
);
13571376

nexus/src/app/switch_port.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,16 @@ impl super::Nexus {
9494
params: params::SwitchPortSettingsCreate,
9595
id: Option<Uuid>,
9696
) -> CreateResult<SwitchPortSettingsCombinedResult> {
97-
self.db_datastore.switch_port_settings_create(opctx, &params, id).await
97+
let result = self
98+
.db_datastore
99+
.switch_port_settings_create(opctx, &params, id)
100+
.await?;
101+
102+
// eagerly propagate changes via rpw
103+
self.background_tasks
104+
.activate(&self.background_tasks.task_switch_port_settings_manager);
105+
106+
Ok(result)
98107
}
99108

100109
pub(crate) async fn switch_port_settings_update(

nexus/tests/integration_tests/switch_port.rs

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use nexus_types::external_api::params::{
2020
use nexus_types::external_api::views::Rack;
2121
use omicron_common::api::external::{
2222
self, AddressLotKind, BgpPeer, IdentityMetadataCreateParams, LinkFec,
23-
LinkSpeed, NameOrId, SwitchPort, SwitchPortSettings,
23+
LinkSpeed, NameOrId, SwitchLocation, SwitchPort, SwitchPortSettings,
2424
};
2525
use omicron_common::api::external::{ImportExportPolicy, Name};
2626
use oxnet::IpNet;
@@ -400,7 +400,7 @@ async fn test_port_settings_basic_crud(ctx: &ControlPlaneTestContext) {
400400
.unwrap();
401401
}
402402

403-
#[nexus_test]
403+
#[nexus_test(extra_sled_agents = 1)]
404404
async fn test_port_settings_basic_v6_crud(ctx: &ControlPlaneTestContext) {
405405
let client = &ctx.external_client;
406406

@@ -429,9 +429,11 @@ async fn test_port_settings_basic_v6_crud(ctx: &ControlPlaneTestContext) {
429429
.unwrap();
430430

431431
// Create port settings
432+
let settings_name =
433+
Name::from_str("nacelle").expect("nacell should be a valid name");
432434
let mut settings =
433435
SwitchPortSettingsCreate::new(IdentityMetadataCreateParams {
434-
name: "nacelle".parse().unwrap(),
436+
name: settings_name.clone(),
435437
description: "just a port".into(),
436438
});
437439

@@ -499,4 +501,49 @@ async fn test_port_settings_basic_v6_crud(ctx: &ControlPlaneTestContext) {
499501
let route = &created.routes[0];
500502
assert_eq!(route.dst, IpNet::from_str("2000::/64").unwrap());
501503
assert_eq!(&route.gw.to_string(), "2000::1");
504+
505+
let mgd = &ctx.mgd[&SwitchLocation::Switch0];
506+
let mgd_client = mg_admin_client::Client::new(
507+
&format!("http://localhost:{}", mgd.port),
508+
ctx.logctx.log.clone(),
509+
);
510+
511+
// apply port settings
512+
let apply_settings = SwitchPortApplySettings {
513+
port_settings: NameOrId::Name(settings_name.clone()),
514+
};
515+
516+
let racks_url = "/v1/system/hardware/racks";
517+
let racks: Vec<Rack> =
518+
NexusRequest::iter_collection_authn(client, racks_url, "", None)
519+
.await
520+
.expect("failed to list racks")
521+
.all_items;
522+
523+
let rack_id = racks[0].identity.id;
524+
525+
NexusRequest::new(
526+
RequestBuilder::new(
527+
client,
528+
Method::POST,
529+
&format!("/v1/system/hardware/switch-port/qsfp0/settings?rack_id={rack_id}&switch_location=switch0"),
530+
)
531+
.body(Some(&apply_settings))
532+
.expect_status(Some(StatusCode::NO_CONTENT)),
533+
)
534+
.authn_as(AuthnMode::PrivilegedUser)
535+
.execute()
536+
.await
537+
.unwrap();
538+
539+
// wait for reconciliation
540+
tokio::time::sleep(std::time::Duration::from_secs(10)).await;
541+
542+
// ensure that our route has landed in mgd
543+
let routes = mgd_client
544+
.static_list_v6_routes()
545+
.await
546+
.expect("list maghemite v6 routes");
547+
548+
assert_eq!(routes.len(), 1);
502549
}

0 commit comments

Comments
 (0)