mirror of
https://github.com/robcholz/vibebox.git
synced 2026-05-20 06:54:40 +02:00
feat: added better info log
This commit is contained in:
+13
-2
@@ -27,6 +27,7 @@ use crate::{
|
||||
|
||||
const SSH_KEY_NAME: &str = "ssh_key";
|
||||
pub(crate) const VM_ROOT_LOG_NAME: &str = "vm_root.log";
|
||||
pub(crate) const STATUS_FILE_NAME: &str = "status.txt";
|
||||
pub(crate) const DEFAULT_SSH_USER: &str = "vibecoder";
|
||||
const SSH_CONNECT_RETRIES: usize = 30;
|
||||
const SSH_CONNECT_DELAY_MS: u64 = 500;
|
||||
@@ -247,6 +248,8 @@ fn wait_for_vm_ipv4(
|
||||
let start = Instant::now();
|
||||
let mut next_log_at = start + Duration::from_secs(10);
|
||||
tracing::info!("waiting for vm ipv4");
|
||||
let status_path = instance_dir.join(STATUS_FILE_NAME);
|
||||
let mut last_status: Option<String> = None;
|
||||
let mut once_hint = false;
|
||||
loop {
|
||||
let config = load_or_create_instance_config(instance_dir)?;
|
||||
@@ -260,11 +263,19 @@ fn wait_for_vm_ipv4(
|
||||
let waited = start.elapsed();
|
||||
if waited.as_secs() > 15 && !once_hint {
|
||||
tracing::info!(
|
||||
"if vibebox is just initialized in this directory, it might take up to 1 minutes depending on your machine, and then you can enjoy the speed vibecoding! go pack!"
|
||||
"if vibebox is just initialized in this directory, it might take up to 1 minute depending on your machine, and then you can enjoy secure & speed vibecoding! go pack!"
|
||||
);
|
||||
once_hint = true;
|
||||
}
|
||||
tracing::info!("still waiting for vm ipv4, {}s elapsed", waited.as_secs(),);
|
||||
if let Ok(status) = fs::read_to_string(&status_path) {
|
||||
let status = status.trim().to_string();
|
||||
if !status.is_empty() && last_status.as_deref() != Some(status.as_str()) {
|
||||
tracing::info!("[background]: {}", status);
|
||||
last_status = Some(status);
|
||||
}
|
||||
} else {
|
||||
tracing::info!("still waiting for vm ipv4, {}s elapsed", waited.as_secs(),);
|
||||
}
|
||||
next_log_at += Duration::from_secs(10);
|
||||
}
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::instance::STATUS_FILE_NAME;
|
||||
use crate::session_manager::{GLOBAL_CACHE_DIR_NAME, INSTANCE_DIR_NAME};
|
||||
use std::{
|
||||
env, fs,
|
||||
@@ -38,6 +39,39 @@ const DEFAULT_RAM_MB: u64 = 2048;
|
||||
const DEFAULT_RAM_BYTES: u64 = DEFAULT_RAM_MB * BYTES_PER_MB;
|
||||
const START_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
const LOGIN_EXPECT_TIMEOUT: Duration = Duration::from_secs(120);
|
||||
|
||||
struct StatusFile {
|
||||
path: PathBuf,
|
||||
cleared: AtomicBool,
|
||||
}
|
||||
|
||||
impl StatusFile {
|
||||
fn new(path: PathBuf) -> Self {
|
||||
Self {
|
||||
path,
|
||||
cleared: AtomicBool::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&self, message: &str) {
|
||||
let _ = fs::write(&self.path, message);
|
||||
}
|
||||
|
||||
fn clear(&self) {
|
||||
if !self.cleared.swap(true, Ordering::SeqCst) {
|
||||
let _ = fs::remove_file(&self.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for StatusFile {
|
||||
fn drop(&mut self) {
|
||||
if !self.cleared.load(Ordering::SeqCst) {
|
||||
let _ = fs::remove_file(&self.path);
|
||||
self.cleared.store(true, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
}
|
||||
const PROVISION_SCRIPT: &str = include_str!("provision.sh");
|
||||
const PROVISION_SCRIPT_NAME: &str = "provision.sh";
|
||||
const DEFAULT_RAW_NAME: &str = "default.raw";
|
||||
@@ -170,6 +204,8 @@ where
|
||||
let guest_mise_cache = cache_dir.join(".guest-mise-cache");
|
||||
|
||||
let instance_dir = project_root.join(INSTANCE_DIR_NAME);
|
||||
let status_file = StatusFile::new(instance_dir.join(STATUS_FILE_NAME));
|
||||
status_file.update("preparing VM image...");
|
||||
|
||||
let basename_compressed = DEBIAN_COMPRESSED_DISK_URL.rsplit('/').next().unwrap();
|
||||
let base_compressed = cache_dir.join(basename_compressed);
|
||||
@@ -193,8 +229,9 @@ where
|
||||
&base_compressed,
|
||||
&default_raw,
|
||||
std::slice::from_ref(&mise_directory_share),
|
||||
Some(&status_file),
|
||||
)?;
|
||||
ensure_instance_disk(&instance_raw, &default_raw)?;
|
||||
ensure_instance_disk(&instance_raw, &default_raw, Some(&status_file))?;
|
||||
let disk_path = instance_raw;
|
||||
|
||||
let mut login_actions = Vec::new();
|
||||
@@ -239,6 +276,7 @@ where
|
||||
&directory_shares[..],
|
||||
args.cpu_count,
|
||||
args.ram_bytes,
|
||||
Some(&status_file),
|
||||
io_handler,
|
||||
)
|
||||
}
|
||||
@@ -421,6 +459,7 @@ impl IoControl {
|
||||
fn ensure_base_image(
|
||||
base_raw: &Path,
|
||||
base_compressed: &Path,
|
||||
status: Option<&StatusFile>,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if base_raw.exists() {
|
||||
return Ok(());
|
||||
@@ -429,6 +468,9 @@ fn ensure_base_image(
|
||||
if !base_compressed.exists()
|
||||
|| std::fs::metadata(base_compressed).map(|m| m.len())? < DEBIAN_COMPRESSED_SIZE_BYTES
|
||||
{
|
||||
if let Some(status) = status {
|
||||
status.update("downloading base image...");
|
||||
}
|
||||
tracing::info!("downloading base image");
|
||||
let status = Command::new("curl")
|
||||
.args([
|
||||
@@ -449,6 +491,9 @@ fn ensure_base_image(
|
||||
|
||||
// Check SHA
|
||||
{
|
||||
if let Some(status) = status {
|
||||
status.update("verifying base image...");
|
||||
}
|
||||
let input = format!("{} {}\n", DEBIAN_COMPRESSED_SHA, base_compressed.display());
|
||||
|
||||
let mut child = Command::new("/usr/bin/shasum")
|
||||
@@ -470,6 +515,9 @@ fn ensure_base_image(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(status) = status {
|
||||
status.update("decompressing base image...");
|
||||
}
|
||||
tracing::info!("decompressing base image");
|
||||
let status = Command::new("tar")
|
||||
.args([
|
||||
@@ -492,13 +540,17 @@ fn ensure_default_image(
|
||||
base_compressed: &Path,
|
||||
default_raw: &Path,
|
||||
directory_shares: &[DirectoryShare],
|
||||
status: Option<&StatusFile>,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if default_raw.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
ensure_base_image(base_raw, base_compressed)?;
|
||||
ensure_base_image(base_raw, base_compressed, status)?;
|
||||
|
||||
if let Some(status) = status {
|
||||
status.update("configuring base image...");
|
||||
}
|
||||
tracing::info!("configuring base image");
|
||||
fs::copy(base_raw, default_raw)?;
|
||||
|
||||
@@ -509,6 +561,7 @@ fn ensure_default_image(
|
||||
directory_shares,
|
||||
DEFAULT_CPU_COUNT,
|
||||
DEFAULT_RAM_BYTES,
|
||||
None,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
@@ -517,11 +570,15 @@ fn ensure_default_image(
|
||||
fn ensure_instance_disk(
|
||||
instance_raw: &Path,
|
||||
template_raw: &Path,
|
||||
status: Option<&StatusFile>,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
if instance_raw.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(status) = status {
|
||||
status.update("creating instance disk...");
|
||||
}
|
||||
tracing::info!(path = %template_raw.display(), "creating instance disk");
|
||||
std::fs::create_dir_all(instance_raw.parent().unwrap())?;
|
||||
fs::copy(template_raw, instance_raw)?;
|
||||
@@ -980,6 +1037,7 @@ fn run_vm_with_io<F>(
|
||||
directory_shares: &[DirectoryShare],
|
||||
cpu_count: usize,
|
||||
ram_bytes: u64,
|
||||
status: Option<&StatusFile>,
|
||||
io_handler: F,
|
||||
) -> Result<(), Box<dyn std::error::Error>>
|
||||
where
|
||||
@@ -1042,6 +1100,10 @@ where
|
||||
return Err("Timed out waiting for VM to start".into());
|
||||
}
|
||||
|
||||
if let Some(status) = status {
|
||||
status.update("vm booting... go vibecoder!");
|
||||
status.clear();
|
||||
}
|
||||
tracing::info!("vm booting");
|
||||
|
||||
let output_monitor = Arc::new(OutputMonitor::default());
|
||||
@@ -1142,6 +1204,7 @@ fn run_vm(
|
||||
directory_shares: &[DirectoryShare],
|
||||
cpu_count: usize,
|
||||
ram_bytes: u64,
|
||||
status: Option<&StatusFile>,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
run_vm_with_io(
|
||||
disk_path,
|
||||
@@ -1149,6 +1212,7 @@ fn run_vm(
|
||||
directory_shares,
|
||||
cpu_count,
|
||||
ram_bytes,
|
||||
status,
|
||||
spawn_vm_io,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user