Skip to main content

openvmm_helpers/
hypervisor.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Hypervisor resource construction and auto-detection for OpenVMM entry
5//! points.
6
7use hypervisor_resources::HypervisorKind;
8use vm_resource::Resource;
9
10/// Returns a [`Resource<HypervisorKind>`] for the first available hypervisor
11/// backend.
12///
13/// Backends are checked in registration order (highest priority first).
14pub fn choose_hypervisor() -> anyhow::Result<Resource<HypervisorKind>> {
15    for probe in hypervisor_resources::probes() {
16        if let Some(resource) = probe.try_new_resource()? {
17            return Ok(resource);
18        }
19    }
20    anyhow::bail!("no hypervisor available");
21}
22
23/// Parses a hypervisor specifier of the form `name` or `name:key=val,key,...`.
24///
25/// Returns `(name, params)` where `params` is a list of `(key, value)` pairs.
26/// A bare key (no `=`) is treated as a boolean flag with value `"true"`.
27fn parse_hypervisor_spec(spec: &str) -> anyhow::Result<(&str, Vec<(&str, &str)>)> {
28    let (name, rest) = spec.split_once(':').unwrap_or((spec, ""));
29    anyhow::ensure!(!name.is_empty(), "empty hypervisor name in spec: {spec}");
30    let params = if rest.is_empty() {
31        Vec::new()
32    } else {
33        rest.split(',')
34            .filter(|item| !item.is_empty())
35            .map(|item| {
36                let (key, val) = item.split_once('=').unwrap_or((item, "true"));
37                anyhow::ensure!(!key.is_empty(), "empty parameter key in spec: {spec}");
38                Ok((key, val))
39            })
40            .collect::<anyhow::Result<Vec<_>>>()?
41    };
42    Ok((name, params))
43}
44
45/// Returns a [`Resource<HypervisorKind>`] for the named backend, with
46/// optional parameters.
47///
48/// The specifier format is `name` or `name:key=val,key,...`.
49/// Each backend validates its own parameters — see the probe
50/// implementations for supported keys.
51pub fn hypervisor_resource(spec: &str) -> anyhow::Result<Resource<HypervisorKind>> {
52    let (name, params) = parse_hypervisor_spec(spec)?;
53    let probe = hypervisor_resources::probe_by_name(name)
54        .ok_or_else(|| anyhow::anyhow!("unknown hypervisor: {name}"))?;
55    probe.new_resource(&params)
56}