Gracefully stop the vm
Bug: 381815559
Test: click 'close' in the notification
Change-Id: Ic000bb7e62b5e5ec39b3c89b9cd9a05aee17588b
diff --git a/guest/shutdown_runner/.gitignore b/guest/shutdown_runner/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/guest/shutdown_runner/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/guest/shutdown_runner/Cargo.toml b/guest/shutdown_runner/Cargo.toml
new file mode 100644
index 0000000..b74e7ee
--- /dev/null
+++ b/guest/shutdown_runner/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "shutdown_runner"
+version = "0.1.0"
+edition = "2021"
+license = "Apache-2.0"
+
+[dependencies]
+anyhow = "1.0.94"
+clap = { version = "4.5.20", features = ["derive"] }
+log = "0.4.22"
+netdev = "0.31.0"
+prost = "0.13.3"
+tokio = { version = "1.40.0", features = ["rt-multi-thread"] }
+tonic = "0.12.3"
+
+[build-dependencies]
+tonic-build = "0.12.3"
diff --git a/guest/shutdown_runner/build.rs b/guest/shutdown_runner/build.rs
new file mode 100644
index 0000000..e3939d4
--- /dev/null
+++ b/guest/shutdown_runner/build.rs
@@ -0,0 +1,7 @@
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let proto_file = "../../libs/debian_service/proto/DebianService.proto";
+
+ tonic_build::compile_protos(proto_file).unwrap();
+
+ Ok(())
+}
diff --git a/guest/shutdown_runner/src/main.rs b/guest/shutdown_runner/src/main.rs
new file mode 100644
index 0000000..19e9883
--- /dev/null
+++ b/guest/shutdown_runner/src/main.rs
@@ -0,0 +1,46 @@
+use api::debian_service_client::DebianServiceClient;
+use api::ShutdownQueueOpeningRequest;
+use std::process::Command;
+
+use anyhow::anyhow;
+use clap::Parser;
+use log::debug;
+pub mod api {
+ tonic::include_proto!("com.android.virtualization.terminal.proto");
+}
+
+#[derive(Parser)]
+/// Flags for running command
+pub struct Args {
+ /// grpc port number
+ #[arg(long)]
+ #[arg(alias = "grpc_port")]
+ grpc_port: String,
+}
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let args = Args::parse();
+ let gateway_ip_addr = netdev::get_default_gateway()?.ipv4[0];
+
+ let server_addr = format!("http://{}:{}", gateway_ip_addr.to_string(), args.grpc_port);
+
+ debug!("connect to grpc server {}", server_addr);
+
+ let mut client = DebianServiceClient::connect(server_addr).await.map_err(|e| e.to_string())?;
+
+ let mut res_stream = client
+ .open_shutdown_request_queue(tonic::Request::new(ShutdownQueueOpeningRequest {}))
+ .await?
+ .into_inner();
+
+ while let Some(_response) = res_stream.message().await? {
+ let status = Command::new("poweroff").status().expect("power off");
+ if !status.success() {
+ return Err(anyhow!("Failed to power off: {status}").into());
+ }
+ debug!("poweroff");
+ break;
+ }
+ Ok(())
+}