2023-05-16 16:51:39 +00:00
|
|
|
import { requestAPI, goToPage, getCookie, setTitleAndHeader } from "./utils.js";
|
2023-04-03 21:57:03 +00:00
|
|
|
|
|
|
|
window.addEventListener("DOMContentLoaded", init);
|
|
|
|
|
2023-06-29 22:20:15 +00:00
|
|
|
const prefixes = {
|
2023-05-16 16:51:39 +00:00
|
|
|
1024: [
|
|
|
|
"",
|
|
|
|
"Ki",
|
|
|
|
"Mi",
|
|
|
|
"Gi",
|
|
|
|
"Ti"
|
|
|
|
],
|
|
|
|
1000: [
|
|
|
|
"",
|
|
|
|
"K",
|
|
|
|
"M",
|
|
|
|
"G",
|
|
|
|
"T"
|
|
|
|
]
|
2023-06-29 22:20:15 +00:00
|
|
|
};
|
2023-04-19 03:10:51 +00:00
|
|
|
|
2023-06-29 22:20:15 +00:00
|
|
|
async function init () {
|
2023-05-16 15:18:36 +00:00
|
|
|
setTitleAndHeader();
|
2023-06-29 22:20:15 +00:00
|
|
|
const cookie = document.cookie;
|
2023-04-19 05:58:30 +00:00
|
|
|
if (cookie === "") {
|
|
|
|
goToPage("login.html");
|
|
|
|
}
|
2023-07-05 23:16:20 +00:00
|
|
|
const resources = await requestAPI("/user/dynamic/resources");
|
2023-09-11 19:04:07 +00:00
|
|
|
const meta = await requestAPI("/global/config/resources");
|
2023-06-29 22:20:15 +00:00
|
|
|
const instances = await requestAPI("/user/config/cluster");
|
|
|
|
const nodes = await requestAPI("/user/config/nodes");
|
2023-05-03 21:06:27 +00:00
|
|
|
document.querySelector("#username").innerText = `Username: ${getCookie("username")}`;
|
|
|
|
document.querySelector("#pool").innerText = `Pool: ${instances.pool}`;
|
|
|
|
document.querySelector("#vmid").innerText = `VMID Range: ${instances.vmid.min} - ${instances.vmid.max}`;
|
2023-06-14 22:34:48 +00:00
|
|
|
document.querySelector("#nodes").innerText = `Nodes: ${nodes.toString()}`;
|
2023-09-11 19:04:07 +00:00
|
|
|
populateResources("#resource-container", meta, resources);
|
2023-04-03 21:57:03 +00:00
|
|
|
}
|
|
|
|
|
2023-09-11 19:04:07 +00:00
|
|
|
function populateResources (containerID, meta, resources) {
|
2023-04-21 22:58:15 +00:00
|
|
|
if (resources instanceof Object) {
|
2023-08-31 19:01:58 +00:00
|
|
|
const container = document.querySelector(containerID);
|
2023-09-11 19:04:07 +00:00
|
|
|
Object.keys(meta).forEach((resourceType) => {
|
|
|
|
if (meta[resourceType].display) {
|
|
|
|
if (meta[resourceType].type === "list") {
|
|
|
|
resources[resourceType].forEach((listResource) => {
|
2023-10-04 18:59:46 +00:00
|
|
|
createResourceUsageChart(container, listResource.name, listResource.avail, listResource.used, listResource.max, null);
|
2023-09-11 19:04:07 +00:00
|
|
|
});
|
2023-06-23 03:34:44 +00:00
|
|
|
}
|
|
|
|
else {
|
2023-10-04 18:59:46 +00:00
|
|
|
createResourceUsageChart(container, meta[resourceType].name, resources[resourceType].avail, resources[resourceType].used, resources[resourceType].max, meta[resourceType]);
|
2023-06-23 03:34:44 +00:00
|
|
|
}
|
2023-06-14 04:56:49 +00:00
|
|
|
}
|
2023-04-03 21:57:03 +00:00
|
|
|
});
|
|
|
|
}
|
2023-04-19 03:10:51 +00:00
|
|
|
}
|
|
|
|
|
2023-10-04 18:59:46 +00:00
|
|
|
function createResourceUsageChart (container, resourceName, resourceAvail, resourceUsed, resourceMax, resourceUnitData) {
|
|
|
|
const chart = document.createElement("custom-chart");
|
|
|
|
container.append(chart);
|
2023-08-31 19:01:58 +00:00
|
|
|
const maxStr = parseNumber(resourceMax, resourceUnitData);
|
|
|
|
const usedStr = parseNumber(resourceUsed, resourceUnitData);
|
|
|
|
const usedRatio = resourceUsed / resourceMax;
|
|
|
|
const R = Math.min(usedRatio * 510, 255);
|
|
|
|
const G = Math.min((1 - usedRatio) * 510, 255);
|
|
|
|
const usedColor = `rgb(${R}, ${G}, 0)`;
|
2023-10-04 18:59:46 +00:00
|
|
|
chart.data = {
|
|
|
|
chart: {
|
|
|
|
type: "pie",
|
|
|
|
data: {
|
|
|
|
labels: [
|
|
|
|
"Used",
|
|
|
|
"Available"
|
2023-08-31 19:01:58 +00:00
|
|
|
],
|
2023-10-04 18:59:46 +00:00
|
|
|
datasets: [{
|
|
|
|
label: resourceName,
|
|
|
|
data: [resourceUsed, resourceAvail],
|
|
|
|
backgroundColor: [
|
|
|
|
usedColor,
|
|
|
|
"rgb(140, 140, 140)"
|
|
|
|
],
|
|
|
|
borderWidth: 0,
|
|
|
|
hoverOffset: 4
|
|
|
|
}]
|
|
|
|
},
|
|
|
|
options: {
|
|
|
|
plugins: {
|
|
|
|
title: {
|
|
|
|
display: true,
|
|
|
|
position: "bottom",
|
|
|
|
text: [resourceName, `Used ${usedStr} of ${maxStr}`],
|
|
|
|
color: "white"
|
|
|
|
},
|
|
|
|
legend: {
|
|
|
|
display: false
|
|
|
|
}
|
2023-08-31 19:01:58 +00:00
|
|
|
}
|
|
|
|
}
|
2023-10-04 18:59:46 +00:00
|
|
|
},
|
|
|
|
ariaLabel: `${resourceName} used ${usedStr} of ${maxStr}`
|
|
|
|
};
|
2023-10-05 16:38:25 +00:00
|
|
|
chart.style = "margin: 10px;";
|
|
|
|
chart.responsive = "680px";
|
2023-09-19 20:59:28 +00:00
|
|
|
}
|
|
|
|
|
2023-06-29 22:20:15 +00:00
|
|
|
function parseNumber (value, unitData) {
|
2023-09-11 19:04:07 +00:00
|
|
|
if (!unitData) {
|
|
|
|
return `${value}`;
|
|
|
|
}
|
2023-06-29 22:20:15 +00:00
|
|
|
const compact = unitData.compact;
|
|
|
|
const multiplier = unitData.multiplier;
|
|
|
|
const base = unitData.base;
|
|
|
|
const unit = unitData.unit;
|
2023-04-19 03:10:51 +00:00
|
|
|
value = multiplier * value;
|
2023-04-25 15:20:59 +00:00
|
|
|
if (value <= 0) {
|
|
|
|
return `0 ${unit}`;
|
|
|
|
}
|
|
|
|
else if (compact) {
|
2023-06-29 22:20:15 +00:00
|
|
|
const exponent = Math.floor(Math.log(value) / Math.log(base));
|
2023-05-16 16:51:39 +00:00
|
|
|
value = value / base ** exponent;
|
2023-06-29 22:20:15 +00:00
|
|
|
const unitPrefix = prefixes[base][exponent];
|
|
|
|
return `${value} ${unitPrefix}${unit}`;
|
2023-04-19 03:10:51 +00:00
|
|
|
}
|
|
|
|
else {
|
2023-04-19 03:12:50 +00:00
|
|
|
return `${value} ${unit}`;
|
2023-04-19 03:10:51 +00:00
|
|
|
}
|
2023-06-29 22:20:15 +00:00
|
|
|
}
|