diff --git a/services/src/crash_report.rs b/services/src/crash_report.rs index 6240c19f..31fe1d29 100644 --- a/services/src/crash_report.rs +++ b/services/src/crash_report.rs @@ -5,12 +5,19 @@ use std::path::PathBuf; use log::{debug, error, warn}; +use printnanny_settings::printnanny::PrintNannySettings; use tokio::fs; use tokio::process::Command; use printnanny_settings::error::PrintNannySettingsError; use zip::write::FileOptions; +async fn pip_freeze(venv: &PathBuf) -> io::Result> { + let pip = venv.join("bin/pip"); + let output = Command::new(pip).args(["freeze", "--all"]).output().await?; + Ok(output.stdout) +} + async fn netstat_routes() -> io::Result> { let output = Command::new("netstat").args(["--route"]).output().await?; Ok(output.stdout) @@ -92,11 +99,13 @@ fn write_to_zipfile( pub async fn write_crash_report_zip( file: &File, - crash_report_paths: Vec, + settings: &PrintNannySettings, ) -> Result<(), PrintNannySettingsError> { let mut zip = zip::ZipWriter::new(file); let options = FileOptions::default().unix_permissions(0o755); + let crash_report_paths = settings.paths.crash_report_paths(); + for path in crash_report_paths { // handle path does not exist if !path.exists() { @@ -183,6 +192,12 @@ pub async fn write_crash_report_zip( } } + // run `pip freeze` in all virtual environments + for (filename, venv) in settings.paths.venvs(settings).iter() { + let content = pip_freeze(venv).await?; + write_to_zipfile(filename, &content, &mut zip, options); + } + // write disk usage to zip let fname = "disk_usage.txt"; match &disk_usage().await { diff --git a/services/src/printnanny_api.rs b/services/src/printnanny_api.rs index 76f2e65f..d08e6011 100644 --- a/services/src/printnanny_api.rs +++ b/services/src/printnanny_api.rs @@ -203,8 +203,9 @@ impl ApiService { .tempfile() .map_err(|e| IoError::TempFileError { msg: e.to_string() })?; let (file, filename) = &file.keep()?; + let settings = PrintNannySettings::new().await?; - write_crash_report_zip(file, crash_report_paths).await?; + write_crash_report_zip(file, &settings).await?; warn!("Wrote crash report logs to {}", filename.display()); let serial = match RpiCpuInfo::new() { @@ -256,8 +257,9 @@ impl ApiService { .tempfile() .map_err(|e| IoError::TempFileError { msg: e.to_string() })?; let (file, filename) = &file.keep()?; + let settings = PrintNannySettings::new().await?; - write_crash_report_zip(file, crash_report_paths).await?; + write_crash_report_zip(file, &settings).await?; warn!("Wrote crash report logs to {}", filename.display()); let serial = match RpiCpuInfo::new() { diff --git a/settings/src/paths.rs b/settings/src/paths.rs index 76bfbffd..27c64a34 100644 --- a/settings/src/paths.rs +++ b/settings/src/paths.rs @@ -3,12 +3,15 @@ use figment::providers::Env; use log::{info, warn}; use serde; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; use std::io::Read; use std::path::{Path, PathBuf}; use std::time::{SystemTime, UNIX_EPOCH}; use tokio::fs; use zip::ZipArchive; +use crate::printnanny::PrintNannySettings; + use super::error::PrintNannySettingsError; pub const DEFAULT_PRINTNANNY_USER: &str = "printnanny"; @@ -68,6 +71,21 @@ impl PrintNannyPaths { )) } + pub fn venvs(&self, settings: &PrintNannySettings) -> HashMap { + let mut result = HashMap::new(); + + let octoprint_venv = settings.to_octoprint_settings().venv; + result.insert("octoprint.requirements.txt".to_string(), octoprint_venv); + + let klipper_venv = settings.to_klipper_settings().venv; + result.insert("klipper.requirements.txt".to_string(), klipper_venv); + + let moonraker_venv = settings.to_moonraker_settings().venv; + result.insert("moonraker.requiremens.txt".to_string(), moonraker_venv); + + result + } + pub fn db(&self) -> PathBuf { self.state_dir.join("db.sqlite") }