mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-25 15:02:45 +00:00
Merge pull request #704 from liubin/feature/689-setup-guest-DNS
agent: setup DNS for guest
This commit is contained in:
commit
6e328c0599
@ -3,8 +3,17 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use nix::mount::{self, MntFlags, MsFlags};
|
||||
use protocols::types::{Interface, Route};
|
||||
use slog::Logger;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
|
||||
use crate::Sandbox;
|
||||
|
||||
const KATA_GUEST_SANDBOX_DNS_FILE: &str = "/run/kata-containers/sandbox/resolv.conf";
|
||||
const GUEST_DNS_FILE: &str = "/etc/resolv.conf";
|
||||
|
||||
// Network fully describes a sandbox network with its interfaces, routes and dns
|
||||
// related information.
|
||||
@ -28,3 +37,116 @@ impl Network {
|
||||
self.dns.push(dns);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup_guest_dns(logger: Logger, dns_list: Vec<String>) -> Result<()> {
|
||||
do_setup_guest_dns(
|
||||
logger,
|
||||
dns_list,
|
||||
KATA_GUEST_SANDBOX_DNS_FILE,
|
||||
GUEST_DNS_FILE,
|
||||
)
|
||||
}
|
||||
|
||||
fn do_setup_guest_dns(logger: Logger, dns_list: Vec<String>, src: &str, dst: &str) -> Result<()> {
|
||||
let logger = logger.new(o!( "subsystem" => "network"));
|
||||
|
||||
if dns_list.len() == 0 {
|
||||
info!(
|
||||
logger,
|
||||
"Did not set sandbox DNS as DNS not received as part of request."
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let attr = fs::metadata(dst);
|
||||
if attr.is_err() {
|
||||
// not exists or other errors that we could not use it anymore.
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if attr.unwrap().is_dir() {
|
||||
return Err(anyhow!("{} is a directory", GUEST_DNS_FILE));
|
||||
}
|
||||
|
||||
// write DNS to file
|
||||
let content = dns_list
|
||||
.iter()
|
||||
.map(|x| x.trim())
|
||||
.collect::<Vec<&str>>()
|
||||
.join("\n");
|
||||
fs::write(src, &content)?;
|
||||
|
||||
// bind mount to /etc/resolv.conf
|
||||
mount::mount(Some(src), dst, Some("bind"), MsFlags::MS_BIND, None::<&str>)
|
||||
.map_err(|err| anyhow!(err).context("failed to setup guest DNS"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::skip_if_not_root;
|
||||
use nix::mount;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use tempfile::tempdir;
|
||||
|
||||
#[test]
|
||||
fn test_setup_guest_dns() {
|
||||
skip_if_not_root!();
|
||||
|
||||
let drain = slog::Discard;
|
||||
let logger = slog::Logger::root(drain, o!());
|
||||
|
||||
// create temp for /run/kata-containers/sandbox/resolv.conf
|
||||
let src_dir = tempdir().expect("failed to create tmpdir");
|
||||
let tmp = src_dir.path().join("resolv.conf");
|
||||
let src_filename = tmp.to_str().expect("failed to get resolv file filename");
|
||||
|
||||
// create temp for /etc/resolv.conf
|
||||
let dst_dir = tempdir().expect("failed to create tmpdir");
|
||||
let tmp = dst_dir.path().join("resolv.conf");
|
||||
let dst_filename = tmp.to_str().expect("failed to get resolv file filename");
|
||||
{
|
||||
let _file = File::create(dst_filename).unwrap();
|
||||
}
|
||||
|
||||
// test DNS
|
||||
let dns = vec![
|
||||
"nameserver 1.2.3.4".to_string(),
|
||||
"nameserver 5.6.7.8".to_string(),
|
||||
];
|
||||
|
||||
// write to /run/kata-containers/sandbox/resolv.conf
|
||||
let mut src_file =
|
||||
File::create(src_filename).expect(&format!("failed to create file {:?}", src_filename));
|
||||
let content = dns.join("\n");
|
||||
src_file
|
||||
.write_all(content.as_bytes())
|
||||
.expect(&format!("failed to write file contents"));
|
||||
|
||||
// call do_setup_guest_dns
|
||||
let result = do_setup_guest_dns(logger, dns.clone(), src_filename, dst_filename);
|
||||
|
||||
assert_eq!(
|
||||
true,
|
||||
result.is_ok(),
|
||||
"result should be ok, but {:?}",
|
||||
result
|
||||
);
|
||||
|
||||
// get content of /etc/resolv.conf
|
||||
let content = fs::read_to_string(dst_filename);
|
||||
assert_eq!(true, content.is_ok());
|
||||
let content = content.unwrap();
|
||||
|
||||
let expected_DNS: Vec<&str> = content.split('\n').collect();
|
||||
|
||||
// assert the data are the same as /run/kata-containers/sandbox/resolv.conf
|
||||
assert_eq!(dns, expected_DNS);
|
||||
|
||||
// umount /etc/resolv.conf
|
||||
let _ = mount::umount(dst_filename);
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ use crate::linux_abi::*;
|
||||
use crate::metrics::get_metrics;
|
||||
use crate::mount::{add_storages, remove_mounts, BareMount, STORAGEHANDLERLIST};
|
||||
use crate::namespace::{NSTYPEIPC, NSTYPEPID, NSTYPEUTS};
|
||||
use crate::network::setup_guest_dns;
|
||||
use crate::network::Network;
|
||||
use crate::random;
|
||||
use crate::sandbox::Sandbox;
|
||||
use crate::version::{AGENT_VERSION, API_VERSION};
|
||||
@ -1066,6 +1068,7 @@ impl protocols::agent_ttrpc::AgentService for agentService {
|
||||
) -> ttrpc::Result<Empty> {
|
||||
Ok(Empty::new())
|
||||
}
|
||||
|
||||
fn create_sandbox(
|
||||
&self,
|
||||
_ctx: &ttrpc::TtrpcContext,
|
||||
@ -1131,8 +1134,27 @@ impl protocols::agent_ttrpc::AgentService for agentService {
|
||||
}
|
||||
};
|
||||
|
||||
match setup_guest_dns(sl!(), req.dns.to_vec()) {
|
||||
Ok(dns_list) => {
|
||||
let sandbox = self.sandbox.clone();
|
||||
let mut s = sandbox.lock().unwrap();
|
||||
let _ = req
|
||||
.dns
|
||||
.to_vec()
|
||||
.iter()
|
||||
.map(|dns| s.network.set_dns(dns.to_string()));
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(ttrpc::Error::RpcStatus(ttrpc::get_status(
|
||||
ttrpc::Code::INTERNAL,
|
||||
e.to_string(),
|
||||
)))
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Empty::new())
|
||||
}
|
||||
|
||||
fn destroy_sandbox(
|
||||
&self,
|
||||
_ctx: &ttrpc::TtrpcContext,
|
||||
|
Loading…
Reference in New Issue
Block a user