diff --git a/account.html b/account.html index e286147..237f03c 100644 --- a/account.html +++ b/account.html @@ -31,7 +31,7 @@

VMID Range:

Nodes:

-
+

Cluster Resources

diff --git a/config.html b/config.html index 58cbb3a..b216a9f 100644 --- a/config.html +++ b/config.html @@ -28,9 +28,9 @@
Resources -
+
-
+
Disks
@@ -38,6 +38,10 @@ Add New CDROM
+
+ Network Interface +
+
diff --git a/css/style.css b/css/style.css index 6bbaf27..c232c8d 100644 --- a/css/style.css +++ b/css/style.css @@ -47,6 +47,10 @@ main, dialog { box-shadow: var(--main-card-box-shadow); } +.w3-card + .w3-card { + margin-top: 16px; +} + th { background-color: var(--main-table-header-bg-color); } diff --git a/images/actions/network/config.svg b/images/actions/network/config.svg new file mode 100644 index 0000000..7cda8f7 --- /dev/null +++ b/images/actions/network/config.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/resources/drive.svg b/images/resources/drive.svg index 8c9f975..8479a8f 100644 --- a/images/resources/drive.svg +++ b/images/resources/drive.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/resources/network.svg b/images/resources/network.svg new file mode 100644 index 0000000..1cd0fa1 --- /dev/null +++ b/images/resources/network.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/scripts/config.js b/scripts/config.js index b654576..9665dbb 100644 --- a/scripts/config.js +++ b/scripts/config.js @@ -3,7 +3,8 @@ import {alert, dialog} from "./dialog.js"; window.addEventListener("DOMContentLoaded", init); // do the dumb thing where the disk config refreshes every second -let diskMetaData = resources.disk; +let diskMetaData = resources_config.disk; +let networkMetaData = resources_config.network; let node; let type; @@ -25,10 +26,16 @@ async function init () { populateResources(); populateDisk(); + populateNetworks(); document.querySelector("#exit").addEventListener("click", handleFormExit); } +function getOrdered(keys){ + let ordered_keys = Object.keys(keys).sort((a,b) => {parseInt(a) - parseInt(b)}); // ordered integer list + return ordered_keys; +} + async function getConfig () { config = await requestPVE(`/nodes/${node}/${type}/${vmid}/config`, "GET"); } @@ -36,11 +43,11 @@ async function getConfig () { function populateResources () { let name = type === "qemu" ? "name" : "hostname"; document.querySelector("#name").innerHTML = document.querySelector("#name").innerHTML.replace("%{vmname}", config.data[name]); - addResourceLine("resources", "images/resources/cpu.svg", "Cores", {type: "number", value: config.data.cores, min: 1, max: 8192}, "Threads"); // TODO add max from quota API - addResourceLine("resources", "images/resources/ram.svg", "Memory", {type: "number", value: config.data.memory, min: 16, step: 1}, "MiB"); // TODO add max from quota API + addResourceLine("resources", "images/resources/cpu.svg", "Cores", {type: "number", value: config.data.cores, min: 1, max: 8192}, "Threads"); + addResourceLine("resources", "images/resources/ram.svg", "Memory", {type: "number", value: config.data.memory, min: 16, step: 1}, "MiB"); if (type === "lxc") { - addResourceLine("resources", "images/resources/swap.svg", "Swap", {type: "number", value: config.data.swap, min: 0, step: 1}, "MiB"); // TODO add max from quota API + addResourceLine("resources", "images/resources/swap.svg", "Swap", {type: "number", value: config.data.swap, min: 0, step: 1}, "MiB"); } } @@ -86,7 +93,7 @@ function populateDisk () { disks[element.replace(prefix, "")] = config.data[element]; } }); - let ordered_keys = getOrderedUsed(disks); + let ordered_keys = getOrdered(disks); ordered_keys.forEach(element => { let disk = disks[element]; addDiskLine("disks", prefix, busName, element, disk); @@ -100,11 +107,6 @@ function populateDisk () { } } -function getOrderedUsed(disks){ - let ordered_keys = Object.keys(disks).sort((a,b) => {parseInt(a) - parseInt(b)}); // ordered integer list - return ordered_keys; -} - function addDiskLine (fieldset, busPrefix, busName, device, diskDetails) { let field = document.querySelector(`#${fieldset}`); @@ -428,6 +430,63 @@ async function handleCDAdd () { }); } +function populateNetworks () { + document.querySelector("#networks").innerHTML = ""; + let networks = {}; + let prefix = networkMetaData.prefix; + Object.keys(config.data).forEach(element => { + if (element.startsWith(prefix)) { + networks[element.replace(prefix, "")] = config.data[element]; + } + }); + let ordered_keys = getOrdered(networks); + ordered_keys.forEach(element => { + addNetworkLine("networks", `${prefix}${element}`, networks[element]); + }); +} + +function addNetworkLine (fieldset, netID, netDetails) { + let field = document.querySelector(`#${fieldset}`); + + let icon = document.createElement("img"); + icon.src = "images/resources/network.svg"; + icon.alt = netID; + icon.dataset.network = netID; + field.appendChild(icon); + + let netLabel = document.createElement("label"); + netLabel.innerText = netID; + netLabel.dataset.network = netID; + field.append(netLabel); + + let netDesc = document.createElement("p"); + netDesc.innerText = netDetails; + netDesc.dataset.network = netID; + field.append(netDesc); + + let actionDiv = document.createElement("div"); + actionDiv.classList.add("last-item"); + let action = document.createElement("img"); + action.classList.add("clickable"); + action.src = `images/actions/network/config.svg`; + action.title = "Config Network"; + action.addEventListener("click", handleNetworkConfig); + action.dataset.network = netID; + actionDiv.appendChild(action); + field.append(actionDiv); +} + +async function handleNetworkConfig () { + let netID = this.dataset.network; + let header = `Edit ${netID}`; + let body = ``; + + dialog(header, body, async (result, form) => { + if (result === "confirm") { + } + }); +} + async function handleFormExit () { let body = { node: node, diff --git a/scripts/utils.js b/scripts/utils.js index 33e612c..687af55 100644 --- a/scripts/utils.js +++ b/scripts/utils.js @@ -22,6 +22,9 @@ export const resources_config = { sata: {name: "SATA", icon: "images/resources/drive.svg", actions: ["detach", "move", "reassign", "resize"]}, unused: {name: "UNUSED", icon: "images/resources/drive.svg", actions: ["attach", "delete", "reassign"]} } + }, + network: { + prefix: "net" } }