code cleanup,
disk paths now under instance Signed-off-by: Arthur Lu <learthurgo@gmail.com>
This commit is contained in:
parent
eeb96a9164
commit
02dbd0dec7
12
db.js
12
db.js
@ -4,18 +4,12 @@ template = "localdb.json.template"
|
|||||||
filename = "localdb.json";
|
filename = "localdb.json";
|
||||||
|
|
||||||
let db = JSON.parse(fs.readFileSync(template));
|
let db = JSON.parse(fs.readFileSync(template));
|
||||||
|
|
||||||
/**
|
|
||||||
* called at app startup, can be used to initialize any variables needed for database access
|
|
||||||
*/
|
|
||||||
function init () {
|
|
||||||
try {
|
try {
|
||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
save();
|
save();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function load () {
|
function load () {
|
||||||
db = JSON.parse(fs.readFileSync(filename));
|
db = JSON.parse(fs.readFileSync(filename));
|
||||||
@ -25,12 +19,12 @@ function save () {
|
|||||||
fs.writeFileSync(filename, JSON.stringify(db));
|
fs.writeFileSync(filename, JSON.stringify(db));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getResources() {
|
function getResourceConfig() {
|
||||||
return db.resources;
|
return db.resources;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUser (username) {
|
function getUserConfig (username) {
|
||||||
return db.users[username];
|
return db.users[username];
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {init, getUser, getResources};
|
module.exports = {getUserConfig, getResourceConfig};
|
73
main.js
73
main.js
@ -7,8 +7,8 @@ const morgan = require("morgan");
|
|||||||
var api = require("./package.json");
|
var api = require("./package.json");
|
||||||
|
|
||||||
const {pveAPIToken, listenPort, domain} = require("./vars.js");
|
const {pveAPIToken, listenPort, domain} = require("./vars.js");
|
||||||
const {checkAuth, requestPVE, handleResponse, getUsedResources, getDiskInfo} = require("./pveutils.js");
|
const {checkAuth, requestPVE, handleResponse, getDiskInfo} = require("./pve.js");
|
||||||
const {init, getUser, getResources} = require("./db.js");
|
const {getUserData, approveResources} = require("./utils.js")
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(helmet());
|
app.use(helmet());
|
||||||
@ -43,47 +43,15 @@ app.post("/api/proxmox/*", async (req, res) => { // proxy endpoint for POST prox
|
|||||||
res.status(result.status).send(result.data);
|
res.status(result.status).send(result.data);
|
||||||
});
|
});
|
||||||
|
|
||||||
async function getUserResources (req, username) {
|
app.get("/api/user", async(req, res) => {
|
||||||
let dbResources = getResources();
|
|
||||||
let used = await getUsedResources(req, dbResources);
|
|
||||||
let max = getUser(username).resources.max;
|
|
||||||
avail = {};
|
|
||||||
Object.keys(max).forEach((k) => {
|
|
||||||
avail[k] = max[k] - used[k];
|
|
||||||
});
|
|
||||||
return {used: used, max: max, avail: avail, units: dbResources};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function approveResources (request, avail) {
|
|
||||||
let approved = true;
|
|
||||||
Object.keys(request).forEach((key) => {
|
|
||||||
if (!(key in avail)) {
|
|
||||||
approved = false;
|
|
||||||
}
|
|
||||||
else if (avail[key] - request[key] < 0) {
|
|
||||||
approved = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return approved;
|
|
||||||
}
|
|
||||||
|
|
||||||
app.get("/api/user/resources", async(req, res) => {
|
|
||||||
// check auth
|
// check auth
|
||||||
await checkAuth(req.cookies, res);
|
await checkAuth(req.cookies, res);
|
||||||
let userResources = await getUserResources(req, req.cookies.username);
|
res.status(200).send(await getUserData(req, req.body.username));
|
||||||
res.status(200).send({resources: userResources});
|
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/api/user/instances", async(req, res) => {
|
app.post("/api/instance/disk/detach", async (req, res) => {
|
||||||
await checkAuth(req.cookies, res);
|
|
||||||
res.status(200).send({instances: getUser(req.cookies.username).instances})
|
|
||||||
res.end();
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
|
|
||||||
app.post("/api/disk/detach", async (req, res) => {
|
|
||||||
// check auth
|
// check auth
|
||||||
await checkAuth(req.cookies, res);
|
await checkAuth(req.cookies, res);
|
||||||
if (req.body.disk.includes("unused")) {
|
if (req.body.disk.includes("unused")) {
|
||||||
@ -97,7 +65,7 @@ app.post("/api/disk/detach", async (req, res) => {
|
|||||||
await handleResponse(req.body.node, result, res);
|
await handleResponse(req.body.node, result, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/disk/attach", async (req, res) => {
|
app.post("/api/instance/disk/attach", async (req, res) => {
|
||||||
// check auth
|
// check auth
|
||||||
await checkAuth(req.cookies, res);
|
await checkAuth(req.cookies, res);
|
||||||
let action = {};
|
let action = {};
|
||||||
@ -108,7 +76,7 @@ app.post("/api/disk/attach", async (req, res) => {
|
|||||||
await handleResponse(req.body.node, result, res);
|
await handleResponse(req.body.node, result, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/disk/resize", async (req, res) => {
|
app.post("/api/instance/disk/resize", async (req, res) => {
|
||||||
// check auth
|
// check auth
|
||||||
await checkAuth(req.cookies, res);
|
await checkAuth(req.cookies, res);
|
||||||
// check disk existence
|
// check disk existence
|
||||||
@ -118,14 +86,12 @@ app.post("/api/disk/resize", async (req, res) => {
|
|||||||
res.end();
|
res.end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// get used resources
|
|
||||||
let userResources = await getUserResources(req, req.cookies.username);
|
|
||||||
// setup request
|
// setup request
|
||||||
let storage = diskConfig.storage; // get the storage
|
let storage = diskConfig.storage; // get the storage
|
||||||
let request = {};
|
let request = {};
|
||||||
request[storage] = Number(req.body.size * 1024 ** 3); // setup request object
|
request[storage] = Number(req.body.size * 1024 ** 3); // setup request object
|
||||||
// check request approval
|
// check request approval
|
||||||
if (!await approveResources(request, userResources.avail)) {
|
if (!await approveResources(req, req.body.username, request)) {
|
||||||
res.status(500).send({request: request, error: `Storage ${storage} could not fulfill request of size ${req.body.size}G.`});
|
res.status(500).send({request: request, error: `Storage ${storage} could not fulfill request of size ${req.body.size}G.`});
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
return;
|
||||||
@ -136,7 +102,7 @@ app.post("/api/disk/resize", async (req, res) => {
|
|||||||
await handleResponse(req.body.node, result, res);
|
await handleResponse(req.body.node, result, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/disk/move", async (req, res) => {
|
app.post("/api/instance/disk/move", async (req, res) => {
|
||||||
// check auth
|
// check auth
|
||||||
await checkAuth(req.cookies, res);
|
await checkAuth(req.cookies, res);
|
||||||
// check disk existence
|
// check disk existence
|
||||||
@ -146,8 +112,6 @@ app.post("/api/disk/move", async (req, res) => {
|
|||||||
res.end();
|
res.end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// get used resources
|
|
||||||
let userResources = await getUserResources(req, req.cookies.username);
|
|
||||||
// setup request
|
// setup request
|
||||||
let size = parseInt(diskConfig.size); // get source disk size
|
let size = parseInt(diskConfig.size); // get source disk size
|
||||||
let srcStorage = diskConfig.storage; // get source storage
|
let srcStorage = diskConfig.storage; // get source storage
|
||||||
@ -159,7 +123,7 @@ app.post("/api/disk/move", async (req, res) => {
|
|||||||
}
|
}
|
||||||
request[dstStorage] = Number(size); // always decrease destination storage by size
|
request[dstStorage] = Number(size); // always decrease destination storage by size
|
||||||
// check request approval
|
// check request approval
|
||||||
if (!await approveResources(request, userResources.avail)) {
|
if (!await approveResources(req, req.body.username, request)) {
|
||||||
res.status(500).send({request: request, error: `Storage ${req.body.storage} could not fulfill request of size ${req.body.size}G.`});
|
res.status(500).send({request: request, error: `Storage ${req.body.storage} could not fulfill request of size ${req.body.size}G.`});
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
return;
|
||||||
@ -178,7 +142,7 @@ app.post("/api/disk/move", async (req, res) => {
|
|||||||
await handleResponse(req.body.node, result, res);
|
await handleResponse(req.body.node, result, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/disk/delete", async (req, res) => {
|
app.post("/api/instance/disk/delete", async (req, res) => {
|
||||||
// check auth
|
// check auth
|
||||||
await checkAuth(req.cookies, res);
|
await checkAuth(req.cookies, res);
|
||||||
// only ide or unused are allowed to be deleted
|
// only ide or unused are allowed to be deleted
|
||||||
@ -194,17 +158,15 @@ app.post("/api/disk/delete", async (req, res) => {
|
|||||||
await handleResponse(req.body.node, result, res);
|
await handleResponse(req.body.node, result, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/disk/create", async (req, res) => {
|
app.post("/api/instance/disk/create", async (req, res) => {
|
||||||
// check auth
|
// check auth
|
||||||
await checkAuth(req.cookies, res);
|
await checkAuth(req.cookies, res);
|
||||||
// get used resources
|
|
||||||
let userResources = await getUserResources(req, req.cookies.username);
|
|
||||||
// setup request
|
// setup request
|
||||||
let request = {};
|
let request = {};
|
||||||
if (!req.body.disk.includes("ide")) {
|
if (!req.body.disk.includes("ide")) {
|
||||||
request[req.body.storage] = Number(req.body.size * 1024 ** 3); // setup request object
|
request[req.body.storage] = Number(req.body.size * 1024 ** 3); // setup request object
|
||||||
// check request approval
|
// check request approval
|
||||||
if (!await approveResources(request, userResources.avail)) {
|
if (!await approveResources(req, req.body.username, request)) {
|
||||||
res.status(500).send({request: request, error: `Storage ${req.body.storage} could not fulfill request of size ${req.body.size}G.`});
|
res.status(500).send({request: request, error: `Storage ${req.body.storage} could not fulfill request of size ${req.body.size}G.`});
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
return;
|
||||||
@ -230,8 +192,6 @@ app.post("/api/disk/create", async (req, res) => {
|
|||||||
app.post("/api/resources", async (req, res) => {
|
app.post("/api/resources", async (req, res) => {
|
||||||
// check auth
|
// check auth
|
||||||
await checkAuth(req.cookies, res);
|
await checkAuth(req.cookies, res);
|
||||||
// get used resources
|
|
||||||
let userResources = await getUserResources(req, req.cookies.username);
|
|
||||||
// get current config
|
// get current config
|
||||||
let currentConfig = await requestPVE(`/nodes/${req.body.node}/${req.body.type}/${req.body.vmid}/config`, "GET", null, null, pveAPIToken);
|
let currentConfig = await requestPVE(`/nodes/${req.body.node}/${req.body.type}/${req.body.vmid}/config`, "GET", null, null, pveAPIToken);
|
||||||
let request = {
|
let request = {
|
||||||
@ -239,7 +199,7 @@ app.post("/api/resources", async (req, res) => {
|
|||||||
memory: Number(req.body.memory) - Number(currentConfig.data.data.memory)
|
memory: Number(req.body.memory) - Number(currentConfig.data.data.memory)
|
||||||
};
|
};
|
||||||
// check resource approval
|
// check resource approval
|
||||||
if (!await approveResources(request, userResources.avail)) {
|
if (!await approveResources(req, req.body.username, request)) {
|
||||||
res.status(500).send({request: request, error: `Could not fulfil request`});
|
res.status(500).send({request: request, error: `Could not fulfil request`});
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
return;
|
||||||
@ -254,8 +214,6 @@ app.post("/api/resources", async (req, res) => {
|
|||||||
app.post("/api/instance", async (req, res) => {
|
app.post("/api/instance", async (req, res) => {
|
||||||
// check auth
|
// check auth
|
||||||
await checkAuth(req.cookies, res);
|
await checkAuth(req.cookies, res);
|
||||||
// get used resources
|
|
||||||
let userResources = await getUserResources(req, req.cookies.username);
|
|
||||||
// setup request
|
// setup request
|
||||||
let request = {
|
let request = {
|
||||||
cores: Number(req.body.cores),
|
cores: Number(req.body.cores),
|
||||||
@ -294,7 +252,7 @@ app.post("/api/instance", async (req, res) => {
|
|||||||
action.name = req.body.name;
|
action.name = req.body.name;
|
||||||
}
|
}
|
||||||
// check resource approval
|
// check resource approval
|
||||||
if (!approveResources(request, userResources.avail)) { // check resource approval
|
if (!await approveResources(req, req.body.username, request)) { // check resource approval
|
||||||
res.status(500).send({request: request, error: `Not enough resources to satisfy request.`});
|
res.status(500).send({request: request, error: `Not enough resources to satisfy request.`});
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
return;
|
||||||
@ -314,6 +272,5 @@ app.delete("/api/instance", async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.listen(listenPort, () => {
|
app.listen(listenPort, () => {
|
||||||
init();
|
|
||||||
console.log(`proxmoxaas-api v${api.version} listening on port ${listenPort}`);
|
console.log(`proxmoxaas-api v${api.version} listening on port ${listenPort}`);
|
||||||
});
|
});
|
37
utils.js
Normal file
37
utils.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
const {getUsedResources} = require("./pve.js");
|
||||||
|
const {getUserConfig, getResourceConfig} = require("./db.js");
|
||||||
|
|
||||||
|
async function getUserData (req, username) {
|
||||||
|
let resources = await getAllocatedResources(req, username);
|
||||||
|
let instances = getUserConfig(req.cookies.username).instances;
|
||||||
|
return {resources: resources, instances: instances};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getAllocatedResources (req, username) {
|
||||||
|
let dbResources = getResourceConfig();
|
||||||
|
let used = await getUsedResources(req, dbResources);
|
||||||
|
let max = getUserConfig(username).resources.max;
|
||||||
|
avail = {};
|
||||||
|
Object.keys(max).forEach((k) => {
|
||||||
|
avail[k] = max[k] - used[k];
|
||||||
|
});
|
||||||
|
return {used: used, max: max, avail: avail, units: dbResources};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function approveResources (req, username, request) {
|
||||||
|
|
||||||
|
let avail = (await getAllocatedResources(req, username)).avail;
|
||||||
|
|
||||||
|
let approved = true;
|
||||||
|
Object.keys(request).forEach((key) => {
|
||||||
|
if (!(key in avail)) {
|
||||||
|
approved = false;
|
||||||
|
}
|
||||||
|
else if (avail[key] - request[key] < 0) {
|
||||||
|
approved = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return approved;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {getUserData, approveResources}
|
Loading…
Reference in New Issue
Block a user