mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-29 04:04:45 +00:00
libs/types: support load Kata runtime configuration from file
Add structures to load Kata runtime configuration from configuration files. Also define a mechanism for vendor to extend the Kata configuration structure. Signed-off-by: Liu Jiang <gerry@linux.alibaba.com> Signed-off-by: Zhongtao Hu <zhongtaohu.tim@linux.alibaba.com>
This commit is contained in:
parent
5b89c1df2f
commit
21cc02d724
13
src/libs/Cargo.lock
generated
13
src/libs/Cargo.lock
generated
@ -287,9 +287,13 @@ checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
name = "kata-types"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"oci",
|
||||
"serde",
|
||||
"slog",
|
||||
"slog-scope",
|
||||
"thiserror",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -802,6 +806,15 @@ dependencies = [
|
||||
"vsock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ttrpc"
|
||||
version = "0.5.2"
|
||||
|
@ -11,9 +11,16 @@ license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
lazy_static = "1.4.0"
|
||||
serde = { version = "1.0.100", features = ["derive"] }
|
||||
slog = "2.5.2"
|
||||
slog-scope = "4.4.0"
|
||||
thiserror = "1.0"
|
||||
toml = "0.5.8"
|
||||
|
||||
oci = { path = "../oci" }
|
||||
|
||||
[dev-dependencies]
|
||||
[features]
|
||||
default = []
|
||||
enable-vendor = []
|
||||
|
23
src/libs/kata-types/src/config/default.rs
Normal file
23
src/libs/kata-types/src/config/default.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright (c) 2021 Alibaba Cloud
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
//! Default configuration values.
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
lazy_static! {
|
||||
/// Default configuration file paths.
|
||||
pub static ref DEFAULT_RUNTIME_CONFIGURATIONS: Vec::<&'static str> = vec![
|
||||
"/etc/kata-containers2/configuration.toml",
|
||||
"/usr/share/defaults/kata-containers2/configuration.toml",
|
||||
"/etc/kata-containers/configuration_v2.toml",
|
||||
"/usr/share/defaults/kata-containers/configuration_v2.toml",
|
||||
"/etc/kata-containers/configuration.toml",
|
||||
"/usr/share/defaults/kata-containers/configuration.toml",
|
||||
];
|
||||
}
|
||||
|
||||
pub const DEFAULT_INTERNETWORKING_MODEL: &str = "tcfilter";
|
125
src/libs/kata-types/src/config/mod.rs
Normal file
125
src/libs/kata-types/src/config/mod.rs
Normal file
@ -0,0 +1,125 @@
|
||||
// Copyright (c) 2019-2021 Ant Financial
|
||||
// Copyright (c) 2019-2021 Alibaba Cloud
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::fs;
|
||||
use std::io::{self, Result};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::sl;
|
||||
|
||||
/// Default configuration values.
|
||||
pub mod default;
|
||||
|
||||
mod runtime;
|
||||
pub use self::runtime::{Runtime, RuntimeVendor};
|
||||
|
||||
/// Trait to manipulate global Kata configuration information.
|
||||
pub trait ConfigOps {
|
||||
/// Adjust the configuration information after loading from configuration file.
|
||||
fn adjust_configuration(_conf: &mut TomlConfig) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validate the configuration information.
|
||||
fn validate(_conf: &TomlConfig) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait to manipulate global Kata configuration information.
|
||||
pub trait ConfigObjectOps {
|
||||
/// Adjust the configuration information after loading from configuration file.
|
||||
fn adjust_configuration(&mut self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validate the configuration information.
|
||||
fn validate(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Kata configuration information.
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
pub struct TomlConfig {
|
||||
/// Kata runtime configuration information.
|
||||
#[serde(default)]
|
||||
pub runtime: Runtime,
|
||||
}
|
||||
|
||||
impl TomlConfig {
|
||||
/// Load Kata configuration information from configuration files.
|
||||
///
|
||||
/// If `config_file` is valid, it will used, otherwise a built-in default path list will be
|
||||
/// scanned.
|
||||
pub fn load_from_file<P: AsRef<Path>>(config_file: P) -> Result<(TomlConfig, PathBuf)> {
|
||||
let file_path = if !config_file.as_ref().as_os_str().is_empty() {
|
||||
fs::canonicalize(config_file)?
|
||||
} else {
|
||||
Self::get_default_config_file()?
|
||||
};
|
||||
|
||||
info!(
|
||||
sl!(),
|
||||
"load configuration from: {}",
|
||||
file_path.to_string_lossy()
|
||||
);
|
||||
let content = fs::read_to_string(&file_path)?;
|
||||
let config = Self::load(&content)?;
|
||||
|
||||
Ok((config, file_path))
|
||||
}
|
||||
|
||||
/// Load raw Kata configuration information from configuration files.
|
||||
///
|
||||
/// If `config_file` is valid, it will used, otherwise a built-in default path list will be
|
||||
/// scanned.
|
||||
pub fn load_raw_from_file<P: AsRef<Path>>(config_file: P) -> Result<(TomlConfig, PathBuf)> {
|
||||
let file_path = if !config_file.as_ref().as_os_str().is_empty() {
|
||||
fs::canonicalize(config_file)?
|
||||
} else {
|
||||
Self::get_default_config_file()?
|
||||
};
|
||||
|
||||
info!(
|
||||
sl!(),
|
||||
"load configuration from: {}",
|
||||
file_path.to_string_lossy()
|
||||
);
|
||||
let content = fs::read_to_string(&file_path)?;
|
||||
let config: TomlConfig = toml::from_str(&content)?;
|
||||
|
||||
Ok((config, file_path))
|
||||
}
|
||||
|
||||
/// Load Kata configuration information from string.
|
||||
pub fn load(content: &str) -> Result<TomlConfig> {
|
||||
let mut config: TomlConfig = toml::from_str(content)?;
|
||||
|
||||
Runtime::adjust_configuration(&mut config)?;
|
||||
info!(sl!(), "get kata config: {:?}", config);
|
||||
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
/// Validate Kata configuration information.
|
||||
pub fn validate(&self) -> Result<()> {
|
||||
Runtime::validate(self)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Probe configuration file according to the default configuration file list.
|
||||
fn get_default_config_file() -> Result<PathBuf> {
|
||||
for f in default::DEFAULT_RUNTIME_CONFIGURATIONS.iter() {
|
||||
if let Ok(path) = fs::canonicalize(f) {
|
||||
return Ok(path);
|
||||
}
|
||||
}
|
||||
|
||||
Err(io::Error::from(io::ErrorKind::NotFound))
|
||||
}
|
||||
}
|
272
src/libs/kata-types/src/config/runtime.rs
Normal file
272
src/libs/kata-types/src/config/runtime.rs
Normal file
@ -0,0 +1,272 @@
|
||||
// Copyright (c) 2019-2021 Alibaba Cloud
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::io::Result;
|
||||
use std::path::Path;
|
||||
|
||||
use super::default;
|
||||
use crate::config::{ConfigOps, TomlConfig};
|
||||
use crate::{eother, resolve_path, validate_path};
|
||||
|
||||
/// Kata runtime configuration information.
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
pub struct Runtime {
|
||||
/// If enabled, the runtime will log additional debug messages to the system log.
|
||||
#[serde(default, rename = "enable_debug")]
|
||||
pub debug: bool,
|
||||
|
||||
/// Enabled experimental feature list, format: ["a", "b"].
|
||||
///
|
||||
/// Experimental features are features not stable enough for production, they may break
|
||||
/// compatibility, and are prepared for a big version bump.
|
||||
#[serde(default)]
|
||||
pub experimental: Vec<String>,
|
||||
|
||||
/// Determines how the VM should be connected to the container network interface.
|
||||
///
|
||||
/// Options:
|
||||
/// - macvtap: used when the Container network interface can be bridged using macvtap.
|
||||
/// - none: used when customize network. Only creates a tap device. No veth pair.
|
||||
/// - tcfilter: uses tc filter rules to redirect traffic from the network interface provided
|
||||
/// by plugin to a tap interface connected to the VM.
|
||||
#[serde(default)]
|
||||
pub internetworking_model: String,
|
||||
|
||||
/// If enabled, the runtime won't create a network namespace for shim and hypervisor processes.
|
||||
///
|
||||
/// This option may have some potential impacts to your host. It should only be used when you
|
||||
/// know what you're doing.
|
||||
///
|
||||
/// `disable_new_netns` conflicts with `internetworking_model=tcfilter` and
|
||||
/// `internetworking_model=macvtap`. It works only with `internetworking_model=none`.
|
||||
/// The tap device will be in the host network namespace and can connect to a bridge (like OVS)
|
||||
/// directly.
|
||||
///
|
||||
/// If you are using docker, `disable_new_netns` only works with `docker run --net=none`
|
||||
#[serde(default)]
|
||||
pub disable_new_netns: bool,
|
||||
|
||||
/// If specified, sandbox_bind_mounts identifies host paths to be mounted into the sandboxes
|
||||
/// shared path.
|
||||
///
|
||||
/// This is only valid if filesystem sharing is utilized. The provided path(s) will be bind
|
||||
/// mounted into the shared fs directory. If defaults are utilized, these mounts should be
|
||||
/// available in the guest at `/run/kata-containers/shared/containers/passthrough/sandbox-mounts`.
|
||||
/// These will not be exposed to the container workloads, and are only provided for potential
|
||||
/// guest services.
|
||||
#[serde(default)]
|
||||
pub sandbox_bind_mounts: Vec<String>,
|
||||
|
||||
/// If enabled, the runtime will add all the kata processes inside one dedicated cgroup.
|
||||
///
|
||||
/// The container cgroups in the host are not created, just one single cgroup per sandbox.
|
||||
/// The runtime caller is free to restrict or collect cgroup stats of the overall Kata sandbox.
|
||||
/// The sandbox cgroup path is the parent cgroup of a container with the PodSandbox annotation.
|
||||
/// The sandbox cgroup is constrained if there is no container type annotation.
|
||||
/// See: https://pkg.go.dev/github.com/kata-containers/kata-containers/src/runtime/virtcontainers#ContainerType
|
||||
#[serde(default)]
|
||||
pub sandbox_cgroup_only: bool,
|
||||
|
||||
/// If enabled, the runtime will create opentracing.io traces and spans.
|
||||
/// See https://www.jaegertracing.io/docs/getting-started.
|
||||
#[serde(default)]
|
||||
pub enable_tracing: bool,
|
||||
/// The full url to the Jaeger HTTP Thrift collector.
|
||||
#[serde(default)]
|
||||
pub jaeger_endpoint: String,
|
||||
/// The username to be used if basic auth is required for Jaeger.
|
||||
#[serde(default)]
|
||||
pub jaeger_user: String,
|
||||
/// The password to be used if basic auth is required for Jaeger.
|
||||
#[serde(default)]
|
||||
pub jaeger_password: String,
|
||||
|
||||
/// If enabled, user can run pprof tools with shim v2 process through kata-monitor.
|
||||
#[serde(default)]
|
||||
pub enable_pprof: bool,
|
||||
|
||||
/// Determines whether container seccomp profiles are passed to the virtual machine and
|
||||
/// applied by the kata agent. If set to true, seccomp is not applied within the guest.
|
||||
#[serde(default)]
|
||||
pub disable_guest_seccomp: bool,
|
||||
|
||||
/// Determines how VFIO devices should be be presented to the container.
|
||||
///
|
||||
/// Options:
|
||||
/// - vfio: Matches behaviour of OCI runtimes (e.g. runc) as much as possible. VFIO devices
|
||||
/// will appear in the container as VFIO character devices under /dev/vfio. The exact names
|
||||
/// may differ from the host (they need to match the VM's IOMMU group numbers rather than
|
||||
/// the host's)
|
||||
/// - guest-kernel: This is a Kata-specific behaviour that's useful in certain cases.
|
||||
/// The VFIO device is managed by whatever driver in the VM kernel claims it. This means
|
||||
/// it will appear as one or more device nodes or network interfaces depending on the nature
|
||||
/// of the device. Using this mode requires specially built workloads that know how to locate
|
||||
/// the relevant device interfaces within the VM.
|
||||
#[serde(default)]
|
||||
pub vfio_mode: String,
|
||||
|
||||
/// Vendor customized runtime configuration.
|
||||
#[serde(default, flatten)]
|
||||
pub vendor: RuntimeVendor,
|
||||
}
|
||||
|
||||
impl ConfigOps for Runtime {
|
||||
fn adjust_configuration(conf: &mut TomlConfig) -> Result<()> {
|
||||
RuntimeVendor::adjust_configuration(conf)?;
|
||||
|
||||
if conf.runtime.internetworking_model.is_empty() {
|
||||
conf.runtime.internetworking_model = default::DEFAULT_INTERNETWORKING_MODEL.to_owned();
|
||||
}
|
||||
|
||||
for bind in conf.runtime.sandbox_bind_mounts.iter_mut() {
|
||||
resolve_path!(*bind, "sandbox bind mount `{}` is invalid: {}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate(conf: &TomlConfig) -> Result<()> {
|
||||
RuntimeVendor::validate(conf)?;
|
||||
|
||||
let net_model = &conf.runtime.internetworking_model;
|
||||
if !net_model.is_empty()
|
||||
&& net_model != "macvtap"
|
||||
&& net_model != "none"
|
||||
&& net_model != "tcfilter"
|
||||
{
|
||||
return Err(eother!(
|
||||
"Invalid internetworking_model `{}` in configuration file",
|
||||
net_model
|
||||
));
|
||||
}
|
||||
|
||||
let vfio_mode = &conf.runtime.vfio_mode;
|
||||
if !vfio_mode.is_empty() && vfio_mode != "vfio" && vfio_mode != "guest-kernel" {
|
||||
return Err(eother!(
|
||||
"Invalid vfio_mode `{}` in configuration file",
|
||||
vfio_mode
|
||||
));
|
||||
}
|
||||
|
||||
for bind in conf.runtime.sandbox_bind_mounts.iter() {
|
||||
validate_path!(*bind, "sandbox bind mount `{}` is invalid: {}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Runtime {
|
||||
/// Check whether experiment `feature` is enabled or not.
|
||||
pub fn is_experiment_enabled(&self, feature: &str) -> bool {
|
||||
self.experimental.contains(&feature.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "enable-vendor"))]
|
||||
mod vendor {
|
||||
use super::*;
|
||||
|
||||
/// Vendor customization runtime configuration.
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
pub struct RuntimeVendor {}
|
||||
|
||||
impl ConfigOps for RuntimeVendor {}
|
||||
}
|
||||
|
||||
#[cfg(feature = "enable-vendor")]
|
||||
#[path = "runtime_vendor.rs"]
|
||||
mod vendor;
|
||||
|
||||
pub use vendor::RuntimeVendor;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_invalid_config() {
|
||||
let content = r#"
|
||||
[runtime]
|
||||
enable_debug = 10
|
||||
"#;
|
||||
TomlConfig::load(content).unwrap_err();
|
||||
|
||||
let content = r#"
|
||||
[runtime]
|
||||
enable_debug = true
|
||||
internetworking_model = "test"
|
||||
"#;
|
||||
let config: TomlConfig = TomlConfig::load(content).unwrap();
|
||||
config.validate().unwrap_err();
|
||||
|
||||
let content = r#"
|
||||
[runtime]
|
||||
enable_debug = true
|
||||
internetworking_model = "macvtap,none"
|
||||
"#;
|
||||
let config: TomlConfig = TomlConfig::load(content).unwrap();
|
||||
config.validate().unwrap_err();
|
||||
|
||||
let content = r#"
|
||||
[runtime]
|
||||
enable_debug = true
|
||||
vfio_mode = "none"
|
||||
"#;
|
||||
let config: TomlConfig = TomlConfig::load(content).unwrap();
|
||||
config.validate().unwrap_err();
|
||||
|
||||
let content = r#"
|
||||
[runtime]
|
||||
enable_debug = true
|
||||
vfio_mode = "vfio,guest-kernel"
|
||||
"#;
|
||||
let config: TomlConfig = TomlConfig::load(content).unwrap();
|
||||
config.validate().unwrap_err();
|
||||
|
||||
let content = r#"
|
||||
[runtime]
|
||||
enable_debug = true
|
||||
vfio_mode = "guest_kernel"
|
||||
"#;
|
||||
let config: TomlConfig = TomlConfig::load(content).unwrap();
|
||||
config.validate().unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config() {
|
||||
let content = r#"
|
||||
[runtime]
|
||||
enable_debug = true
|
||||
experimental = ["a", "b"]
|
||||
internetworking_model = "macvtap"
|
||||
disable_new_netns = true
|
||||
sandbox_bind_mounts = []
|
||||
sandbox_cgroup_only = true
|
||||
enable_tracing = true
|
||||
jaeger_endpoint = "localhost:1234"
|
||||
jaeger_user = "user"
|
||||
jaeger_password = "pw"
|
||||
enable_pprof = true
|
||||
disable_guest_seccomp = true
|
||||
vfio_mode = "vfio"
|
||||
field_should_be_ignored = true
|
||||
"#;
|
||||
let config: TomlConfig = TomlConfig::load(content).unwrap();
|
||||
config.validate().unwrap();
|
||||
assert!(config.runtime.debug);
|
||||
assert_eq!(config.runtime.experimental.len(), 2);
|
||||
assert_eq!(&config.runtime.experimental[0], "a");
|
||||
assert_eq!(&config.runtime.experimental[1], "b");
|
||||
assert_eq!(&config.runtime.internetworking_model, "macvtap");
|
||||
assert!(config.runtime.disable_new_netns);
|
||||
assert_eq!(config.runtime.sandbox_bind_mounts.len(), 0);
|
||||
assert!(config.runtime.sandbox_cgroup_only);
|
||||
assert!(config.runtime.enable_tracing);
|
||||
assert!(config.runtime.is_experiment_enabled("a"));
|
||||
assert!(config.runtime.is_experiment_enabled("b"));
|
||||
assert!(!config.runtime.is_experiment_enabled("c"));
|
||||
}
|
||||
}
|
88
src/libs/kata-types/src/config/runtime_vendor.rs
Normal file
88
src/libs/kata-types/src/config/runtime_vendor.rs
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright (c) 2021 Alibaba Cloud
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
//! A sample for vendor to customize the runtime implementation.
|
||||
|
||||
use super::*;
|
||||
use crate::{eother, sl};
|
||||
use slog::Level;
|
||||
/// Vendor customization runtime configuration.
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
pub struct RuntimeVendor {
|
||||
/// Log level
|
||||
#[serde(default)]
|
||||
pub log_level: u32,
|
||||
|
||||
/// Prefix for log messages
|
||||
#[serde(default)]
|
||||
pub log_prefix: String,
|
||||
}
|
||||
|
||||
impl ConfigOps for RuntimeVendor {
|
||||
fn adjust_configuration(conf: &mut TomlConfig) -> Result<()> {
|
||||
if conf.runtime.vendor.log_level > Level::Debug as u32 {
|
||||
conf.runtime.debug = true;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Validate the configuration information.
|
||||
fn validate(conf: &TomlConfig) -> Result<()> {
|
||||
if conf.runtime.vendor.log_level > 10 {
|
||||
warn!(
|
||||
sl!(),
|
||||
"log level {} in configuration file is invalid", conf.runtime.vendor.log_level
|
||||
);
|
||||
return Err(eother!(
|
||||
"log level {} in configuration file is invalid",
|
||||
conf.runtime.vendor.log_level
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_invalid_vendor_config() {
|
||||
let content = r#"
|
||||
[runtime]
|
||||
debug = false
|
||||
log_level = 20
|
||||
log_prefix = "test"
|
||||
"#;
|
||||
let config: TomlConfig = TomlConfig::load(content).unwrap();
|
||||
config.validate().unwrap_err();
|
||||
|
||||
let content = r#"
|
||||
[runtime]
|
||||
debug = false
|
||||
log_level = "test"
|
||||
log_prefix = "test"
|
||||
"#;
|
||||
TomlConfig::load(content).unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vendor_config() {
|
||||
let content = r#"
|
||||
[runtime]
|
||||
debug = false
|
||||
log_level = 10
|
||||
log_prefix = "test"
|
||||
log_fmt = "nouse"
|
||||
"#;
|
||||
let config: TomlConfig = TomlConfig::load(content).unwrap();
|
||||
config.validate().unwrap();
|
||||
assert!(config.runtime.debug);
|
||||
assert_eq!(config.runtime.vendor.log_level, 10);
|
||||
assert_eq!(&config.runtime.vendor.log_prefix, "test");
|
||||
}
|
||||
}
|
@ -5,11 +5,18 @@
|
||||
|
||||
//! Constants and Data Types shared by Kata Containers components.
|
||||
|
||||
#[deny(missing_docs)]
|
||||
#![deny(missing_docs)]
|
||||
#[macro_use]
|
||||
extern crate slog;
|
||||
#[macro_use]
|
||||
extern crate serde;
|
||||
|
||||
/// Constants and data types annotations.
|
||||
pub mod annotations;
|
||||
|
||||
/// Kata configuration information from configuration file.
|
||||
pub mod config;
|
||||
|
||||
/// Constants and data types related to container.
|
||||
pub mod container;
|
||||
|
||||
@ -18,3 +25,56 @@ pub mod k8s;
|
||||
|
||||
/// Constants and data types related to mount point.
|
||||
pub mod mount;
|
||||
|
||||
/// Convenience macro to obtain the scoped logger
|
||||
#[macro_export]
|
||||
macro_rules! sl {
|
||||
() => {
|
||||
slog_scope::logger()
|
||||
};
|
||||
}
|
||||
|
||||
/// Helper to create std::io::Error(std::io::ErrorKind::Other)
|
||||
#[macro_export]
|
||||
macro_rules! eother {
|
||||
() => (std::io::Error::new(std::io::ErrorKind::Other, ""));
|
||||
($fmt:expr) => ({
|
||||
std::io::Error::new(std::io::ErrorKind::Other, format!($fmt))
|
||||
});
|
||||
($fmt:expr, $($arg:tt)*) => ({
|
||||
std::io::Error::new(std::io::ErrorKind::Other, format!($fmt, $($arg)*))
|
||||
});
|
||||
}
|
||||
|
||||
/// Resolve a path to its final value.
|
||||
#[macro_export]
|
||||
macro_rules! resolve_path {
|
||||
($field:expr, $fmt:expr) => {{
|
||||
if !$field.is_empty() {
|
||||
match Path::new(&$field).canonicalize() {
|
||||
Err(e) => Err(eother!($fmt, &$field, e)),
|
||||
Ok(path) => {
|
||||
$field = path.to_string_lossy().to_string();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
/// Validate a path.
|
||||
#[macro_export]
|
||||
macro_rules! validate_path {
|
||||
($field:expr, $fmt:expr) => {{
|
||||
if !$field.is_empty() {
|
||||
Path::new(&$field)
|
||||
.canonicalize()
|
||||
.map_err(|e| eother!($fmt, &$field, e))
|
||||
.map(|_| ())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user