initial updates to api v2.0.0:

-  switch access backend to access-manager-api
- change resource quota to pool based
-  simplify backend system
- various cleanup
This commit is contained in:
2026-05-24 19:08:39 +00:00
parent cf47cf6c71
commit 24ed6907c7
26 changed files with 708 additions and 1055 deletions
+8 -9
View File
@@ -33,7 +33,7 @@ router.get("/", async (req, res) => {
const storage = global.config.backups.storage;
const backups = await global.pve.requestPVE(`/nodes/${params.node}/storage/${storage}/content?content=backup&vmid=${params.vmid}`, "GET", { token: true });
if (backups.status === 200) {
res.status(backups.status).send(backups.data.data);
res.status(backups.status).send(backups.data);
}
else {
res.status(backups.status).send({ error: backups.statusText });
@@ -72,9 +72,9 @@ router.post("/", async (req, res) => {
// check if number of backups is less than the allowed number
const storage = global.config.backups.storage;
const backups = await global.pve.requestPVE(`/nodes/${params.node}/storage/${storage}/content?content=backup&vmid=${params.vmid}`, "GET", { token: true });
const numBackups = backups.data.data.length;
const numBackups = backups.data.length;
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
const maxAllowed = (await global.userManager.getUser(userObj, req.cookies)).cluster.backups.max;
const maxAllowed = (await global.access.getUser(userObj, req.cookies)).cluster.backups.max;
if (backups.status !== 200) {
res.status(backups.status).send({ error: backups.statusText });
return;
@@ -94,7 +94,7 @@ router.post("/", async (req, res) => {
"notes-template": params.notes
};
const result = await global.pve.requestPVE(`/nodes/${params.node}/vzdump`, "POST", { token: true }, body);
res.status(result.status).send(result.data.data);
res.status(result.status).send(result.data);
});
/**
@@ -136,7 +136,7 @@ router.post("/notes", async (req, res) => {
return;
}
let found = false;
for (const volume of backups.data.data) {
for (const volume of backups.data) {
if (volume.subtype === params.type && String(volume.vmid) === params.vmid && volume.content === "backup" && volume.volid === params.volid) {
found = true;
}
@@ -196,7 +196,7 @@ router.delete("/", async (req, res) => {
return;
}
let found = false;
for (const volume of backups.data.data) {
for (const volume of backups.data) {
if (volume.subtype === params.type && String(volume.vmid) === params.vmid && volume.content === "backup" && volume.volid === params.volid) {
found = true;
}
@@ -208,7 +208,7 @@ router.delete("/", async (req, res) => {
// found a valid backup with matching vmid and volid
const result = await global.pve.requestPVE(`/nodes/${params.node}/storage/${storage}/content/${params.volid}?delay=5`, "DELETE", { token: true });
res.status(result.status).send(result.data.data);
res.status(result.status).send(result.data);
});
/**
@@ -248,7 +248,7 @@ router.post("/restore", async (req, res) => {
return;
}
let found = false;
for (const volume of backups.data.data) {
for (const volume of backups.data) {
if (volume.subtype === params.type && String(volume.vmid) === params.vmid && volume.content === "backup" && volume.volid === params.volid) {
found = true;
}
@@ -281,7 +281,6 @@ router.post("/restore", async (req, res) => {
}
const result = await global.pve.requestPVE(`/nodes/${params.node}/${params.type}/`, "POST", { token: true }, body);
console.log(result);
if (result.status === 200) {
res.status(result.status).send();
}
+9 -3
View File
@@ -145,6 +145,8 @@ router.post("/:disk/resize", async (req, res) => {
if (!auth) {
return;
}
// get instance config for pool membership
const instance = await global.pve.getInstance(params.node, params.vmid);
// check disk existence
const disk = await global.pve.getDisk(params.node, params.vmid, params.disk); // get target disk
if (!disk) { // exit if disk does not exist
@@ -157,7 +159,7 @@ router.post("/:disk/resize", async (req, res) => {
const request = {};
request[storage] = Number(params.size * 1024 ** 3); // setup request object
// check request approval
const { approved } = await approveResources(req, userObj, request, params.node);
const { approved } = await approveResources(req, userObj, params.node, instance.pool, request);
if (!approved) {
res.status(500).send({ request, error: `Storage ${storage} could not fulfill request of size ${params.size}G.` });
res.end();
@@ -205,6 +207,8 @@ router.post("/:disk/move", async (req, res) => {
if (!auth) {
return;
}
// get instance config for pool membership
const instance = await global.pve.getInstance(params.node, params.vmid);
// check disk existence
const disk = await global.pve.getDisk(params.node, params.vmid, params.disk); // get target disk
if (!disk) { // exit if disk does not exist
@@ -220,7 +224,7 @@ router.post("/:disk/move", async (req, res) => {
request[dstStorage] = Number(size); // always decrease destination storage by size
}
// check request approval
const { approved } = await approveResources(req, userObj, request, params.node);
const { approved } = await approveResources(req, userObj, params.node, instance.pool, request);
if (!approved) {
res.status(500).send({ request, error: `Storage ${params.storage} could not fulfill request of size ${params.size}G.` });
res.end();
@@ -324,6 +328,8 @@ router.post("/:disk/create", async (req, res) => {
if (!auth) {
return;
}
// get instance config for pool membership
const instance = await global.pve.getInstance(params.node, params.vmid);
// disk must not exist
const disk = await global.pve.getDisk(params.node, params.vmid, params.disk);
if (disk) {
@@ -337,7 +343,7 @@ router.post("/:disk/create", async (req, res) => {
// setup request
request[params.storage] = Number(params.size * 1024 ** 3);
// check request approval
const { approved } = await approveResources(req, userObj, request, params.node);
const { approved } = await approveResources(req, userObj, params.node, instance.pool, request);
if (!approved) {
res.status(500).send({ request, error: `Storage ${params.storage} could not fulfill request of size ${params.size}G.` });
res.end();
+7 -3
View File
@@ -36,6 +36,8 @@ router.post("/:netid/create", async (req, res) => {
if (!auth) {
return;
}
// get instance config for pool membership
const instance = await global.pve.getInstance(params.node, params.vmid);
// net interface must not exist
const net = await global.pve.getNet(params.node, params.vmid, params.netid);
if (net) {
@@ -53,14 +55,14 @@ router.post("/:netid/create", async (req, res) => {
};
// check resource approval
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
const { approved } = await approveResources(req, userObj, request, params.node);
const { approved } = await approveResources(req, userObj, params.node, instance.pool, request);
if (!approved) {
res.status(500).send({ request, error: `Could not fulfil network request of ${params.rate}MB/s.` });
res.end();
return;
}
// setup action
const nc = (await global.userManager.getUser(userObj, req.cookies)).templates.network[params.type];
const nc = (await global.access.getUser(userObj, req.cookies)).templates.network[params.type];
const action = {};
if (params.type === "lxc") {
action[`${params.netid}`] = `name=${params.name},bridge=${nc.bridge},ip=${nc.ip},ip6=${nc.ip6},tag=${nc.vlan},type=${nc.type},rate=${params.rate}`;
@@ -105,6 +107,8 @@ router.post("/:netid/modify", async (req, res) => {
if (!auth) {
return;
}
// get instance config for pool membership
const instance = await global.pve.getInstance(params.node, params.vmid);
// net interface must already exist
const net = await global.pve.getNet(params.node, params.vmid, params.netid);
if (!net) {
@@ -117,7 +121,7 @@ router.post("/:netid/modify", async (req, res) => {
};
// check resource approval
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
const { approved } = await approveResources(req, userObj, request, params.node);
const { approved } = await approveResources(req, userObj, params.node, instance.pool, request);
if (!approved) {
res.status(500).send({ request, error: `Could not fulfil network request of ${params.rate}MB/s.` });
res.end();
+6 -2
View File
@@ -78,6 +78,8 @@ router.post("/:hostpci/modify", async (req, res) => {
if (!auth) {
return;
}
// get instance config for pool membership
const instance = await global.pve.getInstance(params.node, params.vmid);
// force all functions
params.device = params.device.split(".")[0];
// device must exist to be modified
@@ -100,7 +102,7 @@ router.post("/:hostpci/modify", async (req, res) => {
return;
}
// check resource approval
const { approved } = await approveResources(req, userObj, request, params.node);
const { approved } = await approveResources(req, userObj, params.node, instance.pool, request);
if (!approved) {
res.status(500).send({ request, error: `Could not fulfil request for ${requestedDevice.device_name}.` });
res.end();
@@ -158,6 +160,8 @@ router.post("/:hostpci/create", async (req, res) => {
if (!auth) {
return;
}
// get instance config for pool membership
const instance = await global.pve.getInstance(params.node, params.vmid);
// force all functions
params.device = params.device.split(".")[0];
// device must not exist to be added
@@ -173,7 +177,7 @@ router.post("/:hostpci/create", async (req, res) => {
const request = { pci: requestedDevice.device_name };
// check resource approval
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
const { approved } = await approveResources(req, userObj, request, params.node);
const { approved } = await approveResources(req, userObj, params.node, instance.pool, request);
if (!approved) {
res.status(500).send({ request, error: `Could not fulfil request for ${requestedDevice.device_name}.` });
res.end();