diff --git a/virtweb_backend/Cargo.lock b/virtweb_backend/Cargo.lock
index 888b25e..2674e19 100644
--- a/virtweb_backend/Cargo.lock
+++ b/virtweb_backend/Cargo.lock
@@ -749,6 +749,30 @@ dependencies = [
"crossbeam-utils",
]
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "memoffset",
+ "scopeguard",
+]
+
[[package]]
name = "crossbeam-utils"
version = "0.8.16"
@@ -843,6 +867,12 @@ dependencies = [
"subtle",
]
+[[package]]
+name = "either"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
+
[[package]]
name = "encoding_rs"
version = "0.8.33"
@@ -1325,6 +1355,15 @@ version = "2.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5486aed0026218e61b8a01d5fbd5a0a134649abb71a0e53b7bc088529dced86e"
+[[package]]
+name = "memoffset"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
+dependencies = [
+ "autocfg",
+]
+
[[package]]
name = "mime"
version = "0.3.17"
@@ -1380,6 +1419,25 @@ dependencies = [
"tempfile",
]
+[[package]]
+name = "ntapi"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
[[package]]
name = "object"
version = "0.32.0"
@@ -1570,6 +1628,28 @@ dependencies = [
"getrandom",
]
+[[package]]
+name = "rayon"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "num_cpus",
+]
+
[[package]]
name = "redox_syscall"
version = "0.3.5"
@@ -1877,6 +1957,22 @@ dependencies = [
"unicode-ident",
]
+[[package]]
+name = "sysinfo"
+version = "0.29.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a18d114d420ada3a891e6bc8e96a2023402203296a47cdd65083377dad18ba5"
+dependencies = [
+ "cfg-if",
+ "core-foundation-sys",
+ "libc",
+ "ntapi",
+ "once_cell",
+ "rayon",
+ "serde",
+ "winapi",
+]
+
[[package]]
name = "tempfile"
version = "3.8.0"
@@ -2145,6 +2241,7 @@ dependencies = [
"reqwest",
"serde",
"serde_json",
+ "sysinfo",
"tempfile",
"url",
"virt",
diff --git a/virtweb_backend/Cargo.toml b/virtweb_backend/Cargo.toml
index 083d145..a9c01b8 100644
--- a/virtweb_backend/Cargo.toml
+++ b/virtweb_backend/Cargo.toml
@@ -26,4 +26,5 @@ actix-multipart = "0.6.1"
tempfile = "3.8.0"
reqwest = { version = "0.11.18", features = ["stream"] }
url = "2.4.0"
-virt = "0.3.0"
\ No newline at end of file
+virt = "0.3.0"
+sysinfo = { version = "0.29.10", features = ["serde"] }
\ No newline at end of file
diff --git a/virtweb_backend/src/controllers/server_controller.rs b/virtweb_backend/src/controllers/server_controller.rs
index cc1ee21..b1425cc 100644
--- a/virtweb_backend/src/controllers/server_controller.rs
+++ b/virtweb_backend/src/controllers/server_controller.rs
@@ -4,6 +4,7 @@ use crate::constants;
use crate::controllers::{HttpResult, LibVirtReq};
use crate::extractors::local_auth_extractor::LocalAuthEnabled;
use actix_web::{HttpResponse, Responder};
+use sysinfo::{System, SystemExt};
pub async fn root_index() -> impl Responder {
HttpResponse::Ok().body("Hello world!")
@@ -31,10 +32,17 @@ pub async fn static_config(local_auth: LocalAuthEnabled) -> impl Responder {
#[derive(serde::Serialize)]
struct ServerInfo {
hypervisor: HypervisorInfo,
+ system: System,
}
pub async fn server_info(client: LibVirtReq) -> HttpResult {
+ let mut system = System::new();
+ system.refresh_disks_list();
+ system.refresh_components_list();
+ system.refresh_all();
+
Ok(HttpResponse::Ok().json(ServerInfo {
hypervisor: client.get_info().await?,
+ system,
}))
}
diff --git a/virtweb_frontend/src/App.tsx b/virtweb_frontend/src/App.tsx
index 63efd12..4f95754 100644
--- a/virtweb_frontend/src/App.tsx
+++ b/virtweb_frontend/src/App.tsx
@@ -14,6 +14,7 @@ import { LoginRoute } from "./routes/auth/LoginRoute";
import { AuthApi } from "./api/AuthApi";
import { IsoFilesRoute } from "./routes/IsoFilesRoute";
import { ServerApi } from "./api/ServerApi";
+import { SysInfoRoute } from "./routes/SysInfoRoute";
interface AuthContext {
signedIn: boolean;
@@ -35,6 +36,7 @@ export function App() {
signedIn || ServerApi.Config.auth_disabled ? (
}>
} />
+ } />
} />
) : (
diff --git a/virtweb_frontend/src/api/ServerApi.ts b/virtweb_frontend/src/api/ServerApi.ts
index 57c62e3..08757a8 100644
--- a/virtweb_frontend/src/api/ServerApi.ts
+++ b/virtweb_frontend/src/api/ServerApi.ts
@@ -10,7 +10,100 @@ export interface ServerConfig {
let config: ServerConfig | null = null;
-export interface ServerInfo {}
+export interface ServerSystemInfo {
+ hypervisor: HypervisorInfo;
+ system: SystemInfo;
+}
+
+interface HypervisorInfo {
+ type: string;
+ hyp_version: number;
+ lib_version: number;
+ capabilities: string;
+ free_memory: number;
+ hostname: string;
+ node: {
+ cpu_model: string;
+ memory_size: number;
+ number_of_active_cpus: number;
+ cpu_frequency_mhz: number;
+ number_of_numa_cell: number;
+ number_of_cpu_socket_per_node: number;
+ number_of_core_per_sockets: number;
+ number_of_threads_per_sockets: number;
+ };
+}
+
+interface SystemInfo {
+ IS_SUPPORTED: boolean;
+ SUPPORTED_SIGNALS: string[];
+ MINIMUM_CPU_UPDATE_INTERVAL: {
+ secs: number;
+ nanos: number;
+ };
+ global_cpu_info: GlobalCPUInfo;
+ cpus: CpuCore[];
+ physical_core_count: number;
+ total_memory: number;
+ free_memory: number;
+ available_memory: number;
+ used_memory: number;
+ total_swap: number;
+ free_swap: number;
+ used_swap: number;
+ components: SysComponent;
+ users: [];
+ disks: DiskInfo[];
+ networks: [];
+ uptime: number;
+ boot_time: number;
+ load_average: SysLoadAverage;
+ name: string;
+ kernel_version: string;
+ os_version: string;
+ long_os_version: string;
+ distribution_id: string;
+ host_name: string;
+}
+
+interface GlobalCPUInfo {
+ cpu_usage: number;
+ name: string;
+ vendor_id: string;
+ brand: string;
+ frequency: number;
+}
+
+interface CpuCore {
+ cpu_usage: number;
+ name: string;
+ vendor_id: string;
+ brand: string;
+ frequency: number;
+}
+
+interface SysComponent {
+ temperature: number;
+ max: number;
+ critical: number;
+ label: string;
+}
+
+interface DiskInfo {
+ DiskKind: "HDD" | "SSD";
+ name: string;
+ file_system: number[];
+ mount_point: string;
+ total_space: number;
+ available_space: number;
+ is_removable: boolean;
+}
+
+interface SysLoadAverage {
+ one: number;
+ five: number;
+ fifteen: number;
+}
export class ServerApi {
/**
@@ -36,7 +129,7 @@ export class ServerApi {
/**
* Get server information
*/
- static async SystemInfo(): Promise {
+ static async SystemInfo(): Promise {
return (
await APIClient.exec({
method: "GET",
diff --git a/virtweb_frontend/src/routes/SysInfoRoute.tsx b/virtweb_frontend/src/routes/SysInfoRoute.tsx
new file mode 100644
index 0000000..142774c
--- /dev/null
+++ b/virtweb_frontend/src/routes/SysInfoRoute.tsx
@@ -0,0 +1,26 @@
+import React from "react";
+import { ServerApi, ServerSystemInfo } from "../api/ServerApi";
+import { AsyncWidget } from "../widgets/AsyncWidget";
+
+export function SysInfoRoute(): React.ReactElement {
+ const [info, setInfo] = React.useState();
+
+ const load = async () => {
+ setInfo(await ServerApi.SystemInfo());
+ };
+
+ return (
+ }
+ errMsg="Failed to load system info"
+ />
+ );
+}
+
+export function SysInfoRouteInner(p: {
+ info: ServerSystemInfo;
+}): React.ReactElement {
+ return <>todo>;
+}
diff --git a/virtweb_frontend/src/widgets/BaseAuthenticatedPage.tsx b/virtweb_frontend/src/widgets/BaseAuthenticatedPage.tsx
index 6ea6ab7..ff71406 100644
--- a/virtweb_frontend/src/widgets/BaseAuthenticatedPage.tsx
+++ b/virtweb_frontend/src/widgets/BaseAuthenticatedPage.tsx
@@ -1,4 +1,4 @@
-import { mdiDisc, mdiHome, mdiLanPending } from "@mdi/js";
+import { mdiDisc, mdiHome, mdiInformation, mdiLanPending } from "@mdi/js";
import Icon from "@mdi/react";
import {
Box,
@@ -54,6 +54,11 @@ export function BaseAuthenticatedPage(): React.ReactElement {
uri="/iso"
icon={}
/>
+ }
+ />