mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-08-22 09:49:35 +00:00
CCv0: Merge main into CCv0 branch
Merge remote-tracking branch 'upstream/main' into CCv0 Fixes: #4090 Signed-off-by: Megan Wright <megan.wright@ibm.com>
This commit is contained in:
commit
a36e9ba87f
@ -46,7 +46,7 @@ The following link shows the latest list of limitations:
|
|||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
If you would like to work on resolving a limitation, please refer to the
|
If you would like to work on resolving a limitation, please refer to the
|
||||||
[contributors guide](https://github.com/kata-containers/community/blob/master/CONTRIBUTING.md).
|
[contributors guide](https://github.com/kata-containers/community/blob/main/CONTRIBUTING.md).
|
||||||
If you wish to raise an issue for a new limitation, either
|
If you wish to raise an issue for a new limitation, either
|
||||||
[raise an issue directly on the runtime](https://github.com/kata-containers/kata-containers/issues/new)
|
[raise an issue directly on the runtime](https://github.com/kata-containers/kata-containers/issues/new)
|
||||||
or see the
|
or see the
|
||||||
|
@ -14,10 +14,6 @@ PROJECT_COMPONENT = kata-agent
|
|||||||
|
|
||||||
TARGET = $(PROJECT_COMPONENT)
|
TARGET = $(PROJECT_COMPONENT)
|
||||||
|
|
||||||
SOURCES := \
|
|
||||||
$(shell find . 2>&1 | grep -E '.*\.rs$$') \
|
|
||||||
Cargo.toml
|
|
||||||
|
|
||||||
VERSION_FILE := ./VERSION
|
VERSION_FILE := ./VERSION
|
||||||
VERSION := $(shell grep -v ^\# $(VERSION_FILE))
|
VERSION := $(shell grep -v ^\# $(VERSION_FILE))
|
||||||
COMMIT_NO := $(shell git rev-parse HEAD 2>/dev/null || true)
|
COMMIT_NO := $(shell git rev-parse HEAD 2>/dev/null || true)
|
||||||
@ -38,7 +34,7 @@ ifeq ($(SECCOMP),yes)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(EXTRA_RUSTFEATURES),)
|
ifneq ($(EXTRA_RUSTFEATURES),)
|
||||||
override EXTRA_RUSTFEATURES := --features $(EXTRA_RUSTFEATURES)
|
override EXTRA_RUSTFEATURES := --features "$(EXTRA_RUSTFEATURES)"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include ../../utils.mk
|
include ../../utils.mk
|
||||||
@ -108,14 +104,14 @@ $(TARGET): $(GENERATED_CODE) logging-crate-tests $(TARGET_PATH)
|
|||||||
logging-crate-tests:
|
logging-crate-tests:
|
||||||
make -C $(CWD)/../libs/logging
|
make -C $(CWD)/../libs/logging
|
||||||
|
|
||||||
$(TARGET_PATH): $(SOURCES) | show-summary
|
$(TARGET_PATH): show-summary
|
||||||
@RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings" cargo build --target $(TRIPLE) --$(BUILD_TYPE) $(EXTRA_RUSTFEATURES)
|
@RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings" cargo build --target $(TRIPLE) --$(BUILD_TYPE) $(EXTRA_RUSTFEATURES)
|
||||||
|
|
||||||
$(GENERATED_FILES): %: %.in
|
$(GENERATED_FILES): %: %.in
|
||||||
@sed $(foreach r,$(GENERATED_REPLACEMENTS),-e 's|@$r@|$($r)|g') "$<" > "$@"
|
@sed $(foreach r,$(GENERATED_REPLACEMENTS),-e 's|@$r@|$($r)|g') "$<" > "$@"
|
||||||
|
|
||||||
##TARGET optimize: optimized build
|
##TARGET optimize: optimized build
|
||||||
optimize: $(SOURCES) | show-summary show-header
|
optimize: show-summary show-header
|
||||||
@RUSTFLAGS="-C link-arg=-s $(EXTRA_RUSTFLAGS) --deny warnings" cargo build --target $(TRIPLE) --$(BUILD_TYPE) $(EXTRA_RUSTFEATURES)
|
@RUSTFLAGS="-C link-arg=-s $(EXTRA_RUSTFLAGS) --deny warnings" cargo build --target $(TRIPLE) --$(BUILD_TYPE) $(EXTRA_RUSTFEATURES)
|
||||||
|
|
||||||
##TARGET install: install agent
|
##TARGET install: install agent
|
||||||
|
@ -593,9 +593,9 @@ fn get_cpuacct_stats(cg: &cgroups::Cgroup) -> SingularPtrField<CpuUsage> {
|
|||||||
|
|
||||||
let h = lines_to_map(&cpuacct.stat);
|
let h = lines_to_map(&cpuacct.stat);
|
||||||
let usage_in_usermode =
|
let usage_in_usermode =
|
||||||
(((*h.get("user").unwrap() * NANO_PER_SECOND) as f64) / *CLOCK_TICKS) as u64;
|
(((*h.get("user").unwrap_or(&0) * NANO_PER_SECOND) as f64) / *CLOCK_TICKS) as u64;
|
||||||
let usage_in_kernelmode =
|
let usage_in_kernelmode =
|
||||||
(((*h.get("system").unwrap() * NANO_PER_SECOND) as f64) / *CLOCK_TICKS) as u64;
|
(((*h.get("system").unwrap_or(&0) * NANO_PER_SECOND) as f64) / *CLOCK_TICKS) as u64;
|
||||||
|
|
||||||
let total_usage = cpuacct.usage;
|
let total_usage = cpuacct.usage;
|
||||||
|
|
||||||
@ -626,9 +626,9 @@ fn get_cpuacct_stats(cg: &cgroups::Cgroup) -> SingularPtrField<CpuUsage> {
|
|||||||
let cpu_controller: &CpuController = get_controller_or_return_singular_none!(cg);
|
let cpu_controller: &CpuController = get_controller_or_return_singular_none!(cg);
|
||||||
let stat = cpu_controller.cpu().stat;
|
let stat = cpu_controller.cpu().stat;
|
||||||
let h = lines_to_map(&stat);
|
let h = lines_to_map(&stat);
|
||||||
let usage_in_usermode = *h.get("user_usec").unwrap();
|
let usage_in_usermode = *h.get("user_usec").unwrap_or(&0);
|
||||||
let usage_in_kernelmode = *h.get("system_usec").unwrap();
|
let usage_in_kernelmode = *h.get("system_usec").unwrap_or(&0);
|
||||||
let total_usage = *h.get("usage_usec").unwrap();
|
let total_usage = *h.get("usage_usec").unwrap_or(&0);
|
||||||
let percpu_usage = vec![];
|
let percpu_usage = vec![];
|
||||||
|
|
||||||
SingularPtrField::some(CpuUsage {
|
SingularPtrField::some(CpuUsage {
|
||||||
|
@ -518,6 +518,7 @@ pub fn grpc_to_oci(grpc: &grpc::Spec) -> oci::Spec {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use super::*;
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! skip_if_not_root {
|
macro_rules! skip_if_not_root {
|
||||||
() => {
|
() => {
|
||||||
@ -527,4 +528,162 @@ mod tests {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_process_grpc_to_oci() {
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct TestData {
|
||||||
|
grpcproc: grpc::Process,
|
||||||
|
result: oci::Process,
|
||||||
|
}
|
||||||
|
|
||||||
|
let tests = &[
|
||||||
|
TestData {
|
||||||
|
// All fields specified
|
||||||
|
grpcproc: grpc::Process {
|
||||||
|
Terminal: true,
|
||||||
|
ConsoleSize: protobuf::SingularPtrField::<grpc::Box>::some(grpc::Box {
|
||||||
|
Height: 123,
|
||||||
|
Width: 456,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
User: protobuf::SingularPtrField::<grpc::User>::some(grpc::User {
|
||||||
|
UID: 1234,
|
||||||
|
GID: 5678,
|
||||||
|
AdditionalGids: Vec::from([910, 1112]),
|
||||||
|
Username: String::from("username"),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
Args: protobuf::RepeatedField::from(Vec::from([
|
||||||
|
String::from("arg1"),
|
||||||
|
String::from("arg2"),
|
||||||
|
])),
|
||||||
|
Env: protobuf::RepeatedField::from(Vec::from([String::from("env")])),
|
||||||
|
Cwd: String::from("cwd"),
|
||||||
|
Capabilities: protobuf::SingularPtrField::some(grpc::LinuxCapabilities {
|
||||||
|
Bounding: protobuf::RepeatedField::from(Vec::from([String::from("bnd")])),
|
||||||
|
Effective: protobuf::RepeatedField::from(Vec::from([String::from("eff")])),
|
||||||
|
Inheritable: protobuf::RepeatedField::from(Vec::from([String::from(
|
||||||
|
"inher",
|
||||||
|
)])),
|
||||||
|
Permitted: protobuf::RepeatedField::from(Vec::from([String::from("perm")])),
|
||||||
|
Ambient: protobuf::RepeatedField::from(Vec::from([String::from("amb")])),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
Rlimits: protobuf::RepeatedField::from(Vec::from([
|
||||||
|
grpc::POSIXRlimit {
|
||||||
|
Type: String::from("r#type"),
|
||||||
|
Hard: 123,
|
||||||
|
Soft: 456,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
grpc::POSIXRlimit {
|
||||||
|
Type: String::from("r#type2"),
|
||||||
|
Hard: 789,
|
||||||
|
Soft: 1011,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
])),
|
||||||
|
NoNewPrivileges: true,
|
||||||
|
ApparmorProfile: String::from("apparmor profile"),
|
||||||
|
OOMScoreAdj: 123456,
|
||||||
|
SelinuxLabel: String::from("Selinux Label"),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
result: oci::Process {
|
||||||
|
terminal: true,
|
||||||
|
console_size: Some(oci::Box {
|
||||||
|
height: 123,
|
||||||
|
width: 456,
|
||||||
|
}),
|
||||||
|
user: oci::User {
|
||||||
|
uid: 1234,
|
||||||
|
gid: 5678,
|
||||||
|
additional_gids: Vec::from([910, 1112]),
|
||||||
|
username: String::from("username"),
|
||||||
|
},
|
||||||
|
args: Vec::from([String::from("arg1"), String::from("arg2")]),
|
||||||
|
env: Vec::from([String::from("env")]),
|
||||||
|
cwd: String::from("cwd"),
|
||||||
|
capabilities: Some(oci::LinuxCapabilities {
|
||||||
|
bounding: Vec::from([String::from("bnd")]),
|
||||||
|
effective: Vec::from([String::from("eff")]),
|
||||||
|
inheritable: Vec::from([String::from("inher")]),
|
||||||
|
permitted: Vec::from([String::from("perm")]),
|
||||||
|
ambient: Vec::from([String::from("amb")]),
|
||||||
|
}),
|
||||||
|
rlimits: Vec::from([
|
||||||
|
oci::PosixRlimit {
|
||||||
|
r#type: String::from("r#type"),
|
||||||
|
hard: 123,
|
||||||
|
soft: 456,
|
||||||
|
},
|
||||||
|
oci::PosixRlimit {
|
||||||
|
r#type: String::from("r#type2"),
|
||||||
|
hard: 789,
|
||||||
|
soft: 1011,
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
no_new_privileges: true,
|
||||||
|
apparmor_profile: String::from("apparmor profile"),
|
||||||
|
oom_score_adj: Some(123456),
|
||||||
|
selinux_label: String::from("Selinux Label"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
// None ConsoleSize
|
||||||
|
grpcproc: grpc::Process {
|
||||||
|
ConsoleSize: protobuf::SingularPtrField::<grpc::Box>::none(),
|
||||||
|
OOMScoreAdj: 0,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
result: oci::Process {
|
||||||
|
console_size: None,
|
||||||
|
oom_score_adj: Some(0),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
// None User
|
||||||
|
grpcproc: grpc::Process {
|
||||||
|
User: protobuf::SingularPtrField::<grpc::User>::none(),
|
||||||
|
OOMScoreAdj: 0,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
result: oci::Process {
|
||||||
|
user: oci::User {
|
||||||
|
uid: 0,
|
||||||
|
gid: 0,
|
||||||
|
additional_gids: vec![],
|
||||||
|
username: String::from(""),
|
||||||
|
},
|
||||||
|
oom_score_adj: Some(0),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
// None Capabilities
|
||||||
|
grpcproc: grpc::Process {
|
||||||
|
Capabilities: protobuf::SingularPtrField::none(),
|
||||||
|
OOMScoreAdj: 0,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
result: oci::Process {
|
||||||
|
capabilities: None,
|
||||||
|
oom_score_adj: Some(0),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (i, d) in tests.iter().enumerate() {
|
||||||
|
let msg = format!("test[{}]: {:?}", i, d);
|
||||||
|
|
||||||
|
let result = process_grpc_to_oci(&d.grpcproc);
|
||||||
|
|
||||||
|
let msg = format!("{}, result: {:?}", msg, result);
|
||||||
|
|
||||||
|
assert_eq!(d.result, result, "{}", msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1497,6 +1497,130 @@ mod tests {
|
|||||||
assert!(testfile.is_file());
|
assert!(testfile.is_file());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mount_storage() {
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct TestData<'a> {
|
||||||
|
test_user: TestUserType,
|
||||||
|
storage: Storage,
|
||||||
|
error_contains: &'a str,
|
||||||
|
|
||||||
|
make_source_dir: bool,
|
||||||
|
make_mount_dir: bool,
|
||||||
|
deny_mount_permission: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TestData<'_> {
|
||||||
|
fn default() -> Self {
|
||||||
|
TestData {
|
||||||
|
test_user: TestUserType::Any,
|
||||||
|
storage: Storage {
|
||||||
|
mount_point: "mnt".to_string(),
|
||||||
|
source: "src".to_string(),
|
||||||
|
fstype: "tmpfs".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
make_source_dir: true,
|
||||||
|
make_mount_dir: false,
|
||||||
|
deny_mount_permission: false,
|
||||||
|
error_contains: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let tests = &[
|
||||||
|
TestData {
|
||||||
|
test_user: TestUserType::NonRootOnly,
|
||||||
|
error_contains: "EPERM: Operation not permitted",
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
test_user: TestUserType::RootOnly,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
storage: Storage {
|
||||||
|
mount_point: "mnt".to_string(),
|
||||||
|
source: "src".to_string(),
|
||||||
|
fstype: "bind".to_string(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
make_source_dir: false,
|
||||||
|
make_mount_dir: true,
|
||||||
|
error_contains: "Could not create mountpoint",
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
test_user: TestUserType::NonRootOnly,
|
||||||
|
deny_mount_permission: true,
|
||||||
|
error_contains: "Could not create mountpoint",
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (i, d) in tests.iter().enumerate() {
|
||||||
|
let msg = format!("test[{}]: {:?}", i, d);
|
||||||
|
if d.test_user == TestUserType::RootOnly {
|
||||||
|
skip_loop_if_not_root!(msg);
|
||||||
|
} else if d.test_user == TestUserType::NonRootOnly {
|
||||||
|
skip_loop_if_root!(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
let drain = slog::Discard;
|
||||||
|
let logger = slog::Logger::root(drain, o!());
|
||||||
|
|
||||||
|
let tempdir = tempdir().unwrap();
|
||||||
|
|
||||||
|
let source = tempdir.path().join(&d.storage.source);
|
||||||
|
let mount_point = tempdir.path().join(&d.storage.mount_point);
|
||||||
|
|
||||||
|
let storage = Storage {
|
||||||
|
source: source.to_str().unwrap().to_string(),
|
||||||
|
mount_point: mount_point.to_str().unwrap().to_string(),
|
||||||
|
..d.storage.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
if d.make_source_dir {
|
||||||
|
fs::create_dir_all(&storage.source).unwrap();
|
||||||
|
}
|
||||||
|
if d.make_mount_dir {
|
||||||
|
fs::create_dir_all(&storage.mount_point).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.deny_mount_permission {
|
||||||
|
fs::set_permissions(
|
||||||
|
mount_point.parent().unwrap(),
|
||||||
|
fs::Permissions::from_mode(0o000),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = mount_storage(&logger, &storage);
|
||||||
|
|
||||||
|
// restore permissions so tempdir can be cleaned up
|
||||||
|
if d.deny_mount_permission {
|
||||||
|
fs::set_permissions(
|
||||||
|
mount_point.parent().unwrap(),
|
||||||
|
fs::Permissions::from_mode(0o755),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.is_ok() {
|
||||||
|
nix::mount::umount(&mount_point).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let msg = format!("{}: result: {:?}", msg, result);
|
||||||
|
if d.error_contains.is_empty() {
|
||||||
|
assert!(result.is_ok(), "{}", msg);
|
||||||
|
} else {
|
||||||
|
assert!(result.is_err(), "{}", msg);
|
||||||
|
let error_msg = format!("{}", result.unwrap_err());
|
||||||
|
assert!(error_msg.contains(d.error_contains), "{}", msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_get_pagesize_and_size_from_option() {
|
fn test_get_pagesize_and_size_from_option() {
|
||||||
let expected_pagesize = 2048;
|
let expected_pagesize = 2048;
|
||||||
@ -1552,4 +1676,55 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_mount_flags_and_options() {
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct TestData<'a> {
|
||||||
|
options_vec: Vec<&'a str>,
|
||||||
|
result: (MsFlags, &'a str),
|
||||||
|
}
|
||||||
|
|
||||||
|
let tests = &[
|
||||||
|
TestData {
|
||||||
|
options_vec: vec![],
|
||||||
|
result: (MsFlags::empty(), ""),
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
options_vec: vec!["ro"],
|
||||||
|
result: (MsFlags::MS_RDONLY, ""),
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
options_vec: vec!["rw"],
|
||||||
|
result: (MsFlags::empty(), ""),
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
options_vec: vec!["ro", "rw"],
|
||||||
|
result: (MsFlags::empty(), ""),
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
options_vec: vec!["ro", "nodev"],
|
||||||
|
result: (MsFlags::MS_RDONLY | MsFlags::MS_NODEV, ""),
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
options_vec: vec!["option1", "nodev", "option2"],
|
||||||
|
result: (MsFlags::MS_NODEV, "option1,option2"),
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
options_vec: vec!["rbind", "", "ro"],
|
||||||
|
result: (MsFlags::MS_BIND | MsFlags::MS_REC | MsFlags::MS_RDONLY, ""),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (i, d) in tests.iter().enumerate() {
|
||||||
|
let msg = format!("test[{}]: {:?}", i, d);
|
||||||
|
|
||||||
|
let result = parse_mount_flags_and_options(d.options_vec.clone());
|
||||||
|
|
||||||
|
let msg = format!("{}: result: {:?}", msg, result);
|
||||||
|
|
||||||
|
let expected_result = (d.result.0, d.result.1.to_owned());
|
||||||
|
assert_eq!(expected_result, result, "{}", msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,6 +88,7 @@ const MODPROBE_PATH: &str = "/sbin/modprobe";
|
|||||||
const ANNO_K8S_IMAGE_NAME: &str = "io.kubernetes.cri.image-name";
|
const ANNO_K8S_IMAGE_NAME: &str = "io.kubernetes.cri.image-name";
|
||||||
const CONFIG_JSON: &str = "config.json";
|
const CONFIG_JSON: &str = "config.json";
|
||||||
|
|
||||||
|
const ERR_CANNOT_GET_WRITER: &str = "Cannot get writer";
|
||||||
const ERR_INVALID_BLOCK_SIZE: &str = "Invalid block size";
|
const ERR_INVALID_BLOCK_SIZE: &str = "Invalid block size";
|
||||||
|
|
||||||
// Convenience macro to obtain the scope logger
|
// Convenience macro to obtain the scope logger
|
||||||
@ -596,7 +597,7 @@ impl AgentService {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let writer = writer.ok_or_else(|| anyhow!("cannot get writer"))?;
|
let writer = writer.ok_or_else(|| anyhow!(ERR_CANNOT_GET_WRITER))?;
|
||||||
writer.lock().await.write_all(req.data.as_slice()).await?;
|
writer.lock().await.write_all(req.data.as_slice()).await?;
|
||||||
|
|
||||||
let mut resp = WriteStreamResponse::new();
|
let mut resp = WriteStreamResponse::new();
|
||||||
@ -1961,7 +1962,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::protocols::agent_ttrpc::AgentService as _;
|
use crate::protocols::agent_ttrpc::AgentService as _;
|
||||||
use oci::{Hook, Hooks};
|
use oci::{Hook, Hooks};
|
||||||
use tempfile::tempdir;
|
use tempfile::{tempdir, TempDir};
|
||||||
use ttrpc::{r#async::TtrpcContext, MessageHeader};
|
use ttrpc::{r#async::TtrpcContext, MessageHeader};
|
||||||
|
|
||||||
// Parameters:
|
// Parameters:
|
||||||
@ -1999,6 +2000,44 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_dummy_opts() -> CreateOpts {
|
||||||
|
let root = Root {
|
||||||
|
path: String::from("/"),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let spec = Spec {
|
||||||
|
linux: Some(oci::Linux::default()),
|
||||||
|
root: Some(root),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
CreateOpts {
|
||||||
|
cgroup_name: "".to_string(),
|
||||||
|
use_systemd_cgroup: false,
|
||||||
|
no_pivot_root: false,
|
||||||
|
no_new_keyring: false,
|
||||||
|
spec: Some(spec),
|
||||||
|
rootless_euid: false,
|
||||||
|
rootless_cgroup: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_linuxcontainer() -> (LinuxContainer, TempDir) {
|
||||||
|
let dir = tempdir().expect("failed to make tempdir");
|
||||||
|
|
||||||
|
(
|
||||||
|
LinuxContainer::new(
|
||||||
|
"some_id",
|
||||||
|
dir.path().join("rootfs").to_str().unwrap(),
|
||||||
|
create_dummy_opts(),
|
||||||
|
&slog_scope::logger(),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
dir,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_load_kernel_module() {
|
fn test_load_kernel_module() {
|
||||||
let mut m = protocols::agent::KernelModule {
|
let mut m = protocols::agent::KernelModule {
|
||||||
@ -2091,6 +2130,149 @@ mod tests {
|
|||||||
assert!(result.is_err(), "expected add arp neighbors to fail");
|
assert!(result.is_err(), "expected add arp neighbors to fail");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_do_write_stream() {
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct TestData<'a> {
|
||||||
|
create_container: bool,
|
||||||
|
has_fd: bool,
|
||||||
|
has_tty: bool,
|
||||||
|
break_pipe: bool,
|
||||||
|
|
||||||
|
container_id: &'a str,
|
||||||
|
exec_id: &'a str,
|
||||||
|
data: Vec<u8>,
|
||||||
|
result: Result<protocols::agent::WriteStreamResponse>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TestData<'_> {
|
||||||
|
fn default() -> Self {
|
||||||
|
TestData {
|
||||||
|
create_container: true,
|
||||||
|
has_fd: true,
|
||||||
|
has_tty: true,
|
||||||
|
break_pipe: false,
|
||||||
|
|
||||||
|
container_id: "1",
|
||||||
|
exec_id: "2",
|
||||||
|
data: vec![1, 2, 3],
|
||||||
|
result: Ok(WriteStreamResponse {
|
||||||
|
len: 3,
|
||||||
|
..WriteStreamResponse::default()
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let tests = &[
|
||||||
|
TestData {
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
has_tty: false,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
break_pipe: true,
|
||||||
|
result: Err(anyhow!(std::io::Error::from_raw_os_error(libc::EPIPE))),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
create_container: false,
|
||||||
|
result: Err(anyhow!(crate::sandbox::ERR_INVALID_CONTAINER_ID)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
container_id: "8181",
|
||||||
|
result: Err(anyhow!(crate::sandbox::ERR_INVALID_CONTAINER_ID)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
data: vec![],
|
||||||
|
result: Ok(WriteStreamResponse {
|
||||||
|
len: 0,
|
||||||
|
..WriteStreamResponse::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
TestData {
|
||||||
|
has_fd: false,
|
||||||
|
result: Err(anyhow!(ERR_CANNOT_GET_WRITER)),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
for (i, d) in tests.iter().enumerate() {
|
||||||
|
let msg = format!("test[{}]: {:?}", i, d);
|
||||||
|
|
||||||
|
let logger = slog::Logger::root(slog::Discard, o!());
|
||||||
|
let mut sandbox = Sandbox::new(&logger).unwrap();
|
||||||
|
|
||||||
|
let (rfd, wfd) = unistd::pipe().unwrap();
|
||||||
|
if d.break_pipe {
|
||||||
|
unistd::close(rfd).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.create_container {
|
||||||
|
let (mut linux_container, _root) = create_linuxcontainer();
|
||||||
|
let exec_process_id = 2;
|
||||||
|
|
||||||
|
linux_container.id = "1".to_string();
|
||||||
|
|
||||||
|
let mut exec_process = Process::new(
|
||||||
|
&logger,
|
||||||
|
&oci::Process::default(),
|
||||||
|
&exec_process_id.to_string(),
|
||||||
|
false,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let fd = {
|
||||||
|
if d.has_fd {
|
||||||
|
Some(wfd)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if d.has_tty {
|
||||||
|
exec_process.parent_stdin = None;
|
||||||
|
exec_process.term_master = fd;
|
||||||
|
} else {
|
||||||
|
exec_process.parent_stdin = fd;
|
||||||
|
exec_process.term_master = None;
|
||||||
|
}
|
||||||
|
linux_container
|
||||||
|
.processes
|
||||||
|
.insert(exec_process_id, exec_process);
|
||||||
|
|
||||||
|
sandbox.add_container(linux_container);
|
||||||
|
}
|
||||||
|
|
||||||
|
let agent_service = Box::new(AgentService {
|
||||||
|
sandbox: Arc::new(Mutex::new(sandbox)),
|
||||||
|
});
|
||||||
|
|
||||||
|
let result = agent_service
|
||||||
|
.do_write_stream(protocols::agent::WriteStreamRequest {
|
||||||
|
container_id: d.container_id.to_string(),
|
||||||
|
exec_id: d.exec_id.to_string(),
|
||||||
|
data: d.data.clone(),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if !d.break_pipe {
|
||||||
|
unistd::close(rfd).unwrap();
|
||||||
|
}
|
||||||
|
unistd::close(wfd).unwrap();
|
||||||
|
|
||||||
|
let msg = format!("{}, result: {:?}", msg, result);
|
||||||
|
assert_result!(d.result, result, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_get_memory_info() {
|
async fn test_get_memory_info() {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -32,6 +32,8 @@ use tokio::sync::oneshot;
|
|||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
|
pub const ERR_INVALID_CONTAINER_ID: &str = "Invalid container id";
|
||||||
|
|
||||||
type UeventWatcher = (Box<dyn UeventMatcher>, oneshot::Sender<Uevent>);
|
type UeventWatcher = (Box<dyn UeventMatcher>, oneshot::Sender<Uevent>);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -234,7 +236,7 @@ impl Sandbox {
|
|||||||
pub fn find_container_process(&mut self, cid: &str, eid: &str) -> Result<&mut Process> {
|
pub fn find_container_process(&mut self, cid: &str, eid: &str) -> Result<&mut Process> {
|
||||||
let ctr = self
|
let ctr = self
|
||||||
.get_container(cid)
|
.get_container(cid)
|
||||||
.ok_or_else(|| anyhow!("Invalid container id"))?;
|
.ok_or_else(|| anyhow!(ERR_INVALID_CONTAINER_ID))?;
|
||||||
|
|
||||||
if eid.is_empty() {
|
if eid.is_empty() {
|
||||||
return ctr
|
return ctr
|
||||||
|
1
src/libs/protocols/.gitignore
vendored
1
src/libs/protocols/.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
Cargo.lock
|
Cargo.lock
|
||||||
src/agent.rs
|
src/agent.rs
|
||||||
src/agent_ttrpc.rs
|
src/agent_ttrpc.rs
|
||||||
|
src/csi.rs
|
||||||
src/empty.rs
|
src/empty.rs
|
||||||
src/health.rs
|
src/health.rs
|
||||||
src/health_ttrpc.rs
|
src/health_ttrpc.rs
|
||||||
|
@ -175,6 +175,15 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func indexPage(w http.ResponseWriter, r *http.Request) {
|
func indexPage(w http.ResponseWriter, r *http.Request) {
|
||||||
|
htmlResponse := kataMonitor.IfReturnHTMLResponse(w, r)
|
||||||
|
if htmlResponse {
|
||||||
|
indexPageHTML(w, r)
|
||||||
|
} else {
|
||||||
|
indexPageText(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func indexPageText(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Write([]byte("Available HTTP endpoints:\n"))
|
w.Write([]byte("Available HTTP endpoints:\n"))
|
||||||
|
|
||||||
spacing := 0
|
spacing := 0
|
||||||
@ -184,13 +193,35 @@ func indexPage(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
spacing = spacing + 3
|
spacing = spacing + 3
|
||||||
|
formatter := fmt.Sprintf("%%-%ds: %%s\n", spacing)
|
||||||
|
|
||||||
formattedString := fmt.Sprintf("%%-%ds: %%s\n", spacing)
|
|
||||||
for _, endpoint := range endpoints {
|
for _, endpoint := range endpoints {
|
||||||
w.Write([]byte(fmt.Sprintf(formattedString, endpoint.path, endpoint.desc)))
|
w.Write([]byte(fmt.Sprintf(formatter, endpoint.path, endpoint.desc)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func indexPageHTML(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
w.Write([]byte("<h1>Available HTTP endpoints:</h1>\n"))
|
||||||
|
|
||||||
|
var formattedString string
|
||||||
|
needLinkPaths := []string{"/metrics", "/sandboxes"}
|
||||||
|
|
||||||
|
w.Write([]byte("<ul>"))
|
||||||
|
for _, endpoint := range endpoints {
|
||||||
|
formattedString = fmt.Sprintf("<b>%s</b>: %s\n", endpoint.path, endpoint.desc)
|
||||||
|
for _, linkPath := range needLinkPaths {
|
||||||
|
if linkPath == endpoint.path {
|
||||||
|
formattedString = fmt.Sprintf("<b><a href='%s'>%s</a></b>: %s\n", endpoint.path, endpoint.path, endpoint.desc)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
formattedString = fmt.Sprintf("<li>%s</li>", formattedString)
|
||||||
|
w.Write([]byte(formattedString))
|
||||||
|
}
|
||||||
|
w.Write([]byte("</ul>"))
|
||||||
|
}
|
||||||
|
|
||||||
// initLog setup logger
|
// initLog setup logger
|
||||||
func initLog() {
|
func initLog() {
|
||||||
kataMonitorLog := logrus.WithFields(logrus.Fields{
|
kataMonitorLog := logrus.WithFields(logrus.Fields{
|
||||||
|
@ -125,7 +125,8 @@ virtio_fs_cache_size = @DEFVIRTIOFSCACHESIZE@
|
|||||||
#
|
#
|
||||||
# Format example:
|
# Format example:
|
||||||
# ["-o", "arg1=xxx,arg2", "-o", "hello world", "--arg3=yyy"]
|
# ["-o", "arg1=xxx,arg2", "-o", "hello world", "--arg3=yyy"]
|
||||||
#
|
# Examples:
|
||||||
|
# Set virtiofsd log level to debug : ["-o", "log_level=debug"] or ["-d"]
|
||||||
# see `virtiofsd -h` for possible options.
|
# see `virtiofsd -h` for possible options.
|
||||||
virtio_fs_extra_args = @DEFVIRTIOFSEXTRAARGS@
|
virtio_fs_extra_args = @DEFVIRTIOFSEXTRAARGS@
|
||||||
|
|
||||||
|
@ -168,6 +168,8 @@ virtio_fs_cache_size = @DEFVIRTIOFSCACHESIZE@
|
|||||||
#
|
#
|
||||||
# Format example:
|
# Format example:
|
||||||
# ["-o", "arg1=xxx,arg2", "-o", "hello world", "--arg3=yyy"]
|
# ["-o", "arg1=xxx,arg2", "-o", "hello world", "--arg3=yyy"]
|
||||||
|
# Examples:
|
||||||
|
# Set virtiofsd log level to debug : ["-o", "log_level=debug"] or ["-d"]
|
||||||
#
|
#
|
||||||
# see `virtiofsd -h` for possible options.
|
# see `virtiofsd -h` for possible options.
|
||||||
virtio_fs_extra_args = @DEFVIRTIOFSEXTRAARGS@
|
virtio_fs_extra_args = @DEFVIRTIOFSEXTRAARGS@
|
||||||
|
@ -78,6 +78,21 @@ func (km *KataMonitor) ProcessMetricsRequest(w http.ResponseWriter, r *http.Requ
|
|||||||
scrapeDurationsHistogram.Observe(float64(time.Since(start).Nanoseconds() / int64(time.Millisecond)))
|
scrapeDurationsHistogram.Observe(float64(time.Since(start).Nanoseconds() / int64(time.Millisecond)))
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// this is likely the same as `kata-runtime metrics <SANDBOX>`.
|
||||||
|
sandboxID, err := getSandboxIDFromReq(r)
|
||||||
|
if err == nil && sandboxID != "" {
|
||||||
|
metrics, err := GetSandboxMetrics(sandboxID)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
w.Write([]byte(err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Write([]byte(metrics))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no sandbox provided, will get all sandbox's metrics.
|
||||||
|
|
||||||
// prepare writer for writing response.
|
// prepare writer for writing response.
|
||||||
contentType := expfmt.Negotiate(r.Header)
|
contentType := expfmt.Negotiate(r.Header)
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ const (
|
|||||||
RuntimeCRIO = "cri-o"
|
RuntimeCRIO = "cri-o"
|
||||||
fsMonitorRetryDelaySeconds = 60
|
fsMonitorRetryDelaySeconds = 60
|
||||||
podCacheRefreshDelaySeconds = 5
|
podCacheRefreshDelaySeconds = 5
|
||||||
|
contentTypeHtml = "text/html"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetLogger sets the logger for katamonitor package.
|
// SetLogger sets the logger for katamonitor package.
|
||||||
@ -194,7 +195,41 @@ func (km *KataMonitor) GetAgentURL(w http.ResponseWriter, r *http.Request) {
|
|||||||
// ListSandboxes list all sandboxes running in Kata
|
// ListSandboxes list all sandboxes running in Kata
|
||||||
func (km *KataMonitor) ListSandboxes(w http.ResponseWriter, r *http.Request) {
|
func (km *KataMonitor) ListSandboxes(w http.ResponseWriter, r *http.Request) {
|
||||||
sandboxes := km.sandboxCache.getSandboxList()
|
sandboxes := km.sandboxCache.getSandboxList()
|
||||||
|
htmlResponse := IfReturnHTMLResponse(w, r)
|
||||||
|
if htmlResponse {
|
||||||
|
listSandboxesHtml(sandboxes, w)
|
||||||
|
} else {
|
||||||
|
listSandboxesText(sandboxes, w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func listSandboxesText(sandboxes []string, w http.ResponseWriter) {
|
||||||
for _, s := range sandboxes {
|
for _, s := range sandboxes {
|
||||||
w.Write([]byte(fmt.Sprintf("%s\n", s)))
|
w.Write([]byte(fmt.Sprintf("%s\n", s)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func listSandboxesHtml(sandboxes []string, w http.ResponseWriter) {
|
||||||
|
w.Write([]byte("<h1>Sandbox list</h1>\n"))
|
||||||
|
w.Write([]byte("<ul>\n"))
|
||||||
|
for _, s := range sandboxes {
|
||||||
|
w.Write([]byte(fmt.Sprintf("<li>%s: <a href='/debug/pprof/?sandbox=%s'>pprof</a>, <a href='/metrics?sandbox=%s'>metrics</a>, <a href='/agent-url?sandbox=%s'>agent-url</a></li>\n", s, s, s, s)))
|
||||||
|
}
|
||||||
|
w.Write([]byte("</ul>\n"))
|
||||||
|
}
|
||||||
|
|
||||||
|
// IfReturnHTMLResponse returns true if request accepts html response
|
||||||
|
// NOTE: IfReturnHTMLResponse will also set response header to `text/html`
|
||||||
|
func IfReturnHTMLResponse(w http.ResponseWriter, r *http.Request) bool {
|
||||||
|
accepts := r.Header["Accept"]
|
||||||
|
for _, accept := range accepts {
|
||||||
|
fields := strings.Split(accept, ",")
|
||||||
|
for _, field := range fields {
|
||||||
|
if field == contentTypeHtml {
|
||||||
|
w.Header().Set("Content-Type", contentTypeHtml)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -55,8 +55,10 @@ func (km *KataMonitor) proxyRequest(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uri := fmt.Sprintf("http://shim%s", r.URL.String())
|
uri := fmt.Sprintf("http://shim%s", r.URL.String())
|
||||||
|
monitorLog.Debugf("proxyRequest to: %s, uri: %s", socketAddress, uri)
|
||||||
resp, err := client.Get(uri)
|
resp, err := client.Get(uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
serveError(w, http.StatusInternalServerError, fmt.Sprintf("failed to request %s through %s", uri, socketAddress))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +234,6 @@ func (clh *cloudHypervisor) createVirtiofsDaemon(sharedPath string) (VirtiofsDae
|
|||||||
sourcePath: sharedPath,
|
sourcePath: sharedPath,
|
||||||
socketPath: virtiofsdSocketPath,
|
socketPath: virtiofsdSocketPath,
|
||||||
extraArgs: clh.config.VirtioFSExtraArgs,
|
extraArgs: clh.config.VirtioFSExtraArgs,
|
||||||
debug: clh.config.Debug,
|
|
||||||
cache: clh.config.VirtioFSCache,
|
cache: clh.config.VirtioFSCache,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -302,7 +301,6 @@ func (clh *cloudHypervisor) loadVirtiofsDaemon(sharedPath string) (VirtiofsDaemo
|
|||||||
return &virtiofsd{
|
return &virtiofsd{
|
||||||
PID: clh.state.VirtiofsDaemonPid,
|
PID: clh.state.VirtiofsDaemonPid,
|
||||||
sourcePath: sharedPath,
|
sourcePath: sharedPath,
|
||||||
debug: clh.config.Debug,
|
|
||||||
socketPath: virtiofsdSocketPath,
|
socketPath: virtiofsdSocketPath,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -499,7 +499,6 @@ func (q *qemu) createVirtiofsDaemon(sharedPath string) (VirtiofsDaemon, error) {
|
|||||||
sourcePath: sharedPath,
|
sourcePath: sharedPath,
|
||||||
socketPath: virtiofsdSocketPath,
|
socketPath: virtiofsdSocketPath,
|
||||||
extraArgs: q.config.VirtioFSExtraArgs,
|
extraArgs: q.config.VirtioFSExtraArgs,
|
||||||
debug: q.config.Debug,
|
|
||||||
cache: q.config.VirtioFSCache,
|
cache: q.config.VirtioFSCache,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -70,8 +70,6 @@ type virtiofsd struct {
|
|||||||
sourcePath string
|
sourcePath string
|
||||||
// extraArgs list of extra args to append to virtiofsd command
|
// extraArgs list of extra args to append to virtiofsd command
|
||||||
extraArgs []string
|
extraArgs []string
|
||||||
// debug flag
|
|
||||||
debug bool
|
|
||||||
// PID process ID of virtiosd process
|
// PID process ID of virtiosd process
|
||||||
PID int
|
PID int
|
||||||
}
|
}
|
||||||
@ -199,14 +197,8 @@ func (v *virtiofsd) args(FdSocketNumber uint) ([]string, error) {
|
|||||||
"-o", "source=" + v.sourcePath,
|
"-o", "source=" + v.sourcePath,
|
||||||
// fd number of vhost-user socket
|
// fd number of vhost-user socket
|
||||||
fmt.Sprintf("--fd=%v", FdSocketNumber),
|
fmt.Sprintf("--fd=%v", FdSocketNumber),
|
||||||
}
|
|
||||||
|
|
||||||
if v.debug {
|
|
||||||
// enable debug output (implies -f)
|
|
||||||
args = append(args, "-d")
|
|
||||||
} else {
|
|
||||||
// foreground operation
|
// foreground operation
|
||||||
args = append(args, "-f")
|
"-f",
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(v.extraArgs) != 0 {
|
if len(v.extraArgs) != 0 {
|
||||||
|
@ -22,7 +22,6 @@ func TestVirtiofsdStart(t *testing.T) {
|
|||||||
cache string
|
cache string
|
||||||
extraArgs []string
|
extraArgs []string
|
||||||
sourcePath string
|
sourcePath string
|
||||||
debug bool
|
|
||||||
PID int
|
PID int
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
}
|
}
|
||||||
@ -58,7 +57,6 @@ func TestVirtiofsdStart(t *testing.T) {
|
|||||||
cache: tt.fields.cache,
|
cache: tt.fields.cache,
|
||||||
extraArgs: tt.fields.extraArgs,
|
extraArgs: tt.fields.extraArgs,
|
||||||
sourcePath: tt.fields.sourcePath,
|
sourcePath: tt.fields.sourcePath,
|
||||||
debug: tt.fields.debug,
|
|
||||||
PID: tt.fields.PID,
|
PID: tt.fields.PID,
|
||||||
ctx: tt.fields.ctx,
|
ctx: tt.fields.ctx,
|
||||||
}
|
}
|
||||||
@ -86,7 +84,6 @@ func TestVirtiofsdArgs(t *testing.T) {
|
|||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
assert.Equal(expected, strings.Join(args, " "))
|
assert.Equal(expected, strings.Join(args, " "))
|
||||||
|
|
||||||
v.debug = false
|
|
||||||
expected = "--syslog -o cache=none -o no_posix_lock -o source=/run/kata-shared/foo --fd=456 -f"
|
expected = "--syslog -o cache=none -o no_posix_lock -o source=/run/kata-shared/foo --fd=456 -f"
|
||||||
args, err = v.args(456)
|
args, err = v.args(456)
|
||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
|
Loading…
Reference in New Issue
Block a user