Skip to content

Commit

Permalink
RSS could provision external DNS zone (#2837)
Browse files Browse the repository at this point in the history
  • Loading branch information
davepacheco authored Apr 17, 2023
1 parent 4d442b4 commit 687eaf8
Show file tree
Hide file tree
Showing 19 changed files with 284 additions and 28 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion common/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub const DNS_REDUNDANCY: usize = 1;
pub const MAX_DNS_REDUNDANCY: usize = 5;

pub const DNS_PORT: u16 = 53;
pub const DNS_SERVER_PORT: u16 = 5353;
pub const DNS_HTTP_PORT: u16 = 5353;
pub const SLED_AGENT_PORT: u16 = 12345;

/// The port propolis-server listens on inside the propolis zone.
Expand Down
7 changes: 3 additions & 4 deletions dns-server/src/bin/dns-server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct Args {
http_address: SocketAddrV6,

#[clap(long, action)]
dns_address: SocketAddrV6,
dns_address: SocketAddr,
}

#[derive(Deserialize, Debug)]
Expand All @@ -50,9 +50,8 @@ async fn main() -> Result<(), anyhow::Error> {
.to_logger("dns-server")
.context("failed to create logger")?;

let dns_server_config = dns_server::dns_server::Config {
bind_address: SocketAddr::V6(args.dns_address),
};
let dns_server_config =
dns_server::dns_server::Config { bind_address: args.dns_address };

info!(&log, "config";
"config" => ?config,
Expand Down
3 changes: 2 additions & 1 deletion docs/how-to-run.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,8 @@ be set as a default route for the Nexus zone.
| Crucible Downstairs 2 | `[fd00:1122:3344:0101::8]:32345`
| Crucible Downstairs 3 | `[fd00:1122:3344:0101::9]:32345`
| Internal DNS Service | `[fd00:1122:3344:0001::1]:5353`
| Nexus: External API | `192.168.1.20:80`
| External DNS | `192.168.1.20:53`
| Nexus: External API | `192.168.1.21:80`
| Internet Gateway | None, but can be set in `smf/sled-agent/config-rss.toml`
|===================================================================================================

Expand Down
1 change: 1 addition & 0 deletions end-to-end-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ reqwest.workspace = true
russh = "0.37.1"
russh-keys = "0.37.1"
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
trust-dns-resolver.workspace = true
68 changes: 68 additions & 0 deletions end-to-end-tests/src/external_dns.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//! End-to-end test for external DNS
//!
//! External DNS is not yet configured with any DNS names. For now, this just
//! tests basic connectivity.
#![cfg(test)]

use anyhow::{anyhow, Context as _, Result};
use omicron_sled_agent::rack_setup::config::SetupServiceConfig;
use std::net::SocketAddr;
use std::path::Path;
use trust_dns_resolver::config::{
NameServerConfig, Protocol, ResolverConfig, ResolverOpts,
};
use trust_dns_resolver::error::ResolveErrorKind;
use trust_dns_resolver::TokioAsyncResolver;

#[tokio::test]
async fn dns_smoke() -> Result<()> {
let dns_addr = dns_addr();

let mut resolver_config = ResolverConfig::new();
resolver_config.add_name_server(NameServerConfig {
socket_addr: dns_addr,
protocol: Protocol::Udp,
tls_dns_name: None,
trust_nx_responses: false,
bind_addr: None,
});

let resolver =
TokioAsyncResolver::tokio(resolver_config, ResolverOpts::default())
.context("failed to create resolver")?;
match resolver.lookup_ip("oxide.test.").await {
Ok(_) => {
Err(anyhow!("unexpectedly resolved made-up external DNS name"))
}
Err(error) => match error.kind() {
ResolveErrorKind::NoRecordsFound { .. } => Ok(()),
_ => Err(anyhow!(
"unexpected error querying external DNS: {:?}",
error
)),
},
}
}

fn dns_addr() -> SocketAddr {
// If we can find config-rss.toml, grab the first address from the
// configured services IP pool. Otherwise, choose a lab default.
// (This is the same mechanism used for finding Nexus addresses.)
let rss_config_path = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../smf/sled-agent/non-gimlet/config-rss.toml");
if rss_config_path.exists() {
if let Ok(config) = SetupServiceConfig::from_file(rss_config_path) {
if let Some(addr) = config
.internal_services_ip_pool_ranges
.iter()
.flat_map(|range| range.iter())
.next()
{
return (addr, 53).into();
}
}
}

([192, 168, 1, 20], 53).into()
}
5 changes: 3 additions & 2 deletions end-to-end-tests/src/helpers/ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pub fn nexus_addr() -> SocketAddr {
return host;
}

// If we can find config-rss.toml, grab the first address from the
// If we can find config-rss.toml, grab the second address from the
// configured services IP pool.
let rss_config_path = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../smf/sled-agent/non-gimlet/config-rss.toml");
Expand All @@ -94,14 +94,15 @@ pub fn nexus_addr() -> SocketAddr {
.internal_services_ip_pool_ranges
.iter()
.flat_map(|range| range.iter())
.skip(1)
.next()
{
return (addr, 80).into();
}
}
}

([192, 168, 1, 20], 80).into()
([192, 168, 1, 21], 80).into()
}

fn get_base_url() -> String {
Expand Down
1 change: 1 addition & 0 deletions end-to-end-tests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod helpers;

mod external_dns;
mod instance_launch;
3 changes: 3 additions & 0 deletions internal-dns/src/names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub enum ServiceName {
Clickhouse,
Cockroach,
InternalDNS,
ExternalDNS,
Nexus,
Oximeter,
ManagementGatewayService,
Expand All @@ -34,6 +35,7 @@ impl ServiceName {
match self {
ServiceName::Clickhouse => "clickhouse",
ServiceName::Cockroach => "cockroach",
ServiceName::ExternalDNS => "external-dns",
ServiceName::InternalDNS => "nameservice",
ServiceName::Nexus => "nexus",
ServiceName::Oximeter => "oximeter",
Expand All @@ -57,6 +59,7 @@ impl ServiceName {
ServiceName::Clickhouse
| ServiceName::Cockroach
| ServiceName::InternalDNS
| ServiceName::ExternalDNS
| ServiceName::Nexus
| ServiceName::Oximeter
| ServiceName::ManagementGatewayService
Expand Down
6 changes: 6 additions & 0 deletions nexus/db-model/src/service_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ impl From<ServiceUsingCertificate> for ServiceKind {
impl From<internal_api::params::ServiceKind> for ServiceKind {
fn from(k: internal_api::params::ServiceKind) -> Self {
match k {
internal_api::params::ServiceKind::ExternalDNS => {
ServiceKind::ExternalDNS
}
internal_api::params::ServiceKind::ExternalDNSConfig => {
ServiceKind::ExternalDNSConfig
}
internal_api::params::ServiceKind::InternalDNS => {
ServiceKind::InternalDNS
}
Expand Down
4 changes: 4 additions & 0 deletions nexus/types/src/internal_api/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ pub struct DatasetPutRequest {
)]
#[serde(rename_all = "snake_case", tag = "type", content = "content")]
pub enum ServiceKind {
ExternalDNS,
ExternalDNSConfig,
InternalDNS,
InternalDNSConfig,
Nexus { external_address: IpAddr },
Expand All @@ -175,6 +177,8 @@ impl fmt::Display for ServiceKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ServiceKind::*;
let s = match self {
ExternalDNSConfig => "external_dns_config",
ExternalDNS => "external_dns",
InternalDNSConfig => "internal_dns_config",
InternalDNS => "internal_dns",
Nexus { .. } => "nexus",
Expand Down
28 changes: 28 additions & 0 deletions openapi/nexus-internal.json
Original file line number Diff line number Diff line change
Expand Up @@ -2258,6 +2258,34 @@
"ServiceKind": {
"description": "Describes the purpose of the service.",
"oneOf": [
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"external_d_n_s"
]
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"external_d_n_s_config"
]
}
},
"required": [
"type"
]
},
{
"type": "object",
"properties": {
Expand Down
27 changes: 25 additions & 2 deletions openapi/sled-agent.json
Original file line number Diff line number Diff line change
Expand Up @@ -1648,7 +1648,29 @@
"dns_address": {
"type": "string"
},
"server_address": {
"http_address": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"external_dns"
]
}
},
"required": [
"dns_address",
"http_address",
"type"
]
},
{
"type": "object",
"properties": {
"dns_address": {
"type": "string"
},
"http_address": {
"type": "string"
},
"type": {
Expand All @@ -1660,7 +1682,7 @@
},
"required": [
"dns_address",
"server_address",
"http_address",
"type"
]
},
Expand Down Expand Up @@ -2238,6 +2260,7 @@
"description": "The type of zone which may be requested from Sled Agent",
"type": "string",
"enum": [
"external_dns",
"internal_dns",
"nexus",
"oximeter",
Expand Down
21 changes: 18 additions & 3 deletions sled-agent/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,12 @@ pub enum ServiceType {
internal_ip: Ipv6Addr,
external_ip: IpAddr,
},
ExternalDns {
http_address: SocketAddrV6,
dns_address: SocketAddr,
},
InternalDns {
server_address: SocketAddrV6,
http_address: SocketAddrV6,
dns_address: SocketAddrV6,
},
Oximeter,
Expand Down Expand Up @@ -301,6 +305,7 @@ impl std::fmt::Display for ServiceType {
fn fmt(&self, f: &mut Formatter<'_>) -> FormatResult {
match self {
ServiceType::Nexus { .. } => write!(f, "nexus"),
ServiceType::ExternalDns { .. } => write!(f, "external_dns"),
ServiceType::InternalDns { .. } => write!(f, "internal_dns"),
ServiceType::Oximeter => write!(f, "oximeter"),
ServiceType::ManagementGatewayService => write!(f, "mgs"),
Expand Down Expand Up @@ -335,9 +340,15 @@ impl From<ServiceType> for sled_agent_client::types::ServiceType {
St::Nexus { internal_ip, external_ip } => {
AutoSt::Nexus { internal_ip, external_ip }
}
St::InternalDns { server_address, dns_address } => {
St::ExternalDns { http_address, dns_address } => {
AutoSt::ExternalDns {
http_address: http_address.to_string(),
dns_address: dns_address.to_string(),
}
}
St::InternalDns { http_address, dns_address } => {
AutoSt::InternalDns {
server_address: server_address.to_string(),
http_address: http_address.to_string(),
dns_address: dns_address.to_string(),
}
}
Expand Down Expand Up @@ -368,6 +379,8 @@ impl From<ServiceType> for sled_agent_client::types::ServiceType {
Clone, Debug, Deserialize, Serialize, JsonSchema, PartialEq, Eq, Hash,
)]
pub enum ZoneType {
#[serde(rename = "external_dns")]
ExternalDNS,
#[serde(rename = "internal_dns")]
InternalDNS,
#[serde(rename = "nexus")]
Expand All @@ -386,6 +399,7 @@ impl From<ZoneType> for sled_agent_client::types::ZoneType {
fn from(zt: ZoneType) -> Self {
match zt {
ZoneType::InternalDNS => Self::InternalDns,
ZoneType::ExternalDNS => Self::ExternalDns,
ZoneType::Nexus => Self::Nexus,
ZoneType::Oximeter => Self::Oximeter,
ZoneType::Switch => Self::Switch,
Expand All @@ -399,6 +413,7 @@ impl std::fmt::Display for ZoneType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use ZoneType::*;
let name = match self {
ExternalDNS => "external_dns",
InternalDNS => "internal_dns",
Nexus => "nexus",
Oximeter => "oximeter",
Expand Down
Loading

0 comments on commit 687eaf8

Please sign in to comment.