Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .envrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ PATH_add out/cockroachdb/bin
PATH_add out/clickhouse
PATH_add out/dendrite-stub/bin
PATH_add out/mgd/root/opt/oxide/mgd/bin
PATH_add out/mg-ddm/root/opt/oxide/mg-ddm/bin

if [ "$OMICRON_USE_FLAKE" = 1 ] && nix flake show &> /dev/null
then
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ cfg-if = "1.0"
chrono = { version = "0.4", features = [ "serde" ] }
chrono-tz = { version = "0.10.4", features = [ "serde" ] }
ciborium = "0.2.2"
clap = { version = "4.5", features = ["cargo", "derive", "env", "wrap_help"] }
clap = { version = "4.6", features = ["cargo", "derive", "env", "wrap_help"] }
clickana = { path = "dev-tools/clickana" }
clickhouse-admin-api = { path = "clickhouse-admin/api" }
clickhouse-admin-keeper-client = { path = "clients/clickhouse-admin-keeper-client" }
Expand Down
4 changes: 1 addition & 3 deletions clients/ddm-admin-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub use ddm_admin_client::types;

use ddm_admin_client::Client as InnerClient;
use either::Either;
use omicron_common::address::DDMD_PORT;
use oxnet::Ipv6Net;
use sled_hardware_types::underlay::BOOTSTRAP_MASK;
use sled_hardware_types::underlay::BOOTSTRAP_PREFIX;
Expand All @@ -26,9 +27,6 @@ use thiserror::Error;

use crate::types::EnableStatsRequest;

// TODO-cleanup Is it okay to hardcode this port number here?
const DDMD_PORT: u16 = 8000;

