mirror of
https://github.com/kata-containers/kata-containers.git
synced 2026-04-10 14:02:59 +00:00
Compare commits
8 Commits
dependabot
...
burgerdev/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c97d373e2d | ||
|
|
72fb41d33b | ||
|
|
9e8069569e | ||
|
|
38382a59c4 | ||
|
|
2bac201364 | ||
|
|
10b24a19c8 | ||
|
|
f133b81579 | ||
|
|
d6546f2a56 |
@@ -139,7 +139,7 @@ async-trait = "0.1.48"
|
||||
capctl = "0.2.0"
|
||||
cfg-if = "1.0.0"
|
||||
cgroups = { package = "cgroups-rs", git = "https://github.com/kata-containers/cgroups-rs", rev = "v0.3.5" }
|
||||
clap = { version = "4.5.60", features = ["derive"] }
|
||||
clap = { version = "4.5.40", features = ["derive"] }
|
||||
const_format = "0.2.30"
|
||||
containerd-shim = { version = "0.10.0", features = ["async"] }
|
||||
containerd-shim-protos = { version = "0.10.0", features = ["async"] }
|
||||
|
||||
@@ -10,7 +10,7 @@ use std::sync::Arc;
|
||||
|
||||
use crate::storage::{common_storage_handler, new_device, StorageContext, StorageHandler};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use kata_types::device::{DRIVER_9P_TYPE, DRIVER_OVERLAYFS_TYPE, DRIVER_VIRTIOFS_TYPE};
|
||||
use kata_types::device::{DRIVER_OVERLAYFS_TYPE, DRIVER_VIRTIOFS_TYPE};
|
||||
use kata_types::mount::{StorageDevice, KATA_VOLUME_OVERLAYFS_CREATE_DIR};
|
||||
use protocols::agent::Storage;
|
||||
use tracing::instrument;
|
||||
@@ -69,27 +69,6 @@ impl StorageHandler for OverlayfsHandler {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Virtio9pHandler {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl StorageHandler for Virtio9pHandler {
|
||||
#[instrument]
|
||||
fn driver_types(&self) -> &[&str] {
|
||||
&[DRIVER_9P_TYPE]
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
async fn create_device(
|
||||
&self,
|
||||
storage: Storage,
|
||||
ctx: &mut StorageContext,
|
||||
) -> Result<Arc<dyn StorageDevice>> {
|
||||
let path = common_storage_handler(ctx.logger, &storage)?;
|
||||
new_device(path)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VirtioFsHandler {}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ use tracing::instrument;
|
||||
use self::bind_watcher_handler::BindWatcherHandler;
|
||||
use self::block_handler::{PmemHandler, ScsiHandler, VirtioBlkMmioHandler, VirtioBlkPciHandler};
|
||||
use self::ephemeral_handler::EphemeralHandler;
|
||||
use self::fs_handler::{OverlayfsHandler, Virtio9pHandler, VirtioFsHandler};
|
||||
use self::fs_handler::{OverlayfsHandler, VirtioFsHandler};
|
||||
use self::image_pull_handler::ImagePullHandler;
|
||||
use self::local_handler::LocalHandler;
|
||||
use crate::mount::{baremount, is_mounted, remove_mounts};
|
||||
@@ -134,7 +134,6 @@ lazy_static! {
|
||||
pub static ref STORAGE_HANDLERS: StorageHandlerManager<Arc<dyn StorageHandler>> = {
|
||||
let mut manager: StorageHandlerManager<Arc<dyn StorageHandler>> = StorageHandlerManager::new();
|
||||
let handlers: Vec<Arc<dyn StorageHandler>> = vec![
|
||||
Arc::new(Virtio9pHandler {}),
|
||||
Arc::new(VirtioBlkMmioHandler {}),
|
||||
Arc::new(VirtioBlkPciHandler {}),
|
||||
Arc::new(EphemeralHandler {}),
|
||||
|
||||
@@ -425,7 +425,7 @@ impl SandboxStorages {
|
||||
/// or updated file to a target mount point, or remove the removed file from the target mount point. All WatchableStorage
|
||||
/// target mount points are expected to reside within a single tmpfs, whose root is created by the BindWatcher.
|
||||
///
|
||||
/// This is a temporary workaround to handle config map updates until we get inotify on 9p/virtio-fs.
|
||||
/// This is a temporary workaround to handle config map updates until we get inotify on virtio-fs.
|
||||
/// More context on this:
|
||||
/// - https://github.com/kata-containers/runtime/issues/1505
|
||||
/// - https://github.com/kata-containers/kata-containers/issues/1879
|
||||
|
||||
@@ -257,7 +257,7 @@ pub const KATA_ANNO_CFG_HYPERVISOR_ENABLE_ROOTLESS_HYPERVISOR: &str =
|
||||
"io.katacontainers.config.hypervisor.rootless";
|
||||
|
||||
// Hypervisor Shared File System related annotations
|
||||
/// A sandbox annotation to specify the shared file system type, either inline-virtio-fs (default), virtio-9p, virtio-fs or virtio-fs-nydus.
|
||||
/// A sandbox annotation to specify the shared file system type, either virtio-fs(default), inline-virtio-fs, virtio-fs-nydus or none.
|
||||
pub const KATA_ANNO_CFG_HYPERVISOR_SHARED_FS: &str =
|
||||
"io.katacontainers.config.hypervisor.shared_fs";
|
||||
/// A sandbox annotations to specify virtio-fs vhost-user daemon path.
|
||||
@@ -272,8 +272,6 @@ pub const KATA_ANNO_CFG_HYPERVISOR_VIRTIO_FS_CACHE_SIZE: &str =
|
||||
/// A sandbox annotation to pass options to virtiofsd daemon.
|
||||
pub const KATA_ANNO_CFG_HYPERVISOR_VIRTIO_FS_EXTRA_ARGS: &str =
|
||||
"io.katacontainers.config.hypervisor.virtio_fs_extra_args";
|
||||
/// A sandbox annotation to specify as the msize for 9p shares.
|
||||
pub const KATA_ANNO_CFG_HYPERVISOR_MSIZE_9P: &str = "io.katacontainers.config.hypervisor.msize_9p";
|
||||
/// The initdata annotation passed in when CVM launchs
|
||||
pub const KATA_ANNO_CFG_HYPERVISOR_INIT_DATA: &str =
|
||||
"io.katacontainers.config.hypervisor.cc_init_data";
|
||||
@@ -975,14 +973,6 @@ impl Annotation {
|
||||
hv.shared_fs.virtio_fs_extra_args.push(arg.to_string());
|
||||
}
|
||||
}
|
||||
KATA_ANNO_CFG_HYPERVISOR_MSIZE_9P => match self.get_value::<u32>(key) {
|
||||
Ok(v) => {
|
||||
hv.shared_fs.msize_9p = v.unwrap_or_default();
|
||||
}
|
||||
Err(_e) => {
|
||||
return Err(u32_err);
|
||||
}
|
||||
},
|
||||
KATA_ANNO_CFG_HYPERVISOR_BLOCK_DEV_NUM_QUEUES => {
|
||||
match self.get_value::<usize>(key) {
|
||||
Ok(v) => {
|
||||
|
||||
@@ -47,9 +47,6 @@ pub const DEFAULT_BLOCK_DEVICE_QUEUE_SIZE: u32 = 128;
|
||||
pub const DEFAULT_SHARED_FS_TYPE: &str = "virtio-fs";
|
||||
pub const DEFAULT_VIRTIO_FS_CACHE_MODE: &str = "never";
|
||||
pub const DEFAULT_VIRTIO_FS_DAX_SIZE_MB: u32 = 1024;
|
||||
pub const DEFAULT_SHARED_9PFS_SIZE_MB: u32 = 8 * 1024;
|
||||
pub const MIN_SHARED_9PFS_SIZE_MB: u32 = 4 * 1024;
|
||||
pub const MAX_SHARED_9PFS_SIZE_MB: u32 = 8 * 1024 * 1024;
|
||||
|
||||
pub const DEFAULT_GUEST_HOOK_PATH: &str = "/opt/kata/hooks";
|
||||
pub const DEFAULT_GUEST_DNS_FILE: &str = "/etc/resolv.conf";
|
||||
|
||||
@@ -346,7 +346,7 @@ mod drop_in_directory_handling {
|
||||
|
||||
let dropin_override_data = r#"
|
||||
[hypervisor.qemu]
|
||||
shared_fs = "virtio-9p"
|
||||
shared_fs = "none"
|
||||
[runtime]
|
||||
vfio_mode="vfio"
|
||||
"#;
|
||||
@@ -372,7 +372,7 @@ mod drop_in_directory_handling {
|
||||
assert_eq!(config.hypervisor["qemu"].device_info.default_bridges, 4);
|
||||
assert_eq!(
|
||||
config.hypervisor["qemu"].shared_fs.shared_fs.as_deref(),
|
||||
Some("virtio-9p")
|
||||
Some("none")
|
||||
);
|
||||
assert!(config.runtime.debug);
|
||||
assert!(config.runtime.sandbox_cgroup_only);
|
||||
|
||||
@@ -68,7 +68,6 @@ mod firecracker;
|
||||
pub use self::firecracker::{FirecrackerConfig, HYPERVISOR_NAME_FIRECRACKER};
|
||||
|
||||
const NO_VIRTIO_FS: &str = "none";
|
||||
const VIRTIO_9P: &str = "virtio-9p";
|
||||
const VIRTIO_FS: &str = "virtio-fs";
|
||||
const VIRTIO_FS_INLINE: &str = "inline-virtio-fs";
|
||||
const MAX_BRIDGE_SIZE: u32 = 5;
|
||||
@@ -1419,12 +1418,13 @@ impl SecurityInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration information for shared filesystems, such as virtio-9p and virtio-fs.
|
||||
/// Configuration information for shared filesystems, such as virtio-fs-nydus and virtio-fs.
|
||||
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
|
||||
pub struct SharedFsInfo {
|
||||
/// Type of shared file system to use:
|
||||
/// - `virtio-fs` (default)
|
||||
/// - `virtio-9p`
|
||||
/// - `inline-virtio-fs`
|
||||
/// - `virtio-fs-nydus`
|
||||
/// - `none` (disables shared filesystem)
|
||||
pub shared_fs: Option<String>,
|
||||
|
||||
@@ -1466,18 +1466,13 @@ pub struct SharedFsInfo {
|
||||
/// Enables `virtio-fs` DAX (Direct Access) window if `true`.
|
||||
#[serde(default)]
|
||||
pub virtio_fs_is_dax: bool,
|
||||
|
||||
/// This is the `msize` used for 9p shares. It represents the number of bytes
|
||||
/// used for the 9p packet payload.
|
||||
#[serde(default)]
|
||||
pub msize_9p: u32,
|
||||
}
|
||||
|
||||
impl SharedFsInfo {
|
||||
/// Adjusts the shared filesystem configuration after loading from a configuration file.
|
||||
///
|
||||
/// Handles default values for `shared_fs` type, `virtio-fs` specific settings
|
||||
/// (daemon path, cache mode, DAX), and `virtio-9p` msize.
|
||||
/// (daemon path, cache mode, DAX) or `inline-virtio-fs` settings.
|
||||
pub fn adjust_config(&mut self) -> Result<()> {
|
||||
if self.shared_fs.as_deref() == Some(NO_VIRTIO_FS) {
|
||||
self.shared_fs = None;
|
||||
@@ -1490,11 +1485,6 @@ impl SharedFsInfo {
|
||||
match self.shared_fs.as_deref() {
|
||||
Some(VIRTIO_FS) => self.adjust_virtio_fs(false)?,
|
||||
Some(VIRTIO_FS_INLINE) => self.adjust_virtio_fs(true)?,
|
||||
Some(VIRTIO_9P) => {
|
||||
if self.msize_9p == 0 {
|
||||
self.msize_9p = default::DEFAULT_SHARED_9PFS_SIZE_MB;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@@ -1504,23 +1494,12 @@ impl SharedFsInfo {
|
||||
/// Validates the shared filesystem configuration.
|
||||
///
|
||||
/// Checks the validity of the selected `shared_fs` type and
|
||||
/// performs specific validations for `virtio-fs` and `virtio-9p` settings.
|
||||
/// performs specific validations for `virtio-fs` and `inline-virtio-fs` settings.
|
||||
pub fn validate(&self) -> Result<()> {
|
||||
match self.shared_fs.as_deref() {
|
||||
None => Ok(()),
|
||||
Some(VIRTIO_FS) => self.validate_virtio_fs(false),
|
||||
Some(VIRTIO_FS_INLINE) => self.validate_virtio_fs(true),
|
||||
Some(VIRTIO_9P) => {
|
||||
if self.msize_9p < default::MIN_SHARED_9PFS_SIZE_MB
|
||||
|| self.msize_9p > default::MAX_SHARED_9PFS_SIZE_MB
|
||||
{
|
||||
return Err(std::io::Error::other(format!(
|
||||
"Invalid 9p configuration msize 0x{:x}, min value is 0x{:x}, max value is 0x{:x}",
|
||||
self.msize_9p,default::MIN_SHARED_9PFS_SIZE_MB, default::MAX_SHARED_9PFS_SIZE_MB
|
||||
)));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Some(v) => Err(std::io::Error::other(format!("Invalid shared_fs type {v}"))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@ pub const DRIVER_VFIO_AP_TYPE: &str = "vfio-ap";
|
||||
/// DRIVER_VFIO_AP_COLD_TYPE is the device driver for vfio-ap coldplug.
|
||||
pub const DRIVER_VFIO_AP_COLD_TYPE: &str = "vfio-ap-cold";
|
||||
|
||||
/// DRIVER_9P_TYPE is the driver for 9pfs volume.
|
||||
pub const DRIVER_9P_TYPE: &str = "9p";
|
||||
/// DRIVER_EPHEMERAL_TYPE is the driver for ephemeral volume.
|
||||
pub const DRIVER_EPHEMERAL_TYPE: &str = "ephemeral";
|
||||
/// DRIVER_LOCAL_TYPE is the driver for local volume.
|
||||
|
||||
@@ -48,7 +48,6 @@ file_mem_backend = "/dev/shm"
|
||||
valid_file_mem_backends = ["/dev/shm","/dev/snd","./test_file_backend_mem_root"]
|
||||
pflashes = ["/proc/mounts"]
|
||||
enable_debug = true
|
||||
msize_9p = 16384
|
||||
disable_image_nvdimm = true
|
||||
hotplug_vfio_on_root_bus = true
|
||||
pcie_root_port = 2
|
||||
|
||||
@@ -47,7 +47,6 @@ file_mem_backend = "/dev/shm"
|
||||
valid_file_mem_backends = ["/dev/shm"]
|
||||
pflashes = ["/proc/mounts"]
|
||||
enable_debug = true
|
||||
msize_9p = 16384
|
||||
disable_image_nvdimm = true
|
||||
hotplug_vfio_on_root_bus = true
|
||||
pcie_root_port = 2
|
||||
|
||||
@@ -493,7 +493,7 @@ message SharedMount {
|
||||
// could have been defined through the Mount list of the OCI specification.
|
||||
message Storage {
|
||||
// Driver is used to define the way the storage is passed through the
|
||||
// virtual machine. It can be "9p", "blk", or something else, but for
|
||||
// virtual machine. It can be "blk", or something else, but for
|
||||
// all cases, this will define if some extra steps are required before
|
||||
// this storage gets mounted into the container.
|
||||
string driver = 1;
|
||||
@@ -509,7 +509,7 @@ message Storage {
|
||||
string source = 3;
|
||||
// Fstype represents the filesystem that needs to be used to mount the
|
||||
// storage inside the VM. For instance, it could be "xfs" for block
|
||||
// device, "9p" for shared filesystem, or "tmpfs" for shared /dev/shm.
|
||||
// device, or "tmpfs" for shared /dev/shm.
|
||||
string fstype = 4;
|
||||
// Options describes the additional options that might be needed to
|
||||
// mount properly the storage filesystem.
|
||||
|
||||
@@ -174,7 +174,6 @@ guest_hook_path = ""
|
||||
# Shared file system type:
|
||||
# - inline-virtio-fs (default)
|
||||
# - virtio-fs
|
||||
# - virtio-9p
|
||||
# - virtio-fs-nydus
|
||||
# "inline-virtio-fs" is the same as "virtio-fs", but it is running in the same process
|
||||
# of shim, does not need an external virtiofsd process.
|
||||
|
||||
@@ -179,7 +179,6 @@ disable_block_device_use = @DEFDISABLEBLOCK@
|
||||
|
||||
# Shared file system type:
|
||||
# - virtio-fs (default)
|
||||
# - virtio-9p
|
||||
# - virtio-fs-nydus
|
||||
# - none
|
||||
shared_fs = "@DEFSHAREDFS_QEMU_COCO_DEV_VIRTIOFS@"
|
||||
|
||||
@@ -163,7 +163,6 @@ disable_block_device_use = @DEFDISABLEBLOCK@
|
||||
|
||||
# Shared file system type:
|
||||
# - virtio-fs (default)
|
||||
# - virtio-9p
|
||||
# - virtio-fs-nydus
|
||||
# - none
|
||||
shared_fs = "@DEFSHAREDFS_QEMU_VIRTIOFS@"
|
||||
|
||||
@@ -162,7 +162,6 @@ disable_block_device_use = @DEFDISABLEBLOCK@
|
||||
|
||||
# Shared file system type:
|
||||
# - virtio-fs (default)
|
||||
# - virtio-9p
|
||||
# - virtio-fs-nydus
|
||||
# - none
|
||||
shared_fs = "@DEFSHAREDFS_QEMU_SEL_VIRTIOFS@"
|
||||
|
||||
18
src/tools/agent-ctl/Cargo.lock
generated
18
src/tools/agent-ctl/Cargo.lock
generated
@@ -731,9 +731,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.60"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a"
|
||||
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -741,9 +741,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.60"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876"
|
||||
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -753,9 +753,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.55"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5"
|
||||
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
@@ -765,9 +765,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "1.1.0"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
|
||||
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
|
||||
|
||||
[[package]]
|
||||
name = "cmac"
|
||||
@@ -5913,7 +5913,7 @@ version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||
dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -14,7 +14,7 @@ license = "Apache-2.0"
|
||||
protocols = { path = "../../libs/protocols", features = ["with-serde"] }
|
||||
oci-spec = { version = "0.8.1", features = ["runtime"] }
|
||||
|
||||
clap = { version = "4.5.60", features = ["derive", "cargo"] }
|
||||
clap = { version = "4.5.40", features = ["derive", "cargo"] }
|
||||
lazy_static = "1.4.0"
|
||||
anyhow = "1.0.31"
|
||||
hex = "0.4.2"
|
||||
|
||||
@@ -1519,6 +1519,8 @@ CopyFileRequest if {
|
||||
|
||||
check_directory_traversal(input.path)
|
||||
|
||||
allow_copy_file(input.path, input.file_mode, input.data)
|
||||
|
||||
some regex1 in policy_data.request_defaults.CopyFileRequest
|
||||
regex2 := replace(regex1, "$(sfprefix)", policy_data.common.sfprefix)
|
||||
regex3 := replace(regex2, "$(cpath)", policy_data.common.cpath)
|
||||
@@ -1530,6 +1532,39 @@ CopyFileRequest if {
|
||||
print("CopyFileRequest: true")
|
||||
}
|
||||
|
||||
allow_copy_file(path, mode, data) if {
|
||||
print("allow_copy_file regular")
|
||||
|
||||
bits.and(mode, 61440) == 32768
|
||||
|
||||
print("allow_copy_file regular: true")
|
||||
}
|
||||
|
||||
allow_copy_file(path, mode, data) if {
|
||||
print("allow_copy_file dir")
|
||||
|
||||
bits.and(mode, 61440) == 16384
|
||||
|
||||
print("allow_copy_file dir: true")
|
||||
}
|
||||
|
||||
allow_copy_file(path, mode, data) if {
|
||||
print("allow_copy_file symlink")
|
||||
|
||||
bits.and(mode, 61440) == 40960
|
||||
|
||||
target := concat("", [sprintf("%c", [c]) | c := data[_]])
|
||||
check_directory_traversal(target)
|
||||
not startswith(target, "/")
|
||||
|
||||
regex1 := concat("", [policy_data.common.sfprefix, ".*/.+"])
|
||||
regex2 := replace(regex1, "$(cpath)", policy_data.common.cpath)
|
||||
regex3 := replace(regex2, "$(bundle-id)", "[a-z0-9]{64}")
|
||||
regex.match(regex3, path)
|
||||
|
||||
print("allow_copy_file symlink: true")
|
||||
}
|
||||
|
||||
CreateSandboxRequest if {
|
||||
print("CreateSandboxRequest: input.guest_hook_path =", input.guest_hook_path)
|
||||
count(input.guest_hook_path) == 0
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"description": "copy initiated by k8s mount",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 33206,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-resolv.conf"
|
||||
}
|
||||
},
|
||||
@@ -12,6 +13,7 @@
|
||||
"description": "a dirname can have trailing dots",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 33206,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo../bar"
|
||||
}
|
||||
},
|
||||
@@ -20,6 +22,7 @@
|
||||
"description": "attempt to copy outside of container root",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 33206,
|
||||
"path": "/etc/ssl/cert.pem"
|
||||
}
|
||||
},
|
||||
@@ -28,6 +31,7 @@
|
||||
"description": "attempt to write into container root",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 33206,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc/rootfs/bin/sh"
|
||||
}
|
||||
},
|
||||
@@ -36,6 +40,7 @@
|
||||
"description": "attempt to write into container root - guest pull",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 33206,
|
||||
"path": "/run/kata-containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc/rootfs/bin/sh"
|
||||
}
|
||||
},
|
||||
@@ -44,6 +49,7 @@
|
||||
"description": "attempted directory traversal",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 33206,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/../../../../../etc/ssl/cert.pem"
|
||||
}
|
||||
},
|
||||
@@ -52,6 +58,7 @@
|
||||
"description": "attempted directory traversal - parent directory",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 16895,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/.."
|
||||
}
|
||||
},
|
||||
@@ -60,6 +67,7 @@
|
||||
"description": "relative path",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 33206,
|
||||
"path": "etc/ssl/cert.pem"
|
||||
}
|
||||
},
|
||||
@@ -68,7 +76,122 @@
|
||||
"description": "relative path - parent directory",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 16895,
|
||||
"path": ".."
|
||||
}
|
||||
},
|
||||
{
|
||||
"allowed": false,
|
||||
"description": "unsupported S_IFBLK",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 24576,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/bar"
|
||||
}
|
||||
},
|
||||
{
|
||||
"allowed": false,
|
||||
"description": "unsupported S_IFSOCK",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 49152,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/bar"
|
||||
}
|
||||
},
|
||||
{
|
||||
"allowed": false,
|
||||
"description": "unsupported S_IFIFO",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 4096,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/bar"
|
||||
}
|
||||
},
|
||||
{
|
||||
"allowed": false,
|
||||
"description": "unsupported mixed mode (S_IFREG | S_IFLNK)",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 73728,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/bar"
|
||||
}
|
||||
},
|
||||
{
|
||||
"allowed": false,
|
||||
"description": "unsupported no mode",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 511,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/bar"
|
||||
}
|
||||
},
|
||||
{
|
||||
"allowed": true,
|
||||
"description": "directory in top-level shared directory",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"file_mode": 16895,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"allowed": false,
|
||||
"description": "symlink in top-level shared directory",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"data": [97, 98, 99],
|
||||
"file_mode": 41471,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo"
|
||||
}
|
||||
},
|
||||
{
|
||||
"allowed": true,
|
||||
"description": "symlink beneath top-level shared directory",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"data": [97, 98, 99],
|
||||
"file_mode": 41471,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/lnk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"allowed": false,
|
||||
"description": "symlink pointing up - leading (../abc)",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"data": [46, 46, 47, 97, 98, 99],
|
||||
"file_mode": 41471,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/lnk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"allowed": false,
|
||||
"description": "symlink pointing up - middle (a/../../b)",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"data": [97, 47, 46, 46, 47, 46, 46, 47, 98],
|
||||
"file_mode": 41471,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/lnk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"allowed": false,
|
||||
"description": "symlink with 0-byte in target (a\\x00/b)",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"data": [97, 0, 47, 98],
|
||||
"file_mode": 41471,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/lnk"
|
||||
}
|
||||
},
|
||||
{
|
||||
"allowed": false,
|
||||
"description": "symlink with absolute target (/abc)",
|
||||
"kind": "CopyFileRequest",
|
||||
"request": {
|
||||
"data": [47, 97, 98, 99],
|
||||
"file_mode": 41471,
|
||||
"path": "/run/kata-containers/shared/containers/81e5f43bc8599c5661e66f959ac28df5bfb30da23c5d583f2dcc6f9e0c5186dc-ce23cfeb91e75aaa-foo/lnk"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -184,8 +184,6 @@ pub struct HypervisorInfo {
|
||||
#[serde(default)]
|
||||
virtio_fs_daemon: String,
|
||||
#[serde(default)]
|
||||
msize_9p: u32,
|
||||
#[serde(default)]
|
||||
memory_slots: u32,
|
||||
#[serde(default)]
|
||||
pcie_root_port: u32,
|
||||
@@ -417,7 +415,6 @@ pub fn get_hypervisor_info(
|
||||
.clone()
|
||||
.unwrap_or_else(|| String::from("none")),
|
||||
virtio_fs_daemon: hypervisor_config.shared_fs.virtio_fs_daemon.to_string(),
|
||||
msize_9p: hypervisor_config.shared_fs.msize_9p,
|
||||
memory_slots: hypervisor_config.memory_info.memory_slots,
|
||||
pcie_root_port: hypervisor_config.device_info.pcie_root_port,
|
||||
hotplug_vfio_on_rootbus: hypervisor_config.device_info.hotplug_vfio_on_root_bus,
|
||||
|
||||
24
src/tools/trace-forwarder/Cargo.lock
generated
24
src/tools/trace-forwarder/Cargo.lock
generated
@@ -19,9 +19,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "1.0.0"
|
||||
version = "0.6.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
|
||||
checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
@@ -34,15 +34,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.14"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
|
||||
checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "1.0.0"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
|
||||
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
@@ -172,18 +172,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.6.0"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"
|
||||
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.6.0"
|
||||
version = "4.5.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
|
||||
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -193,9 +193,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "1.1.0"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
|
||||
checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
|
||||
@@ -12,7 +12,7 @@ license = "Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
futures = "0.3.15"
|
||||
clap = { version = "4.6.0", features = ["cargo"] }
|
||||
clap = { version = "4.5.40", features = ["cargo"] }
|
||||
vsock = "0.2.3"
|
||||
nix = { version = "0.30.1", features = ["fs", "user"] }
|
||||
libc = "0.2.94"
|
||||
|
||||
@@ -440,14 +440,46 @@ fn add_kata_deploy_warning(config_file: &Path) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Atomically replace a file with a symlink.
|
||||
///
|
||||
/// Creates the symlink at a temporary path first, then renames it over the
|
||||
/// original so the original is preserved if symlink creation fails.
|
||||
fn atomic_symlink_replace(file_path: &str, symlink_target: &str) -> Result<()> {
|
||||
let temp_symlink = format!("{}.tmp-link", file_path);
|
||||
|
||||
// Clean up any stale temp symlink from a previous interrupted run
|
||||
if Path::new(&temp_symlink).exists() || Path::new(&temp_symlink).is_symlink() {
|
||||
let _ = fs::remove_file(&temp_symlink);
|
||||
}
|
||||
|
||||
std::os::unix::fs::symlink(symlink_target, &temp_symlink).with_context(|| {
|
||||
format!(
|
||||
"Failed to create temporary symlink {} -> {}",
|
||||
temp_symlink, symlink_target
|
||||
)
|
||||
})?;
|
||||
|
||||
fs::rename(&temp_symlink, file_path).map_err(|err| {
|
||||
let _ = fs::remove_file(&temp_symlink);
|
||||
anyhow::anyhow!(
|
||||
"Failed to atomically replace {} with symlink to {}: {}",
|
||||
file_path,
|
||||
symlink_target,
|
||||
err
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set up the runtime directory structure for a shim.
|
||||
/// Creates: {config_path}/runtimes/{shim}/
|
||||
/// {config_path}/runtimes/{shim}/config.d/
|
||||
/// {config_path}/runtimes/{shim}/configuration-{shim}.toml (copy of original)
|
||||
///
|
||||
/// Note: We copy the config file instead of symlinking because kata-containers'
|
||||
/// ResolvePath uses filepath.EvalSymlinks, which would resolve to the original
|
||||
/// location and look for config.d there instead of in our per-shim directory.
|
||||
/// After copying, the original config file is replaced with a symlink pointing
|
||||
/// to the runtime copy. This way the runtime's ResolvePath / EvalSymlinks resolves
|
||||
/// the symlink and finds config.d next to the real file in the per-shim directory.
|
||||
fn setup_runtime_directory(config: &Config, shim: &str) -> Result<()> {
|
||||
let original_config_dir = format!(
|
||||
"/host{}",
|
||||
@@ -466,9 +498,9 @@ fn setup_runtime_directory(config: &Config, shim: &str) -> Result<()> {
|
||||
fs::create_dir_all(&config_d_dir)
|
||||
.with_context(|| format!("Failed to create config.d directory: {}", config_d_dir))?;
|
||||
|
||||
// Copy the original config file to the runtime directory
|
||||
let original_config_file = format!("{}/configuration-{}.toml", original_config_dir, shim);
|
||||
let dest_config_file = format!("{}/configuration-{}.toml", runtime_config_dir, shim);
|
||||
let config_filename = format!("configuration-{}.toml", shim);
|
||||
let original_config_file = format!("{}/{}", original_config_dir, config_filename);
|
||||
let dest_config_file = format!("{}/{}", runtime_config_dir, config_filename);
|
||||
|
||||
// Only copy if original exists
|
||||
if Path::new(&original_config_file).exists() {
|
||||
@@ -481,7 +513,7 @@ fn setup_runtime_directory(config: &Config, shim: &str) -> Result<()> {
|
||||
})?;
|
||||
}
|
||||
|
||||
// Copy the base config file
|
||||
// Copy the base config file to the runtime directory
|
||||
fs::copy(&original_config_file, &dest_config_file).with_context(|| {
|
||||
format!(
|
||||
"Failed to copy config: {} -> {}",
|
||||
@@ -493,13 +525,37 @@ fn setup_runtime_directory(config: &Config, shim: &str) -> Result<()> {
|
||||
add_kata_deploy_warning(Path::new(&dest_config_file))?;
|
||||
|
||||
info!(" Copied base config: {}", dest_config_file);
|
||||
|
||||
let symlink_target = format!("runtimes/{}/{}", shim, config_filename);
|
||||
atomic_symlink_replace(&original_config_file, &symlink_target)?;
|
||||
|
||||
info!(
|
||||
" Symlinked original config: {} -> {}",
|
||||
original_config_file, symlink_target
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Remove the runtime directory for a shim during cleanup
|
||||
/// Remove the runtime directory for a shim during cleanup.
|
||||
/// Also removes the symlink at the original config location that was created
|
||||
/// by setup_runtime_directory.
|
||||
fn remove_runtime_directory(config: &Config, shim: &str) -> Result<()> {
|
||||
// Remove the symlink at the original config location (if present)
|
||||
let original_config_dir = format!(
|
||||
"/host{}",
|
||||
utils::get_kata_containers_original_config_path(shim, &config.dest_dir)
|
||||
);
|
||||
let original_config_file = format!("{}/configuration-{}.toml", original_config_dir, shim);
|
||||
let original_path = Path::new(&original_config_file);
|
||||
if original_path.is_symlink() {
|
||||
fs::remove_file(&original_config_file).with_context(|| {
|
||||
format!("Failed to remove config symlink: {}", original_config_file)
|
||||
})?;
|
||||
log::debug!("Removed config symlink: {}", original_config_file);
|
||||
}
|
||||
|
||||
let runtime_config_dir = format!(
|
||||
"/host{}",
|
||||
utils::get_kata_containers_config_path(shim, &config.dest_dir)
|
||||
@@ -528,7 +584,7 @@ fn remove_runtime_directory(config: &Config, shim: &str) -> Result<()> {
|
||||
}
|
||||
|
||||
async fn configure_shim_config(config: &Config, shim: &str, container_runtime: &str) -> Result<()> {
|
||||
// Set up the runtime directory structure with symlink to original config
|
||||
// Set up the runtime directory: copy config to per-shim dir and replace original with symlink
|
||||
setup_runtime_directory(config, shim)?;
|
||||
|
||||
let runtime_config_dir = format!(
|
||||
@@ -540,11 +596,11 @@ async fn configure_shim_config(config: &Config, shim: &str, container_runtime: &
|
||||
let kata_config_file =
|
||||
Path::new(&runtime_config_dir).join(format!("configuration-{shim}.toml"));
|
||||
|
||||
// The configuration file (symlink) should exist after setup_runtime_directory()
|
||||
// The configuration file should exist after setup_runtime_directory()
|
||||
if !kata_config_file.exists() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"Configuration file not found: {kata_config_file:?}. This file should have been \
|
||||
symlinked from the original config. Check that the shim '{}' has a valid configuration \
|
||||
copied from the original config. Check that the shim '{}' has a valid configuration \
|
||||
file in the artifacts.",
|
||||
shim
|
||||
));
|
||||
@@ -1144,4 +1200,141 @@ mod tests {
|
||||
"following the symlink should yield the real content"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_atomic_symlink_replace_creates_symlink() {
|
||||
let tmpdir = tempfile::tempdir().unwrap();
|
||||
|
||||
// Create the original file and the target it will point to
|
||||
let target_dir = tmpdir.path().join("runtimes/qemu");
|
||||
fs::create_dir_all(&target_dir).unwrap();
|
||||
let target_file = target_dir.join("configuration-qemu.toml");
|
||||
fs::write(&target_file, "real config content").unwrap();
|
||||
|
||||
let original = tmpdir.path().join("configuration-qemu.toml");
|
||||
fs::write(&original, "original content").unwrap();
|
||||
|
||||
let symlink_target = "runtimes/qemu/configuration-qemu.toml";
|
||||
atomic_symlink_replace(original.to_str().unwrap(), symlink_target).unwrap();
|
||||
|
||||
assert!(original.is_symlink(), "original should now be a symlink");
|
||||
assert_eq!(
|
||||
fs::read_link(&original).unwrap().to_str().unwrap(),
|
||||
symlink_target
|
||||
);
|
||||
assert_eq!(
|
||||
fs::read_to_string(&original).unwrap(),
|
||||
"real config content",
|
||||
"reading through the symlink should yield the target's content"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_atomic_symlink_replace_is_idempotent() {
|
||||
let tmpdir = tempfile::tempdir().unwrap();
|
||||
|
||||
let target_dir = tmpdir.path().join("runtimes/qemu");
|
||||
fs::create_dir_all(&target_dir).unwrap();
|
||||
let target_file = target_dir.join("configuration-qemu.toml");
|
||||
fs::write(&target_file, "config content").unwrap();
|
||||
|
||||
let original = tmpdir.path().join("configuration-qemu.toml");
|
||||
fs::write(&original, "original").unwrap();
|
||||
|
||||
let symlink_target = "runtimes/qemu/configuration-qemu.toml";
|
||||
|
||||
// First call
|
||||
atomic_symlink_replace(original.to_str().unwrap(), symlink_target).unwrap();
|
||||
assert!(original.is_symlink());
|
||||
|
||||
// Second call (e.g. re-install) should succeed and still be a valid symlink
|
||||
atomic_symlink_replace(original.to_str().unwrap(), symlink_target).unwrap();
|
||||
assert!(original.is_symlink());
|
||||
assert_eq!(
|
||||
fs::read_link(&original).unwrap().to_str().unwrap(),
|
||||
symlink_target
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_atomic_symlink_replace_cleans_stale_temp() {
|
||||
let tmpdir = tempfile::tempdir().unwrap();
|
||||
|
||||
let original = tmpdir.path().join("configuration-qemu.toml");
|
||||
fs::write(&original, "original").unwrap();
|
||||
|
||||
// Simulate a stale temp symlink from an interrupted previous run
|
||||
let stale_temp = tmpdir.path().join("configuration-qemu.toml.tmp-link");
|
||||
std::os::unix::fs::symlink("stale-target", &stale_temp).unwrap();
|
||||
assert!(stale_temp.is_symlink());
|
||||
|
||||
let target_dir = tmpdir.path().join("runtimes/qemu");
|
||||
fs::create_dir_all(&target_dir).unwrap();
|
||||
fs::write(target_dir.join("configuration-qemu.toml"), "content").unwrap();
|
||||
|
||||
let symlink_target = "runtimes/qemu/configuration-qemu.toml";
|
||||
atomic_symlink_replace(original.to_str().unwrap(), symlink_target).unwrap();
|
||||
|
||||
assert!(original.is_symlink());
|
||||
assert_eq!(
|
||||
fs::read_link(&original).unwrap().to_str().unwrap(),
|
||||
symlink_target
|
||||
);
|
||||
// Temp file should not linger
|
||||
assert!(!stale_temp.exists() && !stale_temp.is_symlink());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_setup_and_remove_runtime_directory_symlink() {
|
||||
let tmpdir = tempfile::tempdir().unwrap();
|
||||
|
||||
// Simulate the directory layout that setup_runtime_directory expects
|
||||
// (after copy_artifacts has run), using a Go shim as example.
|
||||
let defaults_dir = tmpdir.path().join("share/defaults/kata-containers");
|
||||
fs::create_dir_all(&defaults_dir).unwrap();
|
||||
|
||||
let config_filename = "configuration-qemu.toml";
|
||||
let original_config = defaults_dir.join(config_filename);
|
||||
fs::write(
|
||||
&original_config,
|
||||
"[hypervisor.qemu]\npath = \"/usr/bin/qemu\"",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Create the runtime directory and copy the config (mimics setup_runtime_directory)
|
||||
let runtime_dir = defaults_dir.join("runtimes/qemu");
|
||||
let config_d_dir = runtime_dir.join("config.d");
|
||||
fs::create_dir_all(&config_d_dir).unwrap();
|
||||
|
||||
let dest_config = runtime_dir.join(config_filename);
|
||||
fs::copy(&original_config, &dest_config).unwrap();
|
||||
|
||||
// Atomically replace the original with a symlink
|
||||
let symlink_target = format!("runtimes/qemu/{}", config_filename);
|
||||
atomic_symlink_replace(original_config.to_str().unwrap(), &symlink_target).unwrap();
|
||||
|
||||
// Verify: original is now a symlink
|
||||
assert!(original_config.is_symlink());
|
||||
assert_eq!(
|
||||
fs::read_link(&original_config).unwrap().to_str().unwrap(),
|
||||
symlink_target
|
||||
);
|
||||
|
||||
// Verify: reading through the symlink yields the real file content
|
||||
assert_eq!(
|
||||
fs::read_to_string(&original_config).unwrap(),
|
||||
fs::read_to_string(&dest_config).unwrap()
|
||||
);
|
||||
|
||||
// Verify: config.d is next to the real file (the resolved path)
|
||||
assert!(dest_config.parent().unwrap().join("config.d").is_dir());
|
||||
|
||||
// Simulate remove_runtime_directory: remove symlink then runtime dir
|
||||
assert!(original_config.is_symlink());
|
||||
fs::remove_file(&original_config).unwrap();
|
||||
assert!(!original_config.exists() && !original_config.is_symlink());
|
||||
|
||||
fs::remove_dir_all(&runtime_dir).unwrap();
|
||||
assert!(!runtime_dir.exists());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user