vmm: Make --kernel optional

The kernel path was the only mandatory command line option.
With the addition of the --api-socket option, we can run without a
kernel path and get it later through the API.

Since we can end up with VM configurations that are no longer valid by
default, we need to provide a validation check for it. For now, if the
kernel path is not defined, the VM configuration is invalid.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Samuel Ortiz 2019-09-19 09:52:55 +02:00
parent f27aa21e3f
commit b14fd37db9
3 changed files with 31 additions and 25 deletions

View File

@ -255,9 +255,7 @@ fn main() {
let rng = cmd_arguments.value_of("rng").unwrap(); let rng = cmd_arguments.value_of("rng").unwrap();
let serial = cmd_arguments.value_of("serial").unwrap(); let serial = cmd_arguments.value_of("serial").unwrap();
let kernel = cmd_arguments let kernel = cmd_arguments.value_of("kernel");
.value_of("kernel")
.expect("Missing argument: kernel");
let cmdline = cmd_arguments.value_of("cmdline"); let cmdline = cmd_arguments.value_of("cmdline");
let disks: Option<Vec<&str>> = cmd_arguments.values_of("disk").map(|x| x.collect()); let disks: Option<Vec<&str>> = cmd_arguments.values_of("disk").map(|x| x.collect());
@ -332,7 +330,7 @@ fn main() {
api_socket_path, api_socket_path,
u8::from(&vm_config.cpus), u8::from(&vm_config.cpus),
vm_config.memory.size >> 20, vm_config.memory.size >> 20,
vm_config.kernel.path, vm_config.kernel,
vm_config.cmdline.args.as_str(), vm_config.cmdline.args.as_str(),
vm_config.disks, vm_config.disks,
); );
@ -349,6 +347,7 @@ fn main() {
} }
}; };
if cmd_arguments.is_present("vm-config") && vm_config.valid() {
// Create and start the VM based off the VM config we just built. // Create and start the VM based off the VM config we just built.
let sender = api_request_sender.clone(); let sender = api_request_sender.clone();
vmm::vm_create( vmm::vm_create(
@ -358,6 +357,7 @@ fn main() {
) )
.expect("Could not create the VM"); .expect("Could not create the VM");
vmm::vm_start(api_evt.try_clone().unwrap(), sender).expect("Could not start the VM"); vmm::vm_start(api_evt.try_clone().unwrap(), sender).expect("Could not start the VM");
}
match vmm_thread.join() { match vmm_thread.join() {
Ok(res) => match res { Ok(res) => match res {

View File

@ -75,13 +75,15 @@ pub enum Error<'a> {
ParseVsockCidParam(std::num::ParseIntError), ParseVsockCidParam(std::num::ParseIntError),
/// Failed parsing vsock socket path parameter. /// Failed parsing vsock socket path parameter.
ParseVsockSockParam, ParseVsockSockParam,
/// Missing kernel configuration
ValidateMissingKernelConfig,
} }
pub type Result<'a, T> = result::Result<T, Error<'a>>; pub type Result<'a, T> = result::Result<T, Error<'a>>;
pub struct VmParams<'a> { pub struct VmParams<'a> {
pub cpus: &'a str, pub cpus: &'a str,
pub memory: &'a str, pub memory: &'a str,
pub kernel: &'a str, pub kernel: Option<&'a str>,
pub cmdline: Option<&'a str>, pub cmdline: Option<&'a str>,
pub disks: Option<Vec<&'a str>>, pub disks: Option<Vec<&'a str>>,
pub net: Option<Vec<&'a str>>, pub net: Option<Vec<&'a str>>,
@ -177,14 +179,6 @@ pub struct KernelConfig {
pub path: PathBuf, pub path: PathBuf,
} }
impl KernelConfig {
pub fn parse(kernel: &str) -> Result<Self> {
Ok(KernelConfig {
path: PathBuf::from(kernel),
})
}
}
#[derive(Clone)] #[derive(Clone)]
pub struct CmdlineConfig { pub struct CmdlineConfig {
pub args: Cmdline, pub args: Cmdline,
@ -617,7 +611,7 @@ impl VhostUserBlkConfig {
pub struct VmConfig { pub struct VmConfig {
pub cpus: CpusConfig, pub cpus: CpusConfig,
pub memory: MemoryConfig, pub memory: MemoryConfig,
pub kernel: KernelConfig, pub kernel: Option<KernelConfig>,
pub cmdline: CmdlineConfig, pub cmdline: CmdlineConfig,
pub disks: Option<Vec<DiskConfig>>, pub disks: Option<Vec<DiskConfig>>,
pub net: Option<Vec<NetConfig>>, pub net: Option<Vec<NetConfig>>,
@ -633,6 +627,10 @@ pub struct VmConfig {
} }
impl VmConfig { impl VmConfig {
pub fn valid(&self) -> bool {
self.kernel.is_some()
}
pub fn parse(vm_params: VmParams) -> Result<Self> { pub fn parse(vm_params: VmParams) -> Result<Self> {
let mut disks: Option<Vec<DiskConfig>> = None; let mut disks: Option<Vec<DiskConfig>> = None;
if let Some(disk_list) = &vm_params.disks { if let Some(disk_list) = &vm_params.disks {
@ -712,10 +710,17 @@ impl VmConfig {
vhost_user_blk = Some(vhost_user_blk_config_list); vhost_user_blk = Some(vhost_user_blk_config_list);
} }
let mut kernel: Option<KernelConfig> = None;
if let Some(k) = vm_params.kernel {
kernel = Some(KernelConfig {
path: PathBuf::from(k),
});
}
Ok(VmConfig { Ok(VmConfig {
cpus: CpusConfig::parse(vm_params.cpus)?, cpus: CpusConfig::parse(vm_params.cpus)?,
memory: MemoryConfig::parse(vm_params.memory)?, memory: MemoryConfig::parse(vm_params.memory)?,
kernel: KernelConfig::parse(vm_params.kernel)?, kernel,
cmdline: CmdlineConfig::parse(vm_params.cmdline)?, cmdline: CmdlineConfig::parse(vm_params.cmdline)?,
disks, disks,
net, net,

View File

@ -463,7 +463,8 @@ fn get_host_cpu_phys_bits() -> u8 {
impl Vm { impl Vm {
pub fn new(config: Arc<VmConfig>, exit_evt: EventFd, reset_evt: EventFd) -> Result<Self> { pub fn new(config: Arc<VmConfig>, exit_evt: EventFd, reset_evt: EventFd) -> Result<Self> {
let kvm = Kvm::new().map_err(Error::KvmNew)?; let kvm = Kvm::new().map_err(Error::KvmNew)?;
let kernel = File::open(&config.kernel.path).map_err(Error::KernelFile)?; let kernel =
File::open(&config.kernel.as_ref().unwrap().path).map_err(Error::KernelFile)?;
let fd = kvm.create_vm().map_err(Error::VmCreate)?; let fd = kvm.create_vm().map_err(Error::VmCreate)?;
let fd = Arc::new(fd); let fd = Arc::new(fd);
let creation_ts = std::time::Instant::now(); let creation_ts = std::time::Instant::now();