mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 13:45:20 +00:00
vhost_user_net, vhost_user_block, option_parser: Remove vmm dependency
Remove the vmm dependency from vhost_user_block and vhost_user_net where it was existing to use config::OptionParser. By moving the OptionParser to its own crate at the top-level we can remove the very heavy dependency that these vhost-user backends had. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
90261bb9c7
commit
b69f6d4f6c
9
Cargo.lock
generated
9
Cargo.lock
generated
@ -676,6 +676,10 @@ dependencies = [
|
||||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "option_parser"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.10.2"
|
||||
@ -1433,13 +1437,13 @@ dependencies = [
|
||||
"epoll",
|
||||
"libc",
|
||||
"log 0.4.8",
|
||||
"option_parser",
|
||||
"qcow",
|
||||
"vhost",
|
||||
"vhost_user_backend",
|
||||
"virtio-bindings",
|
||||
"virtio-devices",
|
||||
"vm-memory",
|
||||
"vmm",
|
||||
"vmm-sys-util",
|
||||
]
|
||||
|
||||
@ -1473,12 +1477,12 @@ dependencies = [
|
||||
"libc",
|
||||
"log 0.4.8",
|
||||
"net_util",
|
||||
"option_parser",
|
||||
"vhost",
|
||||
"vhost_user_backend",
|
||||
"virtio-bindings",
|
||||
"virtio-devices",
|
||||
"vm-memory",
|
||||
"vmm",
|
||||
"vmm-sys-util",
|
||||
]
|
||||
|
||||
@ -1591,6 +1595,7 @@ dependencies = [
|
||||
"log 0.4.8",
|
||||
"micro_http",
|
||||
"net_util",
|
||||
"option_parser",
|
||||
"pci",
|
||||
"qcow",
|
||||
"seccomp",
|
||||
|
@ -65,4 +65,5 @@ members = [
|
||||
"arch_gen",
|
||||
"net_gen",
|
||||
"vm-allocator",
|
||||
"option_parser"
|
||||
]
|
||||
|
5
option_parser/Cargo.toml
Normal file
5
option_parser/Cargo.toml
Normal file
@ -0,0 +1,5 @@
|
||||
[package]
|
||||
name = "option_parser"
|
||||
version = "0.1.0"
|
||||
authors = ["The Cloud Hypervisor Authors"]
|
||||
edition = "2018"
|
172
option_parser/src/lib.rs
Normal file
172
option_parser/src/lib.rs
Normal file
@ -0,0 +1,172 @@
|
||||
// Copyright © 2020 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct OptionParser {
|
||||
options: HashMap<String, OptionParserValue>,
|
||||
}
|
||||
|
||||
struct OptionParserValue {
|
||||
value: Option<String>,
|
||||
requires_value: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum OptionParserError {
|
||||
UnknownOption(String),
|
||||
InvalidSyntax(String),
|
||||
Conversion(String, String),
|
||||
}
|
||||
|
||||
impl fmt::Display for OptionParserError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
OptionParserError::UnknownOption(s) => write!(f, "unknown option: {}", s),
|
||||
OptionParserError::InvalidSyntax(s) => write!(f, "invalid syntax:{}", s),
|
||||
OptionParserError::Conversion(field, value) => {
|
||||
write!(f, "unable to parse {} for {}", value, field)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type OptionParserResult<T> = std::result::Result<T, OptionParserError>;
|
||||
|
||||
impl OptionParser {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
options: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(&mut self, input: &str) -> OptionParserResult<()> {
|
||||
if input.trim().is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let options_list: Vec<&str> = input.trim().split(',').collect();
|
||||
|
||||
for option in options_list.iter() {
|
||||
let parts: Vec<&str> = option.split('=').collect();
|
||||
|
||||
match self.options.get_mut(parts[0]) {
|
||||
None => return Err(OptionParserError::UnknownOption(parts[0].to_owned())),
|
||||
Some(value) => {
|
||||
if value.requires_value {
|
||||
if parts.len() != 2 {
|
||||
return Err(OptionParserError::InvalidSyntax((*option).to_owned()));
|
||||
}
|
||||
value.value = Some(parts[1].trim().to_owned());
|
||||
} else {
|
||||
value.value = Some(String::new());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add(&mut self, option: &str) -> &mut Self {
|
||||
self.options.insert(
|
||||
option.to_owned(),
|
||||
OptionParserValue {
|
||||
value: None,
|
||||
requires_value: true,
|
||||
},
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_valueless(&mut self, option: &str) -> &mut Self {
|
||||
self.options.insert(
|
||||
option.to_owned(),
|
||||
OptionParserValue {
|
||||
value: None,
|
||||
requires_value: false,
|
||||
},
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn get(&self, option: &str) -> Option<String> {
|
||||
self.options
|
||||
.get(option)
|
||||
.and_then(|v| v.value.clone())
|
||||
.and_then(|s| if s.is_empty() { None } else { Some(s) })
|
||||
}
|
||||
|
||||
pub fn is_set(&self, option: &str) -> bool {
|
||||
self.options
|
||||
.get(option)
|
||||
.and_then(|v| v.value.as_ref())
|
||||
.is_some()
|
||||
}
|
||||
|
||||
pub fn convert<T: FromStr>(&self, option: &str) -> OptionParserResult<Option<T>> {
|
||||
match self.get(option) {
|
||||
None => Ok(None),
|
||||
Some(v) => Ok(Some(v.parse().map_err(|_| {
|
||||
OptionParserError::Conversion(option.to_owned(), v.to_owned())
|
||||
})?)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Toggle(pub bool);
|
||||
|
||||
pub enum ToggleParseError {
|
||||
InvalidValue(String),
|
||||
}
|
||||
|
||||
impl FromStr for Toggle {
|
||||
type Err = ToggleParseError;
|
||||
|
||||
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||
match s.to_lowercase().as_str() {
|
||||
"" => Ok(Toggle(false)),
|
||||
"on" => Ok(Toggle(true)),
|
||||
"off" => Ok(Toggle(false)),
|
||||
"true" => Ok(Toggle(true)),
|
||||
"false" => Ok(Toggle(false)),
|
||||
_ => Err(ToggleParseError::InvalidValue(s.to_owned())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ByteSized(pub u64);
|
||||
|
||||
pub enum ByteSizedParseError {
|
||||
InvalidValue(String),
|
||||
}
|
||||
|
||||
impl FromStr for ByteSized {
|
||||
type Err = ByteSizedParseError;
|
||||
|
||||
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||
Ok(ByteSized({
|
||||
let s = s.trim();
|
||||
let shift = if s.ends_with('K') {
|
||||
10
|
||||
} else if s.ends_with('M') {
|
||||
20
|
||||
} else if s.ends_with('G') {
|
||||
30
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let s = s.trim_end_matches(|c| c == 'K' || c == 'M' || c == 'G');
|
||||
s.parse::<u64>()
|
||||
.map_err(|_| ByteSizedParseError::InvalidValue(s.to_owned()))?
|
||||
<< shift
|
||||
}))
|
||||
}
|
||||
}
|
@ -9,11 +9,11 @@ clap = { version = "2.33.1", features=["wrap_help"] }
|
||||
epoll = ">=4.0.1"
|
||||
libc = "0.2.71"
|
||||
log = "0.4.8"
|
||||
option_parser = { path = "../option_parser" }
|
||||
qcow = { path = "../qcow" }
|
||||
vhost_user_backend = { path = "../vhost_user_backend" }
|
||||
vhost_rs = { git = "https://github.com/cloud-hypervisor/vhost", branch = "dragonball", package = "vhost", features = ["vhost-user-slave"] }
|
||||
virtio-bindings = "0.1.0"
|
||||
virtio-devices = { path = "../virtio-devices" }
|
||||
vm-memory = "0.2.1"
|
||||
vmm = { path = "../vmm" }
|
||||
vmm-sys-util = ">=0.3.1"
|
||||
|
@ -15,6 +15,7 @@ extern crate virtio_devices;
|
||||
|
||||
use libc::EFD_NONBLOCK;
|
||||
use log::*;
|
||||
use option_parser::{OptionParser, OptionParserError, Toggle};
|
||||
use qcow::{self, ImageType, QcowFile};
|
||||
use std::fs::File;
|
||||
use std::fs::OpenOptions;
|
||||
@ -40,7 +41,6 @@ use virtio_devices::block::{build_disk_image_id, Request};
|
||||
use virtio_devices::VirtioBlockConfig;
|
||||
use vm_memory::ByteValued;
|
||||
use vm_memory::{Bytes, GuestMemoryMmap};
|
||||
use vmm::config::{OptionParser, OptionParserError, Toggle};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
const SECTOR_SHIFT: u8 = 9;
|
||||
|
@ -10,10 +10,10 @@ epoll = ">=4.0.1"
|
||||
libc = "0.2.71"
|
||||
log = "0.4.8"
|
||||
net_util = { path = "../net_util" }
|
||||
option_parser = { path = "../option_parser" }
|
||||
vhost_user_backend = { path = "../vhost_user_backend" }
|
||||
vhost_rs = { git = "https://github.com/cloud-hypervisor/vhost", branch = "dragonball", package = "vhost", features = ["vhost-user-slave"] }
|
||||
virtio-bindings = "0.1.0"
|
||||
virtio-devices = { path = "../virtio-devices" }
|
||||
vm-memory = "0.2.1"
|
||||
vmm = { path = "../vmm" }
|
||||
vmm-sys-util = ">=0.3.1"
|
||||
|
@ -11,11 +11,11 @@ extern crate net_util;
|
||||
extern crate vhost_rs;
|
||||
extern crate vhost_user_backend;
|
||||
extern crate virtio_devices;
|
||||
extern crate vmm;
|
||||
|
||||
use libc::{self, EFD_NONBLOCK};
|
||||
use log::*;
|
||||
use net_util::{MacAddr, Tap};
|
||||
use option_parser::{OptionParser, OptionParserError};
|
||||
use std::fmt;
|
||||
use std::io::{self};
|
||||
use std::net::Ipv4Addr;
|
||||
@ -31,7 +31,6 @@ use virtio_bindings::bindings::virtio_ring::VIRTIO_RING_F_EVENT_IDX;
|
||||
use virtio_devices::net_util::{open_tap, RxVirtio, TxVirtio};
|
||||
use virtio_devices::{NetCounters, NetQueuePair};
|
||||
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
|
||||
use vmm::config::{OptionParser, OptionParserError};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
pub type VhostUserResult<T> = std::result::Result<T, VhostUserError>;
|
||||
|
@ -26,6 +26,7 @@ libc = "0.2.71"
|
||||
log = "0.4.8"
|
||||
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "master" }
|
||||
net_util = { path = "../net_util" }
|
||||
option_parser = { path = "../option_parser" }
|
||||
pci = {path = "../pci", optional = true}
|
||||
qcow = { path = "../qcow" }
|
||||
seccomp = { git = "https://github.com/firecracker-microvm/firecracker", tag = "v0.21.1" }
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
use clap::ArgMatches;
|
||||
use net_util::MacAddr;
|
||||
use std::collections::HashMap;
|
||||
use option_parser::{ByteSized, OptionParser, OptionParserError, Toggle};
|
||||
use std::convert::From;
|
||||
use std::fmt;
|
||||
use std::net::Ipv4Addr;
|
||||
@ -155,119 +155,6 @@ impl fmt::Display for Error {
|
||||
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct OptionParser {
|
||||
options: HashMap<String, OptionParserValue>,
|
||||
}
|
||||
|
||||
struct OptionParserValue {
|
||||
value: Option<String>,
|
||||
requires_value: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum OptionParserError {
|
||||
UnknownOption(String),
|
||||
InvalidSyntax(String),
|
||||
Conversion(String, String),
|
||||
}
|
||||
|
||||
impl fmt::Display for OptionParserError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
OptionParserError::UnknownOption(s) => write!(f, "unknown option: {}", s),
|
||||
OptionParserError::InvalidSyntax(s) => write!(f, "invalid syntax:{}", s),
|
||||
OptionParserError::Conversion(field, value) => {
|
||||
write!(f, "unable to parse {} for {}", value, field)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type OptionParserResult<T> = std::result::Result<T, OptionParserError>;
|
||||
|
||||
impl OptionParser {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
options: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(&mut self, input: &str) -> OptionParserResult<()> {
|
||||
if input.trim().is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let options_list: Vec<&str> = input.trim().split(',').collect();
|
||||
|
||||
for option in options_list.iter() {
|
||||
let parts: Vec<&str> = option.split('=').collect();
|
||||
|
||||
match self.options.get_mut(parts[0]) {
|
||||
None => return Err(OptionParserError::UnknownOption(parts[0].to_owned())),
|
||||
Some(value) => {
|
||||
if value.requires_value {
|
||||
if parts.len() != 2 {
|
||||
return Err(OptionParserError::InvalidSyntax((*option).to_owned()));
|
||||
}
|
||||
value.value = Some(parts[1].trim().to_owned());
|
||||
} else {
|
||||
value.value = Some(String::new());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn add(&mut self, option: &str) -> &mut Self {
|
||||
self.options.insert(
|
||||
option.to_owned(),
|
||||
OptionParserValue {
|
||||
value: None,
|
||||
requires_value: true,
|
||||
},
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_valueless(&mut self, option: &str) -> &mut Self {
|
||||
self.options.insert(
|
||||
option.to_owned(),
|
||||
OptionParserValue {
|
||||
value: None,
|
||||
requires_value: false,
|
||||
},
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn get(&self, option: &str) -> Option<String> {
|
||||
self.options
|
||||
.get(option)
|
||||
.and_then(|v| v.value.clone())
|
||||
.and_then(|s| if s.is_empty() { None } else { Some(s) })
|
||||
}
|
||||
|
||||
pub fn is_set(&self, option: &str) -> bool {
|
||||
self.options
|
||||
.get(option)
|
||||
.and_then(|v| v.value.as_ref())
|
||||
.is_some()
|
||||
}
|
||||
|
||||
pub fn convert<T: FromStr>(&self, option: &str) -> OptionParserResult<Option<T>> {
|
||||
match self.get(option) {
|
||||
None => Ok(None),
|
||||
Some(v) => Ok(Some(v.parse().map_err(|_| {
|
||||
OptionParserError::Conversion(option.to_owned(), v.to_owned())
|
||||
})?)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VmParams<'a> {
|
||||
pub cpus: &'a str,
|
||||
pub memory: &'a str,
|
||||
@ -324,27 +211,6 @@ impl<'a> VmParams<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Toggle(pub bool);
|
||||
|
||||
pub enum ToggleParseError {
|
||||
InvalidValue(String),
|
||||
}
|
||||
|
||||
impl FromStr for Toggle {
|
||||
type Err = ToggleParseError;
|
||||
|
||||
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||
match s.to_lowercase().as_str() {
|
||||
"" => Ok(Toggle(false)),
|
||||
"on" => Ok(Toggle(true)),
|
||||
"off" => Ok(Toggle(false)),
|
||||
"true" => Ok(Toggle(true)),
|
||||
"false" => Ok(Toggle(false)),
|
||||
_ => Err(ToggleParseError::InvalidValue(s.to_owned())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
|
||||
pub enum HotplugMethod {
|
||||
Acpi,
|
||||
@ -374,36 +240,6 @@ impl FromStr for HotplugMethod {
|
||||
}
|
||||
}
|
||||
|
||||
struct ByteSized(u64);
|
||||
|
||||
enum ByteSizedParseError {
|
||||
InvalidValue(String),
|
||||
}
|
||||
|
||||
impl FromStr for ByteSized {
|
||||
type Err = ByteSizedParseError;
|
||||
|
||||
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
|
||||
Ok(ByteSized({
|
||||
let s = s.trim();
|
||||
let shift = if s.ends_with('K') {
|
||||
10
|
||||
} else if s.ends_with('M') {
|
||||
20
|
||||
} else if s.ends_with('G') {
|
||||
30
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let s = s.trim_end_matches(|c| c == 'K' || c == 'M' || c == 'G');
|
||||
s.parse::<u64>()
|
||||
.map_err(|_| ByteSizedParseError::InvalidValue(s.to_owned()))?
|
||||
<< shift
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum CpuTopologyParseError {
|
||||
InvalidValue(String),
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
extern crate anyhow;
|
||||
extern crate arc_swap;
|
||||
extern crate hypervisor;
|
||||
extern crate option_parser;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
|
Loading…
Reference in New Issue
Block a user