various code cleanup and commenting
This commit is contained in:
@@ -17,5 +17,5 @@ GET {{baseUrl}}/access/pools/
|
||||
### Get pool
|
||||
GET {{baseUrl}}/access/pools/{{poolname}}
|
||||
|
||||
### Get all pools
|
||||
### Get all nodes
|
||||
GET {{baseUrl}}/cluster/nodes
|
||||
@@ -8,6 +8,9 @@ username={{username}}
|
||||
### Get instance resources
|
||||
GET {{baseUrl}}/cluster/{{testvmpath}}
|
||||
|
||||
### Get instance backups
|
||||
GET {{baseUrl}}/cluster/{{testvmpath}}/backup
|
||||
|
||||
### Test create instance
|
||||
|
||||
POST {{baseUrl}}/cluster/{{testvmpath}}/create
|
||||
|
||||
+15
-1
@@ -62,9 +62,11 @@ router.post("/ticket", async (req, res) => {
|
||||
password: req.body.password
|
||||
};
|
||||
|
||||
const domain = global.config.application.domain;
|
||||
// get user and user backends from config
|
||||
const userObj = global.utils.getUserObjFromUsername(params.username);
|
||||
const backends = [global.config.handlers.users, global.config.handlers.instance];
|
||||
|
||||
// fetch cookies using cookie fetcher
|
||||
const cm = new CookieFetcher();
|
||||
const error = await cm.fetchBackends(backends, userObj, params.password);
|
||||
if (error) {
|
||||
@@ -72,6 +74,11 @@ router.post("/ticket", async (req, res) => {
|
||||
return;
|
||||
}
|
||||
const cookies = cm.exportCookies();
|
||||
|
||||
// get global config domain name
|
||||
const domain = global.config.application.domain;
|
||||
|
||||
// for each cookie, add the cookie to response and also compute the minimum across all cookies
|
||||
let minimumExpires = Infinity;
|
||||
for (const cookie of cookies) {
|
||||
const expiresDate = new Date(Date.now() + cookie.expiresMSFromNow);
|
||||
@@ -80,6 +87,8 @@ router.post("/ticket", async (req, res) => {
|
||||
minimumExpires = cookie.expiresMSFromNow;
|
||||
}
|
||||
}
|
||||
|
||||
// set username and auth cookie with the minimum cookie length
|
||||
const expiresDate = new Date(Date.now() + minimumExpires);
|
||||
res.cookie("username", params.username, { domain, path: "/", secure: true, expires: expiresDate, sameSite: "none" });
|
||||
res.cookie("auth", 1, { domain, path: "/", secure: true, expires: expiresDate, sameSite: "none" });
|
||||
@@ -92,15 +101,20 @@ router.post("/ticket", async (req, res) => {
|
||||
* - 200: {auth: false}
|
||||
*/
|
||||
router.delete("/ticket", async (req, res) => {
|
||||
// must have cookies to delete, otherwise just return ok
|
||||
if (Object.keys(req.cookies).length === 0) {
|
||||
res.status(200).send({ auth: false });
|
||||
return;
|
||||
}
|
||||
|
||||
// for each cookie, set the expire date to 0
|
||||
const domain = global.config.application.domain;
|
||||
const expire = new Date(0);
|
||||
for (const cookie in req.cookies) {
|
||||
res.cookie(cookie, "", { domain, path: "/", expires: expire, secure: true, sameSite: "none" });
|
||||
}
|
||||
|
||||
// call close session on each backend, even if was not used
|
||||
await global.pve.closeSession(req.cookies);
|
||||
await global.access.closeSession(req.cookies);
|
||||
res.status(200).send({ auth: false });
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { Router } from "express";
|
||||
export const router = Router({ mergeParams: true });
|
||||
|
||||
const checkAuth = global.utils.checkAuth;
|
||||
|
||||
/**
|
||||
* GET - get specific group
|
||||
* request:
|
||||
@@ -16,18 +14,24 @@ router.get("/:groupname", async (req, res) => {
|
||||
groupname: req.params.groupname
|
||||
};
|
||||
// check auth
|
||||
const auth = await checkAuth(req.cookies, res);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// attempt to parse group from groupname
|
||||
const groupObj = global.utils.getGroupObjFromGroupname(params.groupname);
|
||||
if (groupObj == null) {
|
||||
res.status(400).send({ auth: true, error:`Groupname ${params.groupname} does not match format gid-realm or gid.` });
|
||||
}
|
||||
|
||||
// get group
|
||||
const g = await global.access.getGroup(groupObj, req.cookies);
|
||||
if (g.ok !== true) {
|
||||
res.status(g.status).send(g);
|
||||
res.status(g.status).send({ auth:true, error:g });
|
||||
return;
|
||||
}
|
||||
const group = g.group;
|
||||
|
||||
res.status(200).send({ group });
|
||||
res.status(200).send({ auth:true, group });
|
||||
});
|
||||
|
||||
+15
-13
@@ -1,9 +1,6 @@
|
||||
import { Router } from "express";
|
||||
export const router = Router({ mergeParams: true });
|
||||
|
||||
const checkAuth = global.utils.checkAuth;
|
||||
const checkUserInPool = global.utils.checkUserInPool;
|
||||
|
||||
/**
|
||||
* GET - get all available cluster pools
|
||||
* returns only pool IDs
|
||||
@@ -13,27 +10,30 @@ const checkUserInPool = global.utils.checkUserInPool;
|
||||
*/
|
||||
router.get("/", async (req, res) => {
|
||||
// check auth
|
||||
const auth = await checkAuth(req.cookies, res);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get user object
|
||||
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
|
||||
|
||||
const pools = {};
|
||||
|
||||
// get all pool names using api token
|
||||
const poolnames = await global.pve.requestPVE("/pools", "GET", { token: true });
|
||||
|
||||
// setup pools (return value)
|
||||
const pools = {};
|
||||
// for each poolname
|
||||
for (const poolpartial of poolnames.data) {
|
||||
const poolname = poolpartial.poolid;
|
||||
|
||||
// get the pool
|
||||
const p = await global.access.getPool(poolname, req.cookies);
|
||||
if (p.ok !== true) {
|
||||
continue;
|
||||
}
|
||||
const pool = p.pool;
|
||||
|
||||
if (checkUserInPool(pool, userObj)) {
|
||||
// if user is in the pool, add it to pools (return value)
|
||||
if (global.utils.checkUserInPool(pool, userObj)) {
|
||||
const resources = await global.utils.getPoolResources(req, poolname);
|
||||
pool.resources = resources;
|
||||
pools[poolname] = pool;
|
||||
@@ -57,20 +57,22 @@ router.get("/:poolname", async (req, res) => {
|
||||
poolname: req.params.poolname
|
||||
};
|
||||
// check auth
|
||||
const auth = await checkAuth(req.cookies, res);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get pool
|
||||
const p = await global.access.getPool(params.poolname, req.cookies);
|
||||
if (p.ok !== true) {
|
||||
res.status(p.status).send(p);
|
||||
res.status(p.status).send({ auth:true, error: p });
|
||||
return;
|
||||
}
|
||||
const pool = p.pool;
|
||||
// get resources
|
||||
const resources = await global.utils.getPoolResources(req, params.poolname);
|
||||
|
||||
// append resources to pool
|
||||
pool.resources = resources;
|
||||
|
||||
res.status(200).send({ pool });
|
||||
res.status(200).send({ auth: true, pool });
|
||||
});
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { Router } from "express";
|
||||
export const router = Router({ mergeParams: true });
|
||||
|
||||
const checkAuth = global.utils.checkAuth;
|
||||
|
||||
/**
|
||||
* GET - get specific user
|
||||
* request:
|
||||
@@ -16,15 +14,21 @@ router.get("/:username", async (req, res) => {
|
||||
username: req.params.username
|
||||
};
|
||||
// check auth
|
||||
const auth = await checkAuth(req.cookies, res);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// attempt to parse user from username
|
||||
const userObj = global.utils.getUserObjFromUsername(params.username);
|
||||
if (userObj == null) {
|
||||
res.status(400).send({ auth:true, error:`username ${params.username} does not match format uid@realm.` });
|
||||
}
|
||||
|
||||
// get user
|
||||
const u = await global.access.getUser(userObj, req.cookies);
|
||||
if (u.ok !== true) {
|
||||
res.status(u.status).send(u);
|
||||
res.status(u.status).send({ auth: true, error: u });
|
||||
return;
|
||||
}
|
||||
const user = u.user;
|
||||
|
||||
+24
-18
@@ -1,10 +1,6 @@
|
||||
import { Router } from "express";
|
||||
export const router = Router({ mergeParams: true });
|
||||
|
||||
const checkAuth = global.utils.checkAuth;
|
||||
const approveResources = global.utils.approveResources;
|
||||
const checkUserInPool = global.utils.checkUserInPool;
|
||||
|
||||
const nodeRegexP = "[\\w-]+";
|
||||
const typeRegexP = "qemu|lxc";
|
||||
const vmidRegexP = "\\d+";
|
||||
@@ -23,13 +19,13 @@ global.utils.recursiveImportRoutes(router, basePath, "cluster", import.meta.url)
|
||||
*/
|
||||
router.get("/nodes", async (req, res) => {
|
||||
// check auth
|
||||
const auth = await checkAuth(req.cookies, res);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get all nodes
|
||||
const allNodes = await global.pve.requestPVE("/nodes", "GET", { cookies: req.cookies });
|
||||
|
||||
if (allNodes.status === 200) {
|
||||
const allNodesIDs = Array.from(allNodes.data, (x) => x.node);
|
||||
res.status(allNodes.status).send({ nodes: allNodesIDs });
|
||||
@@ -60,14 +56,13 @@ router.get(`${basePath}`, async (req, res) => {
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get current config
|
||||
const instance = await global.pve.getInstance(params.node, params.vmid);
|
||||
|
||||
res.status(200).send(instance);
|
||||
});
|
||||
|
||||
@@ -99,11 +94,9 @@ router.post(`${basePath}/resources`, async (req, res) => {
|
||||
boot: req.body.boot
|
||||
};
|
||||
|
||||
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
@@ -119,13 +112,16 @@ router.post(`${basePath}/resources`, async (req, res) => {
|
||||
else if (params.type === "qemu") {
|
||||
request.cpu = params.proctype;
|
||||
}
|
||||
|
||||
// check resource approval
|
||||
const { approved, reason } = await approveResources(req, userObj, params.node, instance.pool, request);
|
||||
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
|
||||
const { approved, reason } = await global.utils.approveResources(req, userObj, params.node, instance.pool, request);
|
||||
if (!approved) {
|
||||
res.status(400).send({ request, error: "Not enough resources to satisfy request.", reason });
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup action
|
||||
const action = { cores: params.cores, memory: params.memory };
|
||||
if (params.type === "lxc") {
|
||||
@@ -136,6 +132,7 @@ router.post(`${basePath}/resources`, async (req, res) => {
|
||||
action.boot = `order=${params.boot.toString().replaceAll(",", ";")};`;
|
||||
}
|
||||
const method = params.type === "qemu" ? "POST" : "PUT";
|
||||
|
||||
// commit action
|
||||
const result = await global.pve.requestPVE(`${vmpath}/config`, method, { token: true }, action);
|
||||
await global.pve.handleResponse(params.node, result, res);
|
||||
@@ -181,36 +178,40 @@ router.post(`${basePath}/create`, async (req, res) => {
|
||||
rootfssize: req.body.rootfssize
|
||||
};
|
||||
|
||||
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
|
||||
|
||||
// check auth
|
||||
const auth = await checkAuth(req.cookies, res);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get pool config
|
||||
const pool = (await global.access.getPool(params.pool, req.cookies)).pool;
|
||||
const vmid = Number.parseInt(params.vmid);
|
||||
const vmidMin = pool["vmid-allowed"].min;
|
||||
const vmidMax = pool["vmid-allowed"].max;
|
||||
|
||||
// check vmid is within allowed range
|
||||
if (vmid < vmidMin || vmid > vmidMax) {
|
||||
res.status(500).send({ error: `Requested vmid ${vmid} is out of allowed range [${vmidMin},${vmidMax}].` });
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// check node is within allowed list
|
||||
if (pool["nodes-allowed"][params.node] !== true) {
|
||||
res.status(500).send({ error: `Requested node ${params.node} is not in allowed nodes [${pool["nodes-allowed"]}].` });
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// check if user is in pool
|
||||
if(checkUserInPool(pool, userObj) !== true) {
|
||||
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
|
||||
if(global.utils.checkUserInPool(pool, userObj) !== true) {
|
||||
res.status(500).send({ error: `Requested pool ${params.pool} does not contain user ${req.cookies.username}]` });
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup request
|
||||
const request = {
|
||||
cores: Number(params.cores),
|
||||
@@ -231,13 +232,15 @@ router.post(`${basePath}/create`, async (req, res) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check resource approval
|
||||
const { approved, reason } = await await approveResources(req, userObj, params.node, params.pool, request);
|
||||
const { approved, reason } = await await global.utils.approveResources(req, userObj, params.node, params.pool, request);
|
||||
if (!approved) {
|
||||
res.status(400).send({ request, error: "Not enough resources to satisfy request.", reason });
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup action by adding non resource values
|
||||
const action = {
|
||||
vmid: params.vmid,
|
||||
@@ -260,6 +263,7 @@ router.post(`${basePath}/create`, async (req, res) => {
|
||||
else {
|
||||
action.name = params.name;
|
||||
}
|
||||
|
||||
// commit action
|
||||
const result = await global.pve.requestPVE(`/nodes/${params.node}/${params.type}`, "POST", { token: true }, action);
|
||||
await global.pve.handleResponse(params.node, result, res);
|
||||
@@ -283,12 +287,14 @@ router.delete(`${basePath}/delete`, async (req, res) => {
|
||||
type: req.params.type,
|
||||
vmid: req.params.vmid
|
||||
};
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// commit action
|
||||
const result = await global.pve.requestPVE(vmpath, "DELETE", { token: true });
|
||||
await global.pve.handleResponse(params.node, result, res);
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { Router } from "express";
|
||||
export const router = Router({ mergeParams: true }); ;
|
||||
|
||||
const checkAuth = global.utils.checkAuth;
|
||||
|
||||
/**
|
||||
* GET - get backups for an instance
|
||||
* request:
|
||||
@@ -24,7 +22,7 @@ router.get("/", async (req, res) => {
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
@@ -32,11 +30,12 @@ router.get("/", async (req, res) => {
|
||||
// get vm backups
|
||||
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);
|
||||
}
|
||||
else {
|
||||
res.status(backups.status).send({ error: backups.statusText });
|
||||
res.status(backups.status).send({ auth: true, error: backups.statusText });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -64,22 +63,37 @@ router.post("/", async (req, res) => {
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check if number of backups is less than the allowed number
|
||||
// get number of currently backups used
|
||||
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.length;
|
||||
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
|
||||
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;
|
||||
}
|
||||
else if (numBackups >= maxAllowed) {
|
||||
const numBackups = backups.data.length;
|
||||
|
||||
// get instance
|
||||
const instance = await global.pve.getInstance(params.node, params.vmid);
|
||||
if (instance === null) {
|
||||
res.status(400).send({ error: `failed to get instance ${params.node}/${params.vmid}` });
|
||||
return;
|
||||
}
|
||||
|
||||
// get pool and pool allowed nodes
|
||||
const pool = await global.access.getPool(instance.pool, req.cookies);
|
||||
if (!pool.ok) {
|
||||
res.status(pool.status).send({ error: `failed to get pool ${pool}` });
|
||||
return;
|
||||
}
|
||||
const maxAllowed = pool.pool["backups-allowed"].max;
|
||||
|
||||
// check if used backups is more than maximum allowed, if so exit
|
||||
if (numBackups >= maxAllowed) {
|
||||
res.status(backups.status).send({ error: `${params.vmid} already has ${numBackups} >= ${maxAllowed} max backups allowed` });
|
||||
return;
|
||||
}
|
||||
@@ -122,7 +136,7 @@ router.post("/notes", async (req, res) => {
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
@@ -146,7 +160,7 @@ router.post("/notes", async (req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
// create backup using vzdump path
|
||||
// modify backup notes
|
||||
const body = {
|
||||
notes: params.notes
|
||||
};
|
||||
@@ -182,7 +196,7 @@ router.delete("/", async (req, res) => {
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
@@ -234,7 +248,7 @@ router.post("/restore", async (req, res) => {
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
+48
-22
@@ -1,9 +1,6 @@
|
||||
import { Router } from "express";
|
||||
export const router = Router({ mergeParams: true });
|
||||
|
||||
const checkAuth = global.utils.checkAuth;
|
||||
const approveResources = global.utils.approveResources;
|
||||
|
||||
/**
|
||||
* POST - detach mounted disk from instance
|
||||
* request:
|
||||
@@ -25,12 +22,14 @@ router.post("/:disk/detach", async (req, res) => {
|
||||
vmid: req.params.vmid,
|
||||
disk: req.params.disk
|
||||
};
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// disk must exist
|
||||
const disk = await global.pve.getDisk(params.node, params.vmid, params.disk);
|
||||
if (!disk) {
|
||||
@@ -38,14 +37,19 @@ router.post("/:disk/detach", async (req, res) => {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// disk cannot be unused
|
||||
if (params.disk.includes("unused")) {
|
||||
res.status(500).send({ error: `Requested disk ${params.disk} cannot be unused. Use /disk/delete to permanently delete unused disks.` });
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup detach action
|
||||
const action = { delete: params.disk };
|
||||
const method = params.type === "qemu" ? "POST" : "PUT";
|
||||
|
||||
// commit action
|
||||
const result = await global.pve.requestPVE(`${vmpath}/config`, method, { token: true }, action);
|
||||
await global.pve.handleResponse(params.node, result, res);
|
||||
await global.pve.syncInstance(params.node, params.vmid);
|
||||
@@ -75,9 +79,10 @@ router.post("/:disk/attach", async (req, res) => {
|
||||
source: req.body.source,
|
||||
mp: req.body.mp
|
||||
};
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
@@ -89,6 +94,7 @@ router.post("/:disk/attach", async (req, res) => {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// target disk must be allowed according to source disk's storage options
|
||||
const resourceConfig = global.config.resources;
|
||||
if (!resourceConfig[disk.storage].disks.some(diskPrefix => params.disk.startsWith(diskPrefix))) {
|
||||
@@ -96,14 +102,10 @@ router.post("/:disk/attach", async (req, res) => {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup action using source disk info from vm config
|
||||
const action = {};
|
||||
if (params.type === "qemu") {
|
||||
action[params.disk] = `${disk.file}`;
|
||||
}
|
||||
else if (params.type === "lxc") {
|
||||
action[params.disk] = `${disk.file},mp=${params.mp},backup=1`;
|
||||
}
|
||||
action[params.disk] = params.type === "qemu" ? `${disk.file}` : `${disk.file},mp=${params.mp},backup=1`;
|
||||
const method = params.type === "qemu" ? "POST" : "PUT";
|
||||
|
||||
// commit action
|
||||
@@ -137,16 +139,22 @@ router.post("/:disk/resize", async (req, res) => {
|
||||
size: req.body.size
|
||||
};
|
||||
|
||||
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
|
||||
// attempt to parse user from username
|
||||
const userObj = global.utils.getUserObjFromUsername(params.username);
|
||||
if (userObj == null) {
|
||||
res.status(400).send({ auth:true, error:`username ${params.username} does not match format uid@realm.` });
|
||||
}
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
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
|
||||
@@ -154,17 +162,20 @@ router.post("/:disk/resize", async (req, res) => {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup request
|
||||
const storage = disk.storage; // get the storage
|
||||
const request = {};
|
||||
request[storage] = Number(params.size * 1024 ** 3); // setup request object
|
||||
|
||||
// check request approval
|
||||
const { approved } = await approveResources(req, userObj, params.node, instance.pool, request);
|
||||
const { approved } = await global.utils.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();
|
||||
return;
|
||||
}
|
||||
|
||||
// action approved, commit to action
|
||||
const action = { disk: params.disk, size: `+${params.size}G` };
|
||||
const result = await global.pve.requestPVE(`${vmpath}/resize`, "PUT", { token: true }, action);
|
||||
@@ -199,11 +210,15 @@ router.post("/:disk/move", async (req, res) => {
|
||||
delete: req.body.delete
|
||||
};
|
||||
|
||||
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
|
||||
// attempt to parse user from username
|
||||
const userObj = global.utils.getUserObjFromUsername(params.username);
|
||||
if (userObj == null) {
|
||||
res.status(400).send({ auth:true, error:`username ${params.username} does not match format uid@realm.` });
|
||||
}
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
@@ -224,7 +239,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, params.node, instance.pool, request);
|
||||
const { approved } = await global.utils.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();
|
||||
@@ -268,7 +283,7 @@ router.delete("/:disk/delete", async (req, res) => {
|
||||
};
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
@@ -321,15 +336,23 @@ router.post("/:disk/create", async (req, res) => {
|
||||
size: req.body.size,
|
||||
iso: req.body.iso
|
||||
};
|
||||
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
|
||||
|
||||
// attempt to parse user from username
|
||||
const userObj = global.utils.getUserObjFromUsername(params.username);
|
||||
if (userObj == null) {
|
||||
res.status(400).send({ auth:true, error:`username ${params.username} does not match format uid@realm.` });
|
||||
}
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
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,13 +360,14 @@ router.post("/:disk/create", async (req, res) => {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup request
|
||||
const request = {};
|
||||
if (!params.disk.includes("ide")) {
|
||||
if (!params.disk.includes("ide")) { // ignore resource request if the type is ide (iso file)
|
||||
// setup request
|
||||
request[params.storage] = Number(params.size * 1024 ** 3);
|
||||
// check request approval
|
||||
const { approved } = await approveResources(req, userObj, params.node, instance.pool, request);
|
||||
const { approved } = await global.utils.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();
|
||||
@@ -357,6 +381,7 @@ router.post("/:disk/create", async (req, res) => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// setup action
|
||||
const action = {};
|
||||
if (params.disk.includes("ide") && params.iso) {
|
||||
@@ -369,6 +394,7 @@ router.post("/:disk/create", async (req, res) => {
|
||||
action[params.disk] = `${params.storage}:${params.size},mp=/${params.disk}/,backup=1`;
|
||||
}
|
||||
const method = params.type === "qemu" ? "POST" : "PUT";
|
||||
|
||||
// commit action
|
||||
const result = await global.pve.requestPVE(`${vmpath}/config`, method, { token: true }, action);
|
||||
await global.pve.handleResponse(params.node, result, res);
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { Router } from "express";
|
||||
export const router = Router({ mergeParams: true }); ;
|
||||
|
||||
const checkAuth = global.utils.checkAuth;
|
||||
const approveResources = global.utils.approveResources;
|
||||
|
||||
/**
|
||||
* POST - create new virtual network interface
|
||||
* request:
|
||||
@@ -30,14 +27,17 @@ router.post("/:netid/create", async (req, res) => {
|
||||
rate: req.body.rate,
|
||||
name: req.body.name
|
||||
};
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
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) {
|
||||
@@ -50,17 +50,21 @@ router.post("/:netid/create", async (req, res) => {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup request
|
||||
const request = {
|
||||
network: Number(params.rate)
|
||||
};
|
||||
|
||||
// check resource approval
|
||||
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
|
||||
const { approved } = await approveResources(req, userObj, params.node, instance.pool, request);
|
||||
const { approved } = await global.utils.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.access.getUser(userObj, req.cookies)).templates.network[params.type];
|
||||
const action = {};
|
||||
@@ -71,6 +75,7 @@ router.post("/:netid/create", async (req, res) => {
|
||||
action[`${params.netid}`] = `${nc.type},bridge=${nc.bridge},tag=${nc.vlan},rate=${params.rate}`;
|
||||
}
|
||||
const method = params.type === "qemu" ? "POST" : "PUT";
|
||||
|
||||
// commit action
|
||||
const result = await global.pve.requestPVE(`${vmpath}/config`, method, { token: true }, action);
|
||||
await global.pve.handleResponse(params.node, result, res);
|
||||
@@ -101,14 +106,17 @@ router.post("/:netid/modify", async (req, res) => {
|
||||
netid: req.params.netid,
|
||||
rate: req.body.rate
|
||||
};
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
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) {
|
||||
@@ -116,21 +124,26 @@ router.post("/:netid/modify", async (req, res) => {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup request
|
||||
const request = {
|
||||
network: Number(params.rate) - Number(net.rate)
|
||||
};
|
||||
|
||||
// check resource approval
|
||||
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
|
||||
const { approved } = await approveResources(req, userObj, params.node, instance.pool, request);
|
||||
const { approved } = await global.utils.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 action = {};
|
||||
action[`${params.netid}`] = net.value.replace(`rate=${net.rate}`, `rate=${params.rate}`);
|
||||
const method = params.type === "qemu" ? "POST" : "PUT";
|
||||
|
||||
// commit action
|
||||
const result = await global.pve.requestPVE(`${vmpath}/config`, method, { token: true }, action);
|
||||
await global.pve.handleResponse(params.node, result, res);
|
||||
@@ -158,12 +171,14 @@ router.delete("/:netid/delete", async (req, res) => {
|
||||
vmid: req.params.vmid,
|
||||
netid: req.params.netid
|
||||
};
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// net interface must already exist
|
||||
const net = await global.pve.getNet(params.node, params.vmid, params.netid);
|
||||
if (!net) {
|
||||
@@ -171,10 +186,13 @@ router.delete("/:netid/delete", async (req, res) => {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup action
|
||||
const action = { delete: `${params.netid}` };
|
||||
const method = params.type === "qemu" ? "POST" : "PUT";
|
||||
|
||||
// commit action
|
||||
const result = await global.pve.requestPVE(`${vmpath}/config`, method, { token: true }, { delete: `${params.netid}` });
|
||||
const result = await global.pve.requestPVE(`${vmpath}/config`, method, { token: true }, action);
|
||||
await global.pve.handleResponse(params.node, result, res);
|
||||
await global.pve.syncInstance(params.node, params.vmid);
|
||||
});
|
||||
|
||||
+34
-12
@@ -1,10 +1,6 @@
|
||||
import { Router } from "express";
|
||||
export const router = Router({ mergeParams: true }); ;
|
||||
|
||||
const checkAuth = global.utils.checkAuth;
|
||||
const getPoolResources = global.utils.getPoolResources;
|
||||
const approveResources = global.utils.approveResources;
|
||||
|
||||
/**
|
||||
* GET - get available pcie devices for the given node and user
|
||||
* request:
|
||||
@@ -21,8 +17,9 @@ router.get("/", async (req, res) => {
|
||||
type: req.params.type,
|
||||
vmid: req.params.vmid,
|
||||
};
|
||||
|
||||
// check auth
|
||||
const auth = await checkAuth(req.cookies, res);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
@@ -48,7 +45,7 @@ router.get("/", async (req, res) => {
|
||||
}
|
||||
|
||||
// get remaining user resources
|
||||
const poolAvailPci = (await getPoolResources(req, instance.pool)).pci.nodes[params.node]; // we assume that the node list is used. TODO support global lists
|
||||
const poolAvailPci = (await global.utils.getPoolResources(req, instance.pool)).pci.nodes[params.node]; // we assume that the node list is used. TODO support global lists
|
||||
if (poolAvailPci === undefined) { // user has no available devices on this node, so send an empty list
|
||||
res.status(200).send([]);
|
||||
res.end();
|
||||
@@ -93,12 +90,14 @@ router.get("/:hostpci", async (req, res) => {
|
||||
vmid: req.params.vmid,
|
||||
hostpci: req.params.hostpci
|
||||
};
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get device
|
||||
const device = await global.pve.getDevice(params.node, params.vmid, params.hostpci);
|
||||
if (!device) {
|
||||
@@ -135,22 +134,27 @@ router.post("/:hostpci/modify", async (req, res) => {
|
||||
device: req.body.device,
|
||||
pcie: req.body.pcie
|
||||
};
|
||||
|
||||
// check if type is qemu
|
||||
if (params.type !== "qemu") {
|
||||
res.status(500).send({ error: "Type must be qemu (vm)." });
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
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
|
||||
const existingDevice = await global.pve.getDevice(params.node, params.vmid, params.hostpci);
|
||||
if (!existingDevice) {
|
||||
@@ -158,6 +162,7 @@ router.post("/:hostpci/modify", async (req, res) => {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// only check user and node availability if base id is different, we do the split in case of existing partial-function hostpci
|
||||
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
|
||||
if (existingDevice.device_bus.split(".")[0] !== params.device) {
|
||||
@@ -171,7 +176,7 @@ router.post("/:hostpci/modify", async (req, res) => {
|
||||
return;
|
||||
}
|
||||
// check resource approval
|
||||
const { approved } = await approveResources(req, userObj, params.node, instance.pool, request);
|
||||
const { approved } = await global.utils.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();
|
||||
@@ -184,9 +189,11 @@ router.post("/:hostpci/modify", async (req, res) => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// setup action
|
||||
const action = {};
|
||||
action[`${params.hostpci}`] = `${params.device},pcie=${params.pcie}`;
|
||||
|
||||
// commit action
|
||||
const result = await global.pve.requestPVE(`${vmpath}/config`, "POST", { root: true }, action);
|
||||
await global.pve.handleResponse(params.node, result, res);
|
||||
@@ -217,22 +224,27 @@ router.post("/:hostpci/create", async (req, res) => {
|
||||
device: req.body.device,
|
||||
pcie: req.body.pcie
|
||||
};
|
||||
|
||||
// check if type is qemu
|
||||
if (params.type !== "qemu") {
|
||||
res.status(500).send({ error: "Type must be qemu (vm)." });
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
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
|
||||
const existingDevice = await global.pve.getDevice(params.node, params.vmid, params.hostpci);
|
||||
if (existingDevice) {
|
||||
@@ -240,27 +252,32 @@ router.post("/:hostpci/create", async (req, res) => {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup request
|
||||
const node = await global.pve.getNode(params.node);
|
||||
const requestedDevice = node.devices[`${params.device}`];
|
||||
const request = { pci: requestedDevice.device_name };
|
||||
|
||||
// check resource approval
|
||||
const userObj = global.utils.getUserObjFromUsername(req.cookies.username);
|
||||
const { approved } = await approveResources(req, userObj, params.node, instance.pool, request);
|
||||
const { approved } = await global.utils.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();
|
||||
return;
|
||||
}
|
||||
|
||||
// check node availability
|
||||
if (!Object.values(node.devices).some(element => element.device_bus.split(".")[0] === params.device && element.reserved === false)) {
|
||||
res.status(500).send({ error: `Device ${params.device} is already in use on ${params.node}.` });
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup action
|
||||
const action = {};
|
||||
action[`${params.hostpci}`] = `${params.device},pcie=${params.pcie}`;
|
||||
|
||||
// commit action
|
||||
const result = await global.pve.requestPVE(`${vmpath}/config`, "POST", { root: true }, action);
|
||||
await global.pve.handleResponse(params.node, result, res);
|
||||
@@ -288,18 +305,21 @@ router.delete("/:hostpci/delete", async (req, res) => {
|
||||
vmid: req.params.vmid,
|
||||
hostpci: req.params.hostpci
|
||||
};
|
||||
|
||||
// check if type is qemu
|
||||
if (params.type !== "qemu") {
|
||||
res.status(500).send({ error: "Type must be qemu (vm)." });
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// check auth for specific instance
|
||||
const vmpath = `/nodes/${params.node}/${params.type}/${params.vmid}`;
|
||||
const auth = await checkAuth(req.cookies, res, vmpath);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res, vmpath);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check device is in instance config
|
||||
const device = global.pve.getDevice(params.node, params.vmid, params.hostpci);
|
||||
if (!device) {
|
||||
@@ -307,8 +327,10 @@ router.delete("/:hostpci/delete", async (req, res) => {
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// setup action
|
||||
const action = { delete: `${params.hostpci}` };
|
||||
|
||||
// commit action, need to use root user here because proxmox api only allows root to modify hostpci for whatever reason
|
||||
const result = await global.pve.requestPVE(`${vmpath}/config`, "POST", { root: true }, action);
|
||||
await global.pve.handleResponse(params.node, result, res);
|
||||
|
||||
@@ -12,11 +12,15 @@ router.get("/config/:key", async (req, res) => {
|
||||
const params = {
|
||||
key: req.params.key
|
||||
};
|
||||
|
||||
// check auth
|
||||
const auth = await checkAuth(req.cookies, res);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check if users are allowed to get the config value
|
||||
// return the value if so, otherwise send unauthorized
|
||||
const allowKeys = ["resources"];
|
||||
if (allowKeys.includes(params.key)) {
|
||||
const config = global.config;
|
||||
|
||||
+5
-9
@@ -2,11 +2,7 @@ import { WebSocketServer } from "ws";
|
||||
import * as cookie from "cookie";
|
||||
|
||||
import { Router } from "express";
|
||||
export const router = Router({ mergeParams: true }); ;
|
||||
|
||||
const checkAuth = global.utils.checkAuth;
|
||||
const getObjectHash = global.utils.getObjectHash;
|
||||
const getTimeLeft = global.utils.getTimeLeft;
|
||||
export const router = Router({ mergeParams: true });
|
||||
|
||||
// maps usernames to socket object(s)
|
||||
const userSocketMap = {};
|
||||
@@ -47,7 +43,7 @@ if (schemes.hash.enabled) {
|
||||
*/
|
||||
router.get("/hash", async (req, res) => {
|
||||
// check auth
|
||||
const auth = await checkAuth(req.cookies, res);
|
||||
const auth = await global.utils.checkAuth(req.cookies, res);
|
||||
if (!auth) {
|
||||
return;
|
||||
}
|
||||
@@ -55,7 +51,7 @@ if (schemes.hash.enabled) {
|
||||
const status = (await global.pve.requestPVE("/cluster/resources", "GET", { cookies: req.cookies })).data;
|
||||
// filter out just state information of resources that are needed
|
||||
const state = extractClusterState(status, resourceTypes);
|
||||
res.status(200).send(getObjectHash(state));
|
||||
res.status(200).send(global.utils.getObjectHash(state));
|
||||
});
|
||||
console.log("clientsync: enabled hash sync");
|
||||
}
|
||||
@@ -135,7 +131,7 @@ if (schemes.interrupt.enabled) {
|
||||
// AND if the next event trigger is more than the new rate in the future,
|
||||
// restart the timer with the new rate
|
||||
// avoids a large requested rate preventing a faster rate from being fulfilled
|
||||
else if (rate < Math.min.apply(null, Object.values(requestedRates)) && getTimeLeft(timer) > rate) {
|
||||
else if (rate < Math.min.apply(null, Object.values(requestedRates)) && global.utils.getTimeLeft(timer) > rate) {
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(handleInterruptSync, rate);
|
||||
const time = global.process.uptime();
|
||||
@@ -259,7 +255,7 @@ function extractClusterState (status, resourceTypes, hashIndividual = false) {
|
||||
pool: resource.pool || null
|
||||
};
|
||||
if (hashIndividual) {
|
||||
const hash = getObjectHash(state[resource.id]);
|
||||
const hash = global.utils.getObjectHash(state[resource.id]);
|
||||
state[resource.id].hash = hash;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-14
@@ -230,16 +230,13 @@ export async function getPoolResources (req, pool) {
|
||||
export async function approveResources (req, user, node, pool, request) {
|
||||
const configResources = global.config.resources;
|
||||
const poolResources = await getPoolResources(req, pool);
|
||||
// let approved = true;
|
||||
const reason = {};
|
||||
|
||||
for (const key in request) {
|
||||
// if requested resource is not specified in user resources, assume it's not allowed
|
||||
if (!(key in poolResources)) {
|
||||
// approved = false;
|
||||
reason[key] = { approved: false, reason: `${key} not allowed` };
|
||||
continue;
|
||||
// return;
|
||||
}
|
||||
|
||||
// use node specific quota if there is one available, otherwise use the global resource quota
|
||||
@@ -252,25 +249,21 @@ export async function approveResources (req, user, node, pool, request) {
|
||||
// if no matching resource when index == -1, then remaining is -1 otherwise use the remaining value
|
||||
const avail = index === -1 ? false : resourceData[index].avail > 0;
|
||||
if (avail !== configResources[key].whitelist) {
|
||||
// approved = false;
|
||||
reason[key] = { approved: false, reason: `${key} ${configResources[key].whitelist ? "not in whitelist" : "in blacklist"}` };
|
||||
// return;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// if either the requested or avail resource is not strictly a number, block
|
||||
else if (typeof (resourceData.avail) !== "number" || typeof (request[key]) !== "number") {
|
||||
// approved = false;
|
||||
if (typeof (resourceData.avail) !== "number" || typeof (request[key]) !== "number") {
|
||||
reason[key] = { approved: false, reason: `expected ${key} to be a number but got ${request[key]}` };
|
||||
continue;
|
||||
// return;
|
||||
}
|
||||
|
||||
// if the avail resources is less than the requested resources, block
|
||||
else if (resourceData.avail - request[key] < 0) {
|
||||
// approved = false;
|
||||
if (resourceData.avail - request[key] < 0) {
|
||||
reason[key] = { approved: false, reason: `${key} requested ${request[key]} which is more than ${resourceData.avail} available` };
|
||||
continue;
|
||||
// return;
|
||||
}
|
||||
|
||||
reason[key] = { approved: true, reason: "ok" };
|
||||
@@ -340,7 +333,7 @@ export function readJSONFile (path) {
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* Parse username into user object using the uid@realm format.
|
||||
* @param {*} username
|
||||
* @returns {Object | null} user object containing userid and realm or null if username format was invalid
|
||||
*/
|
||||
@@ -357,7 +350,7 @@ export function getUserObjFromUsername (username) {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Parse groupname into group object using the gid-realm format.
|
||||
* @param {*} groupname
|
||||
* @returns {Object | null} user object containing groupid and realm or null if groupname format was invalid
|
||||
*/
|
||||
@@ -382,7 +375,7 @@ export function getGroupObjFromGroupname (groupname) {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Inspect pool object and return true if pool contains any groups which contain the user object.
|
||||
* @param {Object} poolObj pool data object
|
||||
* @param {Object} userObj user object containing id and realm
|
||||
* @returns {boolean} true if userObj in poolObj
|
||||
|
||||
Reference in New Issue
Block a user