virtualization_rs/virtualization/
virtual_machine.rs

1//! virtual machine module
2
3use crate::{
4    base::{Id, NSArray, NSError},
5    virtualization::boot_loader::VZBootLoader,
6    virtualization::entropy_device::VZEntropyDeviceConfiguration,
7    virtualization::memory_device::VZMemoryBalloonDeviceConfiguration,
8    virtualization::network_device::VZNetworkDeviceConfiguration,
9    virtualization::serial_port::VZSerialPortConfiguration,
10    virtualization::socket_device::VZSocketDeviceConfiguration,
11    virtualization::storage_device::VZStorageDeviceConfiguration,
12};
13
14use block::Block;
15use objc::runtime::BOOL;
16use objc::{class, msg_send, sel, sel_impl};
17use objc::{rc::StrongPtr, runtime::YES};
18
19/// builder for VZVirtualMachineConfiguration
20/// # Examples
21/// ```rust
22/// let conf = VZVirtualMachineConfigurationBuilder::new()
23///     .boot_loader(boot_loader)
24///     .cpu_count(cpu_count)
25///     .memory_size(memory_size)
26///     .entropy_devices(vec![entropy])
27///     .memory_balloon_devices(vec![memory_balloon])
28///     .network_devices(vec![network_device])
29///     .serial_ports(vec![serial])
30///     .storage_devices(vec![block_device])
31///     .build();
32/// ```
33pub struct VZVirtualMachineConfigurationBuilder {
34    conf: VZVirtualMachineConfiguration,
35}
36
37impl VZVirtualMachineConfigurationBuilder {
38    pub fn new() -> Self {
39        VZVirtualMachineConfigurationBuilder {
40            conf: VZVirtualMachineConfiguration::new(),
41        }
42    }
43
44    pub fn boot_loader<T: VZBootLoader>(mut self, boot_loader: T) -> Self {
45        self.conf.set_boot_loader(boot_loader);
46        self
47    }
48
49    pub fn cpu_count(mut self, cpu_count: usize) -> Self {
50        self.conf.set_cpu_count(cpu_count);
51        self
52    }
53
54    pub fn memory_size(mut self, memory_size: usize) -> Self {
55        self.conf.set_memory_size(memory_size);
56        self
57    }
58
59    pub fn entropy_devices<T: VZEntropyDeviceConfiguration>(
60        mut self,
61        entropy_devices: Vec<T>,
62    ) -> Self {
63        self.conf.set_entropy_devices(entropy_devices);
64        self
65    }
66
67    pub fn memory_balloon_devices<T: VZMemoryBalloonDeviceConfiguration>(
68        mut self,
69        memory_balloon_devices: Vec<T>,
70    ) -> Self {
71        self.conf.set_memory_balloon_devices(memory_balloon_devices);
72        self
73    }
74
75    pub fn network_devices<T: VZNetworkDeviceConfiguration>(
76        mut self,
77        network_devices: Vec<T>,
78    ) -> Self {
79        self.conf.set_network_devices(network_devices);
80        self
81    }
82
83    pub fn serial_ports<T: VZSerialPortConfiguration>(mut self, serial_ports: Vec<T>) -> Self {
84        self.conf.set_serial_ports(serial_ports);
85        self
86    }
87
88    pub fn socket_devices<T: VZSocketDeviceConfiguration>(
89        mut self,
90        socket_devices: Vec<T>,
91    ) -> Self {
92        self.conf.set_socket_devices(socket_devices);
93        self
94    }
95
96    pub fn storage_devices<T: VZStorageDeviceConfiguration>(
97        mut self,
98        storage_devices: Vec<T>,
99    ) -> Self {
100        self.conf.set_storage_devices(storage_devices);
101        self
102    }
103
104    pub fn build(self) -> VZVirtualMachineConfiguration {
105        self.conf
106    }
107}
108
109/// configure of virtual machine
110pub struct VZVirtualMachineConfiguration(StrongPtr);
111
112impl VZVirtualMachineConfiguration {
113    fn new() -> VZVirtualMachineConfiguration {
114        unsafe {
115            let obj = StrongPtr::new(msg_send![class!(VZVirtualMachineConfiguration), new]);
116            VZVirtualMachineConfiguration(obj)
117        }
118    }
119
120    fn set_boot_loader<T: VZBootLoader>(&mut self, boot_loader: T) {
121        unsafe {
122            let _: () = msg_send![*self.0, setBootLoader: boot_loader.id()];
123        }
124    }
125
126    fn set_cpu_count(&mut self, cnt: usize) {
127        unsafe {
128            let _: () = msg_send![*self.0, setCPUCount: cnt];
129        }
130    }
131
132    fn set_memory_size(&mut self, size: usize) {
133        unsafe {
134            let _: () = msg_send![*self.0, setMemorySize: size];
135        }
136    }
137
138    fn set_entropy_devices<T: VZEntropyDeviceConfiguration>(&mut self, devices: Vec<T>) {
139        let device_ids = devices.iter().map(|x| x.id()).collect();
140        let arr: NSArray<T> = NSArray::array_with_objects(device_ids);
141        unsafe {
142            let _: () = msg_send![*self.0, setEntropyDevices:*arr.p];
143        }
144    }
145
146    fn set_memory_balloon_devices<T: VZMemoryBalloonDeviceConfiguration>(
147        &mut self,
148        devices: Vec<T>,
149    ) {
150        let device_ids = devices.iter().map(|x| x.id()).collect();
151        let arr: NSArray<T> = NSArray::array_with_objects(device_ids);
152        unsafe {
153            let _: () = msg_send![*self.0, setMemoryBalloonDevices:*arr.p];
154        }
155    }
156
157    fn set_network_devices<T: VZNetworkDeviceConfiguration>(&mut self, devices: Vec<T>) {
158        let device_ids = devices.iter().map(|x| x.id()).collect();
159        let arr: NSArray<T> = NSArray::array_with_objects(device_ids);
160        unsafe {
161            let _: () = msg_send![*self.0, setNetworkDevices:*arr.p];
162        }
163    }
164
165    fn set_serial_ports<T: VZSerialPortConfiguration>(&mut self, devices: Vec<T>) {
166        let device_ids = devices.iter().map(|x| x.id()).collect();
167        let arr: NSArray<T> = NSArray::array_with_objects(device_ids);
168        unsafe {
169            let _: () = msg_send![*self.0, setSerialPorts:*arr.p];
170        }
171    }
172
173    fn set_socket_devices<T: VZSocketDeviceConfiguration>(&mut self, devices: Vec<T>) {
174        let device_ids = devices.iter().map(|x| x.id()).collect();
175        let arr: NSArray<T> = NSArray::array_with_objects(device_ids);
176        unsafe {
177            let _: () = msg_send![*self.0, setSocketDevices:*arr.p];
178        }
179    }
180
181    fn set_storage_devices<T: VZStorageDeviceConfiguration>(&mut self, devices: Vec<T>) {
182        let device_ids = devices.iter().map(|x| x.id()).collect();
183        let arr: NSArray<T> = NSArray::array_with_objects(device_ids);
184        unsafe {
185            let _: () = msg_send![*self.0, setStorageDevices:*arr.p];
186        }
187    }
188
189    pub fn validate_with_error(&self) -> Result<BOOL, NSError> {
190        unsafe {
191            let error = NSError(StrongPtr::new(0 as Id));
192            let obj: Id = msg_send![*self.0, validateWithError: &(*error.0)];
193            if error.code() != 0 {
194                Err(error)
195            } else {
196                Ok(obj as BOOL)
197            }
198        }
199    }
200}
201
202/// virtual machine
203#[derive(Clone)]
204pub struct VZVirtualMachine(StrongPtr);
205
206/// state of virtual machine
207#[derive(Debug)]
208pub enum VZVirtualMachineState {
209    /// Initial state before the virtual machine is started.
210    VZVirtualMachineStateStopped,
211
212    /// Running virtual machine.
213    VZVirtualMachineStateRunning,
214
215    /// A started virtual machine is paused. This state can only be transitioned from VZVirtualMachineStatePausing.
216    VZVirtualMachineStatePaused,
217
218    /// The virtual machine has encountered an internal error.
219    VZVirtualMachineStateError,
220
221    /// The virtual machine is configuring the hardware and starting.
222    VZVirtualMachineStateStarting,
223
224    /// The virtual machine is being paused. This is the intermediate state between VZVirtualMachineStateRunning and VZVirtualMachineStatePaused.
225    VZVirtualMachineStatePausing,
226
227    /// The virtual machine is being resumed. This is the intermediate state between VZVirtualMachineStatePaused and VZVirtualMachineStateRunning. */
228    VZVirtualMachineStateResuming,
229
230    /// Other
231    Other,
232}
233
234impl VZVirtualMachine {
235    pub fn new(conf: VZVirtualMachineConfiguration, queue: Id) -> VZVirtualMachine {
236        unsafe {
237            let i: Id = msg_send![class!(VZVirtualMachine), alloc];
238            let p = StrongPtr::new(msg_send![i, initWithConfiguration:*conf.0 queue:queue]);
239            VZVirtualMachine(p)
240        }
241    }
242
243    pub fn start_with_completion_handler(&self, completion_handler: &Block<(Id,), ()>) {
244        unsafe {
245            let _: Id = msg_send![*self.0, startWithCompletionHandler: completion_handler];
246        }
247    }
248
249    pub unsafe fn request_stop_with_error(&mut self) -> Result<bool, NSError> {
250        let error = NSError(StrongPtr::new(0 as Id));
251        let ret: BOOL = msg_send![*self.0, requestStopWithError:*error.0];
252        if error.code() != 0 {
253            Err(error)
254        } else {
255            Ok(ret == 1i8)
256        }
257    }
258
259    pub fn supported() -> bool {
260        unsafe {
261            let b: BOOL = msg_send![class!(VZVirtualMachine), isSupported];
262            b == YES
263        }
264    }
265
266    pub unsafe fn state(&self) -> VZVirtualMachineState {
267        let n: isize = msg_send![*self.0, state];
268        match n {
269            0 => VZVirtualMachineState::VZVirtualMachineStateStopped,
270            1 => VZVirtualMachineState::VZVirtualMachineStateRunning,
271            2 => VZVirtualMachineState::VZVirtualMachineStatePaused,
272            3 => VZVirtualMachineState::VZVirtualMachineStateError,
273            4 => VZVirtualMachineState::VZVirtualMachineStateStarting,
274            5 => VZVirtualMachineState::VZVirtualMachineStatePausing,
275            6 => VZVirtualMachineState::VZVirtualMachineStateResuming,
276            _ => VZVirtualMachineState::Other,
277        }
278    }
279}