• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

google / alioth / 17385686062

01 Sep 2025 07:20PM UTC coverage: 18.016% (-0.1%) from 18.149%
17385686062

Pull #281

github

web-flow
Merge f6f978f6a into 6ec9a6d6b
Pull Request #281: Port to Apple Hypervisor framework

0 of 152 new or added lines in 11 files covered. (0.0%)

1323 existing lines in 30 files now uncovered.

1362 of 7560 relevant lines covered (18.02%)

18.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/alioth-cli/src/vu.rs
1
// Copyright 2025 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     https://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
use std::marker::PhantomData;
16
use std::os::unix::net::UnixListener;
17
use std::path::PathBuf;
18
use std::sync::Arc;
19
use std::thread::spawn;
20

21
use alioth::errors::{DebugTrace, trace_error};
22
use alioth::mem::mapped::RamBus;
23
use alioth::virtio::dev::blk::BlkFileParam;
24
use alioth::virtio::dev::fs::shared_dir::SharedDirParam;
25
use alioth::virtio::dev::net::NetTapParam;
26
use alioth::virtio::dev::{DevParam, Virtio, VirtioDevice};
27
use alioth::virtio::vu::backend::{VuBackend, VuEventfd, VuIrqSender};
28
use clap::{Args, Subcommand};
29
use serde::Deserialize;
30
use serde_aco::{Help, help_text};
31
use snafu::{ResultExt, Snafu};
32

33
use crate::objects::{DOC_OBJECTS, parse_objects};
34

35
#[trace_error]
36
#[derive(Snafu, DebugTrace)]
37
#[snafu(module, context(suffix(false)))]
38
pub enum Error {
39
    #[snafu(display("Failed to parse {arg}"))]
40
    ParseArg {
41
        arg: String,
42
        error: serde_aco::Error,
43
    },
44
    #[snafu(display("Failed to parse objects"), context(false))]
45
    ParseObjects { source: crate::objects::Error },
46
    #[snafu(display("Failed to bind socket {socket:?}"))]
47
    Bind {
48
        socket: PathBuf,
49
        error: std::io::Error,
50
    },
51
    #[snafu(display("Failed to accept connections"))]
52
    Accept { error: std::io::Error },
53
    #[snafu(display("Failed to create a VirtIO device"))]
54
    CreateVirtio { source: alioth::virtio::Error },
55
    #[snafu(display("Failed to create a vhost-user backend"))]
56
    CreateVu {
57
        source: alioth::virtio::vu::backend::Error,
58
    },
59
    #[snafu(display("vhost-user device runtime error"))]
60
    Runtime {
61
        source: alioth::virtio::vu::backend::Error,
62
    },
63
}
64

65
fn phantom_parser<T>(_: &str) -> Result<PhantomData<T>, &'static str> {
×
66
    Ok(PhantomData)
×
67
}
68

69
#[derive(Args, Debug, Clone)]
70
pub struct DevArgs<T>
71
where
72
    T: Help + Send + Sync + 'static,
73
{
74
    #[arg(short, long, value_name("PARAM"), help(help_text::<T>("Specify device parameters.")))]
75
    pub param: String,
76

77
    #[arg(short, long("object"), help(DOC_OBJECTS), value_name("OBJECT"))]
78
    pub objects: Vec<String>,
79

80
    #[arg(hide(true), value_parser(phantom_parser::<T>), default_value(""))]
81
    pub phantom: PhantomData<T>,
82
}
83

84
#[derive(Subcommand, Debug, Clone)]
85
pub enum DevType {
86
    /// VirtIO net device backed by TUN/TAP, MacVTap, or IPVTap.
87
    Net(DevArgs<NetTapParam>),
88
    /// VirtIO block device backed by a file.
89
    Blk(DevArgs<BlkFileParam>),
90
    /// VirtIO filesystem device backed by a shared host directory.
91
    Fs(DevArgs<SharedDirParam>),
92
}
93

94
#[derive(Args, Debug, Clone)]
95
#[command(arg_required_else_help = true)]
96
pub struct VuArgs {
97
    /// Path to a Unix domain socket to listen on.
98
    #[arg(short, long, value_name = "PATH")]
99
    pub socket: PathBuf,
100

101
    #[command(subcommand)]
102
    pub ty: DevType,
103
}
104

UNCOV
105
fn create_dev<D, P>(
106
    name: String,
107
    args: &DevArgs<P>,
108
    memory: Arc<RamBus>,
109
) -> Result<VirtioDevice<VuIrqSender, VuEventfd>, Error>
110
where
111
    D: Virtio,
112
    P: DevParam<Device = D> + Help + for<'a> Deserialize<'a> + Send + Sync + 'static,
113
{
114
    let name: Arc<str> = name.into();
×
115
    let objects = parse_objects(&args.objects)?;
×
116
    let param: P = serde_aco::from_args(&args.param, &objects)
×
117
        .context(error::ParseArg { arg: &args.param })?;
×
118
    let dev = param.build(name.clone()).context(error::CreateVirtio)?;
×
119
    let dev = VirtioDevice::new(name, dev, memory, false).context(error::CreateVirtio)?;
×
120
    Ok(dev)
×
121
}
122

UNCOV
123
fn run_backend(mut backend: VuBackend) {
UNCOV
124
    let r = backend.run().context(error::Runtime);
UNCOV
125
    let name = backend.name();
UNCOV
126
    match r {
UNCOV
127
        Ok(()) => log::info!("{name}: done"),
UNCOV
128
        Err(e) => log::error!("{name}: {e:?}"),
129
    }
130
}
131

UNCOV
132
pub fn start(args: VuArgs) -> Result<(), Error> {
UNCOV
133
    let VuArgs { socket, ty } = args;
UNCOV
134
    let listener = UnixListener::bind(&socket).context(error::Bind { socket })?;
UNCOV
135
    let mut index = 0i32;
136
    loop {
UNCOV
137
        let memory = Arc::new(RamBus::new());
UNCOV
138
        let dev = match &ty {
UNCOV
139
            DevType::Net(args) => create_dev(format!("net-{index}"), args, memory.clone()),
UNCOV
140
            DevType::Blk(args) => create_dev(format!("blk-{index}"), args, memory.clone()),
UNCOV
141
            DevType::Fs(args) => create_dev(format!("fs-{index}"), args, memory.clone()),
142
        }?;
UNCOV
143
        let (conn, _) = listener.accept().context(error::Accept)?;
UNCOV
144
        let backend = VuBackend::new(conn, dev, memory).context(error::CreateVu)?;
UNCOV
145
        spawn(move || run_backend(backend));
UNCOV
146
        index = index.wrapping_add(1);
147
    }
148
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc