diff --git a/src/app/monitoring/monitoring-nodes.tsx b/src/app/monitoring/monitoring-nodes.tsx index 38d11df..0196a62 100644 --- a/src/app/monitoring/monitoring-nodes.tsx +++ b/src/app/monitoring/monitoring-nodes.tsx @@ -29,22 +29,24 @@ export default async function ResourcesNodes({ resourcesNodes }: { resourcesNode Name - CPU % - CPU - RAM % - RAM - Disk GB + CPU Absolut + CPU Capacity + RAM Absolut + RAM Capacity + Disk Absolut + Disk Capacity {resourcesNodes.map((node) => ( {node.name} - {node.cpuUsagePercent} {node.cpuUsageAbsolut} - {node.ramUsagePercent} + {node.cpuUsageCapacity} {node.ramUsageAbsolut} - {node.diskUsagePercent} + {node.ramUsageCapacity} + {node.diskUsageAbsolut} + {node.diskUsageCapacity} ))} diff --git a/src/server/adapter/longhorn-api.adapter.ts b/src/server/adapter/longhorn-api.adapter.ts index 8b18126..263f63f 100644 --- a/src/server/adapter/longhorn-api.adapter.ts +++ b/src/server/adapter/longhorn-api.adapter.ts @@ -1,3 +1,5 @@ +import { any, number } from "zod"; + class LonghornApiAdapter { async getLonghornVolume(pvcName: String) { //Soll PVC Name und Used Size zurückgeben @@ -31,6 +33,57 @@ class LonghornApiAdapter { return -1; // Rückgabe mit Fehlerfall } } + + + async getNodeStorageInfo(nodeName: String) { //Soll PVC Name und Used Size zurückgeben + let longhornApiUrl = process.env.NODE_ENV === 'production' ? 'http://longhorn-frontend.longhorn-system.svc.cluster.local/v1/nodes' : 'http://localhost:4000/v1/nodes'; + // Request senden + const response = await fetch(`${longhornApiUrl}/${nodeName}`, { + cache: 'no-cache', + method: 'GET', // Standardmäßig GET + headers: { + + 'Accept': 'application/json', // Optional, falls JSON erwartet wird + 'Content-Type': 'application/json' // Optional, falls JSON zurückgegeben wird + } + }); + + // Überprüfen, ob die Anfrage erfolgreich war + if (!response.ok) { + throw new Error(`HTTP-Error: ${response.status}`); + } + + // Antwort als JSON parsen + const data = await response.json() as { + disks: { + [key: string]: { + storageMaximum: number, + storageAvailable: number + } + } + }; + + if (!data.disks || typeof data.disks !== "object") { + throw new Error("Invalid node data: 'disks' property is missing or not an object."); + } + + // Initialize totals + let totalStorageMaximum = 0; + let totalStorageAvailable = 0; + + // Iterate over each disk and sum up the values + Object.values(data.disks).forEach(disk => { + + totalStorageMaximum += disk.storageMaximum; + totalStorageAvailable += disk.storageAvailable; + }); + + return { + totalStorageMaximum, + totalStorageAvailable + }; + +} } const longhornApiAdapter = new LonghornApiAdapter(); export default longhornApiAdapter; \ No newline at end of file diff --git a/src/server/services/node.service.ts b/src/server/services/node.service.ts index 95b93e5..c32a09d 100644 --- a/src/server/services/node.service.ts +++ b/src/server/services/node.service.ts @@ -5,6 +5,7 @@ import { NodeInfoModel } from "@/shared/model/node-info.model"; import { NodeResourceModel } from "@/shared/model/node-resource.model"; import { Tags } from "../utils/cache-tag-generator.utils"; import { revalidateTag, unstable_cache } from "next/cache"; +import longhornApiAdapter from "../adapter/longhorn-api.adapter"; class ClusterService { @@ -68,20 +69,23 @@ class ClusterService { return parseFloat(((current / capacity) * 100).toFixed(2)); } + + function bytesToMb(bytes: number): number { return parseFloat((bytes / (1024 * 1024)).toFixed(2)); } - return topNodes.map((node) => { + return await Promise.all (topNodes.map(async (node) => { + const diskInfo = await longhornApiAdapter.getNodeStorageInfo(node.Node.metadata?.name!); return { name: node.Node.metadata?.name!, - cpuUsagePercent: `${calculatePercent(Number(node.CPU?.RequestTotal!), Number(node.CPU?.Capacity!))}%`, - cpuUsageAbsolut: `${Number(node.CPU?.RequestTotal!).toFixed(2)} cores`, - ramUsagePercent: `${calculatePercent(bytesToMb(Number(node.Memory?.RequestTotal!)), bytesToMb(Number(node.Memory?.Capacity!)))}%`, - ramUsageAbsolut: `${bytesToMb(Number(node.Memory?.RequestTotal!))} MB`, - diskUsagePercent: "94%", - diskUsageAbsolut: "117GB%", - }}); + cpuUsageAbsolut: Number(node.CPU?.RequestTotal!), + cpuUsageCapacity: Number(node.CPU?.Capacity!), + ramUsageAbsolut: Number(node.Memory?.RequestTotal!), + ramUsageCapacity: Number(node.Memory?.Capacity!), + diskUsageAbsolut: diskInfo.totalStorageMaximum - diskInfo.totalStorageAvailable, + diskUsageCapacity: diskInfo.totalStorageMaximum, + }})); } } diff --git a/src/shared/model/node-resource.model.ts b/src/shared/model/node-resource.model.ts index 5e2e8eb..868fc42 100644 --- a/src/shared/model/node-resource.model.ts +++ b/src/shared/model/node-resource.model.ts @@ -4,11 +4,12 @@ import { z } from "zod"; export const nodeResourceZodModel = z.object({ name: z.string(), - cpuUsagePercent: z.string(), - cpuUsageAbsolut: z.string(), - ramUsagePercent: z.string(), - ramUsageAbsolut: z.string(), - diskUsagePercent: z.string(), + cpuUsageAbsolut: z.number(), + cpuUsageCapacity: z.number(), + ramUsageAbsolut: z.number(), + ramUsageCapacity: z.number(), + diskUsageAbsolut: z.number(), + diskUsageCapacity: z.number(), }) export type NodeResourceModel = z.infer; \ No newline at end of file