Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d4dc0e853 | |||
| 311bdbc66d | |||
| 0df716b8b0 | |||
| 243c97d71b | |||
| e0ed96309c | |||
| 93747e4a04 | |||
| b93b55d5a8 | |||
| 46209b2965 | |||
| 775d54f07c | |||
| e9524858f5 | |||
| 1a1202abcf | |||
| c526a6e5ca |
@@ -0,0 +1,9 @@
|
||||
[target.x86_64-unknown-linux-musl]
|
||||
linker = "musl-gcc"
|
||||
|
||||
[target.aarch64-unknown-linux-musl]
|
||||
linker = "aarch64-linux-gnu-gcc"
|
||||
|
||||
[env]
|
||||
CC_aarch64_unknown_linux_musl = "aarch64-linux-gnu-gcc"
|
||||
AR_aarch64_unknown_linux_musl = "aarch64-linux-gnu-ar"
|
||||
@@ -10,4 +10,10 @@ server/*.test
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
config.toml
|
||||
# Config locaux (contiennent des IPs/secrets)
|
||||
agent/config.toml
|
||||
server/config.toml
|
||||
|
||||
# Sauf les configs cargo (pas de secrets)
|
||||
!.cargo/config.toml
|
||||
!agent/.cargo/config.toml
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
[target.x86_64-unknown-linux-musl]
|
||||
linker = "musl-gcc"
|
||||
|
||||
[target.aarch64-unknown-linux-musl]
|
||||
linker = "aarch64-linux-gnu-gcc"
|
||||
|
||||
[env]
|
||||
CC_aarch64_unknown_linux_musl = "aarch64-linux-gnu-gcc"
|
||||
AR_aarch64_unknown_linux_musl = "aarch64-linux-gnu-ar"
|
||||
@@ -38,9 +38,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.10.1"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
|
||||
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"libc",
|
||||
@@ -65,7 +65,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -97,21 +97,6 @@ version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||
dependencies = [
|
||||
"foreign-types-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types-shared"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.32"
|
||||
@@ -142,6 +127,17 @@ dependencies = [
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.4.2"
|
||||
@@ -247,13 +243,14 @@ checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi",
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanometrics-agent"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rumqttc",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -262,23 +259,6 @@ dependencies = [
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"openssl",
|
||||
"openssl-probe",
|
||||
"openssl-sys",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.4.3"
|
||||
@@ -294,48 +274,11 @@ version = "1.21.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.80"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"foreign-types",
|
||||
"libc",
|
||||
"openssl-macros",
|
||||
"openssl-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-macros"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl-probe"
|
||||
version = "0.2.1"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
|
||||
|
||||
[[package]]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.116"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
@@ -343,12 +286,6 @@ version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e"
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.37"
|
||||
@@ -383,6 +320,20 @@ version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"getrandom 0.2.17",
|
||||
"libc",
|
||||
"untrusted",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rumqttc"
|
||||
version = "0.24.0"
|
||||
@@ -393,10 +344,12 @@ dependencies = [
|
||||
"flume",
|
||||
"futures-util",
|
||||
"log",
|
||||
"native-tls",
|
||||
"rustls-native-certs",
|
||||
"rustls-pemfile",
|
||||
"rustls-webpki",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tokio-rustls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -409,7 +362,63 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.22.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432"
|
||||
dependencies = [
|
||||
"log",
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"rustls-webpki",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-native-certs"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5"
|
||||
dependencies = [
|
||||
"openssl-probe",
|
||||
"rustls-pemfile",
|
||||
"rustls-pki-types",
|
||||
"schannel",
|
||||
"security-framework",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pki-types"
|
||||
version = "1.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9"
|
||||
dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.102.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
|
||||
dependencies = [
|
||||
"ring",
|
||||
"rustls-pki-types",
|
||||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -418,7 +427,7 @@ version = "0.1.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -429,9 +438,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "3.7.0"
|
||||
version = "2.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d"
|
||||
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"core-foundation",
|
||||
@@ -527,7 +536,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -539,6 +548,12 @@ dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
@@ -571,10 +586,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"getrandom",
|
||||
"getrandom 0.4.2",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -609,7 +624,7 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -624,12 +639,13 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-native-tls"
|
||||
version = "0.3.1"
|
||||
name = "tokio-rustls"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
|
||||
checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f"
|
||||
dependencies = [
|
||||
"native-tls",
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
@@ -687,10 +703,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "vcpkg"
|
||||
version = "0.2.15"
|
||||
name = "untrusted"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
@@ -797,6 +813,15 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
@@ -973,6 +998,12 @@ dependencies = [
|
||||
"wasmparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.21"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "nanometrics-agent"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
@@ -19,10 +19,11 @@ codegen-units = 1
|
||||
|
||||
[dependencies]
|
||||
sysinfo = { version = "0.30", default-features = false }
|
||||
libc = "0.2"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
toml = "0.8"
|
||||
rumqttc = { version = "0.24", default-features = false, features = ["use-native-tls"] }
|
||||
rumqttc = { version = "0.24", default-features = false, features = ["use-rustls"] }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use nanometrics_agent::{config, metrics, payload, transport};
|
||||
use sysinfo::{Components, Disks, Networks, System};
|
||||
use sysinfo::{Components, Networks, System};
|
||||
use std::time::{Duration, Instant};
|
||||
use std::sync::mpsc;
|
||||
|
||||
@@ -34,7 +34,6 @@ fn main() {
|
||||
|
||||
let mut sys = System::new();
|
||||
let mut networks = Networks::new_with_refreshed_list();
|
||||
let mut disks = Disks::new_with_refreshed_list();
|
||||
let mut components = Components::new_with_refreshed_list();
|
||||
|
||||
let udp_sender = if cfg.protocols.udp.enabled {
|
||||
@@ -69,6 +68,7 @@ fn main() {
|
||||
hostname: hostname.clone(),
|
||||
ip: ip.clone(),
|
||||
status: "online".to_string(),
|
||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@@ -102,9 +102,8 @@ fn main() {
|
||||
}
|
||||
|
||||
if first_slow || now.duration_since(last_slow).as_secs() >= 60 {
|
||||
disks.refresh();
|
||||
if cfg.metrics.disk.udp || cfg.metrics.disk.mqtt {
|
||||
let (used, free, total) = metrics::disk::get(&disks);
|
||||
let (used, free, total) = metrics::disk::get();
|
||||
m.hdd_used = Some(used);
|
||||
m.hdd_free = Some(free);
|
||||
m.hdd_total = Some(total);
|
||||
|
||||
@@ -1,34 +1,36 @@
|
||||
use sysinfo::Disks;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
pub fn get(disks: &Disks) -> (u64, u64, u64) {
|
||||
for disk in disks.list() {
|
||||
let mount = disk.mount_point().to_string_lossy();
|
||||
if mount == "/" {
|
||||
let total = disk.total_space();
|
||||
let free = disk.available_space();
|
||||
let used = total.saturating_sub(free);
|
||||
return (used, free, total);
|
||||
}
|
||||
/// Retourne (used, free, total) en octets pour le système de fichiers racine "/".
|
||||
/// Utilise statvfs() directement pour correspondre exactement aux chiffres de `df` :
|
||||
/// - total = f_blocks × f_frsize
|
||||
/// - used = (f_blocks − f_bfree) × f_frsize (blocs effectivement écrits)
|
||||
/// - free = f_bavail × f_frsize (disponible pour utilisateurs non-root)
|
||||
pub fn get() -> (u64, u64, u64) {
|
||||
let path = b"/\0";
|
||||
let mut stat = MaybeUninit::<libc::statvfs>::uninit();
|
||||
let ret = unsafe { libc::statvfs(path.as_ptr() as *const libc::c_char, stat.as_mut_ptr()) };
|
||||
if ret != 0 {
|
||||
return (0, 0, 0);
|
||||
}
|
||||
if let Some(disk) = disks.list().first() {
|
||||
let total = disk.total_space();
|
||||
let free = disk.available_space();
|
||||
return (total.saturating_sub(free), free, total);
|
||||
}
|
||||
(0, 0, 0)
|
||||
let stat = unsafe { stat.assume_init() };
|
||||
let bsize = stat.f_frsize as u64;
|
||||
let total = stat.f_blocks.saturating_mul(bsize);
|
||||
let used = stat.f_blocks.saturating_sub(stat.f_bfree).saturating_mul(bsize);
|
||||
let free = stat.f_bavail.saturating_mul(bsize);
|
||||
(used, free, total)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sysinfo::Disks;
|
||||
|
||||
#[test]
|
||||
fn test_disk_coherent() {
|
||||
let disks = Disks::new_with_refreshed_list();
|
||||
let (used, free, total) = get(&disks);
|
||||
let (used, free, total) = get();
|
||||
eprintln!("résultat statvfs : used={used} free={free} total={total}");
|
||||
if total > 0 {
|
||||
assert!(used + free <= total + 1024, "used + free > total");
|
||||
assert!(used + free <= total + 1024 * 1024, "used + free > total");
|
||||
assert!(total > 0, "total doit être > 0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ pub struct AgentMetrics {
|
||||
pub hostname: String,
|
||||
pub ip: String,
|
||||
pub status: String,
|
||||
pub version: String,
|
||||
pub cpu_percent: Option<f32>,
|
||||
pub memory_used: Option<u64>,
|
||||
pub memory_free: Option<u64>,
|
||||
|
||||
@@ -115,9 +115,15 @@ body{background:var(--bg-1);color:var(--ink-1);font-family:var(--font-ui);font-s
|
||||
.g-bar{flex:1;height:5px;border-radius:3px;background:var(--bg-1);overflow:hidden}
|
||||
.g-fill{height:100%;border-radius:3px;background:var(--ok);transition:width .3s}
|
||||
.g-fill.w{background:var(--warn)}.g-fill.e{background:var(--err)}
|
||||
.g-val{font-family:var(--font-mono);font-size:11px;color:var(--ink-2);width:34px;text-align:right}
|
||||
.g-val{font-family:var(--font-mono);font-size:11px;color:var(--ink-2);
|
||||
min-width:34px;white-space:nowrap;flex-shrink:0;text-align:right}
|
||||
.tile-foot{font-family:var(--font-terminal);font-size:10px;color:var(--ink-4);
|
||||
display:flex;align-items:center;gap:5px;user-select:none}
|
||||
display:flex;align-items:center;justify-content:space-between;user-select:none}
|
||||
.tile-foot-info{display:flex;align-items:center;gap:5px;min-width:0;overflow:hidden}
|
||||
.btn-del-agent{border:none;background:transparent;cursor:pointer;flex-shrink:0;
|
||||
color:var(--ink-5);font-size:11px;padding:2px 4px;border-radius:4px;
|
||||
line-height:1;transition:color .15s,background .15s;user-select:none}
|
||||
.btn-del-agent:hover{color:var(--err);background:color-mix(in srgb,var(--err) 12%,transparent)}
|
||||
|
||||
/* FOOTER */
|
||||
.footer{background:var(--bg-0);border-top:1px solid var(--border-2);height:26px;
|
||||
|
||||
|
After Width: | Height: | Size: 173 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 235 B |
|
After Width: | Height: | Size: 306 B |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 576 B |
|
After Width: | Height: | Size: 768 B |
@@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||
<!-- Fond arrondi -->
|
||||
<rect width="64" height="64" rx="14" fill="#282828"/>
|
||||
<!-- Cercle accent -->
|
||||
<circle cx="32" cy="32" r="22" fill="none" stroke="#fe8019" stroke-width="4"/>
|
||||
<!-- Barre CPU style jauge -->
|
||||
<rect x="18" y="28" width="28" height="4" rx="2" fill="#504945"/>
|
||||
<rect x="18" y="28" width="18" height="4" rx="2" fill="#fe8019"/>
|
||||
<!-- Point LED vert -->
|
||||
<circle cx="43" cy="21" r="4" fill="#b8bb26"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 498 B |
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "Nanometrics",
|
||||
"short_name": "Nanometrics",
|
||||
"description": "Tableau de bord de surveillance système",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"background_color": "#282828",
|
||||
"theme_color": "#fe8019",
|
||||
"icons": [
|
||||
{ "src": "favicon-192.png", "sizes": "192x192", "type": "image/png" },
|
||||
{ "src": "favicon-512.png", "sizes": "512x512", "type": "image/png" }
|
||||
]
|
||||
}
|
||||
@@ -4,6 +4,13 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Nanometrics</title>
|
||||
<link rel="icon" type="image/x-icon" href="favicon/favicon.ico">
|
||||
<link rel="icon" type="image/svg+xml" href="favicon/favicon.svg">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="favicon/favicon-32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="favicon/favicon-16.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="favicon/favicon-180.png">
|
||||
<link rel="manifest" href="favicon/site.webmanifest">
|
||||
<meta name="theme-color" content="#282828">
|
||||
<link rel="stylesheet" href="vendor/fontawesome/css/all.min.css">
|
||||
<link rel="stylesheet" href="css/app.css">
|
||||
</head>
|
||||
@@ -147,6 +154,29 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- DIALOG SUPPRESSION AGENT -->
|
||||
<div class="overlay" id="overlay-del" style="display:none;z-index:400" onclick="if(event.target===this)this.style.display='none'">
|
||||
<div class="popup" style="width:360px;max-width:96vw" onclick="event.stopPropagation()">
|
||||
<div style="padding:20px 20px 0">
|
||||
<div style="display:flex;align-items:center;gap:12px;margin-bottom:14px">
|
||||
<div style="width:36px;height:36px;border-radius:8px;background:color-mix(in srgb,var(--err) 15%,transparent);display:flex;align-items:center;justify-content:center;color:var(--err);font-size:16px;flex-shrink:0"><i class="fa-solid fa-triangle-exclamation"></i></div>
|
||||
<div>
|
||||
<div style="font-weight:700;font-size:14px">Supprimer l'agent</div>
|
||||
<div style="font-size:12px;color:var(--fg2);margin-top:2px">Cette action est irréversible</div>
|
||||
</div>
|
||||
</div>
|
||||
<p style="font-size:13px;margin:0 0 8px">Supprimer <strong id="del-agent-name">—</strong> ?<br>
|
||||
<span style="font-size:11px;color:var(--fg2)">Toutes les métriques historiques seront effacées.</span></p>
|
||||
</div>
|
||||
<div style="padding:16px 20px;display:flex;justify-content:flex-end;gap:8px">
|
||||
<button class="btn" onclick="document.getElementById('overlay-del').style.display='none'">Annuler</button>
|
||||
<button class="btn" id="del-agent-confirm"
|
||||
style="background:var(--err);color:#fff;border-color:var(--err)"
|
||||
onclick="Popups.doDeleteAgent()"><i class="fa-solid fa-trash"></i> Supprimer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="js/api.js"></script>
|
||||
<script src="js/charts.js"></script>
|
||||
<script src="js/grid.js"></script>
|
||||
|
||||
@@ -27,6 +27,11 @@ const API = (() => {
|
||||
if (!r.ok) throw new Error(`PUT ${path}: ${r.status}`);
|
||||
}
|
||||
|
||||
async function del(path) {
|
||||
const r = await fetch(BASE + path, { method: 'DELETE' });
|
||||
if (!r.ok) throw new Error(`DELETE ${path}: ${r.status}`);
|
||||
}
|
||||
|
||||
async function postForm(path, formData) {
|
||||
const r = await fetch(BASE + path, { method: 'POST', body: formData });
|
||||
if (!r.ok) throw new Error(`POST ${path}: ${r.status}`);
|
||||
@@ -44,6 +49,7 @@ const API = (() => {
|
||||
fd.append('icon', file);
|
||||
return postForm(`/api/agents/${id}/icon`, fd);
|
||||
},
|
||||
deleteAgent: (id) => del(`/api/agents/${id}`),
|
||||
iconUrl: (id) => `/api/agents/${id}/icon`,
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -81,7 +81,7 @@ const Grid = (() => {
|
||||
<div class="g-ico" data-tip="RAM"><i class="fa-solid fa-memory"></i></div>
|
||||
<div class="g-bar"><div class="g-fill ${offline ? '' : gFill(memPct ?? 0)}"
|
||||
style="width:${offline ? 0 : (memPct ?? 0).toFixed(0)}%"></div></div>
|
||||
<span class="g-val">${offline ? '—' : fmtPct(memPct)}</span>
|
||||
<span class="g-val">${offline ? '—' : (metrics?.memory_used && metrics?.memory_total ? fmt(metrics.memory_used) + '/' + fmt(metrics.memory_total) : '—')}</span>
|
||||
</div>
|
||||
<div class="g-row">
|
||||
<div class="g-ico" data-tip="Disque"><i class="fa-solid fa-hard-drive"></i></div>
|
||||
@@ -91,9 +91,15 @@ const Grid = (() => {
|
||||
</div>
|
||||
</div>
|
||||
<div class="tile-foot">
|
||||
${offline
|
||||
<span class="tile-foot-info">
|
||||
${offline
|
||||
? '<i class="fa-solid fa-circle-xmark" style="color:var(--err)"></i><span style="color:var(--err)">Hors ligne</span>'
|
||||
: `<i class="fa-solid fa-clock"></i><span>${uptimeStr}</span>`}
|
||||
: `<i class="fa-solid fa-clock"></i><span>${uptimeStr || '—'}</span>`}
|
||||
</span>
|
||||
<button class="btn-del-agent" title="Supprimer cet agent"
|
||||
onclick="event.stopPropagation();Popups.confirmDeleteAgent('${esc(id)}','${esc(agent.hostname)}')">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
@@ -101,6 +107,12 @@ const Grid = (() => {
|
||||
function update(agentId, metrics) {
|
||||
const entry = _agents.get(agentId);
|
||||
if (!entry) return;
|
||||
// Conserver les valeurs lentes (disque, smart) quand le paquet ne les contient pas
|
||||
if (entry.metrics) {
|
||||
for (const k of Object.keys(entry.metrics)) {
|
||||
if (metrics[k] == null && entry.metrics[k] != null) metrics[k] = entry.metrics[k];
|
||||
}
|
||||
}
|
||||
entry.metrics = metrics;
|
||||
const el = document.getElementById('tile-' + agentId);
|
||||
if (el) {
|
||||
@@ -139,6 +151,13 @@ const Grid = (() => {
|
||||
document.getElementById('stat-err').textContent = err;
|
||||
}
|
||||
|
||||
function removeAgent(id) {
|
||||
_agents.delete(id);
|
||||
const el = document.getElementById('tile-' + id);
|
||||
if (el) el.remove();
|
||||
updateStats();
|
||||
}
|
||||
|
||||
function getAgent(id) { return _agents.get(id); }
|
||||
|
||||
function updateStatus(agentId, status) {
|
||||
@@ -150,5 +169,5 @@ const Grid = (() => {
|
||||
updateStats();
|
||||
}
|
||||
|
||||
return { refresh, update, updateStatus, getAgent, fmt, fmtPct };
|
||||
return { refresh, update, updateStatus, removeAgent, getAgent, fmt, fmtPct };
|
||||
})();
|
||||
|
||||
@@ -119,6 +119,9 @@ const Popups = (() => {
|
||||
<div class="meta-grid">
|
||||
<div class="meta"><div class="meta-lbl">HOSTNAME</div><div class="meta-val">${esc(agent.hostname)}</div></div>
|
||||
<div class="meta"><div class="meta-lbl">ADRESSE IP</div><div class="meta-val">${esc(agent.ip) || '—'}</div></div>
|
||||
<div class="meta"><div class="meta-lbl">VERSION AGENT</div><div class="meta-val" style="display:flex;align-items:center;gap:6px">
|
||||
${agent.version ? `<span style="font-family:var(--font-mono);background:var(--bg-1);border:1px solid var(--border-2);border-radius:5px;padding:1px 7px;font-size:11px;color:var(--accent)">v${esc(agent.version)}</span>` : '<span style="color:var(--ink-4)">—</span>'}
|
||||
</div></div>
|
||||
<div class="meta"><div class="meta-lbl">PROTOCOLES ACTIFS</div><div style="display:flex;gap:5px;margin-top:4px">${protos || '—'}</div></div>
|
||||
<div class="meta"><div class="meta-lbl">DERNIER CONTACT</div><div class="meta-val">${new Date(agent.last_seen * 1000).toLocaleTimeString('fr-FR')}</div></div>
|
||||
</div>
|
||||
@@ -305,6 +308,21 @@ const Popups = (() => {
|
||||
${[[15,'15 min'],[30,'30 min'],[60,'1 heure'],[360,'6 heures']].map(([v,l]) =>
|
||||
`<option value="${v}" ${(cfg.chart_duration_min??30)==v?'selected':''}>${l}</option>`).join('')}
|
||||
</select></div>
|
||||
</div>
|
||||
<div style="display:flex;flex-direction:column;gap:8px">
|
||||
<div class="scfg-sec-title">INSTALLATION AGENT</div>
|
||||
<div class="scfg-row" style="flex-direction:column;align-items:stretch;gap:6px">
|
||||
<label style="font-size:0.85em;color:var(--fg2)">Commande curl — copiez et lancez en root sur la machine cible</label>
|
||||
<div style="display:flex;gap:6px;align-items:center">
|
||||
<input type="text" id="s-install-cmd" readonly
|
||||
style="flex:1;font-family:var(--font-mono);font-size:0.78em;padding:6px 8px;
|
||||
background:var(--bg2);border:1px solid var(--border);border-radius:6px;
|
||||
color:var(--fg);cursor:text;min-width:0"
|
||||
value="SERVER_IP=${window.location.hostname} curl -fsSL https://git.maison43gil.com/gilles/nano_metrics/raw/branch/main/deploy/install.sh | sudo bash">
|
||||
<button class="btn" style="padding:5px 10px;font-size:0.8em;white-space:nowrap"
|
||||
onclick="navigator.clipboard.writeText(document.getElementById('s-install-cmd').value).then(()=>{this.textContent='✓ Copié';setTimeout(()=>this.textContent='Copier',1500)})">Copier</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
document.getElementById('overlay-srvcfg').style.display = 'flex';
|
||||
}
|
||||
@@ -391,10 +409,32 @@ const Popups = (() => {
|
||||
document.getElementById('overlay-smart').style.display = 'flex';
|
||||
}
|
||||
|
||||
// ══ SUPPRESSION AGENT ══
|
||||
let _delAgentId = null;
|
||||
|
||||
function confirmDeleteAgent(id, hostname) {
|
||||
_delAgentId = id;
|
||||
document.getElementById('del-agent-name').textContent = hostname || id;
|
||||
document.getElementById('overlay-del').style.display = 'flex';
|
||||
}
|
||||
|
||||
async function doDeleteAgent() {
|
||||
if (!_delAgentId) return;
|
||||
const id = _delAgentId;
|
||||
document.getElementById('overlay-del').style.display = 'none';
|
||||
_delAgentId = null;
|
||||
try {
|
||||
await API.deleteAgent(id);
|
||||
Grid.removeAgent(id);
|
||||
} catch (e) {
|
||||
alert('Erreur lors de la suppression : ' + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
showDetail, hideDetail,
|
||||
showAgentCfg, sendAgentConfig, toggleCbox,
|
||||
showSrvCfg, hideSrvCfg, saveSrvCfg,
|
||||
showSrvCfg, hideSrvCfg, saveSrvCfg, confirmDeleteAgent, doDeleteAgent,
|
||||
showSmart,
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -82,22 +82,23 @@ ok "Binaire téléchargé ($(du -sh "$TMP_BIN" | cut -f1))"
|
||||
echo ""
|
||||
echo "--- Configuration du serveur ---"
|
||||
|
||||
if [ -z "${SERVER_IP:-}" ]; then
|
||||
read -rp "Adresse IP du serveur Nanometrics : " SERVER_IP
|
||||
fi
|
||||
if [ -z "${SERVER_IP:-}" ]; then
|
||||
err "SERVER_IP est requis."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SERVER_IP="${SERVER_IP:-10.0.0.50}"
|
||||
SERVER_PORT="${SERVER_PORT:-9999}"
|
||||
MQTT_HOST="${MQTT_HOST:-10.0.0.3}"
|
||||
MQTT_ENABLED="${MQTT_ENABLED:-false}"
|
||||
|
||||
ok "Serveur : $SERVER_IP:$SERVER_PORT"
|
||||
ok "Serveur : $SERVER_IP:$SERVER_PORT | MQTT broker : $MQTT_HOST"
|
||||
|
||||
# ── 5. Installer le binaire ────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "[1/5] Installation du binaire dans /usr/local/bin/"
|
||||
|
||||
# Arrêter le service si en cours (le binaire ne peut pas être écrasé à chaud)
|
||||
if systemctl is-active --quiet nanometrics-agent 2>/dev/null; then
|
||||
warn "Service en cours — arrêt temporaire..."
|
||||
systemctl stop nanometrics-agent
|
||||
fi
|
||||
|
||||
cp "$TMP_BIN" "$INSTALL_BIN"
|
||||
chmod 755 "$INSTALL_BIN"
|
||||
ok "Binaire installé"
|
||||
@@ -125,7 +126,7 @@ enabled = true
|
||||
|
||||
[protocols.mqtt]
|
||||
enabled = $MQTT_ENABLED
|
||||
host = "10.0.0.3"
|
||||
host = "$MQTT_HOST"
|
||||
port = 1883
|
||||
topic_base = "nanometrics/agents"
|
||||
auto_discovery = true
|
||||
@@ -160,7 +161,7 @@ mqtt = false
|
||||
udp = true
|
||||
mqtt = false
|
||||
TOML
|
||||
chmod 640 "$CONFIG_FILE"
|
||||
chmod 644 "$CONFIG_FILE"
|
||||
ok "config.toml créé"
|
||||
fi
|
||||
|
||||
|
||||
@@ -40,7 +40,9 @@ for i in "${!TARGETS[@]}"; do
|
||||
# Installer la cible si absente
|
||||
rustup target add "$TARGET" 2>/dev/null || true
|
||||
|
||||
# Compiler
|
||||
# Compiler (CC requis par la crate ring pour les cibles musl cross)
|
||||
CC_aarch64_unknown_linux_musl=aarch64-linux-gnu-gcc \
|
||||
AR_aarch64_unknown_linux_musl=aarch64-linux-gnu-ar \
|
||||
cargo build --release \
|
||||
--manifest-path "$CARGO_TOML" \
|
||||
--target "$TARGET" \
|
||||
|
||||
@@ -20,7 +20,7 @@ const schema = `
|
||||
CREATE TABLE IF NOT EXISTS agents (
|
||||
id TEXT PRIMARY KEY, hostname TEXT NOT NULL,
|
||||
ip TEXT NOT NULL DEFAULT '', status TEXT NOT NULL DEFAULT 'offline',
|
||||
last_seen INTEGER NOT NULL DEFAULT 0
|
||||
last_seen INTEGER NOT NULL DEFAULT 0, version TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS metrics (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT, agent_id TEXT NOT NULL, ts INTEGER NOT NULL,
|
||||
@@ -57,8 +57,12 @@ func Open(path string) (*DB, error) {
|
||||
}
|
||||
|
||||
func (d *DB) migrate() error {
|
||||
_, err := d.conn.Exec(schema)
|
||||
return err
|
||||
if _, err := d.conn.Exec(schema); err != nil {
|
||||
return err
|
||||
}
|
||||
// Migrations additives pour les colonnes ajoutées après la création initiale
|
||||
_, _ = d.conn.Exec(`ALTER TABLE agents ADD COLUMN version TEXT NOT NULL DEFAULT ''`)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *DB) Close() { _ = d.conn.Close() }
|
||||
@@ -66,11 +70,12 @@ func (d *DB) Close() { _ = d.conn.Close() }
|
||||
func (d *DB) UpsertAgent(m *models.AgentMetrics) error {
|
||||
ts := time.Now().Unix()
|
||||
_, err := d.conn.Exec(`
|
||||
INSERT INTO agents (id, hostname, ip, status, last_seen)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
INSERT INTO agents (id, hostname, ip, status, last_seen, version)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
ip=excluded.ip, status=excluded.status, last_seen=excluded.last_seen`,
|
||||
m.Hostname, m.Hostname, m.IP, m.Status, ts)
|
||||
ip=excluded.ip, status=excluded.status, last_seen=excluded.last_seen,
|
||||
version=CASE WHEN excluded.version != '' THEN excluded.version ELSE version END`,
|
||||
m.Hostname, m.Hostname, m.IP, m.Status, ts, m.Version)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -104,7 +109,7 @@ func (d *DB) InsertMetrics(m *models.AgentMetrics) error {
|
||||
}
|
||||
|
||||
func (d *DB) GetAgents() ([]models.Agent, error) {
|
||||
rows, err := d.conn.Query(`SELECT id, hostname, ip, status, last_seen FROM agents`)
|
||||
rows, err := d.conn.Query(`SELECT id, hostname, ip, status, last_seen, version FROM agents`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -112,7 +117,7 @@ func (d *DB) GetAgents() ([]models.Agent, error) {
|
||||
var agents []models.Agent
|
||||
for rows.Next() {
|
||||
var a models.Agent
|
||||
if err := rows.Scan(&a.ID, &a.Hostname, &a.IP, &a.Status, &a.LastSeen); err != nil {
|
||||
if err := rows.Scan(&a.ID, &a.Hostname, &a.IP, &a.Status, &a.LastSeen, &a.Version); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
agents = append(agents, a)
|
||||
@@ -238,6 +243,20 @@ func (d *DB) MarkOffline(timeoutSec int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (d *DB) DeleteAgent(agentID string) error {
|
||||
for _, q := range []string{
|
||||
`DELETE FROM metrics WHERE agent_id = ?`,
|
||||
`DELETE FROM agent_configs WHERE agent_id = ?`,
|
||||
`DELETE FROM agent_icons WHERE agent_id = ?`,
|
||||
`DELETE FROM agents WHERE id = ?`,
|
||||
} {
|
||||
if _, err := d.conn.Exec(q, agentID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarkOfflineAndGetIDs marque les agents inactifs et retourne leurs IDs.
|
||||
func (d *DB) MarkOfflineAndGetIDs(timeoutSec int64) ([]string, error) {
|
||||
cutoff := time.Now().Unix() - timeoutSec
|
||||
|
||||
@@ -3,6 +3,7 @@ package handlers
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/user/nanometrics/server/db"
|
||||
)
|
||||
@@ -18,3 +19,19 @@ func AgentsHandler(database *db.DB) http.HandlerFunc {
|
||||
json.NewEncoder(w).Encode(agents)
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteAgentHandler(database *db.DB) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
parts := strings.Split(strings.Trim(r.URL.Path, "/"), "/")
|
||||
if len(parts) < 3 {
|
||||
http.Error(w, "invalid path", 400)
|
||||
return
|
||||
}
|
||||
agentID := parts[2]
|
||||
if err := database.DeleteAgent(agentID); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ func AgentConfigHandler(database *db.DB, pushConfig func(agentID string, cfg *mo
|
||||
return
|
||||
}
|
||||
if cfg == nil {
|
||||
cfg = &models.AgentConfig{}
|
||||
cfg = models.DefaultAgentConfig()
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(cfg)
|
||||
|
||||
@@ -110,6 +110,8 @@ func main() {
|
||||
handlers.IconUploadHandler(database)(w, r)
|
||||
case endsWith(r.URL.Path, "/icon") && r.Method == http.MethodGet:
|
||||
handlers.IconGetHandler(database)(w, r)
|
||||
case r.Method == http.MethodDelete:
|
||||
handlers.DeleteAgentHandler(database)(w, r)
|
||||
default:
|
||||
http.NotFound(w, r)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ type AgentMetrics struct {
|
||||
Hostname string `json:"hostname"`
|
||||
IP string `json:"ip"`
|
||||
Status string `json:"status"`
|
||||
Version string `json:"version"`
|
||||
CPUPercent *float64 `json:"cpu_percent"`
|
||||
MemoryUsed *int64 `json:"memory_used"`
|
||||
MemoryFree *int64 `json:"memory_free"`
|
||||
@@ -32,6 +33,7 @@ type Agent struct {
|
||||
IP string `json:"ip"`
|
||||
Status string `json:"status"`
|
||||
LastSeen int64 `json:"last_seen"`
|
||||
Version string `json:"version,omitempty"`
|
||||
LastMetrics *AgentMetrics `json:"last_metrics,omitempty"`
|
||||
}
|
||||
|
||||
@@ -88,6 +90,20 @@ type ServerConfig struct {
|
||||
PopupDetailH int `json:"popup_detail_h"`
|
||||
}
|
||||
|
||||
func DefaultAgentConfig() *AgentConfig {
|
||||
on := MetricProto{UDP: true, MQTT: false}
|
||||
return &AgentConfig{
|
||||
Protocols: ProtocolsConfig{UDP: UDPConfig{Enabled: true}},
|
||||
Metrics: MetricsConfig{
|
||||
CPU: on,
|
||||
Memory: on,
|
||||
Disk: on,
|
||||
Smart: on,
|
||||
Uptime: on,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func DefaultServerConfig() ServerConfig {
|
||||
return ServerConfig{
|
||||
TileMinWidth: 220, FontSize: 13,
|
||||
|
||||