diff --git a/src/main.rs b/src/main.rs index cd5a8d202..e99da773c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,7 +19,7 @@ use std::sync::mpsc::channel; use std::sync::{Arc, Mutex}; use thiserror::Error; #[cfg(feature = "dbus_api")] -use vmm::api::dbus::dbus_api_graceful_shutdown; +use vmm::api::dbus::{dbus_api_graceful_shutdown, DBusApiOptions}; use vmm::config; use vmm_sys_util::eventfd::EventFd; use vmm_sys_util::signal::block_signal; @@ -59,6 +59,12 @@ enum Error { ParsingApiSocket(std::num::ParseIntError), #[error("Error parsing --event-monitor: {0}")] ParsingEventMonitor(option_parser::OptionParserError), + #[cfg(feature = "dbus_api")] + #[error("`--dbus-object-path` option isn't provided")] + MissingDBusObjectPath, + #[cfg(feature = "dbus_api")] + #[error("`--dbus-service-name` option isn't provided")] + MissingDBusServiceName, #[error("Error parsing --event-monitor: path or fd required")] BareEventMonitor, #[error("Error doing event monitor I/O: {0}")] @@ -239,6 +245,21 @@ pub struct TopLevel { /// path=|fd= api_socket: Option, + #[cfg(feature = "dbus_api")] + #[argh(option, long = "dbus-service-name")] + /// well known name of the service + dbus_name: Option, + + #[cfg(feature = "dbus_api")] + #[argh(option, long = "dbus-object-path")] + /// object path to serve the dbus interface + dbus_path: Option, + + #[cfg(feature = "dbus_api")] + #[argh(switch, long = "dbus-system-bus")] + /// use the system bus instead of a session bus + dbus_system_bus: bool, + #[argh(option, long = "event-monitor")] /// path=|fd= event_monitor: Option, @@ -418,6 +439,18 @@ fn start_vmm(toplevel: TopLevel) -> Result, Error> { (None, None) }; + #[cfg(feature = "dbus_api")] + let dbus_options = match (&toplevel.dbus_name, &toplevel.dbus_path) { + (Some(ref name), Some(ref path)) => Ok(Some(DBusApiOptions { + service_name: name.to_owned(), + object_path: path.to_owned(), + system_bus: toplevel.dbus_system_bus, + })), + (Some(_), None) => Err(Error::MissingDBusObjectPath), + (None, Some(_)) => Err(Error::MissingDBusServiceName), + (None, None) => Ok(None), + }?; + if let Some(ref monitor_config) = toplevel.event_monitor { let mut parser = OptionParser::new(); parser.add("path").add("fd"); @@ -519,6 +552,8 @@ fn start_vmm(toplevel: TopLevel) -> Result, Error> { vmm::VmmVersionInfo::new(env!("BUILD_VERSION"), env!("CARGO_PKG_VERSION")), &api_socket_path, api_socket_fd, + #[cfg(feature = "dbus_api")] + dbus_options, api_evt.try_clone().unwrap(), api_request_sender_clone, api_request_receiver, @@ -577,7 +612,9 @@ fn start_vmm(toplevel: TopLevel) -> Result, Error> { .map_err(Error::VmmThread)?; #[cfg(feature = "dbus_api")] - dbus_api_graceful_shutdown(vmm_thread_handle.dbus_shutdown_chs); + if let Some(chs) = vmm_thread_handle.dbus_shutdown_chs { + dbus_api_graceful_shutdown(chs); + } r.map(|_| api_socket_path) } diff --git a/vmm/src/api/dbus/mod.rs b/vmm/src/api/dbus/mod.rs index 49dbb9f0f..deb058e32 100644 --- a/vmm/src/api/dbus/mod.rs +++ b/vmm/src/api/dbus/mod.rs @@ -20,6 +20,12 @@ use zbus::{dbus_interface, ConnectionBuilder}; pub type DBusApiShutdownChannels = (oneshot::Sender<()>, oneshot::Receiver<()>); +pub struct DBusApiOptions { + pub service_name: String, + pub object_path: String, + pub system_bus: bool, +} + pub struct DBusApi { api_notifier: EventFd, api_sender: futures::lock::Mutex>, @@ -278,8 +284,8 @@ impl DBusApi { } } -// TODO: add command line arguments to make this configurable pub fn start_dbus_thread( + dbus_options: DBusApiOptions, api_notifier: EventFd, api_sender: Sender, seccomp_action: &SeccompAction, @@ -288,10 +294,16 @@ pub fn start_dbus_thread( ) -> VmmResult<(thread::JoinHandle>, DBusApiShutdownChannels)> { let dbus_iface = DBusApi::new(api_notifier, api_sender); let connection = executor::block_on(async move { - ConnectionBuilder::session()? + let conn_builder = if dbus_options.system_bus { + ConnectionBuilder::system()? + } else { + ConnectionBuilder::session()? + }; + + conn_builder .internal_executor(false) - .name("org.cloudhypervisor.DBusApi")? - .serve_at("/org/cloudhypervisor/DBusApi", dbus_iface)? + .name(dbus_options.service_name)? + .serve_at(dbus_options.object_path, dbus_iface)? .build() .await }) diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs index 4f90d22d5..f885b7893 100644 --- a/vmm/src/lib.rs +++ b/vmm/src/lib.rs @@ -26,7 +26,7 @@ use crate::seccomp_filters::{get_seccomp_filter, Thread}; use crate::vm::{Error as VmError, Vm, VmState}; use anyhow::anyhow; #[cfg(feature = "dbus_api")] -use api::dbus::DBusApiShutdownChannels; +use api::dbus::{DBusApiOptions, DBusApiShutdownChannels}; use libc::{tcsetattr, termios, EFD_NONBLOCK, SIGINT, SIGTERM, TCSANOW}; use memory_manager::MemoryManagerSnapshotData; use pci::PciBdf; @@ -294,6 +294,7 @@ pub fn start_vmm_thread( vmm_version: VmmVersionInfo, http_path: &Option, http_fd: Option, + #[cfg(feature = "dbus_api")] dbus_options: Option, api_event: EventFd, api_sender: Sender, api_receiver: Receiver, @@ -357,13 +358,20 @@ pub fn start_vmm_thread( // The VMM thread is started, we can start the dbus thread // and start serving HTTP requests #[cfg(feature = "dbus_api")] - let (_, dbus_shutdown_chs) = api::start_dbus_thread( - api_event_clone.try_clone().map_err(Error::EventFdClone)?, - api_sender.clone(), - seccomp_action, - exit_event.try_clone().map_err(Error::EventFdClone)?, - hypervisor_type, - )?; + let dbus_shutdown_chs = match dbus_options { + Some(opts) => { + let (_, chs) = api::start_dbus_thread( + opts, + api_event_clone.try_clone().map_err(Error::EventFdClone)?, + api_sender.clone(), + seccomp_action, + exit_event.try_clone().map_err(Error::EventFdClone)?, + hypervisor_type, + )?; + Some(chs) + } + None => None, + }; if let Some(http_path) = http_path { api::start_http_path_thread( @@ -432,7 +440,7 @@ impl VmmVersionInfo { pub struct VmmThreadHandle { pub thread_handle: thread::JoinHandle>, #[cfg(feature = "dbus_api")] - pub dbus_shutdown_chs: DBusApiShutdownChannels, + pub dbus_shutdown_chs: Option, } pub struct Vmm {