@tyevco/homelab-lxc-agent 1.9.14 → 1.9.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lxc.js +23 -2
- package/dist/server.js +41 -2
- package/package.json +1 -1
package/dist/lxc.js
CHANGED
|
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.joinExecTerminal = exports.getDistributions = exports.listSnapshots = exports.cloneContainer = exports.createContainer = exports.saveConfig = exports.deleteContainer = exports.unfreezeContainer = exports.freezeContainer = exports.restartContainer = exports.stopContainer = exports.startContainer = exports.getContainer = exports.getContainerList = exports.STACK_TYPE_LXC = exports.FROZEN = exports.EXITED = exports.RUNNING = exports.UNKNOWN = void 0;
|
|
26
|
+
exports.joinExecTerminal = exports.getDistributions = exports.deleteSnapshot = exports.createSnapshot = exports.listSnapshots = exports.cloneContainer = exports.createContainer = exports.saveConfig = exports.deleteContainer = exports.unfreezeContainer = exports.freezeContainer = exports.restartContainer = exports.stopContainer = exports.startContainer = exports.getContainer = exports.getContainerList = exports.STACK_TYPE_LXC = exports.FROZEN = exports.EXITED = exports.RUNNING = exports.UNKNOWN = void 0;
|
|
27
27
|
const promisify_child_process_1 = require("promisify-child-process");
|
|
28
28
|
const fs = __importStar(require("fs"));
|
|
29
29
|
const path = __importStar(require("path"));
|
|
@@ -224,7 +224,7 @@ async function deleteContainer(socket, endpoint, name, status) {
|
|
|
224
224
|
console.log(`[lxc] Stopping ${name} before delete`);
|
|
225
225
|
await terminal_1.AgentTerminal.exec(socket, termName, "lxc-stop", ["-n", name], LXC_PATH);
|
|
226
226
|
}
|
|
227
|
-
const code = await terminal_1.AgentTerminal.exec(socket, termName, "lxc-destroy", ["-n", name], LXC_PATH);
|
|
227
|
+
const code = await terminal_1.AgentTerminal.exec(socket, termName, "lxc-destroy", ["-n", name, "--snapshots"], LXC_PATH);
|
|
228
228
|
if (code !== 0) {
|
|
229
229
|
throw new Error("Failed to destroy LXC container");
|
|
230
230
|
}
|
|
@@ -309,6 +309,27 @@ async function listSnapshots(containerName) {
|
|
|
309
309
|
}
|
|
310
310
|
}
|
|
311
311
|
exports.listSnapshots = listSnapshots;
|
|
312
|
+
async function createSnapshot(containerName) {
|
|
313
|
+
if (!/^[a-z0-9_.-]+$/.test(containerName)) {
|
|
314
|
+
throw new Error("Invalid container name");
|
|
315
|
+
}
|
|
316
|
+
const before = await listSnapshots(containerName);
|
|
317
|
+
await (0, promisify_child_process_1.spawn)("lxc-snapshot", ["-n", containerName], { encoding: "utf-8" });
|
|
318
|
+
const after = await listSnapshots(containerName);
|
|
319
|
+
const newSnap = after.find(s => !before.includes(s));
|
|
320
|
+
return newSnap || after[after.length - 1] || "";
|
|
321
|
+
}
|
|
322
|
+
exports.createSnapshot = createSnapshot;
|
|
323
|
+
async function deleteSnapshot(containerName, snapshotName) {
|
|
324
|
+
if (!/^[a-z0-9_.-]+$/.test(containerName)) {
|
|
325
|
+
throw new Error("Invalid container name");
|
|
326
|
+
}
|
|
327
|
+
if (!/^[a-z0-9_.-]+$/.test(snapshotName)) {
|
|
328
|
+
throw new Error("Invalid snapshot name");
|
|
329
|
+
}
|
|
330
|
+
await (0, promisify_child_process_1.spawn)("lxc-snapshot", ["-n", containerName, "-d", snapshotName], { encoding: "utf-8" });
|
|
331
|
+
}
|
|
332
|
+
exports.deleteSnapshot = deleteSnapshot;
|
|
312
333
|
async function appendConfig(name, extra) {
|
|
313
334
|
const configPath = path.join(LXC_PATH, name, "config");
|
|
314
335
|
const existing = await fs.promises.readFile(configPath, "utf-8").catch(() => "");
|
package/dist/server.js
CHANGED
|
@@ -84,6 +84,10 @@ function createAgentServer(config) {
|
|
|
84
84
|
// Initial scan, then periodic rescan
|
|
85
85
|
rescan().then(() => {
|
|
86
86
|
setInterval(rescan, config.scanInterval * 1000);
|
|
87
|
+
}).catch((e) => {
|
|
88
|
+
console.error("[agent] Initial scan failed:", e instanceof Error ? e.message : e);
|
|
89
|
+
// Still set up periodic rescans so recovery is possible
|
|
90
|
+
setInterval(rescan, config.scanInterval * 1000);
|
|
87
91
|
});
|
|
88
92
|
io.on("connection", (socket) => {
|
|
89
93
|
// The main server sends its own endpoint string in the header so we can
|
|
@@ -237,8 +241,19 @@ async function dispatch(socket, endpoint, eventName, args) {
|
|
|
237
241
|
if (typeof name !== "string") {
|
|
238
242
|
throw new Error("Name must be a string");
|
|
239
243
|
}
|
|
240
|
-
|
|
241
|
-
|
|
244
|
+
try {
|
|
245
|
+
const container = await lxc.getContainer(name, endpoint);
|
|
246
|
+
await lxc.deleteContainer(socket, endpoint, name, container.status);
|
|
247
|
+
}
|
|
248
|
+
catch (e) {
|
|
249
|
+
// If the container is already gone, treat as success
|
|
250
|
+
if (e instanceof Error && e.message.includes("not found")) {
|
|
251
|
+
console.log(`[lxc] Container ${name} already removed, nothing to delete`);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
throw e;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
242
257
|
await pushList();
|
|
243
258
|
ok("Destroyed");
|
|
244
259
|
break;
|
|
@@ -285,6 +300,30 @@ async function dispatch(socket, endpoint, eventName, args) {
|
|
|
285
300
|
snapshots });
|
|
286
301
|
break;
|
|
287
302
|
}
|
|
303
|
+
case "createLxcSnapshot": {
|
|
304
|
+
const [containerName] = args;
|
|
305
|
+
if (typeof containerName !== "string") {
|
|
306
|
+
throw new Error("Container name must be a string");
|
|
307
|
+
}
|
|
308
|
+
const snapshotName = await lxc.createSnapshot(containerName);
|
|
309
|
+
callback?.({ ok: true,
|
|
310
|
+
msg: "Snapshot created",
|
|
311
|
+
snapshotName });
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
case "deleteLxcSnapshot": {
|
|
315
|
+
const [containerName, snapshotName] = args;
|
|
316
|
+
if (typeof containerName !== "string") {
|
|
317
|
+
throw new Error("Container name must be a string");
|
|
318
|
+
}
|
|
319
|
+
if (typeof snapshotName !== "string") {
|
|
320
|
+
throw new Error("Snapshot name must be a string");
|
|
321
|
+
}
|
|
322
|
+
await lxc.deleteSnapshot(containerName, snapshotName);
|
|
323
|
+
callback?.({ ok: true,
|
|
324
|
+
msg: "Snapshot deleted" });
|
|
325
|
+
break;
|
|
326
|
+
}
|
|
288
327
|
case "getLxcDistributions": {
|
|
289
328
|
const distributions = await lxc.getDistributions();
|
|
290
329
|
callback?.({ ok: true,
|