API v2.0.0: #3

Open
alu wants to merge 13 commits from v2.0.0 into main
Showing only changes of commit 60ade723a4 - Show all commits
+68 -64
View File
@@ -63,41 +63,44 @@ export async function checkAuth (cookies, res, vmpath = null) {
* Get pool resource data including used, available, and maximum resources. * Get pool resource data including used, available, and maximum resources.
* @param {Object} req ProxmoxAAS API request object. * @param {Object} req ProxmoxAAS API request object.
* @param {{id: string, realm: string}} user object of user to get resource data. * @param {{id: string, realm: string}} user object of user to get resource data.
* @returns {{used: Object, avail: Object, max: Object, resources: Object}} used, available, maximum, and resource metadata for the specified user. * @returns {{used: Object, avail: Object, max: Object, resources: Object}} used, available, maximum, and resource metadata for the specified pool or null if an error occured
*/ */
export async function getPoolResources (req, pool) { export async function getPoolResources (req, pool) {
const configResources = global.config.resources; const configResources = global.config.resources;
const poolConfig = await global.access.getPool(pool, req.cookies); const poolConfig = await global.access.getPool(pool, req.cookies);
const poolResources = poolConfig.pool.resources; if (poolConfig.ok !== true) {
return null;
}
const poolConfigResources = poolConfig.pool.resources;
// setup the pool resource object with used and avail for each resource and each resource pool // setup the pool resource object with used and avail for each resource and each resource pool
// also add a total counter for each resource (only used for display, not used to check requests) // also add a total counter for each resource (only used for display, not used to check requests)
for (const resourceName of Object.keys(poolResources)) { for (const resourceName of Object.keys(poolConfigResources)) {
if (configResources[resourceName].type === "list") { if (configResources[resourceName].type === "list") {
poolResources[resourceName].total = []; poolConfigResources[resourceName].total = [];
poolResources[resourceName].global.forEach((e) => { poolConfigResources[resourceName].global.forEach((e) => {
e.used = 0; e.used = 0;
e.avail = e.max; e.avail = e.max;
const index = poolResources[resourceName].total.findIndex((availEelement) => e.match === availEelement.match); const index = poolConfigResources[resourceName].total.findIndex((availEelement) => e.match === availEelement.match);
if (index === -1) { if (index === -1) {
poolResources[resourceName].total.push(structuredClone(e)); poolConfigResources[resourceName].total.push(structuredClone(e));
} }
else { else {
poolResources[resourceName].total[index].max += e.max; poolConfigResources[resourceName].total[index].max += e.max;
poolResources[resourceName].total[index].avail += e.avail; poolConfigResources[resourceName].total[index].avail += e.avail;
} }
}); });
for (const nodeName of Object.keys(poolResources[resourceName].nodes)) { for (const nodeName of Object.keys(poolConfigResources[resourceName].nodes)) {
poolResources[resourceName].nodes[nodeName].forEach((e) => { poolConfigResources[resourceName].nodes[nodeName].forEach((e) => {
e.used = 0; e.used = 0;
e.avail = e.max; e.avail = e.max;
const index = poolResources[resourceName].total.findIndex((availEelement) => e.match === availEelement.match); const index = poolConfigResources[resourceName].total.findIndex((availEelement) => e.match === availEelement.match);
if (index === -1) { if (index === -1) {
poolResources[resourceName].total.push(structuredClone(e)); poolConfigResources[resourceName].total.push(structuredClone(e));
} }
else { else {
poolResources[resourceName].total[index].max += e.max; poolConfigResources[resourceName].total[index].max += e.max;
poolResources[resourceName].total[index].avail += e.avail; poolConfigResources[resourceName].total[index].avail += e.avail;
} }
}); });
} }
@@ -108,27 +111,27 @@ export async function getPoolResources (req, pool) {
used: 0, used: 0,
avail: 0 avail: 0
}; };
poolResources[resourceName].global.used = 0; poolConfigResources[resourceName].global.used = 0;
poolResources[resourceName].global.avail = poolResources[resourceName].global.max; poolConfigResources[resourceName].global.avail = poolConfigResources[resourceName].global.max;
total.max += poolResources[resourceName].global.max; total.max += poolConfigResources[resourceName].global.max;
total.avail += poolResources[resourceName].global.avail; total.avail += poolConfigResources[resourceName].global.avail;
for (const nodeName of Object.keys(poolResources[resourceName].nodes)) { for (const nodeName of Object.keys(poolConfigResources[resourceName].nodes)) {
poolResources[resourceName].nodes[nodeName].used = 0; poolConfigResources[resourceName].nodes[nodeName].used = 0;
poolResources[resourceName].nodes[nodeName].avail = poolResources[resourceName].nodes[nodeName].max; poolConfigResources[resourceName].nodes[nodeName].avail = poolConfigResources[resourceName].nodes[nodeName].max;
total.max += poolResources[resourceName].nodes[nodeName].max; total.max += poolConfigResources[resourceName].nodes[nodeName].max;
total.avail += poolResources[resourceName].nodes[nodeName].avail; total.avail += poolConfigResources[resourceName].nodes[nodeName].avail;
} }
poolResources[resourceName].total = total; poolConfigResources[resourceName].total = total;
} }
} }
const configs = await global.pve.getPoolResources(req.cookies, pool); const resources = await global.pve.getPoolResources(req.cookies, pool);
if (configs === null) { if (resources === null) {
return null; return null;
} }
for (const vmid in configs) { for (const vmid in resources) {
const config = configs[vmid]; const config = resources[vmid];
const nodeName = config.node; const nodeName = config.node;
// count basic numeric resources // count basic numeric resources
for (const resourceName of Object.keys(config)) { for (const resourceName of Object.keys(config)) {
@@ -136,17 +139,17 @@ export async function getPoolResources (req, pool) {
if (resourceName in configResources && configResources[resourceName].type === "numeric") { if (resourceName in configResources && configResources[resourceName].type === "numeric") {
const val = Number(config[resourceName]); const val = Number(config[resourceName]);
// if the instance's node is restricted by this resource, add it to the instance's used value // if the instance's node is restricted by this resource, add it to the instance's used value
if (nodeName in poolResources[resourceName].nodes) { if (nodeName in poolConfigResources[resourceName].nodes) {
poolResources[resourceName].nodes[nodeName].used += val; poolConfigResources[resourceName].nodes[nodeName].used += val;
poolResources[resourceName].nodes[nodeName].avail -= val; poolConfigResources[resourceName].nodes[nodeName].avail -= val;
} }
// otherwise add the resource to the global pool // otherwise add the resource to the global pool
else { else {
poolResources[resourceName].global.used += val; poolConfigResources[resourceName].global.used += val;
poolResources[resourceName].global.avail -= val; poolConfigResources[resourceName].global.avail -= val;
} }
poolResources[resourceName].total.used += val; poolConfigResources[resourceName].total.used += val;
poolResources[resourceName].total.avail -= val; poolConfigResources[resourceName].total.avail -= val;
} }
} }
// count disk resources in volumes // count disk resources in volumes
@@ -155,38 +158,38 @@ export async function getPoolResources (req, pool) {
const storage = disk.storage; const storage = disk.storage;
const size = disk.size; const size = disk.size;
// only process disk if its storage is in the user resources to be counted // only process disk if its storage is in the user resources to be counted
if (storage in poolResources) { if (storage in poolConfigResources) {
// if the instance's node is restricted by this resource, add it to the instance's used value // if the instance's node is restricted by this resource, add it to the instance's used value
if (nodeName in poolResources[storage].nodes) { if (nodeName in poolConfigResources[storage].nodes) {
poolResources[storage].nodes[nodeName].used += size; poolConfigResources[storage].nodes[nodeName].used += size;
poolResources[storage].nodes[nodeName].avail -= size; poolConfigResources[storage].nodes[nodeName].avail -= size;
} }
// otherwise add the resource to the global pool // otherwise add the resource to the global pool
else { else {
poolResources[storage].global.used += size; poolConfigResources[storage].global.used += size;
poolResources[storage].global.avail -= size; poolConfigResources[storage].global.avail -= size;
} }
poolResources[storage].total.used += size; poolConfigResources[storage].total.used += size;
poolResources[storage].total.avail -= size; poolConfigResources[storage].total.avail -= size;
} }
} }
// count net resources in nets // count net resources in nets
for (const netid in config.nets) { for (const netid in config.nets) {
const net = config.nets[netid]; const net = config.nets[netid];
const rate = net.rate; const rate = net.rate;
if (poolResources.network) { if (poolConfigResources.network) {
// if the instance's node is restricted by this resource, add it to the instance's used value // if the instance's node is restricted by this resource, add it to the instance's used value
if (nodeName in poolResources.network.nodes) { if (nodeName in poolConfigResources.network.nodes) {
poolResources.network.nodes[nodeName].used += rate; poolConfigResources.network.nodes[nodeName].used += rate;
poolResources.network.nodes[nodeName].avail -= rate; poolConfigResources.network.nodes[nodeName].avail -= rate;
} }
// otherwise add the resource to the global pool // otherwise add the resource to the global pool
else { else {
poolResources.network.global.used += rate; poolConfigResources.network.global.used += rate;
poolResources.network.global.avail -= rate; poolConfigResources.network.global.avail -= rate;
} }
poolResources.network.total.used += rate; poolConfigResources.network.total.used += rate;
poolResources.network.total.avail -= rate; poolConfigResources.network.total.avail -= rate;
} }
} }
// count pci device resources in devices // count pci device resources in devices
@@ -194,31 +197,31 @@ export async function getPoolResources (req, pool) {
const device = config.devices[deviceid]; const device = config.devices[deviceid];
const name = device.device_name; const name = device.device_name;
// if the node has a node specific rule, add it there // if the node has a node specific rule, add it there
if (nodeName in poolResources.pci.nodes) { if (nodeName in poolConfigResources.pci.nodes) {
const index = poolResources.pci.nodes[nodeName].findIndex((availEelement) => name.includes(availEelement.match)); const index = poolConfigResources.pci.nodes[nodeName].findIndex((availEelement) => name.includes(availEelement.match));
if (index >= 0) { if (index >= 0) {
poolResources.pci.nodes[nodeName][index].used++; poolConfigResources.pci.nodes[nodeName][index].used++;
poolResources.pci.nodes[nodeName][index].avail--; poolConfigResources.pci.nodes[nodeName][index].avail--;
} }
} }
// otherwise try to add the resource to the global pool // otherwise try to add the resource to the global pool
else { else {
const index = poolResources.pci.global.findIndex((availEelement) => name.includes(availEelement.match)); const index = poolConfigResources.pci.global.findIndex((availEelement) => name.includes(availEelement.match));
if (index >= 0) { // device resource is in the user's global list then increment it by 1 if (index >= 0) { // device resource is in the user's global list then increment it by 1
poolResources.pci.global[index].used++; poolConfigResources.pci.global[index].used++;
poolResources.pci.global[index].avail--; poolConfigResources.pci.global[index].avail--;
} }
} }
// finally, add the device to the total map // finally, add the device to the total map
const index = poolResources.pci.total.findIndex((availEelement) => name.includes(availEelement.match)); const index = poolConfigResources.pci.total.findIndex((availEelement) => name.includes(availEelement.match));
if (index >= 0) { if (index >= 0) {
poolResources.pci.total[index].used++; poolConfigResources.pci.total[index].used++;
poolResources.pci.total[index].avail--; poolConfigResources.pci.total[index].avail--;
} }
} }
} }
return poolResources; return poolConfigResources;
} }
/** /**
@@ -228,7 +231,8 @@ export async function getPoolResources (req, pool) {
* @param {string} node name of node hosting requested resource(s) * @param {string} node name of node hosting requested resource(s)
* @param {string} pool name of pool hosting requested resource(s) * @param {string} pool name of pool hosting requested resource(s)
* @param {Object} request k-v pairs of resources and requested amounts * @param {Object} request k-v pairs of resources and requested amounts
* @returns {boolean, Object} true if the available resources can fullfill the requested resources, false otherwise. * @returns {boolean} true if the available resources can fullfill the requested resources, false otherwise.
* @returns {Object} map of key values and reason for success or failure
*/ */
export async function approveResources (req, user, node, pool, request) { export async function approveResources (req, user, node, pool, request) {
const configResources = global.config.resources; const configResources = global.config.resources;