Merge pull request #5220 from liubin/fix/5184-rs-inotify

runtime-rs: support watchable mount
This commit is contained in:
Zhongtao Hu
2022-09-28 11:19:53 +08:00
committed by GitHub
8 changed files with 311 additions and 30 deletions

View File

@@ -25,7 +25,10 @@ const VIRTIO_FS: &str = "virtio-fs";
const INLINE_VIRTIO_FS: &str = "inline-virtio-fs";
const KATA_HOST_SHARED_DIR: &str = "/run/kata-containers/shared/sandboxes/";
/// share fs (for example virtio-fs) mount path in the guest
const KATA_GUEST_SHARE_DIR: &str = "/run/kata-containers/shared/containers/";
pub(crate) const DEFAULT_KATA_GUEST_SANDBOX_DIR: &str = "/run/kata-containers/sandbox/";
const PASSTHROUGH_FS_DIR: &str = "passthrough";
@@ -51,10 +54,12 @@ pub struct ShareFsVolumeConfig {
pub source: String,
pub target: String,
pub readonly: bool,
pub mount_options: Vec<String>,
}
pub struct ShareFsMountResult {
pub guest_path: String,
pub storages: Vec<agent::Storage>,
}
#[async_trait]

View File

@@ -42,12 +42,12 @@ pub(crate) fn share_to_guest(
Ok(do_get_guest_path(target, cid, is_volume))
}
pub(crate) fn get_host_ro_shared_path(id: &str) -> PathBuf {
Path::new(KATA_HOST_SHARED_DIR).join(id).join("ro")
pub(crate) fn get_host_ro_shared_path(sid: &str) -> PathBuf {
Path::new(KATA_HOST_SHARED_DIR).join(sid).join("ro")
}
pub(crate) fn get_host_rw_shared_path(id: &str) -> PathBuf {
Path::new(KATA_HOST_SHARED_DIR).join(id).join("rw")
pub(crate) fn get_host_rw_shared_path(sid: &str) -> PathBuf {
Path::new(KATA_HOST_SHARED_DIR).join(sid).join("rw")
}
fn do_get_guest_any_path(target: &str, cid: &str, is_volume: bool, is_virtiofs: bool) -> String {
@@ -66,11 +66,11 @@ fn do_get_guest_any_path(target: &str, cid: &str, is_volume: bool, is_virtiofs:
path.to_str().unwrap().to_string()
}
fn do_get_guest_path(target: &str, cid: &str, is_volume: bool) -> String {
pub(crate) fn do_get_guest_path(target: &str, cid: &str, is_volume: bool) -> String {
do_get_guest_any_path(target, cid, is_volume, false)
}
fn do_get_host_path(
pub(crate) fn do_get_host_path(
target: &str,
sid: &str,
cid: &str,

View File

@@ -4,10 +4,21 @@
// SPDX-License-Identifier: Apache-2.0
//
use anyhow::{Context, Result};
use agent::Storage;
use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use kata_types::k8s::is_watchable_mount;
use std::fs;
use std::os::unix::fs::PermissionsExt;
use std::path::Path;
use super::{utils, ShareFsMount, ShareFsMountResult, ShareFsRootfsConfig, ShareFsVolumeConfig};
const WATCHABLE_PATH_NAME: &str = "watchable";
const WATCHABLE_BIND_DEV_TYPE: &str = "watchable-bind";
use super::{
utils, ShareFsMount, ShareFsMountResult, ShareFsRootfsConfig, ShareFsVolumeConfig,
KATA_GUEST_SHARE_DIR, PASSTHROUGH_FS_DIR,
};
pub struct VirtiofsShareMount {
id: String,
@@ -32,11 +43,14 @@ impl ShareFsMount for VirtiofsShareMount {
false,
)
.context("share to guest")?;
Ok(ShareFsMountResult { guest_path })
Ok(ShareFsMountResult {
guest_path,
storages: vec![],
})
}
async fn share_volume(&self, config: ShareFsVolumeConfig) -> Result<ShareFsMountResult> {
let guest_path = utils::share_to_guest(
let mut guest_path = utils::share_to_guest(
&config.source,
&config.target,
&self.id,
@@ -45,6 +59,61 @@ impl ShareFsMount for VirtiofsShareMount {
true,
)
.context("share to guest")?;
Ok(ShareFsMountResult { guest_path })
// watchable mounts
if is_watchable_mount(&config.source) {
// Create path in shared directory for creating watchable mount:
let host_rw_path = utils::get_host_rw_shared_path(&self.id);
// "/run/kata-containers/shared/sandboxes/$sid/rw/passthrough/watchable"
let watchable_host_path = Path::new(&host_rw_path)
.join(PASSTHROUGH_FS_DIR)
.join(WATCHABLE_PATH_NAME);
fs::create_dir_all(&watchable_host_path).context(format!(
"unable to create watchable path: {:?}",
&watchable_host_path,
))?;
fs::set_permissions(watchable_host_path, fs::Permissions::from_mode(0o750))?;
// path: /run/kata-containers/shared/containers/passthrough/watchable/config-map-name
let file_name = Path::new(&guest_path)
.file_name()
.context("get file name from guest path")?;
let watchable_guest_mount = Path::new(KATA_GUEST_SHARE_DIR)
.join(PASSTHROUGH_FS_DIR)
.join(WATCHABLE_PATH_NAME)
.join(file_name)
.into_os_string()
.into_string()
.map_err(|e| anyhow!("failed to get watchable guest mount path {:?}", e))?;
let watchable_storage: Storage = Storage {
driver: String::from(WATCHABLE_BIND_DEV_TYPE),
driver_options: Vec::new(),
source: guest_path,
fs_type: String::from("bind"),
fs_group: None,
options: config.mount_options,
mount_point: watchable_guest_mount.clone(),
};
// Update the guest_path, in order to identify what will
// change in the OCI spec.
guest_path = watchable_guest_mount;
let storages = vec![watchable_storage];
return Ok(ShareFsMountResult {
guest_path,
storages,
});
}
Ok(ShareFsMountResult {
guest_path,
storages: vec![],
})
}
}

View File

@@ -19,6 +19,7 @@ use crate::share_fs::{ShareFs, ShareFsVolumeConfig};
// skip the volumes whose source had already set to guest share dir.
pub(crate) struct ShareFsVolume {
mounts: Vec<oci::Mount>,
storages: Vec<agent::Storage>,
}
impl ShareFsVolume {
@@ -30,7 +31,10 @@ impl ShareFsVolume {
let file_name = Path::new(&m.source).file_name().unwrap().to_str().unwrap();
let file_name = generate_mount_path(cid, file_name);
let mut volume = Self { mounts: vec![] };
let mut volume = Self {
mounts: vec![],
storages: vec![],
};
match share_fs {
None => {
let src = match std::fs::canonicalize(&m.source) {
@@ -61,10 +65,15 @@ impl ShareFsVolume {
source: m.source.clone(),
target: file_name,
readonly: false,
mount_options: m.options.clone(),
})
.await
.context("share fs volume")?;
// set storages for the volume
volume.storages = mount_result.storages;
// set mount for the volume
volume.mounts.push(oci::Mount {
destination: m.destination.clone(),
r#type: "bind".to_string(),
@@ -83,7 +92,7 @@ impl Volume for ShareFsVolume {
}
fn get_storage(&self) -> Result<Vec<agent::Storage>> {
Ok(vec![])
Ok(self.storages.clone())
}
fn cleanup(&self) -> Result<()> {