@tyevco/homelab-lxc-agent 1.9.8 → 1.9.10
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 +31 -5
- package/dist/server.js +12 -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.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.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"));
|
|
@@ -265,24 +265,50 @@ async function createContainer(socket, endpoint, name, dist, release, arch, init
|
|
|
265
265
|
console.log(`[lxc] Created: ${name}`);
|
|
266
266
|
}
|
|
267
267
|
exports.createContainer = createContainer;
|
|
268
|
-
async function cloneContainer(socket, endpoint, sourceName, destName, initialConfig) {
|
|
268
|
+
async function cloneContainer(socket, endpoint, sourceName, destName, snapshotName, initialConfig) {
|
|
269
269
|
if (!/^[a-z0-9_.-]+$/.test(sourceName)) {
|
|
270
270
|
throw new Error("Invalid source container name");
|
|
271
271
|
}
|
|
272
272
|
if (!/^[a-z0-9_.-]+$/.test(destName)) {
|
|
273
273
|
throw new Error("Invalid destination container name");
|
|
274
274
|
}
|
|
275
|
-
|
|
276
|
-
|
|
275
|
+
if (snapshotName && !/^[a-z0-9_.-]+$/.test(snapshotName)) {
|
|
276
|
+
throw new Error("Invalid snapshot name");
|
|
277
|
+
}
|
|
278
|
+
const args = snapshotName
|
|
279
|
+
? ["-n", sourceName, "-s", snapshotName, "-N", destName]
|
|
280
|
+
: ["-n", sourceName, "-N", destName];
|
|
281
|
+
console.log(`[lxc] Cloning container: ${sourceName}${snapshotName ? `@${snapshotName}` : ""} → ${destName}`);
|
|
282
|
+
const code = await terminal_1.AgentTerminal.exec(socket, getLxcTerminalName(endpoint, destName), "lxc-copy", args, LXC_PATH);
|
|
277
283
|
if (code !== 0) {
|
|
278
284
|
throw new Error("Failed to clone LXC container");
|
|
279
285
|
}
|
|
280
286
|
if (initialConfig) {
|
|
281
287
|
await appendConfig(destName, initialConfig);
|
|
282
288
|
}
|
|
283
|
-
console.log(`[lxc] Cloned: ${sourceName} → ${destName}`);
|
|
289
|
+
console.log(`[lxc] Cloned: ${sourceName}${snapshotName ? `@${snapshotName}` : ""} → ${destName}`);
|
|
284
290
|
}
|
|
285
291
|
exports.cloneContainer = cloneContainer;
|
|
292
|
+
async function listSnapshots(containerName) {
|
|
293
|
+
if (!/^[a-z0-9_.-]+$/.test(containerName)) {
|
|
294
|
+
throw new Error("Invalid container name");
|
|
295
|
+
}
|
|
296
|
+
try {
|
|
297
|
+
const res = await (0, promisify_child_process_1.spawn)("lxc-snapshot", ["-n", containerName, "-L"], { encoding: "utf-8" });
|
|
298
|
+
const output = (res.stdout || "").trim();
|
|
299
|
+
if (!output) {
|
|
300
|
+
return [];
|
|
301
|
+
}
|
|
302
|
+
// Each line: "snap0 (/var/lib/lxc/.../snap0) 2024-01-01 ..."
|
|
303
|
+
return output.split("\n")
|
|
304
|
+
.map(line => line.trim().split(" ")[0])
|
|
305
|
+
.filter(name => name.length > 0);
|
|
306
|
+
}
|
|
307
|
+
catch {
|
|
308
|
+
return [];
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
exports.listSnapshots = listSnapshots;
|
|
286
312
|
async function appendConfig(name, extra) {
|
|
287
313
|
const configPath = path.join(LXC_PATH, name, "config");
|
|
288
314
|
const existing = await fs.promises.readFile(configPath, "utf-8").catch(() => "");
|
package/dist/server.js
CHANGED
|
@@ -263,18 +263,28 @@ async function dispatch(socket, endpoint, eventName, args) {
|
|
|
263
263
|
break;
|
|
264
264
|
}
|
|
265
265
|
case "cloneLxcContainer": {
|
|
266
|
-
const [sourceName, destName, initialConfig] = args;
|
|
266
|
+
const [sourceName, destName, snapshotName, initialConfig] = args;
|
|
267
267
|
if (typeof sourceName !== "string") {
|
|
268
268
|
throw new Error("Source name must be a string");
|
|
269
269
|
}
|
|
270
270
|
if (typeof destName !== "string") {
|
|
271
271
|
throw new Error("Destination name must be a string");
|
|
272
272
|
}
|
|
273
|
-
await lxc.cloneContainer(socket, endpoint, sourceName, destName, initialConfig || undefined);
|
|
273
|
+
await lxc.cloneContainer(socket, endpoint, sourceName, destName, snapshotName || undefined, initialConfig || undefined);
|
|
274
274
|
await pushList();
|
|
275
275
|
ok("Cloned");
|
|
276
276
|
break;
|
|
277
277
|
}
|
|
278
|
+
case "getLxcSnapshots": {
|
|
279
|
+
const [containerName] = args;
|
|
280
|
+
if (typeof containerName !== "string") {
|
|
281
|
+
throw new Error("Container name must be a string");
|
|
282
|
+
}
|
|
283
|
+
const snapshots = await lxc.listSnapshots(containerName);
|
|
284
|
+
callback?.({ ok: true,
|
|
285
|
+
snapshots });
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
278
288
|
case "getLxcDistributions": {
|
|
279
289
|
const distributions = await lxc.getDistributions();
|
|
280
290
|
callback?.({ ok: true,
|