@@ -68,7 +68,7 @@ pub fn run_with_ssh(manager_conn: UnixStream) -> Result<(), Box<dyn std::error::
6868 tracing::debug!(ssh_user = %ssh_user, "loaded instance config");
6969
7070 let _manager_conn = manager_conn;
71− wait_for_vm_ipv4(&instance_dir, Duration::from_secs(120))?;
71+ wait_for_vm_ipv4(&instance_dir, Duration::from_secs(480))?;
7272
7373 let ip = load_or_create_instance_config(&instance_dir)?
7474 .vm_ipv4
@@ -242,19 +242,41 @@ fn wait_for_vm_ipv4(
242242) -> Result<(), Box<dyn std::error::Error>> {
243243 let start = Instant::now();
244244 let mut next_log_at = start + Duration::from_secs(10);
245+ let mut next_status_check = start;
245246 tracing::info!("waiting for vm ipv4");
246247 let status_path = instance_dir.join(STATUS_FILE_NAME);
247248 let mut last_status: Option<String> = None;
249+ let mut status_missing = true;
248250 let mut once_hint = false;
249251 loop {
250252 let config = load_or_create_instance_config(instance_dir)?;
251253 if config.vm_ipv4.is_some() {
254+ let _ = fs::remove_file(&status_path);
252255 return Ok(());
253256 }
254257 if start.elapsed() > timeout {
258+ let _ = fs::remove_file(&status_path);
255259 return Err("Timed out waiting for VM IPv4".into());
256260 }
257− if Instant::now() >= next_log_at {
261+ let now = Instant::now();
262+ if now >= next_status_check {
263+ match fs::read_to_string(&status_path) {
264+ Ok(status) => {
265+ status_missing = false;
266+ let status = status.trim().to_string();
267+ if !status.is_empty() && last_status.as_deref() != Some(status.as_str()) {
268+ tracing::info!("[background]: {}", status);
269+ last_status = Some(status);
270+ next_log_at = now + Duration::from_secs(20);
271+ }
272+ }
273+ Err(_) => {
274+ status_missing = true;
275+ }
276+ }
277+ next_status_check = now + Duration::from_millis(500);
278+ }
279+ if now >= next_log_at {
258280 let waited = start.elapsed();
259281 if waited.as_secs() > 15 && !once_hint {
260282 tracing::info!(
@@ -262,16 +284,10 @@ fn wait_for_vm_ipv4(
262284 );
263285 once_hint = true;
264286 }
265− if let Ok(status) = fs::read_to_string(&status_path) {
266− let status = status.trim().to_string();
267− if !status.is_empty() && last_status.as_deref() != Some(status.as_str()) {
268− tracing::info!("[background]: {}", status);
269− last_status = Some(status);
270− }
271− } else {
287+ if status_missing {
272288 tracing::info!("still waiting for vm ipv4, {}s elapsed", waited.as_secs(),);
273289 }
274− next_log_at += Duration::from_secs(10);
290+ next_log_at += Duration::from_secs(20);
275291 }
276292 thread::sleep(Duration::from_millis(200));
277293 }