guest: Wait for a file of gRPC port number getting ready

Some debian services, such as forwarder_guest_launcher and
shutdown_runner, read a gRPC number from a file provided
via virtiofs.
However, since virtiofs and the port number's setup takes some time,
the file soetimes is not ready when systemd tries to start these
daemons. As a result, these daemons could fail to be started
especially at the VM's first boot after installation.

This CL adds a logic to wait for the file getting ready.

Bug: none
Test: Start a VM and check journalctl to ensure the daemons didn't
fail to start.

Change-Id: If5df480815da3ad18f3e412dcabe06e4e7f804ea
diff --git a/guest/forwarder_guest_launcher/debian/service b/guest/forwarder_guest_launcher/debian/service
index ad57a26..7812d67 100644
--- a/guest/forwarder_guest_launcher/debian/service
+++ b/guest/forwarder_guest_launcher/debian/service
@@ -5,7 +5,7 @@
 After=virtiofs_internal.service
 
 [Service]
-ExecStart=/usr/bin/bash -c '/usr/bin/forwarder_guest_launcher --grpc_port $(cat /mnt/internal/debian_service_port)'
+ExecStart=/usr/bin/bash -c '/usr/bin/forwarder_guest_launcher --grpc-port-file /mnt/internal/debian_service_port'
 Type=simple
 Restart=on-failure
 RestartSec=1
diff --git a/guest/forwarder_guest_launcher/src/main.rs b/guest/forwarder_guest_launcher/src/main.rs
index cb8b6a6..3cb557a 100644
--- a/guest/forwarder_guest_launcher/src/main.rs
+++ b/guest/forwarder_guest_launcher/src/main.rs
@@ -52,10 +52,9 @@
 #[derive(Parser)]
 /// Flags for running command
 pub struct Args {
-    /// grpc port number
+    /// path to a file where grpc port number is written
     #[arg(long)]
-    #[arg(alias = "grpc_port")]
-    grpc_port: String,
+    grpc_port_file: String,
 }
 
 async fn process_forwarding_request_queue(
@@ -167,7 +166,19 @@
     debug!("Starting forwarder_guest_launcher");
     let args = Args::parse();
     let gateway_ip_addr = netdev::get_default_gateway()?.ipv4[0];
-    let addr = format!("https://{}:{}", gateway_ip_addr.to_string(), args.grpc_port);
+
+    // Wait for `grpc_port_file` becomes available.
+    const GRPC_PORT_MAX_RETRY_COUNT: u32 = 10;
+    for _ in 0..GRPC_PORT_MAX_RETRY_COUNT {
+        if std::path::Path::new(&args.grpc_port_file).exists() {
+            break;
+        }
+        debug!("{} does not exist. Wait 1 second", args.grpc_port_file);
+        tokio::time::sleep(std::time::Duration::from_secs(1)).await;
+    }
+    let grpc_port = std::fs::read_to_string(&args.grpc_port_file)?.trim().to_string();
+
+    let addr = format!("https://{}:{}", gateway_ip_addr.to_string(), grpc_port);
     let channel = Endpoint::from_shared(addr)?.connect().await?;
     let client = DebianServiceClient::new(channel);
 
diff --git a/guest/shutdown_runner/debian/service b/guest/shutdown_runner/debian/service
index 2668930..a5249d0 100644
--- a/guest/shutdown_runner/debian/service
+++ b/guest/shutdown_runner/debian/service
@@ -4,7 +4,7 @@
 After=virtiofs_internal.service
 
 [Service]
-ExecStart=/usr/bin/bash -c '/usr/bin/shutdown_runner --grpc_port $(cat /mnt/internal/debian_service_port)'
+ExecStart=/usr/bin/bash -c '/usr/bin/shutdown_runner --grpc-port-file /mnt/internal/debian_service_port'
 Type=simple
 Restart=on-failure
 RestartSec=1
diff --git a/guest/shutdown_runner/src/main.rs b/guest/shutdown_runner/src/main.rs
index 397c205..4043002 100644
--- a/guest/shutdown_runner/src/main.rs
+++ b/guest/shutdown_runner/src/main.rs
@@ -26,10 +26,9 @@
 #[derive(Parser)]
 /// Flags for running command
 pub struct Args {
-    /// grpc port number
+    /// Path to a file where grpc port number is written
     #[arg(long)]
-    #[arg(alias = "grpc_port")]
-    grpc_port: String,
+    grpc_port_file: String,
 }
 
 #[tokio::main]
@@ -38,7 +37,17 @@
     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);
+    // Wait for `grpc_port_file` becomes available.
+    const GRPC_PORT_MAX_RETRY_COUNT: u32 = 10;
+    for _ in 0..GRPC_PORT_MAX_RETRY_COUNT {
+        if std::path::Path::new(&args.grpc_port_file).exists() {
+            break;
+        }
+        debug!("{} does not exist. Wait 1 second", args.grpc_port_file);
+        tokio::time::sleep(std::time::Duration::from_secs(1)).await;
+    }
+    let grpc_port = std::fs::read_to_string(&args.grpc_port_file)?.trim().to_string();
+    let server_addr = format!("http://{}:{}", gateway_ip_addr.to_string(), grpc_port);
 
     debug!("connect to grpc server {}", server_addr);