chore: sincroniza alterações locais
This commit is contained in:
parent
c3249e523d
commit
c2050f311a
7 changed files with 362 additions and 26 deletions
|
|
@ -5,6 +5,7 @@ use chrono::{DateTime, Utc};
|
|||
use once_cell::sync::Lazy;
|
||||
use parking_lot::Mutex;
|
||||
use serde::Serialize;
|
||||
use serde_json::json;
|
||||
use sysinfo::{Networks, System};
|
||||
use tauri::async_runtime::{self, JoinHandle};
|
||||
use tokio::sync::Notify;
|
||||
|
|
@ -100,6 +101,181 @@ fn collect_mac_addresses() -> Vec<String> {
|
|||
macs
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn collect_serials_platform() -> Vec<String> {
|
||||
let mut out = Vec::new();
|
||||
for path in [
|
||||
"/sys/class/dmi/id/product_uuid",
|
||||
"/sys/class/dmi/id/product_serial",
|
||||
"/sys/class/dmi/id/board_serial",
|
||||
"/etc/machine-id",
|
||||
] {
|
||||
if let Ok(raw) = std::fs::read_to_string(path) {
|
||||
let s = raw.trim().to_string();
|
||||
if !s.is_empty() && !out.contains(&s) {
|
||||
out.push(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "windows", target_os = "macos"))]
|
||||
fn collect_serials_platform() -> Vec<String> {
|
||||
// Fase 1: sem coleta nativa; será implementada via WMI/ioreg na fase 2.
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
fn collect_serials() -> Vec<String> {
|
||||
collect_serials_platform()
|
||||
}
|
||||
|
||||
fn collect_network_addrs() -> Vec<serde_json::Value> {
|
||||
let mut entries = Vec::new();
|
||||
if let Ok(ifaces) = get_if_addrs::get_if_addrs() {
|
||||
for iface in ifaces {
|
||||
let name = iface.name;
|
||||
let mac = iface.mac.map(|m| m.to_string());
|
||||
let addr = iface.ip();
|
||||
let ip = addr.to_string();
|
||||
entries.push(json!({
|
||||
"name": name,
|
||||
"mac": mac,
|
||||
"ip": ip,
|
||||
}));
|
||||
}
|
||||
}
|
||||
entries
|
||||
}
|
||||
|
||||
fn collect_disks(system: &System) -> Vec<serde_json::Value> {
|
||||
let mut out = Vec::new();
|
||||
for d in system.disks() {
|
||||
let name = d.name().to_string_lossy().to_string();
|
||||
let mount = d.mount_point().to_string_lossy().to_string();
|
||||
let fs = String::from_utf8_lossy(d.file_system()).to_string();
|
||||
let total = d.total_space();
|
||||
let avail = d.available_space();
|
||||
out.push(json!({
|
||||
"name": name,
|
||||
"mountPoint": mount,
|
||||
"fs": fs,
|
||||
"totalBytes": total,
|
||||
"availableBytes": avail,
|
||||
}));
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
fn build_inventory_metadata(system: &System) -> serde_json::Value {
|
||||
let cpu_brand = system
|
||||
.cpus()
|
||||
.first()
|
||||
.map(|cpu| cpu.brand().to_string())
|
||||
.unwrap_or_default();
|
||||
let mem_total_bytes = system.total_memory().saturating_mul(1024);
|
||||
let network = collect_network_addrs();
|
||||
let disks = collect_disks(system);
|
||||
let mut inventory = json!({
|
||||
"cpu": { "brand": cpu_brand },
|
||||
"memory": { "totalBytes": mem_total_bytes },
|
||||
"network": network,
|
||||
"disks": disks,
|
||||
});
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
// Softwares instalados (dpkg ou rpm)
|
||||
let software = collect_software_linux();
|
||||
if let Some(obj) = inventory.as_object_mut() {
|
||||
obj.insert("software".into(), software);
|
||||
}
|
||||
|
||||
// Serviços ativos (systemd)
|
||||
let services = collect_services_linux();
|
||||
if let Some(obj) = inventory.as_object_mut() {
|
||||
obj.insert("services".into(), services);
|
||||
}
|
||||
}
|
||||
|
||||
json!({ "inventory": inventory })
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn collect_software_linux() -> serde_json::Value {
|
||||
use std::process::Command;
|
||||
// Tenta dpkg-query primeiro
|
||||
let dpkg = Command::new("sh")
|
||||
.arg("-lc")
|
||||
.arg("dpkg-query -W -f='${binary:Package}\t${Version}\n' 2>/dev/null || true")
|
||||
.output();
|
||||
if let Ok(out) = dpkg {
|
||||
if out.status.success() {
|
||||
let s = String::from_utf8_lossy(&out.stdout);
|
||||
let mut items = Vec::new();
|
||||
for line in s.lines() {
|
||||
let mut parts = line.split('\t');
|
||||
let name = parts.next().unwrap_or("").trim();
|
||||
let version = parts.next().unwrap_or("").trim();
|
||||
if !name.is_empty() {
|
||||
items.push(json!({"name": name, "version": version, "source": "dpkg"}));
|
||||
}
|
||||
}
|
||||
return json!(items);
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback rpm
|
||||
let rpm = std::process::Command::new("sh")
|
||||
.arg("-lc")
|
||||
.arg("rpm -qa --qf '%{NAME}\t%{VERSION}-%{RELEASE}\n' 2>/dev/null || true")
|
||||
.output();
|
||||
if let Ok(out) = rpm {
|
||||
if out.status.success() {
|
||||
let s = String::from_utf8_lossy(&out.stdout);
|
||||
let mut items = Vec::new();
|
||||
for line in s.lines() {
|
||||
let mut parts = line.split('\t');
|
||||
let name = parts.next().unwrap_or("").trim();
|
||||
let version = parts.next().unwrap_or("").trim();
|
||||
if !name.is_empty() {
|
||||
items.push(json!({"name": name, "version": version, "source": "rpm"}));
|
||||
}
|
||||
}
|
||||
return json!(items);
|
||||
}
|
||||
}
|
||||
json!([])
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn collect_services_linux() -> serde_json::Value {
|
||||
use std::process::Command;
|
||||
let out = Command::new("sh")
|
||||
.arg("-lc")
|
||||
.arg("systemctl list-units --type=service --state=running --no-pager --no-legend 2>/dev/null || true")
|
||||
.output();
|
||||
if let Ok(out) = out {
|
||||
if out.status.success() {
|
||||
let s = String::from_utf8_lossy(&out.stdout);
|
||||
let mut items = Vec::new();
|
||||
for line in s.lines() {
|
||||
// Typical format: UNIT LOAD ACTIVE SUB DESCRIPTION
|
||||
// We take UNIT and ACTIVE
|
||||
let cols: Vec<&str> = line.split_whitespace().collect();
|
||||
if cols.is_empty() { continue; }
|
||||
let unit = cols.get(0).unwrap_or(&"");
|
||||
let active = cols.get(2).copied().unwrap_or("");
|
||||
if !unit.is_empty() {
|
||||
items.push(json!({"name": unit, "status": active}));
|
||||
}
|
||||
}
|
||||
return json!(items);
|
||||
}
|
||||
}
|
||||
json!([])
|
||||
}
|
||||
|
||||
fn collect_system() -> System {
|
||||
let mut system = System::new_all();
|
||||
system.refresh_all();
|
||||
|
|
@ -154,7 +330,7 @@ pub fn collect_profile() -> Result<MachineProfile, AgentError> {
|
|||
let architecture = std::env::consts::ARCH.to_string();
|
||||
|
||||
let mac_addresses = collect_mac_addresses();
|
||||
let serials: Vec<String> = Vec::new();
|
||||
let serials: Vec<String> = collect_serials();
|
||||
|
||||
if mac_addresses.is_empty() && serials.is_empty() {
|
||||
return Err(AgentError::MissingIdentifiers);
|
||||
|
|
@ -216,7 +392,7 @@ async fn post_heartbeat(base_url: &str, token: &str, status: Option<String>) ->
|
|||
hostname: Some(hostname),
|
||||
os: Some(os),
|
||||
metrics: Some(metrics),
|
||||
metadata: None,
|
||||
metadata: Some(build_inventory_metadata(&system)),
|
||||
};
|
||||
|
||||
let url = format!("{}/api/machines/heartbeat", base_url);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue