diff --git a/Cargo.lock b/Cargo.lock index a3d52c52bb4..6f27c725cdb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2467,7 +2467,7 @@ dependencies = [ [[package]] name = "ddm-admin-client" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/maghemite?rev=0df320d42b356e689a3c7a7600eec9b16770237a#0df320d42b356e689a3c7a7600eec9b16770237a" +source = "git+https://github.com/oxidecomputer/maghemite?rev=9e94d6b79560c2e4639cba432fb0ed600e9a3ff8#9e94d6b79560c2e4639cba432fb0ed600e9a3ff8" dependencies = [ "oxnet", "progenitor 0.11.2", @@ -6312,7 +6312,7 @@ dependencies = [ [[package]] name = "mg-admin-client" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/maghemite?rev=0df320d42b356e689a3c7a7600eec9b16770237a#0df320d42b356e689a3c7a7600eec9b16770237a" +source = "git+https://github.com/oxidecomputer/maghemite?rev=9e94d6b79560c2e4639cba432fb0ed600e9a3ff8#9e94d6b79560c2e4639cba432fb0ed600e9a3ff8" dependencies = [ "chrono", "colored 3.0.0", @@ -11319,7 +11319,7 @@ dependencies = [ [[package]] name = "rdb-types" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/maghemite?rev=0df320d42b356e689a3c7a7600eec9b16770237a#0df320d42b356e689a3c7a7600eec9b16770237a" +source = "git+https://github.com/oxidecomputer/maghemite?rev=9e94d6b79560c2e4639cba432fb0ed600e9a3ff8#9e94d6b79560c2e4639cba432fb0ed600e9a3ff8" dependencies = [ "oxnet", "schemars 0.8.22", diff --git a/Cargo.toml b/Cargo.toml index 7a7a3148e2e..f5b2e665779 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -538,8 +538,8 @@ newtype_derive = "0.1.6" ntp-admin-api = { path = "ntp-admin/api" } ntp-admin-client = { path = "clients/ntp-admin-client" } ntp-admin-types = { path = "ntp-admin/types" } -mg-admin-client = { git = "https://github.com/oxidecomputer/maghemite", rev = "0df320d42b356e689a3c7a7600eec9b16770237a" } -ddm-admin-client = { git = "https://github.com/oxidecomputer/maghemite", rev = "0df320d42b356e689a3c7a7600eec9b16770237a" } +mg-admin-client = { git = "https://github.com/oxidecomputer/maghemite", rev = "9e94d6b79560c2e4639cba432fb0ed600e9a3ff8" } +ddm-admin-client = { git = "https://github.com/oxidecomputer/maghemite", rev = "9e94d6b79560c2e4639cba432fb0ed600e9a3ff8" } multimap = "0.10.1" nexus-auth = { path = "nexus/auth" } nexus-background-task-interface = { path = "nexus/background-task-interface" } @@ -666,7 +666,7 @@ ratatui = "0.29.0" raw-cpuid = { git = "https://github.com/oxidecomputer/rust-cpuid.git", rev = "a4cf01df76f35430ff5d39dc2fe470bcb953503b" } rayon = "1.10" rcgen = "0.12.1" -rdb-types = { git = "https://github.com/oxidecomputer/maghemite", rev = "0df320d42b356e689a3c7a7600eec9b16770237a" } +rdb-types = { git = "https://github.com/oxidecomputer/maghemite", rev = "9e94d6b79560c2e4639cba432fb0ed600e9a3ff8" } reconfigurator-cli = { path = "dev-tools/reconfigurator-cli" } reedline = "0.40.0" ref-cast = "1.0" diff --git a/dev-tools/ls-apis/tests/api_dependencies.out b/dev-tools/ls-apis/tests/api_dependencies.out index 94197641c23..d48fe9fcfcf 100644 --- a/dev-tools/ls-apis/tests/api_dependencies.out +++ b/dev-tools/ls-apis/tests/api_dependencies.out @@ -46,6 +46,7 @@ Downstairs Controller (debugging only) (client: dsc-client) Management Gateway Service (client: gateway-client) consumed by: dpd (dendrite/dpd) via 1 path + consumed by: mgd (maghemite/mgd) via 1 path consumed by: omicron-nexus (omicron/nexus) via 4 paths consumed by: omicron-sled-agent (omicron/sled-agent) via 1 path consumed by: wicketd (omicron/wicketd) via 3 paths diff --git a/dev-tools/omdb/tests/successes.out b/dev-tools/omdb/tests/successes.out index 2738d6ff1fb..f915570374f 100644 --- a/dev-tools/omdb/tests/successes.out +++ b/dev-tools/omdb/tests/successes.out @@ -573,7 +573,7 @@ task: "bfd_manager" configured period: every s last completed activation: , triggered by started at (s ago) and ran for ms - last completion reported error: failed to resolve addresses for Dendrite services: proto error: no records found for Query { name: Name("_dendrite._tcp.control-plane.oxide.internal."), query_type: SRV, query_class: IN } + last completion reported error: failed to resolve addresses for Maghemite: proto error: no records found for Query { name: Name("_mgd._tcp.control-plane.oxide.internal."), query_type: SRV, query_class: IN } task: "blueprint_planner" configured period: every m @@ -1141,7 +1141,7 @@ task: "bfd_manager" configured period: every s last completed activation: , triggered by started at (s ago) and ran for ms - last completion reported error: failed to resolve addresses for Dendrite services: proto error: no records found for Query { name: Name("_dendrite._tcp.control-plane.oxide.internal."), query_type: SRV, query_class: IN } + last completion reported error: failed to resolve addresses for Maghemite: proto error: no records found for Query { name: Name("_mgd._tcp.control-plane.oxide.internal."), query_type: SRV, query_class: IN } task: "blueprint_planner" configured period: every m diff --git a/dev-tools/omicron-dev/src/main.rs b/dev-tools/omicron-dev/src/main.rs index 7ba618758b9..8e027c27afa 100644 --- a/dev-tools/omicron-dev/src/main.rs +++ b/dev-tools/omicron-dev/src/main.rs @@ -57,6 +57,9 @@ struct RunAllArgs { /// Override the nexus configuration file. #[clap(long, default_value = DEFAULT_NEXUS_CONFIG)] nexus_config: Utf8PathBuf, + /// Number of "racks" to launch + #[clap(long, default_value_t = 1)] + count: u8, } impl RunAllArgs { @@ -78,121 +81,166 @@ impl RunAllArgs { if_exists: dropshot::ConfigLoggingIfExists::Fail, }; - if let Some(p) = self.nexus_listen_port { - config - .deployment - .dropshot_external - .dropshot - .bind_address - .set_port(p); - } - - println!("omicron-dev: setting up all services ... "); - let cptestctx = nexus_test_utils::omicron_dev_setup_with_config::< - omicron_nexus::Server, - >(&mut config, 0, self.gateway_config.clone()) - .await - .context("error setting up services")?; - - println!("omicron-dev: Adding disks to first sled agent"); - - // This is how our integration tests are identifying that "disks exist" - // within the database. - // - // This inserts: - // - DEFAULT_ZPOOL_COUNT zpools, each of which contains: - // - A crucible dataset - // - A debug dataset - DiskTest::new(&cptestctx).await; - - println!("omicron-dev: services are running."); - - // Print out basic information about what was started. - // NOTE: The stdout strings here are not intended to be stable, but they - // are used by the test suite. - let addr = cptestctx.external_client.bind_address; - println!("omicron-dev: nexus external API: {:?}", addr); - println!( - "omicron-dev: nexus internal API: {:?}", - cptestctx.server.get_http_server_internal_address(), - ); - println!( - "omicron-dev: nexus lockstep API: {:?}", - cptestctx.server.get_http_server_lockstep_address(), - ); - println!( - "omicron-dev: cockroachdb pid: {}", - cptestctx.database.pid(), - ); - println!( - "omicron-dev: cockroachdb URL: {}", - cptestctx.database.pg_config() - ); - println!( - "omicron-dev: cockroachdb directory: {}", - cptestctx.database.temp_dir().display() - ); - println!( - "omicron-dev: clickhouse native addr: {}", - cptestctx.clickhouse.native_address(), - ); - println!( - "omicron-dev: clickhouse http addr: {}", - cptestctx.clickhouse.http_address(), - ); - println!( - "omicron-dev: internal DNS HTTP: http://{}", - cptestctx.internal_dns.dropshot_server.local_addr() - ); - println!( - "omicron-dev: internal DNS: {}", - cptestctx.internal_dns.dns_server.local_address() - ); - println!( - "omicron-dev: external DNS name: {}", - cptestctx.external_dns_zone_name, - ); - println!( - "omicron-dev: external DNS HTTP: http://{}", - cptestctx.external_dns.dropshot_server.local_addr() - ); - println!( - "omicron-dev: external DNS: {}", - cptestctx.external_dns.dns_server.local_address() - ); - println!( - "omicron-dev: e.g. `dig @{} -p {} {}.sys.{}`", - cptestctx.external_dns.dns_server.local_address().ip(), - cptestctx.external_dns.dns_server.local_address().port(), - cptestctx.silo_name, - cptestctx.external_dns_zone_name, - ); - for (location, gateway) in &cptestctx.gateway { + let mut contexts = vec![]; + + for n in 0..self.count { + if self.count > 1 { + config + .deployment + .dropshot_external + .dropshot + .bind_address + .set_ip("0.0.0.0".parse().unwrap()); + config + .deployment + .dropshot_external + .dropshot + .bind_address + .set_port(0); + + config.deployment.dropshot_internal.bind_address.set_port(0); + config.deployment.dropshot_lockstep.bind_address.set_port(0); + config.deployment.techport_external_server_port = 0; + } else { + if let Some(p) = self.nexus_listen_port { + config + .deployment + .dropshot_external + .dropshot + .bind_address + .set_port(p); + } + } + + println!("\nomicron-dev: setting up all services for rack {n}... "); + let cptestctx = + nexus_test_utils::omicron_dev_setup_with_config::< + omicron_nexus::Server, + >(&mut config, 1, self.gateway_config.clone()) + .await + .context("error setting up services")?; + + println!("omicron-dev: Adding disks to first sled agent"); + + // This is how our integration tests are identifying that "disks exist" + // within the database. + // + // This inserts: + // - DEFAULT_ZPOOL_COUNT zpools, each of which contains: + // - A crucible dataset + // - A debug dataset + DiskTest::new(&cptestctx).await; + + println!("omicron-dev: services are running."); + + // Print out basic information about what was started. + // NOTE: The stdout strings here are not intended to be stable, but they + // are used by the test suite. + let addr = cptestctx.external_client.bind_address; + println!("omicron-dev: nexus external API: {:?}", addr); + println!( + "omicron-dev: nexus internal API: {:?}", + cptestctx.server.get_http_server_internal_address(), + ); + println!( + "omicron-dev: nexus lockstep API: {:?}", + cptestctx.server.get_http_server_lockstep_address(), + ); + println!( + "omicron-dev: cockroachdb pid: {}", + cptestctx.database.pid(), + ); + println!( + "omicron-dev: cockroachdb URL: {}", + cptestctx.database.pg_config() + ); + println!( + "omicron-dev: cockroachdb directory: {}", + cptestctx.database.temp_dir().display() + ); println!( - "omicron-dev: management gateway: {} ({})", - gateway.client.baseurl(), - location, + "omicron-dev: clickhouse native addr: {}", + cptestctx.clickhouse.native_address(), ); + println!( + "omicron-dev: clickhouse http addr: {}", + cptestctx.clickhouse.http_address(), + ); + println!( + "omicron-dev: internal DNS HTTP: http://{}", + cptestctx.internal_dns.dropshot_server.local_addr() + ); + println!( + "omicron-dev: internal DNS: {}", + cptestctx.internal_dns.dns_server.local_address() + ); + println!( + "omicron-dev: external DNS name: {}", + cptestctx.external_dns_zone_name, + ); + println!( + "omicron-dev: external DNS HTTP: http://{}", + cptestctx.external_dns.dropshot_server.local_addr() + ); + println!( + "omicron-dev: external DNS: {}", + cptestctx.external_dns.dns_server.local_address() + ); + println!( + "omicron-dev: e.g. `dig @{} -p {} {}.sys.{}`", + cptestctx.external_dns.dns_server.local_address().ip(), + cptestctx.external_dns.dns_server.local_address().port(), + cptestctx.silo_name, + cptestctx.external_dns_zone_name, + ); + for (location, gateway) in &cptestctx.gateway { + println!( + "omicron-dev: management gateway: {} ({})", + gateway.client.baseurl(), + location, + ); + } + for (location, dendrite) in + cptestctx.dendrite.read().unwrap().iter() + { + println!( + "omicron-dev: dendrite: http://[::1]:{} ({})", + dendrite.port, location, + ); + } + for (location, mgd) in &cptestctx.mgd { + println!( + "omicron-dev: maghemite: http://[::1]:{} ({})", + mgd.port, location, + ); + } + println!( + "omicron-dev: silo name: {}", + cptestctx.silo_name, + ); + println!( + "omicron-dev: privileged user name: {}", + cptestctx.user_name.as_ref(), + ); + println!( + "omicron-dev: privileged password: {}", + cptestctx.password + ); + contexts.push(cptestctx); } - println!( - "omicron-dev: silo name: {}", - cptestctx.silo_name, - ); - println!( - "omicron-dev: privileged user name: {}", - cptestctx.user_name.as_ref(), - ); - println!("omicron-dev: privileged password: {}", cptestctx.password); // Wait for a signal. let caught_signal = signal_stream.next().await; assert_eq!(caught_signal.unwrap(), SIGINT); eprintln!( "omicron-dev: caught signal, shutting down and removing \ - temporary directory" + temporary directory" ); - cptestctx.teardown().await; + for context in contexts { + context.teardown().await; + } + Ok(()) } } diff --git a/internal-dns/types/src/names.rs b/internal-dns/types/src/names.rs index 323b2aea07f..fb150c646e1 100644 --- a/internal-dns/types/src/names.rs +++ b/internal-dns/types/src/names.rs @@ -76,7 +76,6 @@ pub enum ServiceName { Crucible(OmicronZoneUuid), BoundaryNtp, InternalNtp, - Maghemite, //TODO change to Dpd - maghemite has several services. Mgd, } @@ -120,7 +119,6 @@ impl ServiceName { ServiceName::Crucible(_) => "crucible", ServiceName::BoundaryNtp => "boundary-ntp", ServiceName::InternalNtp => "internal-ntp", - ServiceName::Maghemite => "maghemite", ServiceName::Mgd => "mgd", } } @@ -152,7 +150,6 @@ impl ServiceName { | ServiceName::CruciblePantry | ServiceName::BoundaryNtp | ServiceName::InternalNtp - | ServiceName::Maghemite | ServiceName::Mgd => { format!("_{}._tcp", self.service_kind()) } diff --git a/nexus/reconfigurator/planning/src/example.rs b/nexus/reconfigurator/planning/src/example.rs index efd690b2815..bcf48f2c1ed 100644 --- a/nexus/reconfigurator/planning/src/example.rs +++ b/nexus/reconfigurator/planning/src/example.rs @@ -1424,7 +1424,6 @@ mod tests { | ServiceName::Dendrite | ServiceName::Tfport | ServiceName::BoundaryNtp - | ServiceName::Maghemite | ServiceName::Mgd => { out.insert(service, Err(QueryError::NoRecordsFound)); } diff --git a/nexus/src/app/background/tasks/bfd.rs b/nexus/src/app/background/tasks/bfd.rs index 8662124e25a..8d3b1c3c4e8 100644 --- a/nexus/src/app/background/tasks/bfd.rs +++ b/nexus/src/app/background/tasks/bfd.rs @@ -5,12 +5,8 @@ //! Background task for managing switch bidirectional forwarding detection //! (BFD) sessions. -use crate::app::{ - background::tasks::networking::build_mgd_clients, - switch_zone_address_mappings, -}; - use crate::app::background::BackgroundTask; +use crate::app::mgd_clients; use futures::FutureExt; use futures::future::BoxFuture; use internal_dns_resolver::Resolver; @@ -118,21 +114,23 @@ impl BackgroundTask for BfdManager { let mut current: HashSet = HashSet::new(); - let mappings = match switch_zone_address_mappings(&self.resolver, log).await { - Ok(mappings) => mappings, - Err(e) => { - error!(log, "failed to resolve addresses for Dendrite services"; "error" => %e); - return json!({ - "error": - format!( - "failed to resolve addresses for Dendrite services: {:#}", - e - ) - }); - }, - }; - - let mgd_clients = build_mgd_clients(mappings, log, &self.resolver).await; + let mgd_clients = match mgd_clients(&self.resolver, log).await + { + Ok(mappings) => mappings, + Err(e) => { + error!( + log, + "failed to resolve addresses for Maghemite"; + "error" => %e); + return json!({ + "error": + format!( + "failed to resolve addresses for Maghemite: {:#}", + e + ) + }); + }, + }; for (location, c) in &mgd_clients { let client_current = match c.get_bfd_peers().await { diff --git a/nexus/src/app/background/tasks/networking.rs b/nexus/src/app/background/tasks/networking.rs index 7ff50a5798d..767a870fb1c 100644 --- a/nexus/src/app/background/tasks/networking.rs +++ b/nexus/src/app/background/tasks/networking.rs @@ -6,47 +6,9 @@ use db::datastore::SwitchPortSettingsCombinedResult; use dpd_client::types::{ LinkCreate, LinkId, LinkSettings, PortFec, PortSettings, PortSpeed, TxEq, }; -use internal_dns_types::names::ServiceName; use nexus_db_model::{SwitchLinkFec, SwitchLinkSpeed}; use nexus_db_queries::db; -use omicron_common::{address::MGD_PORT, api::external::SwitchLocation}; -use std::{ - collections::HashMap, - net::{Ipv6Addr, SocketAddrV6}, -}; - -pub(crate) async fn build_mgd_clients( - mappings: HashMap, - log: &slog::Logger, - resolver: &internal_dns_resolver::Resolver, -) -> HashMap { - let mut clients: Vec<(SwitchLocation, mg_admin_client::Client)> = vec![]; - for (location, addr) in &mappings { - let port = match resolver.lookup_all_socket_v6(ServiceName::Mgd).await { - Ok(addrs) => { - let port_map: HashMap = addrs - .into_iter() - .map(|sockaddr| (*sockaddr.ip(), sockaddr.port())) - .collect(); - - *port_map.get(&addr).unwrap_or(&MGD_PORT) - } - Err(e) => { - error!(log, "failed to addresses"; "error" => %e); - MGD_PORT - } - }; - - let socketaddr = - std::net::SocketAddr::V6(SocketAddrV6::new(*addr, port, 0, 0)); - let client = mg_admin_client::Client::new( - format!("http://{}", socketaddr).as_str(), - log.clone(), - ); - clients.push((*location, client)); - } - clients.into_iter().collect::>() -} +use std::collections::HashMap; pub(crate) fn api_to_dpd_port_settings( settings: &SwitchPortSettingsCombinedResult, diff --git a/nexus/src/app/background/tasks/sync_switch_configuration.rs b/nexus/src/app/background/tasks/sync_switch_configuration.rs index 9a91dd28a7c..a10c33d87dc 100644 --- a/nexus/src/app/background/tasks/sync_switch_configuration.rs +++ b/nexus/src/app/background/tasks/sync_switch_configuration.rs @@ -6,10 +6,8 @@ //! to relevant management daemons (dendrite, mgd, sled-agent, etc.) use crate::app::{ - background::tasks::networking::{ - api_to_dpd_port_settings, build_mgd_clients, - }, - dpd_clients, switch_zone_address_mappings, + background::tasks::networking::api_to_dpd_port_settings, dpd_clients, + mgd_clients, switch_zone_address_mappings, }; use oxnet::Ipv4Net; use slog::{Logger, o}; @@ -393,8 +391,19 @@ impl BackgroundTask for SwitchPortSettingsManager { }; // TODO https://github.com/oxidecomputer/omicron/issues/5201 - // build mgd clients - let mgd_clients = build_mgd_clients(mappings, &log, &self.resolver).await; + let mgd_clients = match + mgd_clients(&self.resolver, &log).await + { + Ok(mappings) => mappings, + Err(e) => { + error!( + log, + "failed to resolve addresses for Maghemite"; + "error" => %e); + continue; + }, + }; + let port_list = match self.switch_ports(opctx, &log).await { Ok(value) => value, diff --git a/nexus/src/app/bfd.rs b/nexus/src/app/bfd.rs index 1ae958c20d4..026c85a85cb 100644 --- a/nexus/src/app/bfd.rs +++ b/nexus/src/app/bfd.rs @@ -14,7 +14,7 @@ impl super::Nexus { switch: SwitchLocation, ) -> Result { let mg_client: mg_admin_client::Client = self - .mg_clients() + .mgd_clients() .await .map_err(|e| { Error::internal_error(&format!("failed to get mg clients: {e}")) diff --git a/nexus/src/app/bgp.rs b/nexus/src/app/bgp.rs index 60f23d958d4..94e5f10dba8 100644 --- a/nexus/src/app/bgp.rs +++ b/nexus/src/app/bgp.rs @@ -104,9 +104,9 @@ impl super::Nexus { ) -> ListResultVec { opctx.authorize(authz::Action::Read, &authz::FLEET).await?; let mut result = Vec::new(); - for (switch, client) in &self.mg_clients().await.map_err(|e| { + for (switch, client) in &self.mgd_clients().await.map_err(|e| { external::Error::internal_error(&format!( - "failed to get mg clients: {e}" + "failed to get mgd clients: {e}" )) })? { let router_info = match client.read_routers().await { @@ -161,9 +161,9 @@ impl super::Nexus { ) -> LookupResult { opctx.authorize(authz::Action::Read, &authz::FLEET).await?; let mut result = BgpExported::default(); - for (switch, client) in &self.mg_clients().await.map_err(|e| { + for (switch, client) in &self.mgd_clients().await.map_err(|e| { external::Error::internal_error(&format!( - "failed to get mg clients: {e}" + "failed to get mgd clients: {e}" )) })? { let router_info = match client.read_routers().await { @@ -231,9 +231,9 @@ impl super::Nexus { opctx.authorize(authz::Action::Read, &authz::FLEET).await?; let mut result = Vec::new(); - for (switch, client) in &self.mg_clients().await.map_err(|e| { + for (switch, client) in &self.mgd_clients().await.map_err(|e| { external::Error::internal_error(&format!( - "failed to get mg clients: {e}" + "failed to get mgd clients: {e}" )) })? { let history = match client @@ -273,9 +273,9 @@ impl super::Nexus { ) -> ListResultVec { opctx.authorize(authz::Action::Read, &authz::FLEET).await?; let mut result = Vec::new(); - for (switch, client) in &self.mg_clients().await.map_err(|e| { + for (switch, client) in &self.mgd_clients().await.map_err(|e| { external::Error::internal_error(&format!( - "failed to get mg clients: {e}" + "failed to get mgd clients: {e}" )) })? { let mut imported: Vec = Vec::new(); diff --git a/nexus/src/app/mod.rs b/nexus/src/app/mod.rs index f9a8057958c..90cc7a506a3 100644 --- a/nexus/src/app/mod.rs +++ b/nexus/src/app/mod.rs @@ -31,7 +31,6 @@ use nexus_mgs_updates::MgsUpdateDriver; use nexus_types::deployment::PendingMgsUpdates; use nexus_types::deployment::ReconfiguratorConfigParam; use nexus_types::fm; -use omicron_common::address::MGD_PORT; use omicron_common::address::MGS_PORT; use omicron_common::api::external::ByteCount; use omicron_common::api::external::Error; @@ -1123,25 +1122,11 @@ impl Nexus { lldpd_clients(resolver, rack_id, &self.log).await } - pub(crate) async fn mg_clients( + pub(crate) async fn mgd_clients( &self, ) -> Result, String> { let resolver = self.resolver(); - let mappings = - switch_zone_address_mappings(resolver, &self.log).await?; - let mut clients: Vec<(SwitchLocation, mg_admin_client::Client)> = - vec![]; - for (location, addr) in &mappings { - let port = MGD_PORT; - let socketaddr = - std::net::SocketAddr::V6(SocketAddrV6::new(*addr, port, 0, 0)); - let client = mg_admin_client::Client::new( - format!("http://{}", socketaddr).as_str(), - self.log.clone(), - ); - clients.push((*location, client)); - } - Ok(clients.into_iter().collect::>()) + mgd_clients(resolver, &self.log).await } pub(crate) fn demo_sagas( @@ -1269,6 +1254,74 @@ pub(crate) async fn dpd_clients( Ok(mappings) } +/// Returns a mapping of clients for the Maghemite daemons of reachable switch zones. +/// If we are unable to communicate with the switch zone and determine the mapping +/// of SwitchLocation -> Zone Underlay Address, we omit an entry for that client. +pub(crate) async fn mgd_clients( + resolver: &internal_dns_resolver::Resolver, + log: &slog::Logger, +) -> Result, String> { + let mgd_socketaddrs = match resolver + .lookup_all_socket_v6(ServiceName::Mgd) + .await + { + Ok(addrs) => addrs, + Err(e) => { + error!(log, "failed to resolve addresses for Maghemite services"; "error" => %e); + return Err(e.to_string()); + } + }; + + let clients: Vec<(SocketAddrV6, mg_admin_client::Client)> = mgd_socketaddrs + .iter() + .map(|socket_addr| { + let client = mg_admin_client::Client::new( + &format!("http://{socket_addr}"), + log.new(o!( + "component" => "MgdClient" + )), + ); + + (*socket_addr, client) + }) + .collect(); + + let mut mappings: HashMap = + HashMap::new(); + + for (addr, client) in clients { + let switch_slot = match client.switch_identifiers().await { + Ok(response) => response.slot, + Err(e) => { + error!( + log, + "failed to determine switch slot for maghemite"; + "error" => %e, + "addr" => %addr, + ); + continue; + } + }; + + let location = match switch_slot { + Some(0) => SwitchLocation::Switch0, + Some(1) => SwitchLocation::Switch1, + Some(v) => { + warn!(log, "unexpected value for switch slot: {v}"); + continue; + } + None => { + warn!(log, "maghemite has not learned switch slot from MGS"); + continue; + } + }; + + mappings.insert(location, client); + } + + Ok(mappings) +} + // We currently ignore the rack_id argument here, as the shared // switch_zone_address_mappings function doesn't allow filtering on the rack ID. // Since we only have a single rack, this is OK for now. diff --git a/nexus/test-utils/src/starter.rs b/nexus/test-utils/src/starter.rs index 412959d3d63..968a3c4a7df 100644 --- a/nexus/test-utils/src/starter.rs +++ b/nexus/test-utils/src/starter.rs @@ -444,9 +444,14 @@ impl<'a, N: NexusServer> ControlPlaneStarter<'a, N> { pub async fn start_mgd(&mut self, switch_location: SwitchLocation) { let log = &self.logctx.log; debug!(log, "Starting mgd for {switch_location}"); + let mgs = self.gateway.get(&switch_location).unwrap(); + let mgs_addr = + SocketAddrV6::new(Ipv6Addr::LOCALHOST, mgs.port, 0, 0).into(); // Set up an instance of mgd - let mgd = dev::maghemite::MgdInstance::start(0).await.unwrap(); + let mgd = dev::maghemite::MgdInstance::start(0, Some(mgs_addr)) + .await + .unwrap(); let port = mgd.port; self.mgd.insert(switch_location, mgd); let address = SocketAddrV6::new(Ipv6Addr::LOCALHOST, port, 0, 0); diff --git a/package-manifest.toml b/package-manifest.toml index cd09595db18..dc7307af99c 100644 --- a/package-manifest.toml +++ b/package-manifest.toml @@ -654,10 +654,10 @@ source.repo = "maghemite" # `tools/maghemite_openapi_version`. Failing to do so will cause a failure when # building `ddm-admin-client` (which will instruct you to update # `tools/maghemite_openapi_version`). -source.commit = "0df320d42b356e689a3c7a7600eec9b16770237a" +source.commit = "9e94d6b79560c2e4639cba432fb0ed600e9a3ff8" # The SHA256 digest is automatically posted to: # https://buildomat.eng.oxide.computer/public/file/oxidecomputer/maghemite/image//mg-ddm-gz.sha256.txt -source.sha256 = "0c6b756f317decd857b1641e300ed38c0f4cdfad4b77ee2322b2c8365fe95274" +source.sha256 = "4a8068799336e59dd1baf93e83c66c22b9fab7375950dbfddae55596eb9448bd" output.type = "tarball" [package.mg-ddm] @@ -670,10 +670,10 @@ source.repo = "maghemite" # `tools/maghemite_openapi_version`. Failing to do so will cause a failure when # building `ddm-admin-client` (which will instruct you to update # `tools/maghemite_openapi_version`). -source.commit = "0df320d42b356e689a3c7a7600eec9b16770237a" +source.commit = "9e94d6b79560c2e4639cba432fb0ed600e9a3ff8" # The SHA256 digest is automatically posted to: # https://buildomat.eng.oxide.computer/public/file/oxidecomputer/maghemite/image//mg-ddm.sha256.txt -source.sha256 = "5ef5389215ca3c1aaeef19a4abb0a01d85a6dabb0c2d6f02449883651e937fef" +source.sha256 = "8f01f601b462314d309b01d3f13672b3f24966c4a2266213506543dcc1fc9644" output.type = "zone" output.intermediate_only = true @@ -685,10 +685,10 @@ source.repo = "maghemite" # `tools/maghemite_openapi_version`. Failing to do so will cause a failure when # building `ddm-admin-client` (which will instruct you to update # `tools/maghemite_openapi_version`). -source.commit = "0df320d42b356e689a3c7a7600eec9b16770237a" +source.commit = "9e94d6b79560c2e4639cba432fb0ed600e9a3ff8" # The SHA256 digest is automatically posted to: # https://buildomat.eng.oxide.computer/public/file/oxidecomputer/maghemite/image//mgd.sha256.txt -source.sha256 = "e32f8202e69f7238efde2470f2f62e533fd78355a28e4ae99664fba3d91e8ae4" +source.sha256 = "b9b7eb4fc04b539c432a5cbc978b53f77ad6942a17137ac2912971e178a68917" output.type = "zone" output.intermediate_only = true diff --git a/test-utils/src/dev/maghemite.rs b/test-utils/src/dev/maghemite.rs index 4c2d85df3ee..343b67c08aa 100644 --- a/test-utils/src/dev/maghemite.rs +++ b/test-utils/src/dev/maghemite.rs @@ -4,6 +4,7 @@ //! Tools for managing Maghemite during development +use std::net::SocketAddr; use std::path::{Path, PathBuf}; use std::process::Stdio; use std::time::Duration; @@ -35,10 +36,13 @@ pub struct MgdInstance { } impl MgdInstance { - pub async fn start(mut port: u16) -> Result { + pub async fn start( + mut port: u16, + mgs_address: Option, + ) -> Result { let temp_dir = TempDir::new()?; - let args = vec![ + let mut args = vec![ "run".to_string(), "--admin-addr".into(), "::1".into(), @@ -53,6 +57,11 @@ impl MgdInstance { uuid::Uuid::new_v4().to_string(), ]; + if let Some(socket_addr) = mgs_address { + args.push("--mgs-addr".to_string()); + args.push(socket_addr.to_string()); + } + let child = tokio::process::Command::new("mgd") .args(&args) .stdin(Stdio::null()) diff --git a/tools/maghemite_ddm_openapi_version b/tools/maghemite_ddm_openapi_version index c066a90d021..c4bcd2c981e 100644 --- a/tools/maghemite_ddm_openapi_version +++ b/tools/maghemite_ddm_openapi_version @@ -1 +1 @@ -COMMIT="0df320d42b356e689a3c7a7600eec9b16770237a" +COMMIT="4a096d2fba90f46ce7c59318e0f4bb9b9d76ed20" diff --git a/tools/maghemite_mg_openapi_version b/tools/maghemite_mg_openapi_version index c066a90d021..bdd090ee327 100644 --- a/tools/maghemite_mg_openapi_version +++ b/tools/maghemite_mg_openapi_version @@ -1 +1 @@ -COMMIT="0df320d42b356e689a3c7a7600eec9b16770237a" +COMMIT="9e94d6b79560c2e4639cba432fb0ed600e9a3ff8" diff --git a/tools/maghemite_mgd_checksums b/tools/maghemite_mgd_checksums index 443275a8b92..47f1a2f3509 100644 --- a/tools/maghemite_mgd_checksums +++ b/tools/maghemite_mgd_checksums @@ -1,2 +1,2 @@ -CIDL_SHA256="e32f8202e69f7238efde2470f2f62e533fd78355a28e4ae99664fba3d91e8ae4" -MGD_LINUX_SHA256="4e7dd03fd7c8fa33b658583c3e95c1b814001e8078e415a4a0dd28e98c87439e" \ No newline at end of file +CIDL_SHA256="b9b7eb4fc04b539c432a5cbc978b53f77ad6942a17137ac2912971e178a68917" +MGD_LINUX_SHA256="0f2bbd3cb8dc061242f2a7735660fff483918c3fb928b0737c688420c78430ba"