1ba8cd4d5SRob Bradford // Copyright © 2020 Intel Corporation
2ba8cd4d5SRob Bradford //
3ba8cd4d5SRob Bradford // SPDX-License-Identifier: Apache-2.0
4ba8cd4d5SRob Bradford //
5ba8cd4d5SRob Bradford
61f13165fSPhilipp Schuster #[cfg(test)]
71f13165fSPhilipp Schuster #[path = "../test_util.rs"]
81f13165fSPhilipp Schuster mod test_util;
91f13165fSPhilipp Schuster
1088a9f799SRob Bradford use std::io::Read;
1188a9f799SRob Bradford use std::marker::PhantomData;
1288a9f799SRob Bradford use std::os::unix::net::UnixStream;
13ab6e1bd2SPhilipp Schuster use std::process;
1488a9f799SRob Bradford
1561e57e1cSRuoqing He use api_client::{
1661e57e1cSRuoqing He simple_api_command, simple_api_command_with_fds, simple_api_full_command,
1761e57e1cSRuoqing He Error as ApiClientError,
1861e57e1cSRuoqing He };
19d1f337aeSRavi kumar Veeramally use clap::{Arg, ArgAction, ArgMatches, Command};
20a86a2711SRob Bradford use option_parser::{ByteSized, ByteSizedParseError};
21ab6e1bd2SPhilipp Schuster use thiserror::Error;
2233c15ca2SSongqian Li use vmm::config::RestoreConfig;
2333c15ca2SSongqian Li use vmm::vm_config::{
2433c15ca2SSongqian Li DeviceConfig, DiskConfig, FsConfig, NetConfig, PmemConfig, UserDeviceConfig, VdpaConfig,
2533c15ca2SSongqian Li VsockConfig,
2633c15ca2SSongqian Li };
27a64d27f8SOmer Faruk Bayram #[cfg(feature = "dbus_api")]
28036e7e37SOmer Faruk Bayram use zbus::{proxy, zvariant::Optional};
29a64d27f8SOmer Faruk Bayram
30a64d27f8SOmer Faruk Bayram type ApiResult = Result<(), Error>;
31ba8cd4d5SRob Bradford
32ab6e1bd2SPhilipp Schuster #[derive(Error, Debug)]
33ba8cd4d5SRob Bradford enum Error {
345711f319SPhilipp Schuster #[error("http client error")]
35ab6e1bd2SPhilipp Schuster HttpApiClient(#[source] ApiClientError),
36a64d27f8SOmer Faruk Bayram #[cfg(feature = "dbus_api")]
375711f319SPhilipp Schuster #[error("dbus api client error")]
38ab6e1bd2SPhilipp Schuster DBusApiClient(#[source] zbus::Error),
395711f319SPhilipp Schuster #[error("Error parsing CPU count")]
40ab6e1bd2SPhilipp Schuster InvalidCpuCount(#[source] std::num::ParseIntError),
415711f319SPhilipp Schuster #[error("Error parsing memory size")]
42ab6e1bd2SPhilipp Schuster InvalidMemorySize(#[source] ByteSizedParseError),
435711f319SPhilipp Schuster #[error("Error parsing balloon size")]
44ab6e1bd2SPhilipp Schuster InvalidBalloonSize(#[source] ByteSizedParseError),
455711f319SPhilipp Schuster #[error("Error parsing device syntax")]
46ab6e1bd2SPhilipp Schuster AddDeviceConfig(#[source] vmm::config::Error),
475711f319SPhilipp Schuster #[error("Error parsing disk syntax")]
48ab6e1bd2SPhilipp Schuster AddDiskConfig(#[source] vmm::config::Error),
495711f319SPhilipp Schuster #[error("Error parsing filesystem syntax")]
50ab6e1bd2SPhilipp Schuster AddFsConfig(#[source] vmm::config::Error),
515711f319SPhilipp Schuster #[error("Error parsing persistent memory syntax")]
52ab6e1bd2SPhilipp Schuster AddPmemConfig(#[source] vmm::config::Error),
535711f319SPhilipp Schuster #[error("Error parsing network syntax")]
54ab6e1bd2SPhilipp Schuster AddNetConfig(#[source] vmm::config::Error),
555711f319SPhilipp Schuster #[error("Error parsing user device syntax")]
56ab6e1bd2SPhilipp Schuster AddUserDeviceConfig(#[source] vmm::config::Error),
575711f319SPhilipp Schuster #[error("Error parsing vDPA device syntax")]
58ab6e1bd2SPhilipp Schuster AddVdpaConfig(#[source] vmm::config::Error),
595711f319SPhilipp Schuster #[error("Error parsing vsock syntax")]
60ab6e1bd2SPhilipp Schuster AddVsockConfig(#[source] vmm::config::Error),
615711f319SPhilipp Schuster #[error("Error parsing restore syntax")]
62ab6e1bd2SPhilipp Schuster Restore(#[source] vmm::config::Error),
635711f319SPhilipp Schuster #[error("Error reading from stdin")]
64ab6e1bd2SPhilipp Schuster ReadingStdin(#[source] std::io::Error),
655711f319SPhilipp Schuster #[error("Error reading from file")]
66ab6e1bd2SPhilipp Schuster ReadingFile(#[source] std::io::Error),
6790e7accfSRob Bradford }
6890e7accfSRob Bradford
69a64d27f8SOmer Faruk Bayram enum TargetApi<'a> {
70a64d27f8SOmer Faruk Bayram HttpApi(UnixStream, PhantomData<&'a ()>),
71a64d27f8SOmer Faruk Bayram #[cfg(feature = "dbus_api")]
72a64d27f8SOmer Faruk Bayram DBusApi(DBusApi1ProxyBlocking<'a>),
73a64d27f8SOmer Faruk Bayram }
74a64d27f8SOmer Faruk Bayram
75a64d27f8SOmer Faruk Bayram #[cfg(feature = "dbus_api")]
76036e7e37SOmer Faruk Bayram #[proxy(name = "org.cloudhypervisor.DBusApi1", assume_defaults = false)]
77a64d27f8SOmer Faruk Bayram trait DBusApi1 {
vmm_ping(&self) -> zbus::Result<String>78a64d27f8SOmer Faruk Bayram fn vmm_ping(&self) -> zbus::Result<String>;
vmm_shutdown(&self) -> zbus::Result<()>79a64d27f8SOmer Faruk Bayram fn vmm_shutdown(&self) -> zbus::Result<()>;
vm_add_device(&self, device_config: &str) -> zbus::Result<Optional<String>>80a64d27f8SOmer Faruk Bayram fn vm_add_device(&self, device_config: &str) -> zbus::Result<Optional<String>>;
vm_add_disk(&self, disk_config: &str) -> zbus::Result<Optional<String>>81a64d27f8SOmer Faruk Bayram fn vm_add_disk(&self, disk_config: &str) -> zbus::Result<Optional<String>>;
vm_add_fs(&self, fs_config: &str) -> zbus::Result<Optional<String>>82a64d27f8SOmer Faruk Bayram fn vm_add_fs(&self, fs_config: &str) -> zbus::Result<Optional<String>>;
vm_add_net(&self, net_config: &str) -> zbus::Result<Optional<String>>83a64d27f8SOmer Faruk Bayram fn vm_add_net(&self, net_config: &str) -> zbus::Result<Optional<String>>;
vm_add_pmem(&self, pmem_config: &str) -> zbus::Result<Optional<String>>84a64d27f8SOmer Faruk Bayram fn vm_add_pmem(&self, pmem_config: &str) -> zbus::Result<Optional<String>>;
vm_add_user_device(&self, vm_add_user_device: &str) -> zbus::Result<Optional<String>>85a64d27f8SOmer Faruk Bayram fn vm_add_user_device(&self, vm_add_user_device: &str) -> zbus::Result<Optional<String>>;
vm_add_vdpa(&self, vdpa_config: &str) -> zbus::Result<Optional<String>>86a64d27f8SOmer Faruk Bayram fn vm_add_vdpa(&self, vdpa_config: &str) -> zbus::Result<Optional<String>>;
vm_add_vsock(&self, vsock_config: &str) -> zbus::Result<Optional<String>>87a64d27f8SOmer Faruk Bayram fn vm_add_vsock(&self, vsock_config: &str) -> zbus::Result<Optional<String>>;
vm_boot(&self) -> zbus::Result<()>88a64d27f8SOmer Faruk Bayram fn vm_boot(&self) -> zbus::Result<()>;
vm_coredump(&self, vm_coredump_data: &str) -> zbus::Result<()>89a64d27f8SOmer Faruk Bayram fn vm_coredump(&self, vm_coredump_data: &str) -> zbus::Result<()>;
vm_counters(&self) -> zbus::Result<Optional<String>>90a64d27f8SOmer Faruk Bayram fn vm_counters(&self) -> zbus::Result<Optional<String>>;
vm_create(&self, vm_config: &str) -> zbus::Result<()>91a64d27f8SOmer Faruk Bayram fn vm_create(&self, vm_config: &str) -> zbus::Result<()>;
vm_delete(&self) -> zbus::Result<()>92a64d27f8SOmer Faruk Bayram fn vm_delete(&self) -> zbus::Result<()>;
vm_info(&self) -> zbus::Result<String>93a64d27f8SOmer Faruk Bayram fn vm_info(&self) -> zbus::Result<String>;
vm_pause(&self) -> zbus::Result<()>94a64d27f8SOmer Faruk Bayram fn vm_pause(&self) -> zbus::Result<()>;
vm_power_button(&self) -> zbus::Result<()>95a64d27f8SOmer Faruk Bayram fn vm_power_button(&self) -> zbus::Result<()>;
vm_reboot(&self) -> zbus::Result<()>96a64d27f8SOmer Faruk Bayram fn vm_reboot(&self) -> zbus::Result<()>;
vm_remove_device(&self, vm_remove_device: &str) -> zbus::Result<()>97a64d27f8SOmer Faruk Bayram fn vm_remove_device(&self, vm_remove_device: &str) -> zbus::Result<()>;
vm_resize(&self, vm_resize: &str) -> zbus::Result<()>98a64d27f8SOmer Faruk Bayram fn vm_resize(&self, vm_resize: &str) -> zbus::Result<()>;
vm_resize_zone(&self, vm_resize_zone: &str) -> zbus::Result<()>99a64d27f8SOmer Faruk Bayram fn vm_resize_zone(&self, vm_resize_zone: &str) -> zbus::Result<()>;
vm_restore(&self, restore_config: &str) -> zbus::Result<()>100a64d27f8SOmer Faruk Bayram fn vm_restore(&self, restore_config: &str) -> zbus::Result<()>;
vm_receive_migration(&self, receive_migration_data: &str) -> zbus::Result<()>101a64d27f8SOmer Faruk Bayram fn vm_receive_migration(&self, receive_migration_data: &str) -> zbus::Result<()>;
vm_send_migration(&self, receive_migration_data: &str) -> zbus::Result<()>102a64d27f8SOmer Faruk Bayram fn vm_send_migration(&self, receive_migration_data: &str) -> zbus::Result<()>;
vm_resume(&self) -> zbus::Result<()>103a64d27f8SOmer Faruk Bayram fn vm_resume(&self) -> zbus::Result<()>;
vm_shutdown(&self) -> zbus::Result<()>104a64d27f8SOmer Faruk Bayram fn vm_shutdown(&self) -> zbus::Result<()>;
vm_snapshot(&self, vm_snapshot_config: &str) -> zbus::Result<()>105a64d27f8SOmer Faruk Bayram fn vm_snapshot(&self, vm_snapshot_config: &str) -> zbus::Result<()>;
106a64d27f8SOmer Faruk Bayram }
107a64d27f8SOmer Faruk Bayram
108a64d27f8SOmer Faruk Bayram #[cfg(feature = "dbus_api")]
109a64d27f8SOmer Faruk Bayram impl<'a> DBusApi1ProxyBlocking<'a> {
new_connection(name: &'a str, path: &'a str, system_bus: bool) -> Result<Self, zbus::Error>110a64d27f8SOmer Faruk Bayram fn new_connection(name: &'a str, path: &'a str, system_bus: bool) -> Result<Self, zbus::Error> {
111a64d27f8SOmer Faruk Bayram let connection = if system_bus {
112a64d27f8SOmer Faruk Bayram zbus::blocking::Connection::system()?
113a64d27f8SOmer Faruk Bayram } else {
114a64d27f8SOmer Faruk Bayram zbus::blocking::Connection::session()?
115a64d27f8SOmer Faruk Bayram };
116a64d27f8SOmer Faruk Bayram
117a64d27f8SOmer Faruk Bayram Self::builder(&connection)
118a64d27f8SOmer Faruk Bayram .destination(name)?
119a64d27f8SOmer Faruk Bayram .path(path)?
120a64d27f8SOmer Faruk Bayram .build()
121a64d27f8SOmer Faruk Bayram }
122a64d27f8SOmer Faruk Bayram
print_response(&self, result: zbus::Result<Optional<String>>) -> ApiResult123a64d27f8SOmer Faruk Bayram fn print_response(&self, result: zbus::Result<Optional<String>>) -> ApiResult {
124a64d27f8SOmer Faruk Bayram result
125a64d27f8SOmer Faruk Bayram .map(|ret| {
126a64d27f8SOmer Faruk Bayram if let Some(ref output) = *ret {
127a64d27f8SOmer Faruk Bayram println!("{output}");
128a64d27f8SOmer Faruk Bayram }
129a64d27f8SOmer Faruk Bayram })
130a64d27f8SOmer Faruk Bayram .map_err(Error::DBusApiClient)
131a64d27f8SOmer Faruk Bayram }
132a64d27f8SOmer Faruk Bayram
api_vmm_ping(&self) -> ApiResult133a64d27f8SOmer Faruk Bayram fn api_vmm_ping(&self) -> ApiResult {
134a64d27f8SOmer Faruk Bayram self.vmm_ping()
135a64d27f8SOmer Faruk Bayram .map(|ping| println!("{ping}"))
136a64d27f8SOmer Faruk Bayram .map_err(Error::DBusApiClient)
137a64d27f8SOmer Faruk Bayram }
138a64d27f8SOmer Faruk Bayram
api_vmm_shutdown(&self) -> ApiResult139a64d27f8SOmer Faruk Bayram fn api_vmm_shutdown(&self) -> ApiResult {
140a64d27f8SOmer Faruk Bayram self.vmm_shutdown().map_err(Error::DBusApiClient)
141a64d27f8SOmer Faruk Bayram }
142a64d27f8SOmer Faruk Bayram
api_vm_add_device(&self, device_config: &str) -> ApiResult143a64d27f8SOmer Faruk Bayram fn api_vm_add_device(&self, device_config: &str) -> ApiResult {
144a64d27f8SOmer Faruk Bayram self.print_response(self.vm_add_device(device_config))
145a64d27f8SOmer Faruk Bayram }
146a64d27f8SOmer Faruk Bayram
api_vm_add_disk(&self, disk_config: &str) -> ApiResult147a64d27f8SOmer Faruk Bayram fn api_vm_add_disk(&self, disk_config: &str) -> ApiResult {
148a64d27f8SOmer Faruk Bayram self.print_response(self.vm_add_disk(disk_config))
149a64d27f8SOmer Faruk Bayram }
150a64d27f8SOmer Faruk Bayram
api_vm_add_fs(&self, fs_config: &str) -> ApiResult151a64d27f8SOmer Faruk Bayram fn api_vm_add_fs(&self, fs_config: &str) -> ApiResult {
152a64d27f8SOmer Faruk Bayram self.print_response(self.vm_add_fs(fs_config))
153a64d27f8SOmer Faruk Bayram }
154a64d27f8SOmer Faruk Bayram
api_vm_add_net(&self, net_config: &str) -> ApiResult155a64d27f8SOmer Faruk Bayram fn api_vm_add_net(&self, net_config: &str) -> ApiResult {
156a64d27f8SOmer Faruk Bayram self.print_response(self.vm_add_net(net_config))
157a64d27f8SOmer Faruk Bayram }
158a64d27f8SOmer Faruk Bayram
api_vm_add_pmem(&self, pmem_config: &str) -> ApiResult159a64d27f8SOmer Faruk Bayram fn api_vm_add_pmem(&self, pmem_config: &str) -> ApiResult {
160a64d27f8SOmer Faruk Bayram self.print_response(self.vm_add_pmem(pmem_config))
161a64d27f8SOmer Faruk Bayram }
162a64d27f8SOmer Faruk Bayram
api_vm_add_user_device(&self, vm_add_user_device: &str) -> ApiResult163a64d27f8SOmer Faruk Bayram fn api_vm_add_user_device(&self, vm_add_user_device: &str) -> ApiResult {
164a64d27f8SOmer Faruk Bayram self.print_response(self.vm_add_user_device(vm_add_user_device))
165a64d27f8SOmer Faruk Bayram }
166a64d27f8SOmer Faruk Bayram
api_vm_add_vdpa(&self, vdpa_config: &str) -> ApiResult167a64d27f8SOmer Faruk Bayram fn api_vm_add_vdpa(&self, vdpa_config: &str) -> ApiResult {
168a64d27f8SOmer Faruk Bayram self.print_response(self.vm_add_vdpa(vdpa_config))
169a64d27f8SOmer Faruk Bayram }
170a64d27f8SOmer Faruk Bayram
api_vm_add_vsock(&self, vsock_config: &str) -> ApiResult171a64d27f8SOmer Faruk Bayram fn api_vm_add_vsock(&self, vsock_config: &str) -> ApiResult {
172a64d27f8SOmer Faruk Bayram self.print_response(self.vm_add_vsock(vsock_config))
173a64d27f8SOmer Faruk Bayram }
174a64d27f8SOmer Faruk Bayram
api_vm_boot(&self) -> ApiResult175a64d27f8SOmer Faruk Bayram fn api_vm_boot(&self) -> ApiResult {
176a64d27f8SOmer Faruk Bayram self.vm_boot().map_err(Error::DBusApiClient)
177a64d27f8SOmer Faruk Bayram }
178a64d27f8SOmer Faruk Bayram
api_vm_coredump(&self, vm_coredump_data: &str) -> ApiResult179a64d27f8SOmer Faruk Bayram fn api_vm_coredump(&self, vm_coredump_data: &str) -> ApiResult {
180a64d27f8SOmer Faruk Bayram self.vm_coredump(vm_coredump_data)
181a64d27f8SOmer Faruk Bayram .map_err(Error::DBusApiClient)
182a64d27f8SOmer Faruk Bayram }
183a64d27f8SOmer Faruk Bayram
api_vm_counters(&self) -> ApiResult184a64d27f8SOmer Faruk Bayram fn api_vm_counters(&self) -> ApiResult {
185a64d27f8SOmer Faruk Bayram self.print_response(self.vm_counters())
186a64d27f8SOmer Faruk Bayram }
187a64d27f8SOmer Faruk Bayram
api_vm_create(&self, vm_config: &str) -> ApiResult188a64d27f8SOmer Faruk Bayram fn api_vm_create(&self, vm_config: &str) -> ApiResult {
189a64d27f8SOmer Faruk Bayram self.vm_create(vm_config).map_err(Error::DBusApiClient)
190a64d27f8SOmer Faruk Bayram }
191a64d27f8SOmer Faruk Bayram
api_vm_delete(&self) -> ApiResult192a64d27f8SOmer Faruk Bayram fn api_vm_delete(&self) -> ApiResult {
193a64d27f8SOmer Faruk Bayram self.vm_delete().map_err(Error::DBusApiClient)
194a64d27f8SOmer Faruk Bayram }
195a64d27f8SOmer Faruk Bayram
api_vm_info(&self) -> ApiResult196a64d27f8SOmer Faruk Bayram fn api_vm_info(&self) -> ApiResult {
197a64d27f8SOmer Faruk Bayram self.vm_info()
198a64d27f8SOmer Faruk Bayram .map(|info| println!("{info}"))
199a64d27f8SOmer Faruk Bayram .map_err(Error::DBusApiClient)
200a64d27f8SOmer Faruk Bayram }
201a64d27f8SOmer Faruk Bayram
api_vm_pause(&self) -> ApiResult202a64d27f8SOmer Faruk Bayram fn api_vm_pause(&self) -> ApiResult {
203a64d27f8SOmer Faruk Bayram self.vm_pause().map_err(Error::DBusApiClient)
204a64d27f8SOmer Faruk Bayram }
205a64d27f8SOmer Faruk Bayram
api_vm_power_button(&self) -> ApiResult206a64d27f8SOmer Faruk Bayram fn api_vm_power_button(&self) -> ApiResult {
207a64d27f8SOmer Faruk Bayram self.vm_power_button().map_err(Error::DBusApiClient)
208a64d27f8SOmer Faruk Bayram }
209a64d27f8SOmer Faruk Bayram
api_vm_reboot(&self) -> ApiResult210a64d27f8SOmer Faruk Bayram fn api_vm_reboot(&self) -> ApiResult {
211a64d27f8SOmer Faruk Bayram self.vm_reboot().map_err(Error::DBusApiClient)
212a64d27f8SOmer Faruk Bayram }
213a64d27f8SOmer Faruk Bayram
api_vm_remove_device(&self, vm_remove_device: &str) -> ApiResult214a64d27f8SOmer Faruk Bayram fn api_vm_remove_device(&self, vm_remove_device: &str) -> ApiResult {
215a64d27f8SOmer Faruk Bayram self.vm_remove_device(vm_remove_device)
216a64d27f8SOmer Faruk Bayram .map_err(Error::DBusApiClient)
217a64d27f8SOmer Faruk Bayram }
218a64d27f8SOmer Faruk Bayram
api_vm_resize(&self, vm_resize: &str) -> ApiResult219a64d27f8SOmer Faruk Bayram fn api_vm_resize(&self, vm_resize: &str) -> ApiResult {
220a64d27f8SOmer Faruk Bayram self.vm_resize(vm_resize).map_err(Error::DBusApiClient)
221a64d27f8SOmer Faruk Bayram }
222a64d27f8SOmer Faruk Bayram
api_vm_resize_zone(&self, vm_resize_zone: &str) -> ApiResult223a64d27f8SOmer Faruk Bayram fn api_vm_resize_zone(&self, vm_resize_zone: &str) -> ApiResult {
224a64d27f8SOmer Faruk Bayram self.vm_resize_zone(vm_resize_zone)
225a64d27f8SOmer Faruk Bayram .map_err(Error::DBusApiClient)
226a64d27f8SOmer Faruk Bayram }
227a64d27f8SOmer Faruk Bayram
api_vm_restore(&self, restore_config: &str) -> ApiResult228a64d27f8SOmer Faruk Bayram fn api_vm_restore(&self, restore_config: &str) -> ApiResult {
229a64d27f8SOmer Faruk Bayram self.vm_restore(restore_config)
230a64d27f8SOmer Faruk Bayram .map_err(Error::DBusApiClient)
231a64d27f8SOmer Faruk Bayram }
232a64d27f8SOmer Faruk Bayram
api_vm_receive_migration(&self, receive_migration_data: &str) -> ApiResult233a64d27f8SOmer Faruk Bayram fn api_vm_receive_migration(&self, receive_migration_data: &str) -> ApiResult {
234a64d27f8SOmer Faruk Bayram self.vm_receive_migration(receive_migration_data)
235a64d27f8SOmer Faruk Bayram .map_err(Error::DBusApiClient)
236a64d27f8SOmer Faruk Bayram }
237a64d27f8SOmer Faruk Bayram
api_vm_send_migration(&self, send_migration_data: &str) -> ApiResult238a64d27f8SOmer Faruk Bayram fn api_vm_send_migration(&self, send_migration_data: &str) -> ApiResult {
239a64d27f8SOmer Faruk Bayram self.vm_send_migration(send_migration_data)
240a64d27f8SOmer Faruk Bayram .map_err(Error::DBusApiClient)
241a64d27f8SOmer Faruk Bayram }
242a64d27f8SOmer Faruk Bayram
api_vm_resume(&self) -> ApiResult243a64d27f8SOmer Faruk Bayram fn api_vm_resume(&self) -> ApiResult {
244a64d27f8SOmer Faruk Bayram self.vm_resume().map_err(Error::DBusApiClient)
245a64d27f8SOmer Faruk Bayram }
246a64d27f8SOmer Faruk Bayram
api_vm_shutdown(&self) -> ApiResult247a64d27f8SOmer Faruk Bayram fn api_vm_shutdown(&self) -> ApiResult {
248a64d27f8SOmer Faruk Bayram self.vm_shutdown().map_err(Error::DBusApiClient)
249a64d27f8SOmer Faruk Bayram }
250a64d27f8SOmer Faruk Bayram
api_vm_snapshot(&self, vm_snapshot_config: &str) -> ApiResult251a64d27f8SOmer Faruk Bayram fn api_vm_snapshot(&self, vm_snapshot_config: &str) -> ApiResult {
252a64d27f8SOmer Faruk Bayram self.vm_snapshot(vm_snapshot_config)
253a64d27f8SOmer Faruk Bayram .map_err(Error::DBusApiClient)
254a64d27f8SOmer Faruk Bayram }
255a64d27f8SOmer Faruk Bayram }
256a64d27f8SOmer Faruk Bayram
2570aab960bSRuoqing He impl TargetApi<'_> {
do_command(&mut self, matches: &ArgMatches) -> ApiResult258d1f337aeSRavi kumar Veeramally fn do_command(&mut self, matches: &ArgMatches) -> ApiResult {
259a64d27f8SOmer Faruk Bayram match self {
260d1f337aeSRavi kumar Veeramally Self::HttpApi(api_socket, _) => rest_api_do_command(matches, api_socket),
261a64d27f8SOmer Faruk Bayram #[cfg(feature = "dbus_api")]
262d1f337aeSRavi kumar Veeramally Self::DBusApi(proxy) => dbus_api_do_command(matches, proxy),
263a64d27f8SOmer Faruk Bayram }
264a64d27f8SOmer Faruk Bayram }
265a64d27f8SOmer Faruk Bayram }
266a64d27f8SOmer Faruk Bayram
rest_api_do_command(matches: &ArgMatches, socket: &mut UnixStream) -> ApiResult267d1f337aeSRavi kumar Veeramally fn rest_api_do_command(matches: &ArgMatches, socket: &mut UnixStream) -> ApiResult {
268d1f337aeSRavi kumar Veeramally match matches.subcommand_name() {
269d1f337aeSRavi kumar Veeramally Some("boot") => {
270a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "boot", None).map_err(Error::HttpApiClient)
271a64d27f8SOmer Faruk Bayram }
272d1f337aeSRavi kumar Veeramally Some("delete") => {
273a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "delete", None).map_err(Error::HttpApiClient)
274a64d27f8SOmer Faruk Bayram }
275d1f337aeSRavi kumar Veeramally Some("shutdown-vmm") => simple_api_full_command(socket, "PUT", "vmm.shutdown", None)
276d1f337aeSRavi kumar Veeramally .map_err(Error::HttpApiClient),
277d1f337aeSRavi kumar Veeramally Some("resume") => {
278a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "resume", None).map_err(Error::HttpApiClient)
279a64d27f8SOmer Faruk Bayram }
280d1f337aeSRavi kumar Veeramally Some("power-button") => {
281a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "power-button", None).map_err(Error::HttpApiClient)
282a64d27f8SOmer Faruk Bayram }
283d1f337aeSRavi kumar Veeramally Some("reboot") => {
284a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "reboot", None).map_err(Error::HttpApiClient)
285a64d27f8SOmer Faruk Bayram }
286d1f337aeSRavi kumar Veeramally Some("pause") => {
287a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "pause", None).map_err(Error::HttpApiClient)
288a64d27f8SOmer Faruk Bayram }
289d1f337aeSRavi kumar Veeramally Some("info") => {
290a64d27f8SOmer Faruk Bayram simple_api_command(socket, "GET", "info", None).map_err(Error::HttpApiClient)
291a64d27f8SOmer Faruk Bayram }
292d1f337aeSRavi kumar Veeramally Some("counters") => {
293a64d27f8SOmer Faruk Bayram simple_api_command(socket, "GET", "counters", None).map_err(Error::HttpApiClient)
294a64d27f8SOmer Faruk Bayram }
295d1f337aeSRavi kumar Veeramally Some("ping") => {
296a64d27f8SOmer Faruk Bayram simple_api_full_command(socket, "GET", "vmm.ping", None).map_err(Error::HttpApiClient)
297a64d27f8SOmer Faruk Bayram }
298d1f337aeSRavi kumar Veeramally Some("shutdown") => {
299a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "shutdown", None).map_err(Error::HttpApiClient)
300a64d27f8SOmer Faruk Bayram }
3011708561cSYi Wang Some("nmi") => simple_api_command(socket, "PUT", "nmi", None).map_err(Error::HttpApiClient),
302d1f337aeSRavi kumar Veeramally Some("resize") => {
303d1f337aeSRavi kumar Veeramally let resize = resize_config(
304d1f337aeSRavi kumar Veeramally matches
305d1f337aeSRavi kumar Veeramally .subcommand_matches("resize")
306d1f337aeSRavi kumar Veeramally .unwrap()
307d1f337aeSRavi kumar Veeramally .get_one::<String>("cpus")
308d1f337aeSRavi kumar Veeramally .map(|x| x as &str),
309d1f337aeSRavi kumar Veeramally matches
310d1f337aeSRavi kumar Veeramally .subcommand_matches("resize")
311d1f337aeSRavi kumar Veeramally .unwrap()
312d1f337aeSRavi kumar Veeramally .get_one::<String>("memory")
313d1f337aeSRavi kumar Veeramally .map(|x| x as &str),
314d1f337aeSRavi kumar Veeramally matches
315d1f337aeSRavi kumar Veeramally .subcommand_matches("resize")
316d1f337aeSRavi kumar Veeramally .unwrap()
317d1f337aeSRavi kumar Veeramally .get_one::<String>("balloon")
318d1f337aeSRavi kumar Veeramally .map(|x| x as &str),
319d1f337aeSRavi kumar Veeramally )?;
320a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "resize", Some(&resize)).map_err(Error::HttpApiClient)
321a64d27f8SOmer Faruk Bayram }
322d1f337aeSRavi kumar Veeramally Some("resize-zone") => {
323d1f337aeSRavi kumar Veeramally let resize_zone = resize_zone_config(
324d1f337aeSRavi kumar Veeramally matches
325d1f337aeSRavi kumar Veeramally .subcommand_matches("resize-zone")
326d1f337aeSRavi kumar Veeramally .unwrap()
327d1f337aeSRavi kumar Veeramally .get_one::<String>("id")
328d1f337aeSRavi kumar Veeramally .unwrap(),
329d1f337aeSRavi kumar Veeramally matches
330d1f337aeSRavi kumar Veeramally .subcommand_matches("resize-zone")
331d1f337aeSRavi kumar Veeramally .unwrap()
332d1f337aeSRavi kumar Veeramally .get_one::<String>("size")
333d1f337aeSRavi kumar Veeramally .unwrap(),
334d1f337aeSRavi kumar Veeramally )?;
335a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "resize-zone", Some(&resize_zone))
336a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
337a64d27f8SOmer Faruk Bayram }
338d1f337aeSRavi kumar Veeramally Some("add-device") => {
339d1f337aeSRavi kumar Veeramally let device_config = add_device_config(
340d1f337aeSRavi kumar Veeramally matches
341d1f337aeSRavi kumar Veeramally .subcommand_matches("add-device")
342d1f337aeSRavi kumar Veeramally .unwrap()
343d1f337aeSRavi kumar Veeramally .get_one::<String>("device_config")
344d1f337aeSRavi kumar Veeramally .unwrap(),
345d1f337aeSRavi kumar Veeramally )?;
346a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "add-device", Some(&device_config))
347a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
348a64d27f8SOmer Faruk Bayram }
349d1f337aeSRavi kumar Veeramally Some("remove-device") => {
350d1f337aeSRavi kumar Veeramally let remove_device_data = remove_device_config(
351d1f337aeSRavi kumar Veeramally matches
352d1f337aeSRavi kumar Veeramally .subcommand_matches("remove-device")
353d1f337aeSRavi kumar Veeramally .unwrap()
354d1f337aeSRavi kumar Veeramally .get_one::<String>("id")
355d1f337aeSRavi kumar Veeramally .unwrap(),
356d1f337aeSRavi kumar Veeramally );
357a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "remove-device", Some(&remove_device_data))
358a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
359a64d27f8SOmer Faruk Bayram }
360d1f337aeSRavi kumar Veeramally Some("add-disk") => {
361d1f337aeSRavi kumar Veeramally let disk_config = add_disk_config(
362d1f337aeSRavi kumar Veeramally matches
363d1f337aeSRavi kumar Veeramally .subcommand_matches("add-disk")
364d1f337aeSRavi kumar Veeramally .unwrap()
365d1f337aeSRavi kumar Veeramally .get_one::<String>("disk_config")
366d1f337aeSRavi kumar Veeramally .unwrap(),
367d1f337aeSRavi kumar Veeramally )?;
368a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "add-disk", Some(&disk_config))
369a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
370a64d27f8SOmer Faruk Bayram }
371d1f337aeSRavi kumar Veeramally Some("add-fs") => {
372d1f337aeSRavi kumar Veeramally let fs_config = add_fs_config(
373d1f337aeSRavi kumar Veeramally matches
374d1f337aeSRavi kumar Veeramally .subcommand_matches("add-fs")
375d1f337aeSRavi kumar Veeramally .unwrap()
376d1f337aeSRavi kumar Veeramally .get_one::<String>("fs_config")
377d1f337aeSRavi kumar Veeramally .unwrap(),
378d1f337aeSRavi kumar Veeramally )?;
379a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "add-fs", Some(&fs_config))
380a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
381a64d27f8SOmer Faruk Bayram }
382d1f337aeSRavi kumar Veeramally Some("add-pmem") => {
383d1f337aeSRavi kumar Veeramally let pmem_config = add_pmem_config(
384d1f337aeSRavi kumar Veeramally matches
385d1f337aeSRavi kumar Veeramally .subcommand_matches("add-pmem")
386d1f337aeSRavi kumar Veeramally .unwrap()
387d1f337aeSRavi kumar Veeramally .get_one::<String>("pmem_config")
388d1f337aeSRavi kumar Veeramally .unwrap(),
389d1f337aeSRavi kumar Veeramally )?;
390a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "add-pmem", Some(&pmem_config))
391a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
392a64d27f8SOmer Faruk Bayram }
393d1f337aeSRavi kumar Veeramally Some("add-net") => {
394d1f337aeSRavi kumar Veeramally let (net_config, fds) = add_net_config(
395d1f337aeSRavi kumar Veeramally matches
396d1f337aeSRavi kumar Veeramally .subcommand_matches("add-net")
397d1f337aeSRavi kumar Veeramally .unwrap()
398d1f337aeSRavi kumar Veeramally .get_one::<String>("net_config")
399d1f337aeSRavi kumar Veeramally .unwrap(),
400d1f337aeSRavi kumar Veeramally )?;
401a64d27f8SOmer Faruk Bayram simple_api_command_with_fds(socket, "PUT", "add-net", Some(&net_config), fds)
402a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
403a64d27f8SOmer Faruk Bayram }
404d1f337aeSRavi kumar Veeramally Some("add-user-device") => {
405d1f337aeSRavi kumar Veeramally let device_config = add_user_device_config(
406d1f337aeSRavi kumar Veeramally matches
407d1f337aeSRavi kumar Veeramally .subcommand_matches("add-user-device")
408d1f337aeSRavi kumar Veeramally .unwrap()
409d1f337aeSRavi kumar Veeramally .get_one::<String>("device_config")
410d1f337aeSRavi kumar Veeramally .unwrap(),
411d1f337aeSRavi kumar Veeramally )?;
412a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "add-user-device", Some(&device_config))
413a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
414a64d27f8SOmer Faruk Bayram }
415d1f337aeSRavi kumar Veeramally Some("add-vdpa") => {
416d1f337aeSRavi kumar Veeramally let vdpa_config = add_vdpa_config(
417d1f337aeSRavi kumar Veeramally matches
418d1f337aeSRavi kumar Veeramally .subcommand_matches("add-vdpa")
419d1f337aeSRavi kumar Veeramally .unwrap()
420d1f337aeSRavi kumar Veeramally .get_one::<String>("vdpa_config")
421d1f337aeSRavi kumar Veeramally .unwrap(),
422d1f337aeSRavi kumar Veeramally )?;
423a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "add-vdpa", Some(&vdpa_config))
424a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
425a64d27f8SOmer Faruk Bayram }
426d1f337aeSRavi kumar Veeramally Some("add-vsock") => {
427d1f337aeSRavi kumar Veeramally let vsock_config = add_vsock_config(
428d1f337aeSRavi kumar Veeramally matches
429d1f337aeSRavi kumar Veeramally .subcommand_matches("add-vsock")
430d1f337aeSRavi kumar Veeramally .unwrap()
431d1f337aeSRavi kumar Veeramally .get_one::<String>("vsock_config")
432d1f337aeSRavi kumar Veeramally .unwrap(),
433d1f337aeSRavi kumar Veeramally )?;
434a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "add-vsock", Some(&vsock_config))
435a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
436a64d27f8SOmer Faruk Bayram }
437d1f337aeSRavi kumar Veeramally Some("snapshot") => {
438d1f337aeSRavi kumar Veeramally let snapshot_config = snapshot_config(
439d1f337aeSRavi kumar Veeramally matches
440d1f337aeSRavi kumar Veeramally .subcommand_matches("snapshot")
441d1f337aeSRavi kumar Veeramally .unwrap()
442d1f337aeSRavi kumar Veeramally .get_one::<String>("snapshot_config")
443d1f337aeSRavi kumar Veeramally .unwrap(),
444d1f337aeSRavi kumar Veeramally );
445a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "snapshot", Some(&snapshot_config))
446a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
447a64d27f8SOmer Faruk Bayram }
448d1f337aeSRavi kumar Veeramally Some("restore") => {
449555c4c41SPurna Pavan Chandra let (restore_config, fds) = restore_config(
450d1f337aeSRavi kumar Veeramally matches
451d1f337aeSRavi kumar Veeramally .subcommand_matches("restore")
452d1f337aeSRavi kumar Veeramally .unwrap()
453d1f337aeSRavi kumar Veeramally .get_one::<String>("restore_config")
454d1f337aeSRavi kumar Veeramally .unwrap(),
455d1f337aeSRavi kumar Veeramally )?;
456555c4c41SPurna Pavan Chandra simple_api_command_with_fds(socket, "PUT", "restore", Some(&restore_config), fds)
457a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
458a64d27f8SOmer Faruk Bayram }
459d1f337aeSRavi kumar Veeramally Some("coredump") => {
460d1f337aeSRavi kumar Veeramally let coredump_config = coredump_config(
461d1f337aeSRavi kumar Veeramally matches
462d1f337aeSRavi kumar Veeramally .subcommand_matches("coredump")
463d1f337aeSRavi kumar Veeramally .unwrap()
464d1f337aeSRavi kumar Veeramally .get_one::<String>("coredump_config")
465d1f337aeSRavi kumar Veeramally .unwrap(),
466d1f337aeSRavi kumar Veeramally );
467a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "coredump", Some(&coredump_config))
468a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
469a64d27f8SOmer Faruk Bayram }
470d1f337aeSRavi kumar Veeramally Some("send-migration") => {
471d1f337aeSRavi kumar Veeramally let send_migration_data = send_migration_data(
472d1f337aeSRavi kumar Veeramally matches
473d1f337aeSRavi kumar Veeramally .subcommand_matches("send-migration")
474d1f337aeSRavi kumar Veeramally .unwrap()
475d1f337aeSRavi kumar Veeramally .get_one::<String>("send_migration_config")
476d1f337aeSRavi kumar Veeramally .unwrap(),
477d1f337aeSRavi kumar Veeramally matches
478d1f337aeSRavi kumar Veeramally .subcommand_matches("send-migration")
479d1f337aeSRavi kumar Veeramally .unwrap()
480d1f337aeSRavi kumar Veeramally .get_flag("send_migration_local"),
481d1f337aeSRavi kumar Veeramally );
482a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "send-migration", Some(&send_migration_data))
483a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
484a64d27f8SOmer Faruk Bayram }
485d1f337aeSRavi kumar Veeramally Some("receive-migration") => {
486d1f337aeSRavi kumar Veeramally let receive_migration_data = receive_migration_data(
487d1f337aeSRavi kumar Veeramally matches
488d1f337aeSRavi kumar Veeramally .subcommand_matches("receive-migration")
489d1f337aeSRavi kumar Veeramally .unwrap()
490d1f337aeSRavi kumar Veeramally .get_one::<String>("receive_migration_config")
491d1f337aeSRavi kumar Veeramally .unwrap(),
492d1f337aeSRavi kumar Veeramally );
493a64d27f8SOmer Faruk Bayram simple_api_command(
494a64d27f8SOmer Faruk Bayram socket,
495a64d27f8SOmer Faruk Bayram "PUT",
496a64d27f8SOmer Faruk Bayram "receive-migration",
497a64d27f8SOmer Faruk Bayram Some(&receive_migration_data),
498a64d27f8SOmer Faruk Bayram )
499a64d27f8SOmer Faruk Bayram .map_err(Error::HttpApiClient)
500a64d27f8SOmer Faruk Bayram }
501d1f337aeSRavi kumar Veeramally Some("create") => {
502d1f337aeSRavi kumar Veeramally let data = create_data(
503d1f337aeSRavi kumar Veeramally matches
504d1f337aeSRavi kumar Veeramally .subcommand_matches("create")
505d1f337aeSRavi kumar Veeramally .unwrap()
506d1f337aeSRavi kumar Veeramally .get_one::<String>("path")
507d1f337aeSRavi kumar Veeramally .unwrap(),
508d1f337aeSRavi kumar Veeramally )?;
509a64d27f8SOmer Faruk Bayram simple_api_command(socket, "PUT", "create", Some(&data)).map_err(Error::HttpApiClient)
510a64d27f8SOmer Faruk Bayram }
511d1f337aeSRavi kumar Veeramally _ => unreachable!(),
512a64d27f8SOmer Faruk Bayram }
513a64d27f8SOmer Faruk Bayram }
514a64d27f8SOmer Faruk Bayram
515a64d27f8SOmer Faruk Bayram #[cfg(feature = "dbus_api")]
dbus_api_do_command(matches: &ArgMatches, proxy: &DBusApi1ProxyBlocking<'_>) -> ApiResult516d1f337aeSRavi kumar Veeramally fn dbus_api_do_command(matches: &ArgMatches, proxy: &DBusApi1ProxyBlocking<'_>) -> ApiResult {
517d1f337aeSRavi kumar Veeramally match matches.subcommand_name() {
518d1f337aeSRavi kumar Veeramally Some("boot") => proxy.api_vm_boot(),
519d1f337aeSRavi kumar Veeramally Some("delete") => proxy.api_vm_delete(),
520d1f337aeSRavi kumar Veeramally Some("shutdown-vmm") => proxy.api_vmm_shutdown(),
521d1f337aeSRavi kumar Veeramally Some("resume") => proxy.api_vm_resume(),
522d1f337aeSRavi kumar Veeramally Some("power-button") => proxy.api_vm_power_button(),
523d1f337aeSRavi kumar Veeramally Some("reboot") => proxy.api_vm_reboot(),
524d1f337aeSRavi kumar Veeramally Some("pause") => proxy.api_vm_pause(),
525d1f337aeSRavi kumar Veeramally Some("info") => proxy.api_vm_info(),
526d1f337aeSRavi kumar Veeramally Some("counters") => proxy.api_vm_counters(),
527d1f337aeSRavi kumar Veeramally Some("ping") => proxy.api_vmm_ping(),
528d1f337aeSRavi kumar Veeramally Some("shutdown") => proxy.api_vm_shutdown(),
529d1f337aeSRavi kumar Veeramally Some("resize") => {
530d1f337aeSRavi kumar Veeramally let resize = resize_config(
531d1f337aeSRavi kumar Veeramally matches
532d1f337aeSRavi kumar Veeramally .subcommand_matches("resize")
533d1f337aeSRavi kumar Veeramally .unwrap()
534d1f337aeSRavi kumar Veeramally .get_one::<String>("cpus")
535d1f337aeSRavi kumar Veeramally .map(|x| x as &str),
536d1f337aeSRavi kumar Veeramally matches
537d1f337aeSRavi kumar Veeramally .subcommand_matches("resize")
538d1f337aeSRavi kumar Veeramally .unwrap()
539d1f337aeSRavi kumar Veeramally .get_one::<String>("memory")
540d1f337aeSRavi kumar Veeramally .map(|x| x as &str),
541d1f337aeSRavi kumar Veeramally matches
542d1f337aeSRavi kumar Veeramally .subcommand_matches("resize")
543d1f337aeSRavi kumar Veeramally .unwrap()
544d1f337aeSRavi kumar Veeramally .get_one::<String>("balloon")
545d1f337aeSRavi kumar Veeramally .map(|x| x as &str),
546d1f337aeSRavi kumar Veeramally )?;
547a64d27f8SOmer Faruk Bayram proxy.api_vm_resize(&resize)
548a64d27f8SOmer Faruk Bayram }
549d1f337aeSRavi kumar Veeramally Some("resize-zone") => {
550d1f337aeSRavi kumar Veeramally let resize_zone = resize_zone_config(
551d1f337aeSRavi kumar Veeramally matches
552d1f337aeSRavi kumar Veeramally .subcommand_matches("resize-zone")
553d1f337aeSRavi kumar Veeramally .unwrap()
554d1f337aeSRavi kumar Veeramally .get_one::<String>("id")
555d1f337aeSRavi kumar Veeramally .unwrap(),
556d1f337aeSRavi kumar Veeramally matches
557d1f337aeSRavi kumar Veeramally .subcommand_matches("resize-zone")
558d1f337aeSRavi kumar Veeramally .unwrap()
559d1f337aeSRavi kumar Veeramally .get_one::<String>("size")
560d1f337aeSRavi kumar Veeramally .unwrap(),
561d1f337aeSRavi kumar Veeramally )?;
562a64d27f8SOmer Faruk Bayram proxy.api_vm_resize_zone(&resize_zone)
563a64d27f8SOmer Faruk Bayram }
564d1f337aeSRavi kumar Veeramally Some("add-device") => {
565d1f337aeSRavi kumar Veeramally let device_config = add_device_config(
566d1f337aeSRavi kumar Veeramally matches
567d1f337aeSRavi kumar Veeramally .subcommand_matches("add-device")
568d1f337aeSRavi kumar Veeramally .unwrap()
569d1f337aeSRavi kumar Veeramally .get_one::<String>("device_config")
570d1f337aeSRavi kumar Veeramally .unwrap(),
571d1f337aeSRavi kumar Veeramally )?;
572a64d27f8SOmer Faruk Bayram proxy.api_vm_add_device(&device_config)
573a64d27f8SOmer Faruk Bayram }
574d1f337aeSRavi kumar Veeramally Some("remove-device") => {
575d1f337aeSRavi kumar Veeramally let remove_device_data = remove_device_config(
576d1f337aeSRavi kumar Veeramally matches
577d1f337aeSRavi kumar Veeramally .subcommand_matches("remove-device")
578d1f337aeSRavi kumar Veeramally .unwrap()
579d1f337aeSRavi kumar Veeramally .get_one::<String>("id")
580d1f337aeSRavi kumar Veeramally .unwrap(),
581d1f337aeSRavi kumar Veeramally );
582a64d27f8SOmer Faruk Bayram proxy.api_vm_remove_device(&remove_device_data)
583a64d27f8SOmer Faruk Bayram }
584d1f337aeSRavi kumar Veeramally Some("add-disk") => {
585d1f337aeSRavi kumar Veeramally let disk_config = add_disk_config(
586d1f337aeSRavi kumar Veeramally matches
587d1f337aeSRavi kumar Veeramally .subcommand_matches("add-disk")
588d1f337aeSRavi kumar Veeramally .unwrap()
589d1f337aeSRavi kumar Veeramally .get_one::<String>("disk_config")
590d1f337aeSRavi kumar Veeramally .unwrap(),
591d1f337aeSRavi kumar Veeramally )?;
592a64d27f8SOmer Faruk Bayram proxy.api_vm_add_disk(&disk_config)
593a64d27f8SOmer Faruk Bayram }
594d1f337aeSRavi kumar Veeramally Some("add-fs") => {
595d1f337aeSRavi kumar Veeramally let fs_config = add_fs_config(
596d1f337aeSRavi kumar Veeramally matches
597d1f337aeSRavi kumar Veeramally .subcommand_matches("add-fs")
598d1f337aeSRavi kumar Veeramally .unwrap()
599d1f337aeSRavi kumar Veeramally .get_one::<String>("fs_config")
600d1f337aeSRavi kumar Veeramally .unwrap(),
601d1f337aeSRavi kumar Veeramally )?;
602a64d27f8SOmer Faruk Bayram proxy.api_vm_add_fs(&fs_config)
603a64d27f8SOmer Faruk Bayram }
604d1f337aeSRavi kumar Veeramally Some("add-pmem") => {
605d1f337aeSRavi kumar Veeramally let pmem_config = add_pmem_config(
606d1f337aeSRavi kumar Veeramally matches
607d1f337aeSRavi kumar Veeramally .subcommand_matches("add-pmem")
608d1f337aeSRavi kumar Veeramally .unwrap()
609d1f337aeSRavi kumar Veeramally .get_one::<String>("pmem_config")
610d1f337aeSRavi kumar Veeramally .unwrap(),
611d1f337aeSRavi kumar Veeramally )?;
612a64d27f8SOmer Faruk Bayram proxy.api_vm_add_pmem(&pmem_config)
613a64d27f8SOmer Faruk Bayram }
614d1f337aeSRavi kumar Veeramally Some("add-net") => {
615d1f337aeSRavi kumar Veeramally let (net_config, _fds) = add_net_config(
616d1f337aeSRavi kumar Veeramally matches
617d1f337aeSRavi kumar Veeramally .subcommand_matches("add-net")
618d1f337aeSRavi kumar Veeramally .unwrap()
619d1f337aeSRavi kumar Veeramally .get_one::<String>("net_config")
620d1f337aeSRavi kumar Veeramally .unwrap(),
621d1f337aeSRavi kumar Veeramally )?;
622a64d27f8SOmer Faruk Bayram proxy.api_vm_add_net(&net_config)
623a64d27f8SOmer Faruk Bayram }
624d1f337aeSRavi kumar Veeramally Some("add-user-device") => {
625d1f337aeSRavi kumar Veeramally let device_config = add_user_device_config(
626d1f337aeSRavi kumar Veeramally matches
627d1f337aeSRavi kumar Veeramally .subcommand_matches("add-user-device")
628d1f337aeSRavi kumar Veeramally .unwrap()
629d1f337aeSRavi kumar Veeramally .get_one::<String>("device_config")
630d1f337aeSRavi kumar Veeramally .unwrap(),
631d1f337aeSRavi kumar Veeramally )?;
632a64d27f8SOmer Faruk Bayram proxy.api_vm_add_user_device(&device_config)
633a64d27f8SOmer Faruk Bayram }
634d1f337aeSRavi kumar Veeramally Some("add-vdpa") => {
635d1f337aeSRavi kumar Veeramally let vdpa_config = add_vdpa_config(
636d1f337aeSRavi kumar Veeramally matches
637d1f337aeSRavi kumar Veeramally .subcommand_matches("add-vdpa")
638d1f337aeSRavi kumar Veeramally .unwrap()
639d1f337aeSRavi kumar Veeramally .get_one::<String>("vdpa_config")
640d1f337aeSRavi kumar Veeramally .unwrap(),
641d1f337aeSRavi kumar Veeramally )?;
642a64d27f8SOmer Faruk Bayram proxy.api_vm_add_vdpa(&vdpa_config)
643a64d27f8SOmer Faruk Bayram }
644d1f337aeSRavi kumar Veeramally Some("add-vsock") => {
645d1f337aeSRavi kumar Veeramally let vsock_config = add_vsock_config(
646d1f337aeSRavi kumar Veeramally matches
647d1f337aeSRavi kumar Veeramally .subcommand_matches("add-vsock")
648d1f337aeSRavi kumar Veeramally .unwrap()
649d1f337aeSRavi kumar Veeramally .get_one::<String>("vsock_config")
650d1f337aeSRavi kumar Veeramally .unwrap(),
651d1f337aeSRavi kumar Veeramally )?;
652a64d27f8SOmer Faruk Bayram proxy.api_vm_add_vsock(&vsock_config)
653a64d27f8SOmer Faruk Bayram }
654d1f337aeSRavi kumar Veeramally Some("snapshot") => {
655d1f337aeSRavi kumar Veeramally let snapshot_config = snapshot_config(
656d1f337aeSRavi kumar Veeramally matches
657d1f337aeSRavi kumar Veeramally .subcommand_matches("snapshot")
658d1f337aeSRavi kumar Veeramally .unwrap()
659d1f337aeSRavi kumar Veeramally .get_one::<String>("snapshot_config")
660d1f337aeSRavi kumar Veeramally .unwrap(),
661d1f337aeSRavi kumar Veeramally );
662a64d27f8SOmer Faruk Bayram proxy.api_vm_snapshot(&snapshot_config)
663a64d27f8SOmer Faruk Bayram }
664d1f337aeSRavi kumar Veeramally Some("restore") => {
665555c4c41SPurna Pavan Chandra let (restore_config, _fds) = restore_config(
666d1f337aeSRavi kumar Veeramally matches
667d1f337aeSRavi kumar Veeramally .subcommand_matches("restore")
668d1f337aeSRavi kumar Veeramally .unwrap()
669d1f337aeSRavi kumar Veeramally .get_one::<String>("restore_config")
670d1f337aeSRavi kumar Veeramally .unwrap(),
671d1f337aeSRavi kumar Veeramally )?;
672a64d27f8SOmer Faruk Bayram proxy.api_vm_restore(&restore_config)
673a64d27f8SOmer Faruk Bayram }
674d1f337aeSRavi kumar Veeramally Some("coredump") => {
675d1f337aeSRavi kumar Veeramally let coredump_config = coredump_config(
676d1f337aeSRavi kumar Veeramally matches
677d1f337aeSRavi kumar Veeramally .subcommand_matches("coredump")
678d1f337aeSRavi kumar Veeramally .unwrap()
679d1f337aeSRavi kumar Veeramally .get_one::<String>("coredump_config")
680d1f337aeSRavi kumar Veeramally .unwrap(),
681d1f337aeSRavi kumar Veeramally );
682a64d27f8SOmer Faruk Bayram proxy.api_vm_coredump(&coredump_config)
683a64d27f8SOmer Faruk Bayram }
684d1f337aeSRavi kumar Veeramally Some("send-migration") => {
685d1f337aeSRavi kumar Veeramally let send_migration_data = send_migration_data(
686d1f337aeSRavi kumar Veeramally matches
687d1f337aeSRavi kumar Veeramally .subcommand_matches("send-migration")
688d1f337aeSRavi kumar Veeramally .unwrap()
689d1f337aeSRavi kumar Veeramally .get_one::<String>("send_migration_config")
690d1f337aeSRavi kumar Veeramally .unwrap(),
691d1f337aeSRavi kumar Veeramally matches
692d1f337aeSRavi kumar Veeramally .subcommand_matches("send-migration")
693d1f337aeSRavi kumar Veeramally .unwrap()
694d1f337aeSRavi kumar Veeramally .get_flag("send_migration_local"),
695d1f337aeSRavi kumar Veeramally );
696a64d27f8SOmer Faruk Bayram proxy.api_vm_send_migration(&send_migration_data)
697a64d27f8SOmer Faruk Bayram }
698d1f337aeSRavi kumar Veeramally Some("receive-migration") => {
699d1f337aeSRavi kumar Veeramally let receive_migration_data = receive_migration_data(
700d1f337aeSRavi kumar Veeramally matches
701d1f337aeSRavi kumar Veeramally .subcommand_matches("receive-migration")
702d1f337aeSRavi kumar Veeramally .unwrap()
703d1f337aeSRavi kumar Veeramally .get_one::<String>("receive_migration_config")
704d1f337aeSRavi kumar Veeramally .unwrap(),
705d1f337aeSRavi kumar Veeramally );
706a64d27f8SOmer Faruk Bayram proxy.api_vm_receive_migration(&receive_migration_data)
707a64d27f8SOmer Faruk Bayram }
708d1f337aeSRavi kumar Veeramally Some("create") => {
709d1f337aeSRavi kumar Veeramally let data = create_data(
710d1f337aeSRavi kumar Veeramally matches
711d1f337aeSRavi kumar Veeramally .subcommand_matches("create")
712d1f337aeSRavi kumar Veeramally .unwrap()
713d1f337aeSRavi kumar Veeramally .get_one::<String>("path")
714d1f337aeSRavi kumar Veeramally .unwrap(),
715d1f337aeSRavi kumar Veeramally )?;
716a64d27f8SOmer Faruk Bayram proxy.api_vm_create(&data)
717a64d27f8SOmer Faruk Bayram }
718d1f337aeSRavi kumar Veeramally _ => unreachable!(),
719a64d27f8SOmer Faruk Bayram }
720a64d27f8SOmer Faruk Bayram }
721d1f337aeSRavi kumar Veeramally
resize_config( cpus: Option<&str>, memory: Option<&str>, balloon: Option<&str>, ) -> Result<String, Error>722a64d27f8SOmer Faruk Bayram fn resize_config(
723d1f337aeSRavi kumar Veeramally cpus: Option<&str>,
724d1f337aeSRavi kumar Veeramally memory: Option<&str>,
725d1f337aeSRavi kumar Veeramally balloon: Option<&str>,
726a64d27f8SOmer Faruk Bayram ) -> Result<String, Error> {
727d1f337aeSRavi kumar Veeramally let desired_vcpus: Option<u8> = if let Some(cpus) = cpus {
728d1f337aeSRavi kumar Veeramally Some(cpus.parse().map_err(Error::InvalidCpuCount)?)
729d1f337aeSRavi kumar Veeramally } else {
730d1f337aeSRavi kumar Veeramally None
731d1f337aeSRavi kumar Veeramally };
732d1f337aeSRavi kumar Veeramally
73321160f74SRob Bradford let desired_ram: Option<u64> = if let Some(memory) = memory {
734a86a2711SRob Bradford Some(
735a86a2711SRob Bradford memory
736a86a2711SRob Bradford .parse::<ByteSized>()
737a86a2711SRob Bradford .map_err(Error::InvalidMemorySize)?
738a86a2711SRob Bradford .0,
739a86a2711SRob Bradford )
74021160f74SRob Bradford } else {
74121160f74SRob Bradford None
74221160f74SRob Bradford };
74321160f74SRob Bradford
74435946852SSebastien Boeuf let desired_balloon: Option<u64> = if let Some(balloon) = balloon {
745a86a2711SRob Bradford Some(
746a86a2711SRob Bradford balloon
747a86a2711SRob Bradford .parse::<ByteSized>()
748a86a2711SRob Bradford .map_err(Error::InvalidBalloonSize)?
749a86a2711SRob Bradford .0,
750a86a2711SRob Bradford )
7518ffbc3d0SHui Zhu } else {
7528ffbc3d0SHui Zhu None
7538ffbc3d0SHui Zhu };
7548ffbc3d0SHui Zhu
75521160f74SRob Bradford let resize = vmm::api::VmResizeData {
75621160f74SRob Bradford desired_vcpus,
75721160f74SRob Bradford desired_ram,
75835946852SSebastien Boeuf desired_balloon,
75921160f74SRob Bradford };
76021160f74SRob Bradford
761a64d27f8SOmer Faruk Bayram Ok(serde_json::to_string(&resize).unwrap())
76221160f74SRob Bradford }
76321160f74SRob Bradford
resize_zone_config(id: &str, size: &str) -> Result<String, Error>764a64d27f8SOmer Faruk Bayram fn resize_zone_config(id: &str, size: &str) -> Result<String, Error> {
765015c7841SSebastien Boeuf let resize_zone = vmm::api::VmResizeZoneData {
766015c7841SSebastien Boeuf id: id.to_owned(),
767015c7841SSebastien Boeuf desired_ram: size
768015c7841SSebastien Boeuf .parse::<ByteSized>()
769015c7841SSebastien Boeuf .map_err(Error::InvalidMemorySize)?
770015c7841SSebastien Boeuf .0,
771015c7841SSebastien Boeuf };
772015c7841SSebastien Boeuf
773a64d27f8SOmer Faruk Bayram Ok(serde_json::to_string(&resize_zone).unwrap())
774015c7841SSebastien Boeuf }
775015c7841SSebastien Boeuf
add_device_config(config: &str) -> Result<String, Error>776a64d27f8SOmer Faruk Bayram fn add_device_config(config: &str) -> Result<String, Error> {
77733c15ca2SSongqian Li let device_config = DeviceConfig::parse(config).map_err(Error::AddDeviceConfig)?;
778a64d27f8SOmer Faruk Bayram let device_config = serde_json::to_string(&device_config).unwrap();
7790d53ba43SRob Bradford
780a64d27f8SOmer Faruk Bayram Ok(device_config)
7810d53ba43SRob Bradford }
7820d53ba43SRob Bradford
add_user_device_config(config: &str) -> Result<String, Error>783a64d27f8SOmer Faruk Bayram fn add_user_device_config(config: &str) -> Result<String, Error> {
78433c15ca2SSongqian Li let device_config = UserDeviceConfig::parse(config).map_err(Error::AddUserDeviceConfig)?;
785a64d27f8SOmer Faruk Bayram let device_config = serde_json::to_string(&device_config).unwrap();
7866f436f02SRob Bradford
787a64d27f8SOmer Faruk Bayram Ok(device_config)
7886f436f02SRob Bradford }
7896f436f02SRob Bradford
remove_device_config(id: &str) -> String790a64d27f8SOmer Faruk Bayram fn remove_device_config(id: &str) -> String {
7919a7d9c94SRob Bradford let remove_device_data = vmm::api::VmRemoveDeviceData { id: id.to_owned() };
7929a7d9c94SRob Bradford
793a64d27f8SOmer Faruk Bayram serde_json::to_string(&remove_device_data).unwrap()
7949a7d9c94SRob Bradford }
7959a7d9c94SRob Bradford
add_disk_config(config: &str) -> Result<String, Error>796a64d27f8SOmer Faruk Bayram fn add_disk_config(config: &str) -> Result<String, Error> {
79733c15ca2SSongqian Li let disk_config = DiskConfig::parse(config).map_err(Error::AddDiskConfig)?;
798a64d27f8SOmer Faruk Bayram let disk_config = serde_json::to_string(&disk_config).unwrap();
79905ce2dc8SRob Bradford
800a64d27f8SOmer Faruk Bayram Ok(disk_config)
80105ce2dc8SRob Bradford }
80205ce2dc8SRob Bradford
add_fs_config(config: &str) -> Result<String, Error>803a64d27f8SOmer Faruk Bayram fn add_fs_config(config: &str) -> Result<String, Error> {
80433c15ca2SSongqian Li let fs_config = FsConfig::parse(config).map_err(Error::AddFsConfig)?;
805a64d27f8SOmer Faruk Bayram let fs_config = serde_json::to_string(&fs_config).unwrap();
806bb2139a4SDean Sheather
807a64d27f8SOmer Faruk Bayram Ok(fs_config)
808bb2139a4SDean Sheather }
809bb2139a4SDean Sheather
add_pmem_config(config: &str) -> Result<String, Error>810a64d27f8SOmer Faruk Bayram fn add_pmem_config(config: &str) -> Result<String, Error> {
81133c15ca2SSongqian Li let pmem_config = PmemConfig::parse(config).map_err(Error::AddPmemConfig)?;
812a64d27f8SOmer Faruk Bayram let pmem_config = serde_json::to_string(&pmem_config).unwrap();
8130b051010SRob Bradford
814a64d27f8SOmer Faruk Bayram Ok(pmem_config)
8150b051010SRob Bradford }
8160b051010SRob Bradford
add_net_config(config: &str) -> Result<(String, Vec<i32>), Error>817a64d27f8SOmer Faruk Bayram fn add_net_config(config: &str) -> Result<(String, Vec<i32>), Error> {
81833c15ca2SSongqian Li let mut net_config = NetConfig::parse(config).map_err(Error::AddNetConfig)?;
819f3f4d075SRob Bradford
820da4cde70SSebastien Boeuf // NetConfig is modified on purpose here by taking the list of file
821da4cde70SSebastien Boeuf // descriptors out. Keeping the list and send it to the server side
822da4cde70SSebastien Boeuf // process would not make any sense since the file descriptor may be
823da4cde70SSebastien Boeuf // represented with different values.
824da4cde70SSebastien Boeuf let fds = net_config.fds.take().unwrap_or_default();
825a64d27f8SOmer Faruk Bayram let net_config = serde_json::to_string(&net_config).unwrap();
826da4cde70SSebastien Boeuf
827a64d27f8SOmer Faruk Bayram Ok((net_config, fds))
828f3f4d075SRob Bradford }
829f3f4d075SRob Bradford
add_vdpa_config(config: &str) -> Result<String, Error>830a64d27f8SOmer Faruk Bayram fn add_vdpa_config(config: &str) -> Result<String, Error> {
83133c15ca2SSongqian Li let vdpa_config = VdpaConfig::parse(config).map_err(Error::AddVdpaConfig)?;
832a64d27f8SOmer Faruk Bayram let vdpa_config = serde_json::to_string(&vdpa_config).unwrap();
8336dcc5572SSebastien Boeuf
834a64d27f8SOmer Faruk Bayram Ok(vdpa_config)
8356dcc5572SSebastien Boeuf }
8366dcc5572SSebastien Boeuf
add_vsock_config(config: &str) -> Result<String, Error>837a64d27f8SOmer Faruk Bayram fn add_vsock_config(config: &str) -> Result<String, Error> {
83833c15ca2SSongqian Li let vsock_config = VsockConfig::parse(config).map_err(Error::AddVsockConfig)?;
839a64d27f8SOmer Faruk Bayram let vsock_config = serde_json::to_string(&vsock_config).unwrap();
8406c2bca5fSRob Bradford
841a64d27f8SOmer Faruk Bayram Ok(vsock_config)
8426c2bca5fSRob Bradford }
8436c2bca5fSRob Bradford
snapshot_config(url: &str) -> String844d1f337aeSRavi kumar Veeramally fn snapshot_config(url: &str) -> String {
84535c0ea6cSSebastien Boeuf let snapshot_config = vmm::api::VmSnapshotConfig {
84635c0ea6cSSebastien Boeuf destination_url: String::from(url),
84735c0ea6cSSebastien Boeuf };
84835c0ea6cSSebastien Boeuf
849a64d27f8SOmer Faruk Bayram serde_json::to_string(&snapshot_config).unwrap()
85035c0ea6cSSebastien Boeuf }
85135c0ea6cSSebastien Boeuf
restore_config(config: &str) -> Result<(String, Vec<i32>), Error>852555c4c41SPurna Pavan Chandra fn restore_config(config: &str) -> Result<(String, Vec<i32>), Error> {
85333c15ca2SSongqian Li let mut restore_config = RestoreConfig::parse(config).map_err(Error::Restore)?;
854555c4c41SPurna Pavan Chandra // RestoreConfig is modified on purpose to take out the file descriptors.
855555c4c41SPurna Pavan Chandra // These fds are passed to the server side process via SCM_RIGHTS
856555c4c41SPurna Pavan Chandra let fds = match &mut restore_config.net_fds {
857555c4c41SPurna Pavan Chandra Some(net_fds) => net_fds
858555c4c41SPurna Pavan Chandra .iter_mut()
859555c4c41SPurna Pavan Chandra .flat_map(|net| net.fds.take().unwrap_or_default())
860555c4c41SPurna Pavan Chandra .collect(),
861555c4c41SPurna Pavan Chandra None => Vec::new(),
862555c4c41SPurna Pavan Chandra };
863a64d27f8SOmer Faruk Bayram let restore_config = serde_json::to_string(&restore_config).unwrap();
864859a9618SSebastien Boeuf
865555c4c41SPurna Pavan Chandra Ok((restore_config, fds))
866859a9618SSebastien Boeuf }
867859a9618SSebastien Boeuf
coredump_config(destination_url: &str) -> String868a64d27f8SOmer Faruk Bayram fn coredump_config(destination_url: &str) -> String {
8690bb2060cSYi Wang let coredump_config = vmm::api::VmCoredumpData {
8700bb2060cSYi Wang destination_url: String::from(destination_url),
8710bb2060cSYi Wang };
8720bb2060cSYi Wang
873a64d27f8SOmer Faruk Bayram serde_json::to_string(&coredump_config).unwrap()
8740bb2060cSYi Wang }
8750bb2060cSYi Wang
receive_migration_data(url: &str) -> String876a64d27f8SOmer Faruk Bayram fn receive_migration_data(url: &str) -> String {
87752302944SRob Bradford let receive_migration_data = vmm::api::VmReceiveMigrationData {
87852302944SRob Bradford receiver_url: url.to_owned(),
87952302944SRob Bradford };
880a64d27f8SOmer Faruk Bayram
881a64d27f8SOmer Faruk Bayram serde_json::to_string(&receive_migration_data).unwrap()
88252302944SRob Bradford }
88352302944SRob Bradford
send_migration_data(url: &str, local: bool) -> String884a64d27f8SOmer Faruk Bayram fn send_migration_data(url: &str, local: bool) -> String {
88552302944SRob Bradford let send_migration_data = vmm::api::VmSendMigrationData {
88652302944SRob Bradford destination_url: url.to_owned(),
887b9c260c0SRob Bradford local,
88852302944SRob Bradford };
889a64d27f8SOmer Faruk Bayram
890a64d27f8SOmer Faruk Bayram serde_json::to_string(&send_migration_data).unwrap()
89152302944SRob Bradford }
89252302944SRob Bradford
create_data(path: &str) -> Result<String, Error>893a64d27f8SOmer Faruk Bayram fn create_data(path: &str) -> Result<String, Error> {
894b0afeeebSRob Bradford let mut data = String::default();
895b0afeeebSRob Bradford if path == "-" {
896b0afeeebSRob Bradford std::io::stdin()
897b0afeeebSRob Bradford .read_to_string(&mut data)
898b0afeeebSRob Bradford .map_err(Error::ReadingStdin)?;
899b0afeeebSRob Bradford } else {
90046bbe0e6SRob Bradford data = std::fs::read_to_string(path).map_err(Error::ReadingFile)?;
90146bbe0e6SRob Bradford }
902b0afeeebSRob Bradford
903a64d27f8SOmer Faruk Bayram Ok(data)
904d5558aeaSWei Liu }
905d5558aeaSWei Liu
90612493db1SPhilipp Schuster /// Returns all [`Arg`]s in alphabetical order.
90712493db1SPhilipp Schuster ///
90812493db1SPhilipp Schuster /// This is the order used in the `--help` output.
get_cli_args() -> Box<[Arg]>90912493db1SPhilipp Schuster fn get_cli_args() -> Box<[Arg]> {
91012493db1SPhilipp Schuster [
911d1f337aeSRavi kumar Veeramally Arg::new("api-socket")
912d1f337aeSRavi kumar Veeramally .long("api-socket")
913d1f337aeSRavi kumar Veeramally .help("HTTP API socket path (UNIX domain socket).")
914d1f337aeSRavi kumar Veeramally .num_args(1),
915d1f337aeSRavi kumar Veeramally #[cfg(feature = "dbus_api")]
916d1f337aeSRavi kumar Veeramally Arg::new("dbus-object-path")
917d1f337aeSRavi kumar Veeramally .long("dbus-object-path")
918d1f337aeSRavi kumar Veeramally .help("Object path which the interface is being served at")
919d1f337aeSRavi kumar Veeramally .num_args(1),
920d1f337aeSRavi kumar Veeramally #[cfg(feature = "dbus_api")]
921d594107cSPhilipp Schuster Arg::new("dbus-service-name")
922d594107cSPhilipp Schuster .long("dbus-service-name")
923d594107cSPhilipp Schuster .help("Well known name of the dbus service")
924d594107cSPhilipp Schuster .num_args(1),
925d594107cSPhilipp Schuster #[cfg(feature = "dbus_api")]
926d1f337aeSRavi kumar Veeramally Arg::new("dbus-system-bus")
927d1f337aeSRavi kumar Veeramally .long("dbus-system-bus")
928d1f337aeSRavi kumar Veeramally .action(ArgAction::SetTrue)
929d1f337aeSRavi kumar Veeramally .num_args(0)
930d1f337aeSRavi kumar Veeramally .help("Use the system bus instead of a session bus"),
93112493db1SPhilipp Schuster ]
93212493db1SPhilipp Schuster .to_vec()
93312493db1SPhilipp Schuster .into_boxed_slice()
93412493db1SPhilipp Schuster }
93512493db1SPhilipp Schuster
93612493db1SPhilipp Schuster /// Returns all [`Command`]s in alphabetical order.
93712493db1SPhilipp Schuster ///
93812493db1SPhilipp Schuster /// This is the order used in the `--help` output.
get_cli_commands_sorted() -> Box<[Command]>93912493db1SPhilipp Schuster fn get_cli_commands_sorted() -> Box<[Command]> {
94012493db1SPhilipp Schuster [
941d1f337aeSRavi kumar Veeramally Command::new("add-device").about("Add VFIO device").arg(
942d1f337aeSRavi kumar Veeramally Arg::new("device_config")
943d1f337aeSRavi kumar Veeramally .index(1)
94433c15ca2SSongqian Li .help(DeviceConfig::SYNTAX),
945d1f337aeSRavi kumar Veeramally ),
94633c15ca2SSongqian Li Command::new("add-disk")
94733c15ca2SSongqian Li .about("Add block device")
94833c15ca2SSongqian Li .arg(Arg::new("disk_config").index(1).help(DiskConfig::SYNTAX)),
949d1f337aeSRavi kumar Veeramally Command::new("add-fs")
950d1f337aeSRavi kumar Veeramally .about("Add virtio-fs backed fs device")
951d1f337aeSRavi kumar Veeramally .arg(
952d1f337aeSRavi kumar Veeramally Arg::new("fs_config")
953d1f337aeSRavi kumar Veeramally .index(1)
95433c15ca2SSongqian Li .help(vmm::vm_config::FsConfig::SYNTAX),
955d1f337aeSRavi kumar Veeramally ),
956d594107cSPhilipp Schuster Command::new("add-net")
957d594107cSPhilipp Schuster .about("Add network device")
958d594107cSPhilipp Schuster .arg(Arg::new("net_config").index(1).help(NetConfig::SYNTAX)),
959d1f337aeSRavi kumar Veeramally Command::new("add-pmem")
960d1f337aeSRavi kumar Veeramally .about("Add persistent memory device")
961d1f337aeSRavi kumar Veeramally .arg(
962d1f337aeSRavi kumar Veeramally Arg::new("pmem_config")
963d1f337aeSRavi kumar Veeramally .index(1)
96433c15ca2SSongqian Li .help(vmm::vm_config::PmemConfig::SYNTAX),
965d1f337aeSRavi kumar Veeramally ),
966d1f337aeSRavi kumar Veeramally Command::new("add-user-device")
967d1f337aeSRavi kumar Veeramally .about("Add userspace device")
968d1f337aeSRavi kumar Veeramally .arg(
969d1f337aeSRavi kumar Veeramally Arg::new("device_config")
970d1f337aeSRavi kumar Veeramally .index(1)
97133c15ca2SSongqian Li .help(UserDeviceConfig::SYNTAX),
972d1f337aeSRavi kumar Veeramally ),
97333c15ca2SSongqian Li Command::new("add-vdpa")
97433c15ca2SSongqian Li .about("Add vDPA device")
97533c15ca2SSongqian Li .arg(Arg::new("vdpa_config").index(1).help(VdpaConfig::SYNTAX)),
97633c15ca2SSongqian Li Command::new("add-vsock")
97733c15ca2SSongqian Li .about("Add vsock device")
97833c15ca2SSongqian Li .arg(Arg::new("vsock_config").index(1).help(VsockConfig::SYNTAX)),
979d594107cSPhilipp Schuster Command::new("boot").about("Boot a created VM"),
980d594107cSPhilipp Schuster Command::new("coredump")
981d594107cSPhilipp Schuster .about("Create a coredump from VM")
982d594107cSPhilipp Schuster .arg(Arg::new("coredump_config").index(1).help("<file_path>")),
983d594107cSPhilipp Schuster Command::new("counters").about("Counters from the VM"),
984d594107cSPhilipp Schuster Command::new("create")
985d594107cSPhilipp Schuster .about("Create VM from a JSON configuration")
986d594107cSPhilipp Schuster .arg(Arg::new("path").index(1).default_value("-")),
987d594107cSPhilipp Schuster Command::new("delete").about("Delete a VM"),
988d594107cSPhilipp Schuster Command::new("info").about("Info on the VM"),
989d594107cSPhilipp Schuster Command::new("nmi").about("Trigger NMI"),
990d594107cSPhilipp Schuster Command::new("pause").about("Pause the VM"),
991d594107cSPhilipp Schuster Command::new("ping").about("Ping the VMM to check for API server availability"),
992d594107cSPhilipp Schuster Command::new("power-button").about("Trigger a power button in the VM"),
993d594107cSPhilipp Schuster Command::new("reboot").about("Reboot the VM"),
994d594107cSPhilipp Schuster Command::new("receive-migration")
995d594107cSPhilipp Schuster .about("Receive a VM migration")
996d594107cSPhilipp Schuster .arg(
997d594107cSPhilipp Schuster Arg::new("receive_migration_config")
998d594107cSPhilipp Schuster .index(1)
999d594107cSPhilipp Schuster .help("<receiver_url>"),
1000d594107cSPhilipp Schuster ),
1001d1f337aeSRavi kumar Veeramally Command::new("remove-device")
10024fd5070fSYi Wang .about("Remove VFIO and PCI device")
1003d1f337aeSRavi kumar Veeramally .arg(Arg::new("id").index(1).help("<device_id>")),
1004d1f337aeSRavi kumar Veeramally Command::new("resize")
1005d1f337aeSRavi kumar Veeramally .about("Resize the VM")
1006d1f337aeSRavi kumar Veeramally .arg(
1007d594107cSPhilipp Schuster Arg::new("balloon")
1008d594107cSPhilipp Schuster .long("balloon")
1009d594107cSPhilipp Schuster .help("New balloon size in bytes (supports K/M/G suffix)")
1010d594107cSPhilipp Schuster .num_args(1),
1011d594107cSPhilipp Schuster )
1012d594107cSPhilipp Schuster .arg(
1013d1f337aeSRavi kumar Veeramally Arg::new("cpus")
1014d1f337aeSRavi kumar Veeramally .long("cpus")
1015d1f337aeSRavi kumar Veeramally .help("New vCPUs count")
1016d1f337aeSRavi kumar Veeramally .num_args(1),
1017d1f337aeSRavi kumar Veeramally )
1018d1f337aeSRavi kumar Veeramally .arg(
1019d1f337aeSRavi kumar Veeramally Arg::new("memory")
1020d1f337aeSRavi kumar Veeramally .long("memory")
1021d1f337aeSRavi kumar Veeramally .help("New memory size in bytes (supports K/M/G suffix)")
1022d1f337aeSRavi kumar Veeramally .num_args(1),
1023d1f337aeSRavi kumar Veeramally ),
1024d1f337aeSRavi kumar Veeramally Command::new("resize-zone")
1025d1f337aeSRavi kumar Veeramally .about("Resize a memory zone")
1026d1f337aeSRavi kumar Veeramally .arg(
1027d1f337aeSRavi kumar Veeramally Arg::new("id")
1028d1f337aeSRavi kumar Veeramally .long("id")
1029d1f337aeSRavi kumar Veeramally .help("Memory zone identifier")
1030d1f337aeSRavi kumar Veeramally .num_args(1),
1031d1f337aeSRavi kumar Veeramally )
1032d1f337aeSRavi kumar Veeramally .arg(
1033d1f337aeSRavi kumar Veeramally Arg::new("size")
1034d1f337aeSRavi kumar Veeramally .long("size")
1035d1f337aeSRavi kumar Veeramally .help("New memory zone size in bytes (supports K/M/G suffix)")
1036d1f337aeSRavi kumar Veeramally .num_args(1),
1037d1f337aeSRavi kumar Veeramally ),
1038d1f337aeSRavi kumar Veeramally Command::new("restore")
1039d1f337aeSRavi kumar Veeramally .about("Restore VM from a snapshot")
1040d1f337aeSRavi kumar Veeramally .arg(
1041d1f337aeSRavi kumar Veeramally Arg::new("restore_config")
1042d1f337aeSRavi kumar Veeramally .index(1)
104333c15ca2SSongqian Li .help(RestoreConfig::SYNTAX),
1044d1f337aeSRavi kumar Veeramally ),
1045d594107cSPhilipp Schuster Command::new("resume").about("Resume the VM"),
1046d1f337aeSRavi kumar Veeramally Command::new("send-migration")
1047d1f337aeSRavi kumar Veeramally .about("Initiate a VM migration")
1048d1f337aeSRavi kumar Veeramally .arg(
1049d1f337aeSRavi kumar Veeramally Arg::new("send_migration_config")
1050d1f337aeSRavi kumar Veeramally .index(1)
1051d1f337aeSRavi kumar Veeramally .help("<destination_url>"),
1052d1f337aeSRavi kumar Veeramally )
1053d1f337aeSRavi kumar Veeramally .arg(
1054d1f337aeSRavi kumar Veeramally Arg::new("send_migration_local")
1055d1f337aeSRavi kumar Veeramally .long("local")
1056d1f337aeSRavi kumar Veeramally .num_args(0)
1057d1f337aeSRavi kumar Veeramally .action(ArgAction::SetTrue),
1058d1f337aeSRavi kumar Veeramally ),
1059d594107cSPhilipp Schuster Command::new("shutdown").about("Shutdown the VM"),
106012493db1SPhilipp Schuster Command::new("shutdown-vmm").about("Shutdown the VMM"),
1061d594107cSPhilipp Schuster Command::new("snapshot")
1062d594107cSPhilipp Schuster .about("Create a snapshot from VM")
1063d594107cSPhilipp Schuster .arg(
1064d594107cSPhilipp Schuster Arg::new("snapshot_config")
1065d594107cSPhilipp Schuster .index(1)
1066d594107cSPhilipp Schuster .help("<destination_url>"),
1067d594107cSPhilipp Schuster ),
106812493db1SPhilipp Schuster ]
106912493db1SPhilipp Schuster .to_vec()
107012493db1SPhilipp Schuster .into_boxed_slice()
107112493db1SPhilipp Schuster }
107212493db1SPhilipp Schuster
main()107312493db1SPhilipp Schuster fn main() {
107412493db1SPhilipp Schuster let app = Command::new("ch-remote")
107512493db1SPhilipp Schuster .author(env!("CARGO_PKG_AUTHORS"))
107612493db1SPhilipp Schuster .version(env!("BUILD_VERSION"))
107712493db1SPhilipp Schuster .about("Remotely control a cloud-hypervisor VMM.")
107812493db1SPhilipp Schuster .arg_required_else_help(true)
107912493db1SPhilipp Schuster .subcommand_required(true)
108012493db1SPhilipp Schuster .args(get_cli_args())
108112493db1SPhilipp Schuster .subcommands(get_cli_commands_sorted());
1082ba8cd4d5SRob Bradford
1083d1f337aeSRavi kumar Veeramally let matches = app.get_matches();
1084ba8cd4d5SRob Bradford
1085a64d27f8SOmer Faruk Bayram let mut target_api = match (
1086d1f337aeSRavi kumar Veeramally matches.get_one::<String>("api-socket"),
1087a64d27f8SOmer Faruk Bayram #[cfg(feature = "dbus_api")]
1088d1f337aeSRavi kumar Veeramally matches.get_one::<String>("dbus-service-name"),
1089a64d27f8SOmer Faruk Bayram #[cfg(feature = "dbus_api")]
1090d1f337aeSRavi kumar Veeramally matches.get_one::<String>("dbus-object-path"),
1091a64d27f8SOmer Faruk Bayram ) {
1092a64d27f8SOmer Faruk Bayram #[cfg(not(feature = "dbus_api"))]
1093d1f337aeSRavi kumar Veeramally (Some(api_sock),) => TargetApi::HttpApi(
1094d1f337aeSRavi kumar Veeramally UnixStream::connect(api_sock).unwrap_or_else(|e| {
1095a64d27f8SOmer Faruk Bayram eprintln!("Error opening HTTP socket: {e}");
1096d5558aeaSWei Liu process::exit(1)
1097a64d27f8SOmer Faruk Bayram }),
1098a64d27f8SOmer Faruk Bayram PhantomData,
1099a64d27f8SOmer Faruk Bayram ),
1100a64d27f8SOmer Faruk Bayram #[cfg(feature = "dbus_api")]
1101d1f337aeSRavi kumar Veeramally (Some(api_sock), None, None) => TargetApi::HttpApi(
1102d1f337aeSRavi kumar Veeramally UnixStream::connect(api_sock).unwrap_or_else(|e| {
1103a64d27f8SOmer Faruk Bayram eprintln!("Error opening HTTP socket: {e}");
1104a64d27f8SOmer Faruk Bayram process::exit(1)
1105a64d27f8SOmer Faruk Bayram }),
1106a64d27f8SOmer Faruk Bayram PhantomData,
1107a64d27f8SOmer Faruk Bayram ),
1108a64d27f8SOmer Faruk Bayram #[cfg(feature = "dbus_api")]
1109d1f337aeSRavi kumar Veeramally (None, Some(dbus_name), Some(dbus_path)) => TargetApi::DBusApi(
1110d1f337aeSRavi kumar Veeramally DBusApi1ProxyBlocking::new_connection(
1111d1f337aeSRavi kumar Veeramally dbus_name,
1112d1f337aeSRavi kumar Veeramally dbus_path,
1113d1f337aeSRavi kumar Veeramally matches.get_flag("dbus-system-bus"),
1114d1f337aeSRavi kumar Veeramally )
1115a64d27f8SOmer Faruk Bayram .map_err(Error::DBusApiClient)
1116a64d27f8SOmer Faruk Bayram .unwrap_or_else(|e| {
1117a64d27f8SOmer Faruk Bayram eprintln!("Error creating D-Bus proxy: {e}");
1118a64d27f8SOmer Faruk Bayram process::exit(1)
1119a64d27f8SOmer Faruk Bayram }),
1120a64d27f8SOmer Faruk Bayram ),
1121a64d27f8SOmer Faruk Bayram #[cfg(feature = "dbus_api")]
1122a64d27f8SOmer Faruk Bayram (Some(_), Some(_) | None, Some(_) | None) => {
1123a64d27f8SOmer Faruk Bayram println!(
1124a64d27f8SOmer Faruk Bayram "`api-socket` and (dbus-service-name or dbus-object-path) are mutually exclusive"
1125a64d27f8SOmer Faruk Bayram );
1126a64d27f8SOmer Faruk Bayram process::exit(1);
1127d5558aeaSWei Liu }
1128a64d27f8SOmer Faruk Bayram _ => {
1129a64d27f8SOmer Faruk Bayram println!("Please either provide the api-socket option or dbus-service-name and dbus-object-path options");
1130a64d27f8SOmer Faruk Bayram process::exit(1);
1131a64d27f8SOmer Faruk Bayram }
1132a64d27f8SOmer Faruk Bayram };
1133d5558aeaSWei Liu
1134060c9de0SPhilipp Schuster if let Err(top_error) = target_api.do_command(&matches) {
1135*190a11f2SPhilipp Schuster // Helper to join strings with a newline.
1136*190a11f2SPhilipp Schuster fn join_strs(mut acc: String, next: String) -> String {
1137*190a11f2SPhilipp Schuster if !acc.is_empty() {
1138*190a11f2SPhilipp Schuster acc.push('\n');
1139*190a11f2SPhilipp Schuster }
1140*190a11f2SPhilipp Schuster acc.push_str(&next);
1141*190a11f2SPhilipp Schuster acc
1142*190a11f2SPhilipp Schuster }
1143*190a11f2SPhilipp Schuster
1144*190a11f2SPhilipp Schuster // This function helps to modify the Display representation of remote
1145*190a11f2SPhilipp Schuster // API failures so that it aligns with the regular output of error
1146*190a11f2SPhilipp Schuster // messages. As we transfer a deep/rich chain of errors as String via
1147*190a11f2SPhilipp Schuster // the HTTP API, the nested error chain is lost. We retrieve it from
1148*190a11f2SPhilipp Schuster // the error response.
1149*190a11f2SPhilipp Schuster //
1150*190a11f2SPhilipp Schuster // In case the repose itself is broken, the error is printed directly
1151*190a11f2SPhilipp Schuster // by using the `X` level.
1152*190a11f2SPhilipp Schuster fn server_api_error_display_modifier(
1153*190a11f2SPhilipp Schuster level: usize,
1154*190a11f2SPhilipp Schuster indention: usize,
1155*190a11f2SPhilipp Schuster error: &(dyn std::error::Error + 'static),
1156*190a11f2SPhilipp Schuster ) -> Option<String> {
1157*190a11f2SPhilipp Schuster if let Some(api_client::Error::ServerResponse(status_code, body)) =
1158*190a11f2SPhilipp Schuster error.downcast_ref::<api_client::Error>()
1159*190a11f2SPhilipp Schuster {
1160*190a11f2SPhilipp Schuster let body = body.as_ref().map(|body| body.as_str()).unwrap_or("");
1161*190a11f2SPhilipp Schuster
1162*190a11f2SPhilipp Schuster // Retrieve the list of error messages back.
1163*190a11f2SPhilipp Schuster let lines: Vec<&str> = match serde_json::from_str(body) {
1164*190a11f2SPhilipp Schuster Ok(json) => json,
1165*190a11f2SPhilipp Schuster Err(e) => {
1166*190a11f2SPhilipp Schuster return Some(format!(
1167*190a11f2SPhilipp Schuster "{idention}X: Can't get remote's error messages from JSON response: {e}: body='{body}'",
1168*190a11f2SPhilipp Schuster idention = " ".repeat(indention)
1169*190a11f2SPhilipp Schuster ));
1170*190a11f2SPhilipp Schuster }
1171*190a11f2SPhilipp Schuster };
1172*190a11f2SPhilipp Schuster
1173*190a11f2SPhilipp Schuster let error_status = format!("Server responded with {status_code:?}");
1174*190a11f2SPhilipp Schuster // Prepend the error status line to the lines iter.
1175*190a11f2SPhilipp Schuster let lines = std::iter::once(error_status.as_str()).chain(lines);
1176*190a11f2SPhilipp Schuster let error_msg_multiline = lines
1177*190a11f2SPhilipp Schuster .enumerate()
1178*190a11f2SPhilipp Schuster .map(|(index, error_msg)| (index + level, error_msg))
1179*190a11f2SPhilipp Schuster .map(|(level, error_msg)| {
1180*190a11f2SPhilipp Schuster format!(
1181*190a11f2SPhilipp Schuster "{idention}{level}: {error_msg}",
1182*190a11f2SPhilipp Schuster idention = " ".repeat(indention)
1183*190a11f2SPhilipp Schuster )
1184*190a11f2SPhilipp Schuster })
1185*190a11f2SPhilipp Schuster .fold(String::new(), join_strs);
1186*190a11f2SPhilipp Schuster
1187*190a11f2SPhilipp Schuster return Some(error_msg_multiline);
1188*190a11f2SPhilipp Schuster }
1189*190a11f2SPhilipp Schuster
1190*190a11f2SPhilipp Schuster None
1191*190a11f2SPhilipp Schuster }
1192*190a11f2SPhilipp Schuster
1193*190a11f2SPhilipp Schuster let top_error: &dyn std::error::Error = &top_error;
1194*190a11f2SPhilipp Schuster cloud_hypervisor::cli_print_error_chain(
1195*190a11f2SPhilipp Schuster top_error,
1196*190a11f2SPhilipp Schuster "ch-remote",
1197*190a11f2SPhilipp Schuster server_api_error_display_modifier,
1198*190a11f2SPhilipp Schuster );
1199ba8cd4d5SRob Bradford process::exit(1)
1200ba8cd4d5SRob Bradford };
1201ba8cd4d5SRob Bradford }
12021f13165fSPhilipp Schuster
12031f13165fSPhilipp Schuster #[cfg(test)]
12041f13165fSPhilipp Schuster mod tests {
12051f13165fSPhilipp Schuster use std::cmp::Ordering;
12061f13165fSPhilipp Schuster
12071f13165fSPhilipp Schuster use super::*;
120853e9c94eSPhilipp Schuster use crate::test_util::assert_args_sorted;
12091f13165fSPhilipp Schuster
12101f13165fSPhilipp Schuster #[test]
test_cli_args_sorted()12111f13165fSPhilipp Schuster fn test_cli_args_sorted() {
12121f13165fSPhilipp Schuster let args = get_cli_args();
12131f13165fSPhilipp Schuster assert_args_sorted(|| args.iter());
12141f13165fSPhilipp Schuster }
12151f13165fSPhilipp Schuster
12161f13165fSPhilipp Schuster #[test]
test_cli_commands_sorted()12171f13165fSPhilipp Schuster fn test_cli_commands_sorted() {
12181f13165fSPhilipp Schuster let commands = get_cli_commands_sorted();
12191f13165fSPhilipp Schuster
12201f13165fSPhilipp Schuster // check commands itself are sorted
12211f13165fSPhilipp Schuster let iter = commands.iter().zip(commands.iter().skip(1));
12221f13165fSPhilipp Schuster for (command, next) in iter {
12231f13165fSPhilipp Schuster assert_ne!(
12241f13165fSPhilipp Schuster command.get_name().cmp(next.get_name()),
12251f13165fSPhilipp Schuster Ordering::Greater,
12261f13165fSPhilipp Schuster "commands not alphabetically sorted: command={}, next={}",
12271f13165fSPhilipp Schuster command.get_name(),
12281f13165fSPhilipp Schuster next.get_name()
12291f13165fSPhilipp Schuster );
12301f13165fSPhilipp Schuster }
12311f13165fSPhilipp Schuster
12321f13165fSPhilipp Schuster // check args of commands sorted
12331f13165fSPhilipp Schuster for command in commands {
12341f13165fSPhilipp Schuster assert_args_sorted(|| command.get_arguments());
12351f13165fSPhilipp Schuster }
12361f13165fSPhilipp Schuster }
12371f13165fSPhilipp Schuster }
1238