Files
incus-backup-ui/management/src/routes/proxy.js
T
Philipp aae54167a1 Builded new structure.
Now with remote setup and management Server
more than one Node can be connected
added user auth
2026-05-21 09:51:07 +02:00

120 lines
3.7 KiB
JavaScript

import { Router } from 'express';
import { agentRequest } from '../agentClient.js';
import { getNode, listNodes, recordNodeHealth } from '../store.js';
export const proxyRouter = Router();
proxyRouter.get('/health', async (_req, res) => {
const nodes = listNodes().filter((node) => node.enabled);
const checks = { database: 'ok' };
let ok = true;
await Promise.all(nodes.map(async (node) => {
try {
const health = await agentRequest(node, '/health', { timeout: 8000 });
checks[node.name] = health?.ok ? 'ok' : 'degraded';
recordNodeHealth(node.id, checks[node.name]);
ok = ok && Boolean(health?.ok);
} catch {
checks[node.name] = 'error';
recordNodeHealth(node.id, 'error');
ok = false;
}
}));
res.json({ ok, checks });
});
proxyRouter.get('/vms', async (_req, res) => {
const nodes = listNodes().filter((node) => node.enabled);
const rows = [];
await Promise.all(nodes.map(async (node) => {
try {
const vms = await agentRequest(node, '/vms');
for (const vm of vms) {
rows.push({ ...vm, id: `${node.id}:${vm.name}`, nodeId: node.id, nodeName: node.name });
}
recordNodeHealth(node.id, 'ok');
} catch {
recordNodeHealth(node.id, 'error');
}
}));
res.json(rows.sort((a, b) => `${a.nodeName}/${a.name}`.localeCompare(`${b.nodeName}/${b.name}`)));
});
proxyRouter.get('/jobs', async (_req, res) => {
const nodes = listNodes().filter((node) => node.enabled);
const rows = [];
await Promise.all(nodes.map(async (node) => {
try {
const jobs = await agentRequest(node, '/jobs');
for (const job of jobs) rows.push({ ...job, nodeId: node.id, nodeName: node.name });
} catch {
recordNodeHealth(node.id, 'error');
}
}));
res.json(rows.sort((a, b) => String(b.startedAt || '').localeCompare(String(a.startedAt || ''))));
});
proxyRouter.get('/snapshots/:nodeId/:vmName', async (req, res, next) => {
try {
const node = requireNode(req.params.nodeId);
res.json(await agentRequest(node, `/snapshots/${encodeURIComponent(req.params.vmName)}`));
} catch (error) {
next(error);
}
});
proxyRouter.get('/snapshots/:nodeId/:vmName/:snapshotId/files', async (req, res, next) => {
try {
const node = requireNode(req.params.nodeId);
res.json(await agentRequest(node, `/snapshots/${encodeURIComponent(req.params.vmName)}/${encodeURIComponent(req.params.snapshotId)}/files`));
} catch (error) {
next(error);
}
});
proxyRouter.post('/backup/:nodeId/:vmName', async (req, res, next) => {
try {
const node = requireNode(req.params.nodeId);
res.status(202).json(await agentRequest(node, `/backup/${encodeURIComponent(req.params.vmName)}`, { method: 'POST', body: req.body || {} }));
} catch (error) {
next(error);
}
});
proxyRouter.post('/restore/:nodeId/:vmName', async (req, res, next) => {
try {
const node = requireNode(req.params.nodeId);
res.status(202).json(await agentRequest(node, `/restore/${encodeURIComponent(req.params.vmName)}`, { method: 'POST', body: req.body || {} }));
} catch (error) {
next(error);
}
});
proxyRouter.get('/settings/:nodeId', async (req, res, next) => {
try {
const node = requireNode(req.params.nodeId);
res.json(await agentRequest(node, '/settings'));
} catch (error) {
next(error);
}
});
proxyRouter.put('/settings/:nodeId', async (req, res, next) => {
try {
const node = requireNode(req.params.nodeId);
res.json(await agentRequest(node, '/settings', { method: 'PUT', body: req.body || {} }));
} catch (error) {
next(error);
}
});
function requireNode(id) {
const node = getNode(id);
if (!node) {
const error = new Error('Node not found.');
error.status = 404;
throw error;
}
return node;
}