cd management
npm run reset-password -- admin "neues-passwort"
- Agent-Hardening
backend/.env unterstützt jetzt:
ALLOWED_MANAGEMENT_IPS="127.0.0.1,DEINE-MANAGEMENT-IP"
Wenn gesetzt, akzeptiert der Agent nur Requests von diesen IPs.
- Audit-Log
Management speichert Aktionen wie Login, Logout, Node-Änderungen, Schedule-Updates, Backup/Restore, Settings-Änderungen.
- Job-History
Management speichert gestartete Backup/Restore/Scheduler-Jobs mit Node, VM, Typ, Agent-Job-ID und Status.
- Operations-Seite
Neue UI-Seite Operations mit:
- Job History
- Audit Log
- systemd Templates
deploy/systemd/incus-backup-agent.service
deploy/systemd/incus-backup-management.service
- Deployment-Doku
docs/deployment.md
42 lines
1.5 KiB
JavaScript
42 lines
1.5 KiB
JavaScript
import { agentRequest } from './agentClient.js';
|
|
import { createAuditEvent, createJobHistory, listDueSchedules, markScheduleRun, nextRunFrom } from './store.js';
|
|
|
|
let timer = null;
|
|
|
|
export function startScheduler() {
|
|
if (timer) return;
|
|
timer = setInterval(runDueSchedules, 30 * 1000);
|
|
timer.unref?.();
|
|
runDueSchedules();
|
|
}
|
|
|
|
async function runDueSchedules() {
|
|
const now = new Date();
|
|
const schedules = listDueSchedules(now);
|
|
for (const schedule of schedules) {
|
|
try {
|
|
const node = {
|
|
id: schedule.node_id,
|
|
name: schedule.node_name,
|
|
baseUrl: schedule.base_url,
|
|
token: schedule.token,
|
|
};
|
|
const result = await agentRequest(node, `/backup/${encodeURIComponent(schedule.vm_name)}`, { method: 'POST' });
|
|
const historyId = createJobHistory({ node, vmName: schedule.vm_name, type: 'scheduled-backup', agentJobId: result?.jobId, status: 'accepted' });
|
|
createAuditEvent({ action: 'scheduled-backup', targetType: 'vm', targetId: `${node.id}:${schedule.vm_name}`, details: { scheduleId: schedule.id, historyId, agentJobId: result?.jobId } });
|
|
|
|
markScheduleRun(schedule.id, {
|
|
lastRunAt: now.toISOString(),
|
|
lastError: '',
|
|
nextRunAt: nextRunFrom(now, schedule.interval_hours, schedule.time_of_day),
|
|
});
|
|
} catch (error) {
|
|
markScheduleRun(schedule.id, {
|
|
lastRunAt: schedule.last_run_at,
|
|
lastError: String(error.message || error),
|
|
nextRunAt: new Date(now.getTime() + 5 * 60 * 1000).toISOString(),
|
|
});
|
|
}
|
|
}
|
|
}
|