#[derive(Debug, Error, SlogInlineError)]
pub enum DdmError {
#[error("Failed to construct an HTTP client:")]
Expand Down
82 changes: 82 additions & 0 deletions dev-tools/downloader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ enum Target {
/// Maghemite mgd binary
MaghemiteMgd,

/// Maghemite ddmd binary
MaghemiteDdmd,

/// SoftNPU, an admin program (scadm) and a pre-compiled P4 program.
Softnpu,

Expand Down Expand Up @@ -137,6 +140,7 @@ pub async fn run_cmd(args: DownloadArgs) -> Result<()> {
Target::Console => downloader.download_console().await,
Target::DendriteStub => downloader.download_dendrite_stub().await,
Target::MaghemiteMgd => downloader.download_maghemite_mgd().await,
Target::MaghemiteDdmd => downloader.download_maghemite_ddmd().await,
Target::Softnpu => downloader.download_softnpu().await,
Target::TransceiverControl => {
downloader.download_transceiver_control().await
Expand Down Expand Up @@ -946,6 +950,84 @@ impl Downloader<'_> {
Ok(())
}

async fn download_maghemite_ddmd(&self) -> Result<()> {
let download_dir = self.output_dir.join("downloads");
tokio::fs::create_dir_all(&download_dir).await?;

let checksums_path = self.versions_dir.join("maghemite_mgd_checksums");
let [mg_ddm_sha2, ddmd_linux_sha2] = get_values_from_file(
["MG_DDM_SHA256", "DDMD_LINUX_SHA256"],
&checksums_path,
)
.await?;
let commit_path =
self.versions_dir.join("maghemite_ddm_openapi_version");
let [commit] = get_values_from_file(["COMMIT"], &commit_path).await?;

let repo = "oxidecomputer/maghemite";
let base_url = format!("{BUILDOMAT_URL}/{repo}/image/{commit}");

let filename = "mg-ddm.tar.gz";
let tarball_path = download_dir.join(filename);
download_file_and_verify(
&self.log,
&tarball_path,
&format!("{base_url}/{filename}"),
ChecksumAlgorithm::Sha2,
&mg_ddm_sha2,
)
.await?;
unpack_tarball(&self.log, &tarball_path, &download_dir).await?;

let destination_dir = self.output_dir.join("mg-ddm");
let _ = tokio::fs::remove_dir_all(&destination_dir).await;
tokio::fs::create_dir_all(&destination_dir).await?;
copy_dir_all(
&download_dir.join("root"),
&destination_dir.join("root"),
)?;

let binary_dir = destination_dir.join("root/opt/oxide/mg-ddm/bin");

match os_name()? {
Os::Linux => {
let filename = "ddmd";
let path = download_dir.join(filename);
download_file_and_verify(
&self.log,
&path,
&format!(
"{BUILDOMAT_URL}/{repo}/linux/{commit}/{filename}"
),
ChecksumAlgorithm::Sha2,
&ddmd_linux_sha2,
)
.await?;
set_permissions(&path, 0o755).await?;
tokio::fs::copy(path, binary_dir.join(filename)).await?;
}
Os::Mac => {
info!(
self.log,
"Building maghemite ddmd from source for macOS"
);

let binaries = [("ddmd", &["--no-default-features"][..])];

let built_binaries = self
.build_from_git("maghemite", &commit, &binaries)
.await?;

let dest = binary_dir.join("ddmd");
tokio::fs::copy(&built_binaries[0], &dest).await?;
set_permissions(&dest, 0o755).await?;
}
Os::Illumos => (),
}

Ok(())
}

async fn download_softnpu(&self) -> Result<()> {
let destination_dir = self.output_dir.join("npuzone");
tokio::fs::create_dir_all(&destination_dir).await?;
Expand Down
1 change: 1 addition & 0 deletions env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export PATH="$OMICRON_WS/out/cockroachdb/bin:$PATH"
export PATH="$OMICRON_WS/out/clickhouse:$PATH"
export PATH="$OMICRON_WS/out/dendrite-stub/bin:$PATH"
export PATH="$OMICRON_WS/out/mgd/root/opt/oxide/mgd/bin:$PATH"
export PATH="$OMICRON_WS/out/mg-ddm/root/opt/oxide/mg-ddm/bin:$PATH"

# if xtrace was set previously, do not unset it
case $OLD_SHELL_OPTS in
Expand Down
98 changes: 93 additions & 5 deletions internal-dns/types/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,20 @@ pub struct DnsConfigBuilder {
service_instances_sleds: BTreeMap<ServiceName, BTreeMap<Sled, u16>>,
}

/// Ports for the per-switch services published in internal DNS by
/// [`DnsConfigBuilder::host_zone_switch`].
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct HostSwitchZonePorts {
/// Dendrite (`dpd`) admin API port.
pub dendrite: u16,
/// Management Gateway Service (`mgs`) port.
pub mgs: u16,
/// Maghemite `mgd` admin API port.
pub mgd: u16,
/// Maghemite `ddmd` admin API port.
pub ddm: u16,
}

/// Describes a host of type "sled" in the control plane DNS zone
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Sled(SledUuid);
Expand Down Expand Up @@ -396,18 +410,23 @@ impl DnsConfigBuilder {
&mut self,
sled_id: SledUuid,
switch_zone_ip: Ipv6Addr,
dendrite_port: u16,
mgs_port: u16,
mgd_port: u16,
ports: HostSwitchZonePorts,
) -> anyhow::Result<()> {
let HostSwitchZonePorts {
dendrite: dendrite_port,
mgs: mgs_port,
mgd: mgd_port,
ddm: ddm_port,
} = ports;
let zone = self.host_dendrite(sled_id, switch_zone_ip)?;
self.service_backend_zone(ServiceName::Dendrite, &zone, dendrite_port)?;
self.service_backend_zone(
ServiceName::ManagementGatewayService,
&zone,
mgs_port,
)?;
self.service_backend_zone(ServiceName::Mgd, &zone, mgd_port)
self.service_backend_zone(ServiceName::Mgd, &zone, mgd_port)?;
self.service_backend_zone(ServiceName::Ddm, &zone, ddm_port)
}

/// Higher-level shorthand for adding a Nexus zone with both its internal
Expand Down Expand Up @@ -731,7 +750,9 @@ impl DnsConfigBuilder {

#[cfg(test)]
mod test {
use super::{DnsConfigBuilder, Host, ServiceName};
use super::{
DnsConfigBuilder, DnsRecord, Host, HostSwitchZonePorts, ServiceName,
};
use crate::{config::Zone, names::DNS_ZONE};
use omicron_common::api::external::Generation;
use omicron_uuid_kinds::{OmicronZoneUuid, SledUuid};
Expand Down Expand Up @@ -779,6 +800,8 @@ mod test {
"_oximeter-reader._tcp",
);
assert_eq!(ServiceName::Dendrite.dns_name(), "_dendrite._tcp",);
assert_eq!(ServiceName::Mgd.dns_name(), "_mgd._tcp",);
assert_eq!(ServiceName::Ddm.dns_name(), "_ddm._tcp",);
assert_eq!(
ServiceName::CruciblePantry.dns_name(),
"_crucible-pantry._tcp",
Expand All @@ -796,6 +819,71 @@ mod test {
);
}

#[test]
fn host_zone_switch_publishes_all_services() {
let sled_uuid: SledUuid =
"001de000-51ed-4000-8000-000000000001".parse().unwrap();
let switch_zone_ip = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1);

// Use distinct port numbers so an arg-order swap in `host_zone_switch`
// surfaces as a port mismatch on the affected service.
let dendrite_port = 11;
let mgs_port = 13;
let mgd_port = 17;
let ddm_port = 19;

let mut builder = DnsConfigBuilder::new();
builder
.host_zone_switch(
sled_uuid,
switch_zone_ip,
HostSwitchZonePorts {
dendrite: dendrite_port,
mgs: mgs_port,
mgd: mgd_port,
ddm: ddm_port,
},
)
.unwrap();

let config = builder.build_full_config_for_initial_generation();

let mut by_name: BTreeMap<&str, &[DnsRecord]> = BTreeMap::new();
for zone in &config.zones {
for (name, records) in &zone.records {
by_name.insert(name.as_str(), records.as_slice());
}
}

for (expected_name, expected_port) in [
("_dendrite._tcp", dendrite_port),
("_mgs._tcp", mgs_port),
("_mgd._tcp", mgd_port),
("_ddm._tcp", ddm_port),
] {
let records = by_name.get(expected_name).unwrap_or_else(|| {
panic!(
"expected {expected_name} in published switch-zone \
services; got {by_name:?}"
)
});
let srv_port = records
.iter()
.find_map(|r| match r {
DnsRecord::Srv(s) => Some(s.port),
_ => None,
})
.unwrap_or_else(|| {
panic!("no SRV record for {expected_name}: {records:?}")
});

assert_eq!(
srv_port, expected_port,
"wrong SRV port for {expected_name}"
);
}
}

#[test]
fn display_hosts() {
let sled_uuid = SledUuid::nil();
Expand Down
5 changes: 4 additions & 1 deletion internal-dns/types/src/names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ pub enum ServiceName {
BoundaryNtp,
InternalNtp,
Mgd,
Ddm,
}

impl ServiceName {
Expand Down Expand Up @@ -116,6 +117,7 @@ impl ServiceName {
ServiceName::BoundaryNtp => "boundary-ntp",
ServiceName::InternalNtp => "internal-ntp",
ServiceName::Mgd => "mgd",
ServiceName::Ddm => "ddm",
}
}

Expand Down Expand Up @@ -144,7 +146,8 @@ impl ServiceName {
| ServiceName::CruciblePantry
| ServiceName::BoundaryNtp
| ServiceName::InternalNtp
| ServiceName::Mgd => {
| ServiceName::Mgd
| ServiceName::Ddm => {
format!("_{}._tcp", self.service_kind())
}
ServiceName::SledAgent(id) => {
Expand Down
2 changes: 1 addition & 1 deletion nexus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ jiff.workspace = true
lldpd_client.workspace = true
macaddr.workspace = true
maplit.workspace = true
mg-api-types.workspace = true
nexus-background-task-interface.workspace = true
# Not under "dev-dependencies"; these also need to be implemented for
# integration tests.
Expand Down Expand Up @@ -96,7 +97,6 @@ qorb.workspace = true
rand.workspace = true
range-requests.workspace = true
ref-cast.workspace = true
mg-api-types.workspace = true
regex.workspace = true
reqwest = { workspace = true, features = ["http2", "json"] }
ring.workspace = true
Expand Down
7 changes: 4 additions & 3 deletions nexus/reconfigurator/execution/src/dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -988,9 +988,8 @@ mod test {
// the previous pass (i.e., that corresponds to an Omicron zone).
//
// There are some ServiceNames missing here because they are not part of
// our representative config (e.g., ClickhouseKeeper) or they don't
// currently have DNS record at all (e.g., SledAgent, Maghemite, Mgd,
// Tfport).
// our representative config (e.g., ClickhouseKeeper) or because they
// do not currently have a DNS record at all (e.g., SledAgent).
let mut srv_kinds_expected = BTreeSet::from([
ServiceName::Clickhouse,
ServiceName::ClickhouseNative,
Expand All @@ -1001,6 +1000,8 @@ mod test {
ServiceName::NexusLockstep,
ServiceName::Oximeter,
ServiceName::Dendrite,
ServiceName::Mgd,
ServiceName::Ddm,
ServiceName::CruciblePantry,
ServiceName::BoundaryNtp,
ServiceName::InternalNtp,
Expand Down
2 changes: 2 additions & 0 deletions nexus/reconfigurator/execution/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,12 @@ pub fn overridables_for_test(
let dendrite_port =
cptestctx.dendrite.read().unwrap().get(&switch_slot).unwrap().port;
let mgd_port = cptestctx.mgd.get(&switch_slot).unwrap().port;
let ddm_port = cptestctx.ddm.get(&switch_slot).unwrap().port;
overrides.override_switch_zone_ip(sled_id, ip);
overrides.override_dendrite_port(sled_id, dendrite_port);
overrides.override_mgs_port(sled_id, mgs_port);
overrides.override_mgd_port(sled_id, mgd_port);
overrides.override_ddm_port(sled_id, ddm_port);
}
overrides
}
3 changes: 2 additions & 1 deletion nexus/reconfigurator/planning/src/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1854,7 +1854,8 @@ mod tests {
| ServiceName::RepoDepot
| ServiceName::ManagementGatewayService
| ServiceName::Dendrite
| ServiceName::Mgd => {
| ServiceName::Mgd
| ServiceName::Ddm => {
out.insert(service, Ok(()));
}
// InternalNtp is too large to fit in a single DNS packet and
Expand Down
4 changes: 4 additions & 0 deletions nexus/test-utils/src/nexus_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ pub struct ControlPlaneTestContext<N> {
/// Ports of stopped dendrite instances (for use by start_dendrite)
pub stopped_dendrite_ports: RwLock<HashMap<SwitchSlot, u16>>,
pub mgd: HashMap<SwitchSlot, dev::maghemite::MgdInstance>,
pub ddm: HashMap<SwitchSlot, dev::maghemite::DdmInstance>,
pub external_dns_zone_name: String,
pub external_dns: TransientDnsServer,
pub internal_dns: TransientDnsServer,
Expand Down Expand Up @@ -320,6 +321,9 @@ impl<N: NexusServer> ControlPlaneTestContext<N> {
for (_, mut mgd) in self.mgd {
mgd.cleanup().await.unwrap();
}
for (_, mut ddm) in self.ddm {
ddm.cleanup().await.unwrap();
}
self.logctx.cleanup_successful();
}
}
Expand Down
Loading
Loading