implement db as class,

improve approveResources

Signed-off-by: Arthur Lu <learthurgo@gmail.com>
This commit is contained in:
Arthur Lu 2023-05-24 22:21:00 +00:00
parent 8396de3a96
commit 7773a4182f
4 changed files with 56 additions and 50 deletions

54
db.js
View File

@ -1,33 +1,35 @@
import { readFileSync, writeFileSync } from "fs"; import { readFileSync, writeFileSync } from "fs";
let template = "localdb.json.template" class localdb {
let filename = "localdb.json"; #template = "localdb.json.template";
#filename = "localdb.json";
let db = JSON.parse(readFileSync(template)); #data = null;
try { constructor () {
load(); try {
} this.load(this.#filename);
catch { }
save(); catch {
} this.load(this.#template);
this.save(this.#filename);
function load() { }
db = JSON.parse(readFileSync(filename)); }
} load(path) {
this.#data = JSON.parse(readFileSync(path));
function save() { }
writeFileSync(filename, JSON.stringify(db)); save(path) {
} writeFileSync(path, JSON.stringify(this.#data));
}
export function getResourceConfig() { getResourceConfig () {
return db.resources; return this.#data.resources;
} }
getUserConfig (username) {
export function getUserConfig(username) { if (this.#data.users[username]) {
if (db.users[username]) { return this.#data.users[username];
return db.users[username];
} }
else { else {
return null; return null;
} }
}
} }
export const db = new localdb();

12
main.js
View File

@ -7,8 +7,8 @@ import api from "./package.json" assert {type: "json"};
import { pveAPIToken, listenPort, hostname, domain } from "./vars.js"; import { pveAPIToken, listenPort, hostname, domain } from "./vars.js";
import { requestPVE, handleResponse, getDiskInfo } from "./pve.js"; import { requestPVE, handleResponse, getDiskInfo } from "./pve.js";
import { checkAuth, getAllocatedResources, approveResources } from "./utils.js"; import { checkAuth, approveResources, getUserResources } from "./utils.js";
import { getUserConfig } from "./db.js"; import { db } from "./db.js";
const app = express(); const app = express();
app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.urlencoded({ extended: true }));
@ -117,7 +117,7 @@ app.get("/api/user/resources", async (req, res) => {
// check auth // check auth
let auth = await checkAuth(req.cookies, res); let auth = await checkAuth(req.cookies, res);
if (!auth) { return; } if (!auth) { return; }
let resources = await getAllocatedResources(req, req.cookies.username); let resources = await getUserResources(req, req.cookies.username);
res.status(200).send(resources); res.status(200).send(resources);
}); });
@ -131,7 +131,7 @@ app.get("/api/user/instances", async (req, res) => {
// check auth // check auth
let auth = await checkAuth(req.cookies, res); let auth = await checkAuth(req.cookies, res);
if (!auth) { return; } if (!auth) { return; }
let config = getUserConfig(req.cookies.username); let config = db.getUserConfig(req.cookies.username);
res.status(200).send(config.instances) res.status(200).send(config.instances)
}); });
@ -145,7 +145,7 @@ app.get("/api/user/nodes", async (req, res) => {
// check auth // check auth
let auth = await checkAuth(req.cookies, res); let auth = await checkAuth(req.cookies, res);
if (!auth) { return; } if (!auth) { return; }
let config = getUserConfig(req.cookies.username); let config = db.getUserConfig(req.cookies.username);
res.status(200).send({ nodes: config.nodes }) res.status(200).send({ nodes: config.nodes })
}) })
@ -514,7 +514,7 @@ app.post("/api/instance", async (req, res) => {
let auth = await checkAuth(req.cookies, res); let auth = await checkAuth(req.cookies, res);
if (!auth) { return; } if (!auth) { return; }
// get user db config // get user db config
let user = await getUserConfig(req.cookies.username); let user = await db.getUserConfig(req.cookies.username);
let vmid = Number.parseInt(req.body.vmid); let vmid = Number.parseInt(req.body.vmid);
let vmid_min = user.instances.vmid.min; let vmid_min = user.instances.vmid.min;
let vmid_max = user.instances.vmid.max; let vmid_max = user.instances.vmid.max;

4
pve.js
View File

@ -88,14 +88,18 @@ export async function getUsedResources(req, resourceMeta) {
} }
else if (diskprefixes.some(prefix => key.startsWith(prefix))) { else if (diskprefixes.some(prefix => key.startsWith(prefix))) {
let diskInfo = await getDiskInfo(instance.node, instance.type, instance.vmid, key); let diskInfo = await getDiskInfo(instance.node, instance.type, instance.vmid, key);
if (diskInfo) { // only count if disk exists
used[diskInfo.storage] += Number(diskInfo.size); used[diskInfo.storage] += Number(diskInfo.size);
} }
}
else if (key.startsWith("net")) { else if (key.startsWith("net")) {
if (config[key].includes("rate=")) { // only count instances with a rate limit
used.network += Number(config[key].split("rate=")[1].split(",")[0]); used.network += Number(config[key].split("rate=")[1].split(",")[0]);
} }
} }
} }
} }
}
return used; return used;
} }

View File

@ -1,10 +1,10 @@
import { getUsedResources, requestPVE } from "./pve.js"; import { getUsedResources, requestPVE } from "./pve.js";
import { getUserConfig, getResourceConfig } from "./db.js"; import { db } from "./db.js";
export async function checkAuth(cookies, res, vmpath = null) { export async function checkAuth(cookies, res, vmpath = null) {
let auth = false; let auth = false;
if (getUserConfig(cookies.username) === null) { if (db.getUserConfig(cookies.username) === null) {
auth = false; auth = false;
res.status(401).send({ auth: auth, path: vmpath ? `${vmpath}/config` : "/version", error: `user ${cookies.username} not found in localdb` }); res.status(401).send({ auth: auth, path: vmpath ? `${vmpath}/config` : "/version", error: `user ${cookies.username} not found in localdb` });
res.end(); res.end();
@ -27,10 +27,10 @@ export async function checkAuth(cookies, res, vmpath = null) {
return auth; return auth;
} }
export async function getAllocatedResources(req, username) { export async function getUserResources (req, username) {
let dbResources = getResourceConfig(); let dbResources = db.getResourceConfig();
let used = await getUsedResources(req, dbResources); let used = await getUsedResources(req, dbResources);
let max = getUserConfig(username).resources.max; let max = db.getUserConfig(username).resources.max;
let avail = {}; let avail = {};
Object.keys(max).forEach((k) => { Object.keys(max).forEach((k) => {
avail[k] = max[k] - used[k]; avail[k] = max[k] - used[k];
@ -39,20 +39,20 @@ export async function getAllocatedResources(req, username) {
} }
export async function approveResources(req, username, request) { export async function approveResources(req, username, request) {
let avail = (await getUserResources(req, username)).avail;
let avail = (await getAllocatedResources(req, username)).avail;
let approved = true;
Object.keys(request).forEach((key) => { Object.keys(request).forEach((key) => {
if (!(key in avail)) { if (!(key in avail)) { // if requested resource is not in avail, block
approved = false; approved = false;
return false;
} }
else if (isNaN(avail[key]) || isNaN(request[key])) { else if (isNaN(avail[key]) || isNaN(request[key])) { // if either the requested or avail resource is NaN, block
approved = false; approved = false;
return false;
} }
else if (avail[key] - request[key] < 0) { else if (avail[key] - request[key] < 0) { // if the avail resources is less than the requested resources, block
approved = false; approved = false;
return false;
} }
}); });
return approved; return true; // if all requested resources pass, allow
} }