guest_cli_args/
lib.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use argh::{ArgsInfo, FromArgValue, FromArgs};
6use std::fmt;
7
8#[cfg(not(target_os = "fuchsia"))]
9use ffx_core::ffx_command;
10
11#[derive(Copy, Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
12pub enum GuestType {
13    Debian,
14    Termina,
15    Zircon,
16}
17
18impl FromArgValue for GuestType {
19    fn from_arg_value(value: &str) -> Result<Self, String> {
20        match value {
21            "debian" => Ok(Self::Debian),
22            "termina" => Ok(Self::Termina),
23            "zircon" => Ok(Self::Zircon),
24            _ => Err(format!(
25                "Unrecognized guest type \"{}\". Supported guest types are: \
26                \"debian\", \"termina\", \"zircon\".",
27                value
28            )),
29        }
30    }
31}
32
33impl fmt::Display for GuestType {
34    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35        match *self {
36            GuestType::Debian => write!(f, "debian"),
37            GuestType::Termina => write!(f, "termina"),
38            GuestType::Zircon => write!(f, "zircon"),
39        }
40    }
41}
42
43impl GuestType {
44    pub fn moniker(&self) -> &str {
45        match self {
46            GuestType::Debian => "/core/debian-guest-manager",
47            GuestType::Termina => "/core/termina-guest-manager",
48            GuestType::Zircon => "/core/zircon-guest-manager",
49        }
50    }
51
52    pub fn guest_manager_interface(&self) -> &str {
53        match *self {
54            GuestType::Zircon => "fuchsia.virtualization.ZirconGuestManager",
55            GuestType::Debian => "fuchsia.virtualization.DebianGuestManager",
56            GuestType::Termina => "fuchsia.virtualization.TerminaGuestManager",
57        }
58    }
59
60    pub fn gn_target_label(self) -> &'static str {
61        match self {
62            GuestType::Zircon => "//src/virtualization/bundles:zircon",
63            GuestType::Debian => "//src/virtualization/bundles:debian",
64            GuestType::Termina => "//src/virtualization/bundles:termina",
65        }
66    }
67
68    pub fn gn_core_shard_label(&self) -> &'static str {
69        match self {
70            GuestType::Zircon => "//src/virtualization/bundles:zircon_core_shards",
71            GuestType::Debian => "//src/virtualization/bundles:debian_core_shards",
72            GuestType::Termina => "//src/virtualization/bundles:termina_core_shards",
73        }
74    }
75
76    pub fn package_url(&self) -> &'static str {
77        match self {
78            GuestType::Zircon => "fuchsia-pkg://fuchsia.com/zircon_guest#meta/zircon_guest.cm",
79            GuestType::Debian => "fuchsia-pkg://fuchsia.com/debian_guest#meta/debian_guest.cm",
80            GuestType::Termina => "fuchsia-pkg://fuchsia.com/termina_guest#meta/termina_guest.cm",
81        }
82    }
83
84    pub fn all_guests() -> Vec<GuestType> {
85        vec![GuestType::Debian, GuestType::Termina, GuestType::Zircon]
86    }
87}
88
89#[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
90/// Top-level command.
91pub struct GuestOptions {
92    #[argh(subcommand)]
93    pub nested: SubCommands,
94}
95
96#[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
97#[argh(subcommand)]
98pub enum SubCommands {
99    Attach(crate::attach_args::AttachArgs),
100    Launch(crate::launch_args::LaunchArgs),
101    Stop(crate::stop_args::StopArgs),
102    Balloon(crate::balloon_args::BalloonArgs),
103    List(crate::list_args::ListArgs),
104    Socat(crate::socat_args::SocatArgs),
105    Vsh(VshArgs),
106    VsockPerf(crate::vsockperf_args::VsockPerfArgs),
107    Wipe(crate::wipe_args::WipeArgs),
108    Mem(crate::mem_args::MemArgs),
109}
110
111pub mod mem_args {
112    use super::*;
113    /// Interact with the guest virtio-mem. Usage: guest mem sub-command [ request-plugged or stats]
114    #[derive(ArgsInfo, FromArgs, Debug, PartialEq)]
115    #[argh(subcommand, name = "mem")]
116    #[cfg_attr(not(target_os = "fuchsia"), ffx_command())]
117    pub struct MemArgs {
118        #[argh(subcommand)]
119        pub mem_cmd: MemCommands,
120    }
121    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
122    #[argh(subcommand)]
123    pub enum MemCommands {
124        RequestPluggedMem(RequestPluggedMem),
125        StatsMem(StatsMem),
126    }
127
128    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
129    /// Modify the requested amount of the dynamically plugged memory. Usage: guest mem request-plugged guest-type size
130    #[argh(subcommand, name = "request-plugged")]
131    pub struct RequestPluggedMem {
132        #[argh(positional)]
133        /// type of the guest
134        pub guest_type: GuestType,
135        #[argh(positional)]
136        /// target amount of memory to be dynamically plugged
137        pub size: u64,
138    }
139    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
140    /// See the stats of a guest's virtio-mem. Usage: guest mem stats guest-type
141    #[argh(subcommand, name = "stats")]
142    pub struct StatsMem {
143        #[argh(positional)]
144        /// type of the guest
145        pub guest_type: GuestType,
146    }
147}
148
149pub mod balloon_args {
150    use super::*;
151    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
152    /// Interact with the guest memory balloon. Usage: guest balloon sub-command guest-type ...
153    #[argh(subcommand, name = "balloon")]
154    #[cfg_attr(not(target_os = "fuchsia"), ffx_command())]
155    pub struct BalloonArgs {
156        #[argh(subcommand)]
157        pub balloon_cmd: BalloonCommands,
158    }
159
160    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
161    #[argh(subcommand)]
162    pub enum BalloonCommands {
163        Set(BalloonSet),
164        Stats(BalloonStats),
165    }
166
167    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
168    /// Modify the size of a memory balloon. Usage: guest balloon set guest-type num-pages
169    #[argh(subcommand, name = "set")]
170    pub struct BalloonSet {
171        #[argh(positional)]
172        /// type of the guest
173        pub guest_type: GuestType,
174        #[argh(positional)]
175        /// number of pages guest balloon will have after use.
176        pub num_pages: u32,
177    }
178
179    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
180    /// See the stats of a guest's memory balloon. Usage: guest balloon stats guest-type
181    #[argh(subcommand, name = "stats")]
182    pub struct BalloonStats {
183        #[argh(positional)]
184        /// type of the guest
185        pub guest_type: GuestType,
186    }
187}
188
189pub mod list_args {
190    use super::*;
191    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
192    /// List available guest environments.
193    #[argh(subcommand, name = "list")]
194    #[cfg_attr(not(target_os = "fuchsia"), ffx_command())]
195    pub struct ListArgs {
196        #[argh(positional)]
197        /// optional guest type to get detailed information about
198        pub guest_type: Option<GuestType>,
199    }
200}
201
202pub mod socat_args {
203    use super::*;
204    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
205    /// Interact with the guest via socat. See the sub-command help for details.
206    #[argh(subcommand, name = "socat")]
207    #[cfg_attr(not(target_os = "fuchsia"), ffx_command())]
208    pub struct SocatArgs {
209        #[argh(subcommand)]
210        pub socat_cmd: SocatCommands,
211    }
212
213    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
214    #[argh(subcommand)]
215    pub enum SocatCommands {
216        Listen(SocatListen),
217        Connect(SocatConnect),
218    }
219
220    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
221    /// Create a socat connection on the specified port. Usage: guest socat connect guest-type port
222    #[argh(subcommand, name = "connect")]
223    pub struct SocatConnect {
224        #[argh(positional)]
225        /// type of the guest
226        pub guest_type: GuestType,
227        #[argh(positional)]
228        /// guest port number to attempt to connect to
229        pub guest_port: u32,
230    }
231
232    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
233    /// Listen through socat on the specified port. Usage: guest socat listen guest-type host-port
234    #[argh(subcommand, name = "listen")]
235    pub struct SocatListen {
236        #[argh(positional)]
237        /// type of the guest
238        pub guest_type: GuestType,
239        #[argh(positional)]
240        /// host port number to accept incoming guest connections on
241        pub host_port: u32,
242    }
243}
244
245#[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
246/// Create virtual shell for a guest or connect via virtual shell.
247#[argh(subcommand, name = "vsh")]
248pub struct VshArgs {
249    #[argh(option)]
250    /// port of a vsh socket to connect to.
251    pub port: Option<u32>,
252    #[argh(switch, short = 'c')]
253    /// connect to the container within the VM
254    pub container: bool,
255    #[argh(positional)]
256    /// list of arguments to run non-interactively on launch.
257    pub args: Vec<String>,
258}
259
260pub mod wipe_args {
261    use super::*;
262    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
263    /// Clears the stateful data for the target guest. Currently only termina is supported.
264    #[argh(subcommand, name = "wipe")]
265    #[cfg_attr(not(target_os = "fuchsia"), ffx_command())]
266    pub struct WipeArgs {
267        #[argh(positional)]
268        /// type of the guest
269        pub guest_type: GuestType,
270    }
271}
272
273pub mod vsockperf_args {
274    use super::*;
275    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
276    /// Perform a vsock micro benchmark on the target guest. Only Debian is supported.
277    #[argh(subcommand, name = "vsock-perf")]
278    #[cfg_attr(not(target_os = "fuchsia"), ffx_command())]
279    pub struct VsockPerfArgs {
280        #[argh(positional)]
281        /// type of the guest
282        pub guest_type: GuestType,
283    }
284}
285
286pub mod launch_args {
287    use super::*;
288    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
289    /// Launch a guest image. Usage: guest launch guest_type [--cmdline-add <arg>...] [--default-net <bool>] [--memory <memory-size>] [--cpus <num-cpus>] [--virtio-* <bool>]
290    #[argh(subcommand, name = "launch")]
291    #[cfg_attr(not(target_os = "fuchsia"), ffx_command())]
292    pub struct LaunchArgs {
293        #[argh(positional)]
294        /// guest type to launch e.g. 'zircon'.
295        pub guest_type: GuestType,
296        /// adds provided strings to the existing kernel command line
297        #[argh(option)]
298        pub cmdline_add: Vec<String>,
299        /// enable a default net device
300        #[argh(option)]
301        pub default_net: Option<bool>,
302        /// allocate 'bytes' of memory for the guest
303        #[argh(option)]
304        pub memory: Option<u64>,
305        /// number of virtual cpus available for the guest
306        #[argh(option)]
307        pub cpus: Option<u8>,
308        /// enable virtio-balloon
309        #[argh(option)]
310        pub virtio_balloon: Option<bool>,
311        /// enable virtio-console
312        #[argh(option)]
313        pub virtio_console: Option<bool>,
314        /// enable virtio-gpu and virtio-input
315        #[argh(option)]
316        pub virtio_gpu: Option<bool>,
317        /// enable virtio-rng
318        #[argh(option)]
319        pub virtio_rng: Option<bool>,
320        /// enable virtio-sound
321        #[argh(option)]
322        pub virtio_sound: Option<bool>,
323        /// enable virtio-sound-input
324        #[argh(option)]
325        pub virtio_sound_input: Option<bool>,
326        /// enable virtio-vsock
327        #[argh(option)]
328        pub virtio_vsock: Option<bool>,
329        /// enable virtio-mem to allow dynamically (un)plug memory to the guest
330        #[argh(option)]
331        pub virtio_mem: Option<bool>,
332        /// virtio-mem pluggable region size
333        #[argh(option)]
334        pub virtio_mem_region_size: Option<u64>,
335        /// virtio-mem pluggable region alignment
336        #[argh(option)]
337        pub virtio_mem_region_alignment: Option<u64>,
338        /// virtio-mem pluggable blocksize
339        #[argh(option)]
340        pub virtio_mem_block_size: Option<u64>,
341        /// detach from a guest allowing it to run in the background
342        #[argh(switch, short = 'd')]
343        pub detach: bool,
344    }
345}
346
347pub mod stop_args {
348    use super::*;
349    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
350    /// Stop a running guest. Usage: guest stop guest_type [-f]
351    #[argh(subcommand, name = "stop")]
352    #[cfg_attr(not(target_os = "fuchsia"), ffx_command())]
353    pub struct StopArgs {
354        /// guest type to stop e.g. 'zircon'
355        #[argh(positional)]
356        pub guest_type: GuestType,
357        /// force stop the guest
358        #[argh(switch, short = 'f')]
359        pub force: bool,
360    }
361}
362
363pub mod attach_args {
364    use super::*;
365    #[derive(ArgsInfo, FromArgs, PartialEq, Debug)]
366    /// Attach console and serial to a running guest. Usage: guest attach guest_type
367    #[argh(subcommand, name = "attach")]
368    #[cfg_attr(not(target_os = "fuchsia"), ffx_command())]
369    pub struct AttachArgs {
370        /// guest type to attach to e.g. 'debian'
371        #[argh(positional)]
372        pub guest_type: GuestType,
373        /// attach via serial instead of virtio-console
374        #[argh(switch)]
375        pub serial: bool,
376    }
377}