1 // Copyright 2021, The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //! Function and types for VM configuration. 16 17 use anyhow::{bail, Error}; 18 use serde::{Deserialize, Serialize}; 19 use std::fs::File; 20 use std::io::BufReader; 21 22 /// Configuration for a particular VM to be started. 23 #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] 24 pub struct VmConfig { 25 /// The filename of the kernel image, if any. 26 pub kernel: Option<String>, 27 /// The filename of the initial ramdisk for the kernel, if any. 28 pub initrd: Option<String>, 29 /// Parameters to pass to the kernel. As far as the VMM and boot protocol are concerned this is 30 /// just a string, but typically it will contain multiple parameters separated by spaces. 31 pub params: Option<String>, 32 /// The bootloader to use. If this is supplied then the kernel and initrd must not be supplied; 33 /// the bootloader is instead responsibly for loading the kernel from one of the disks. 34 pub bootloader: Option<String>, 35 /// Disk images to be made available to the VM. 36 #[serde(default)] 37 pub disks: Vec<DiskImage>, 38 } 39 40 impl VmConfig { 41 /// Ensure that the configuration has a valid combination of fields set, or return an error if 42 /// not. 43 pub fn validate(&self) -> Result<(), Error> { 44 if self.bootloader.is_none() && self.kernel.is_none() { 45 bail!("VM must have either a bootloader or a kernel image."); 46 } 47 if self.bootloader.is_some() && (self.kernel.is_some() || self.initrd.is_some()) { 48 bail!("Can't have both bootloader and kernel/initrd image."); 49 } 50 Ok(()) 51 } 52 53 /// Load the configuration for a VM from the given JSON file. 54 pub fn load(file: &File) -> Result<VmConfig, Error> { 55 let buffered = BufReader::new(file); 56 Ok(serde_json::from_reader(buffered)?) 57 } 58 } 59 60 /// A disk image to be made available to the VM. 61 #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] 62 pub struct DiskImage { 63 /// The filename of the disk image. 64 pub image: String, 65 /// Whether this disk should be writable by the VM. 66 pub writable: bool, 67 } 68