sysmaster/backport-feature-devmaster-add-devctl-control-subcommand-to-l.patch

200 lines
6.4 KiB
Diff
Raw Normal View History

2023-12-07 00:19:38 +08:00
From 714eeceecbe09fd8855cd84279dc13e45a093fb2 Mon Sep 17 00:00:00 2001
From: chenjiayi <chenjiayi22@huawei.com>
Date: Thu, 16 Nov 2023 08:07:07 +0800
Subject: [PATCH 064/103] feature(devmaster): add devctl control subcommand to
let devmaster exit
Also decouple the configuration path into the parameter of run_daemon
function for unit test.
---
exts/devmaster/src/bin/devctl/daemon/mod.rs | 37 ++++++++++++++++++-
exts/devmaster/src/bin/devctl/main.rs | 19 +++++++++-
.../src/lib/framework/control_manager.rs | 9 ++++-
exts/devmaster/src/lib/framework/devmaster.rs | 5 ++-
4 files changed, 63 insertions(+), 7 deletions(-)
diff --git a/exts/devmaster/src/bin/devctl/daemon/mod.rs b/exts/devmaster/src/bin/devctl/daemon/mod.rs
index 6dfe9718..3e4bd96d 100644
--- a/exts/devmaster/src/bin/devctl/daemon/mod.rs
+++ b/exts/devmaster/src/bin/devctl/daemon/mod.rs
@@ -38,10 +38,10 @@ fn notify(unset_env: bool, msg: String) -> std::io::Result<()> {
}
}
-pub fn run_daemon() {
+pub fn run_daemon(config_path: &str) {
let events = Rc::new(Events::new().unwrap());
- let devmaster = Devmaster::new(events);
+ let devmaster = Devmaster::new(config_path, events);
if let Err(e) = notify(false, "READY=1\n".to_string()) {
log::warn!("Failed to notify pid 1: {}", e);
@@ -51,3 +51,36 @@ pub fn run_daemon() {
devmaster.as_ref().borrow().exit();
}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use device::{Device, DeviceAction};
+ use libdevmaster::framework::control_manager::CONTROL_MANAGER_LISTEN_ADDR;
+ use std::io::Write;
+
+ #[test]
+ fn test_run_daemon() {
+ /* Require root privilege, skip in ci environment. */
+ let dev = Device::from_subsystem_sysname("net", "lo").unwrap();
+ if dev.trigger(DeviceAction::Change).is_err() {
+ return;
+ }
+
+ std::thread::spawn(|| {
+ std::thread::sleep(std::time::Duration::from_secs(1));
+
+ let dev = Device::from_subsystem_sysname("net", "lo").unwrap();
+ dev.trigger(DeviceAction::Change).unwrap();
+
+ /* Sleep more than 3 seconds to wait for the workers being recycled. */
+ std::thread::sleep(std::time::Duration::from_secs(4));
+
+ let mut stream =
+ std::os::unix::net::UnixStream::connect(CONTROL_MANAGER_LISTEN_ADDR).unwrap();
+ stream.write_all(b"exit ").unwrap();
+ });
+
+ run_daemon("none");
+ }
+}
diff --git a/exts/devmaster/src/bin/devctl/main.rs b/exts/devmaster/src/bin/devctl/main.rs
index 17645ee6..8f72285e 100644
--- a/exts/devmaster/src/bin/devctl/main.rs
+++ b/exts/devmaster/src/bin/devctl/main.rs
@@ -18,6 +18,7 @@ mod subcmds;
use basic::argv_util::invoked_as;
use clap::Parser;
use daemon::run_daemon;
+use libdevmaster::config::devmaster_conf::DEFAULT_CONFIG;
use libdevmaster::framework::control_manager::CONTROL_MANAGER_LISTEN_ADDR;
use log::init_log_to_console_syslog;
use log::Level;
@@ -204,6 +205,12 @@ enum SubCmd {
#[clap(short, long)]
root: Option<String>,
},
+ ///
+ #[clap(display_order = 7)]
+ Control {
+ #[clap(short, long)]
+ exit: bool,
+ },
}
/// subcommand for killing workers
@@ -212,10 +219,19 @@ fn subcommand_kill() {
stream.write_all(b"kill ").unwrap();
}
+/// subcommand for controlling devmaster
+fn subcommand_control(exit: bool) {
+ let mut stream = UnixStream::connect(CONTROL_MANAGER_LISTEN_ADDR).unwrap();
+
+ if exit {
+ stream.write_all(b"exit ").unwrap();
+ }
+}
+
fn main() -> Result<()> {
let argv: Vec<String> = std::env::args().collect();
if invoked_as(argv, "devmaster") {
- run_daemon();
+ run_daemon(DEFAULT_CONFIG);
return Ok(());
}
@@ -300,6 +316,7 @@ fn main() -> Result<()> {
strict,
root,
} => subcommand_hwdb(update, test, path, usr, strict, root),
+ SubCmd::Control { exit } => subcommand_control(exit),
}
Ok(())
diff --git a/exts/devmaster/src/lib/framework/control_manager.rs b/exts/devmaster/src/lib/framework/control_manager.rs
index 342c6a0c..d5a5f440 100644
--- a/exts/devmaster/src/lib/framework/control_manager.rs
+++ b/exts/devmaster/src/lib/framework/control_manager.rs
@@ -14,7 +14,7 @@
//!
use crate::framework::job_queue::JobQueue;
use crate::framework::worker_manager::WorkerManager;
-use event::Source;
+use event::{Events, Source};
use nix::unistd::unlink;
use std::os::unix::net::UnixListener;
use std::path::Path;
@@ -38,7 +38,7 @@ pub struct ControlManager {
worker_manager: Weak<WorkerManager>,
/// reference to job queue
_job_queue: Weak<JobQueue>,
- // events: Rc<Events>,
+ events: Rc<Events>,
}
/// public methods
@@ -48,6 +48,7 @@ impl ControlManager {
listen_addr: String,
worker_manager: Rc<WorkerManager>,
job_queue: Rc<JobQueue>,
+ events: Rc<Events>,
) -> ControlManager {
/*
* Cleanup remaining socket if it exists.
@@ -67,6 +68,7 @@ impl ControlManager {
listener,
worker_manager: Rc::downgrade(&worker_manager),
_job_queue: Rc::downgrade(&job_queue),
+ events,
}
}
}
@@ -83,6 +85,9 @@ impl ControlManager {
"kill" => {
self.worker_manager.upgrade().unwrap().kill_workers();
}
+ "exit" => {
+ self.events.set_exit();
+ }
_ => {
todo!();
}
diff --git a/exts/devmaster/src/lib/framework/devmaster.rs b/exts/devmaster/src/lib/framework/devmaster.rs
index 94b93ca0..20735614 100644
--- a/exts/devmaster/src/lib/framework/devmaster.rs
+++ b/exts/devmaster/src/lib/framework/devmaster.rs
@@ -71,10 +71,10 @@ impl Cache {
impl Devmaster {
/// generate a devmaster object
- pub fn new(events: Rc<Events>) -> Rc<RefCell<Devmaster>> {
+ pub fn new(config_path: &str, events: Rc<Events>) -> Rc<RefCell<Devmaster>> {
let config = DevmasterConfig::new();
- config.load(DEFAULT_CONFIG);
+ config.load(config_path);
init_log(
"devmaster",
@@ -127,6 +127,7 @@ impl Devmaster {
String::from(CONTROL_MANAGER_LISTEN_ADDR),
worker_manager.clone(),
job_queue.clone(),
+ events.clone(),
));
let monitor = Rc::new(UeventMonitor::new(job_queue.clone()));
let post = Rc::new(GarbageCollect::new(&devmaster));
--
2.33.0