summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Holzinger <pholzing@redhat.com>2024-07-25 16:06:17 +0200
committerPaul Holzinger <pholzing@redhat.com>2024-07-25 18:24:54 +0200
commit1bb0a2871a196ea03b231b2f446c9feb010501c9 (patch)
treeb69a1079a08dc704aee878b13c4e5213d1940795
parent5e635c8cf873d1a9513161680861c06f673a1a95 (diff)
server: split out main loop into new function
The goal here is to make sure the first startup can happen outside the loop so we can handle the error and exit to return a useful error on the first bind/config parsing to netavark which can then return it to podman. The bind problem doesn't work right now but this will be fixed in the next commit. Signed-off-by: Paul Holzinger <pholzing@redhat.com>
-rw-r--r--src/server/serve.rs156
1 files changed, 91 insertions, 65 deletions
diff --git a/src/server/serve.rs b/src/server/serve.rs
index c045c27..16d14d7 100644
--- a/src/server/serve.rs
+++ b/src/server/serve.rs
@@ -69,13 +69,22 @@ pub async fn serve(
port: u32,
filter_search_domain: &str,
ready: OwnedFd,
-) -> Result<(), std::io::Error> {
+) -> anyhow::Result<()> {
let mut signals = signal(SignalKind::hangup())?;
let no_proxy: bool = env::var("AARDVARK_NO_PROXY").is_ok();
- let (backend, mut listen_ip_v4, mut listen_ip_v6) =
- parse_configs(config_path, filter_search_domain)?;
+ let mut handles_v4 = HashMap::new();
+ let mut handles_v6 = HashMap::new();
+ read_config_and_spawn(
+ config_path,
+ port,
+ filter_search_domain,
+ &mut handles_v4,
+ &mut handles_v6,
+ no_proxy,
+ )
+ .await?;
// We are ready now, this is far from perfect we should at least wait for the first bind
// to work but this is not really possible with the current code flow and needs more changes.
daemonize()?;
@@ -83,74 +92,23 @@ pub async fn serve(
unistd::write(&ready, &msg)?;
drop(ready);
- // We store the `DNSBackend` in an `ArcSwap` so we can replace it when the configuration is
- // reloaded.
- static DNSBACKEND: OnceLock<ArcSwap<DNSBackend>> = OnceLock::new();
- let backend = DNSBACKEND.get_or_init(|| ArcSwap::from(Arc::new(backend)));
-
- let mut handles_v4 = HashMap::new();
- let mut handles_v6 = HashMap::new();
-
loop {
- debug!("Successfully parsed config");
- debug!("Listen v4 ip {:?}", listen_ip_v4);
- debug!("Listen v6 ip {:?}", listen_ip_v6);
-
- // kill server if listen_ip's are empty
- if listen_ip_v4.is_empty() && listen_ip_v6.is_empty() {
- info!("No configuration found stopping the sever");
-
- let path = Path::new(config_path).join(AARDVARK_PID_FILE);
- if let Err(err) = fs::remove_file(path) {
- error!("failed to remove the pid file: {}", &err);
- process::exit(1);
- }
-
- // Gracefully stop all server threads first.
- stop_threads(&mut handles_v4, None).await;
- stop_threads(&mut handles_v6, None).await;
-
- process::exit(0);
- }
-
- // get host nameservers
- let nameservers = match get_upstream_resolvers() {
- Ok(n) => n,
- Err(e) => {
- error!("failed to get upstream nameservers: {:#}", e);
- Vec::new()
- }
- };
-
- stop_and_start_threads(
+ // Block until we receive a SIGHUP.
+ signals.recv().await;
+ debug!("Received SIGHUP");
+ if let Err(e) = read_config_and_spawn(
+ config_path,
port,
- backend,
- listen_ip_v4,
+ filter_search_domain,
&mut handles_v4,
- no_proxy,
- &nameservers,
- )
- .await;
-
- stop_and_start_threads(
- port,
- backend,
- listen_ip_v6,
&mut handles_v6,
no_proxy,
- &nameservers,
)
- .await;
-
- // Block until we receive a SIGHUP.
- signals.recv().await;
- debug!("Received SIGHUP");
-
- let (new_backend, new_listen_ip_v4, new_listen_ip_v6) =
- parse_configs(config_path, filter_search_domain)?;
- backend.store(Arc::new(new_backend));
- listen_ip_v4 = new_listen_ip_v4;
- listen_ip_v6 = new_listen_ip_v6;
+ .await
+ {
+ // do not exit here, we just keep running even if something failed
+ error!("{e:#}");
+ };
}
}
@@ -269,6 +227,74 @@ async fn start_dns_server(
server.run().await.context("run dns server")
}
+async fn read_config_and_spawn(
+ config_path: &str,
+ port: u32,
+ filter_search_domain: &str,
+ handles_v4: &mut ThreadHandleMap<Ipv4Addr>,
+ handles_v6: &mut ThreadHandleMap<Ipv6Addr>,
+ no_proxy: bool,
+) -> anyhow::Result<()> {
+ let (conf, listen_ip_v4, listen_ip_v6) = parse_configs(config_path, filter_search_domain)?;
+
+ // We store the `DNSBackend` in an `ArcSwap` so we can replace it when the configuration is
+ // reloaded.
+ static DNSBACKEND: OnceLock<ArcSwap<DNSBackend>> = OnceLock::new();
+ let backend = match DNSBACKEND.get() {
+ Some(b) => {
+ b.store(Arc::new(conf));
+ b
+ }
+ None => DNSBACKEND.get_or_init(|| ArcSwap::from(Arc::new(conf))),
+ };
+
+ debug!("Successfully parsed config");
+ debug!("Listen v4 ip {:?}", listen_ip_v4);
+ debug!("Listen v6 ip {:?}", listen_ip_v6);
+
+ // kill server if listen_ip's are empty
+ if listen_ip_v4.is_empty() && listen_ip_v6.is_empty() {
+ info!("No configuration found stopping the sever");
+
+ let path = Path::new(config_path).join(AARDVARK_PID_FILE);
+ if let Err(err) = fs::remove_file(path) {
+ error!("failed to remove the pid file: {}", &err);
+ process::exit(1);
+ }
+
+ // Gracefully stop all server threads first.
+ stop_threads(handles_v4, None).await;
+ stop_threads(handles_v6, None).await;
+
+ process::exit(0);
+ }
+
+ // get host nameservers
+ let nameservers = get_upstream_resolvers().context("failed to get upstream nameservers")?;
+
+ stop_and_start_threads(
+ port,
+ backend,
+ listen_ip_v4,
+ handles_v4,
+ no_proxy,
+ &nameservers,
+ )
+ .await;
+
+ stop_and_start_threads(
+ port,
+ backend,
+ listen_ip_v6,
+ handles_v6,
+ no_proxy,
+ &nameservers,
+ )
+ .await;
+
+ Ok(())
+}
+
// creates new session and put /dev/null on the stdio streams
fn daemonize() -> Result<(), Error> {
// remove any controlling terminals