@impz/testing 6.4.2 → 6.5.0
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/index.js +239 -148
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -21961,18 +21961,19 @@ function parseKsmConfig(parsed) {
|
|
|
21961
21961
|
}
|
|
21962
21962
|
|
|
21963
21963
|
// packages/daemon/src/create-impd.ts
|
|
21964
|
-
import { readFileSync as
|
|
21964
|
+
import { readFileSync as readFileSync37 } from "fs";
|
|
21965
21965
|
import { release as release2 } from "os";
|
|
21966
|
-
import { join as
|
|
21966
|
+
import { join as join48 } from "path";
|
|
21967
21967
|
// packages/daemon/package.json
|
|
21968
21968
|
var package_default = {
|
|
21969
21969
|
name: "@impz/daemon",
|
|
21970
|
-
version: "6.
|
|
21970
|
+
version: "6.5.0",
|
|
21971
21971
|
private: true,
|
|
21972
21972
|
description: "impd: the imp host daemon",
|
|
21973
21973
|
type: "module",
|
|
21974
21974
|
exports: {
|
|
21975
21975
|
".": "./src/index.ts",
|
|
21976
|
+
"./read-text": "./src/platform/process/read-text.ts",
|
|
21976
21977
|
"./real-clock": "./src/platform/process/real-clock.ts",
|
|
21977
21978
|
"./testing": "./testing/index.ts",
|
|
21978
21979
|
"./testing/build-stub-clock": "./testing/platform/build-stub-clock.ts",
|
|
@@ -41112,7 +41113,8 @@ function createImpContext(deps) {
|
|
|
41112
41113
|
const records = {
|
|
41113
41114
|
config: deps.config,
|
|
41114
41115
|
db: deps.db,
|
|
41115
|
-
identity: deps.identity
|
|
41116
|
+
identity: deps.identity,
|
|
41117
|
+
readHostLoad: deps.readHostLoad
|
|
41116
41118
|
};
|
|
41117
41119
|
const clock = {
|
|
41118
41120
|
now,
|
|
@@ -43497,6 +43499,22 @@ ${readLogTail(plan.paths.logFile, 5)}`, step.fault, error);
|
|
|
43497
43499
|
}
|
|
43498
43500
|
}
|
|
43499
43501
|
|
|
43502
|
+
// packages/daemon/src/imps/imps/format-host-stall.ts
|
|
43503
|
+
var STALL_FIGURES = [
|
|
43504
|
+
["cpu", "cpuStallUs"],
|
|
43505
|
+
["io", "ioStallUs"],
|
|
43506
|
+
["memory", "memoryStallUs"],
|
|
43507
|
+
["steal", "stealUs"]
|
|
43508
|
+
];
|
|
43509
|
+
function formatHostStall(before, after) {
|
|
43510
|
+
const figures = STALL_FIGURES.flatMap(([name, field]) => {
|
|
43511
|
+
const startUs = before[field];
|
|
43512
|
+
const endUs = after[field];
|
|
43513
|
+
return startUs === null || endUs === null ? [] : [`${name}=${String(Math.round((endUs - startUs) / 1000))}ms`];
|
|
43514
|
+
});
|
|
43515
|
+
return figures.length === 0 ? "" : `; host stall ${figures.join(" ")}`;
|
|
43516
|
+
}
|
|
43517
|
+
|
|
43500
43518
|
// packages/daemon/src/imps/imps/start-cold-vm.ts
|
|
43501
43519
|
var CLAIM_SEED_BYTES = 64;
|
|
43502
43520
|
async function startColdVm(context, start) {
|
|
@@ -43552,11 +43570,12 @@ async function startColdVm(context, start) {
|
|
|
43552
43570
|
}
|
|
43553
43571
|
});
|
|
43554
43572
|
context.templates?.reportRestored(template);
|
|
43555
|
-
getImpdLogger("imps").with({ imp: imp.name }).info("restored boot template {key} as pid {pid} {timings}{guestSteps}", {
|
|
43573
|
+
getImpdLogger("imps").with({ imp: imp.name }).info("restored boot template {key} as pid {pid} {timings}{guestSteps}{hostStall}", {
|
|
43556
43574
|
key: template.key.slice(0, 12),
|
|
43557
43575
|
pid: String(vm.pid),
|
|
43558
43576
|
timings: formatTimings({ ...hostSteps, ...vm.timings }),
|
|
43559
|
-
guestSteps: formatGuestSteps(vm.guestSteps)
|
|
43577
|
+
guestSteps: formatGuestSteps(vm.guestSteps),
|
|
43578
|
+
hostStall: formatHostStall(start.loadBefore, context.readHostLoad())
|
|
43560
43579
|
});
|
|
43561
43580
|
return vm;
|
|
43562
43581
|
} catch (error) {
|
|
@@ -43589,10 +43608,11 @@ async function startColdVm(context, start) {
|
|
|
43589
43608
|
isIdentityReset: imp.isIdentityResetPending,
|
|
43590
43609
|
jail: context.findJailUser(imp)
|
|
43591
43610
|
});
|
|
43592
|
-
getImpdLogger("imps").with({ imp: imp.name }).info("booted pid {pid} {timings}{guestSteps}", {
|
|
43611
|
+
getImpdLogger("imps").with({ imp: imp.name }).info("booted pid {pid} {timings}{guestSteps}{hostStall}", {
|
|
43593
43612
|
pid: String(vm.pid),
|
|
43594
43613
|
timings: formatTimings({ ...hostSteps, ...vm.timings }),
|
|
43595
|
-
guestSteps: formatGuestSteps(vm.guestSteps)
|
|
43614
|
+
guestSteps: formatGuestSteps(vm.guestSteps),
|
|
43615
|
+
hostStall: formatHostStall(start.loadBefore, context.readHostLoad())
|
|
43596
43616
|
});
|
|
43597
43617
|
return vm;
|
|
43598
43618
|
}
|
|
@@ -43673,6 +43693,7 @@ function createImpVmOps(host) {
|
|
|
43673
43693
|
hugePagesMib: hugePages === "2M" ? imp.memoryMib : 0
|
|
43674
43694
|
});
|
|
43675
43695
|
const setupStarted = performance.now();
|
|
43696
|
+
const loadBefore = context.readHostLoad();
|
|
43676
43697
|
try {
|
|
43677
43698
|
removeSnapshot(paths);
|
|
43678
43699
|
await context.egress.requireImp(imp.id);
|
|
@@ -43690,6 +43711,7 @@ function createImpVmOps(host) {
|
|
|
43690
43711
|
cgroup,
|
|
43691
43712
|
hugePages,
|
|
43692
43713
|
hostSteps,
|
|
43714
|
+
loadBefore,
|
|
43693
43715
|
diskReady
|
|
43694
43716
|
});
|
|
43695
43717
|
startCounting(context, imp, vm.pid);
|
|
@@ -44394,6 +44416,56 @@ function createImpService(deps, createWatchdog) {
|
|
|
44394
44416
|
};
|
|
44395
44417
|
}
|
|
44396
44418
|
|
|
44419
|
+
// packages/daemon/src/platform/process/read-host-load.ts
|
|
44420
|
+
import { join as join22 } from "path";
|
|
44421
|
+
|
|
44422
|
+
// packages/daemon/src/platform/process/find-unexpected-read-code.ts
|
|
44423
|
+
var UNSUPPORTED_CODES = new Set(["ENOENT", "EOPNOTSUPP"]);
|
|
44424
|
+
function findUnexpectedReadCode(error) {
|
|
44425
|
+
const code = error instanceof Error && "code" in error ? String(error.code) : "unknown";
|
|
44426
|
+
return UNSUPPORTED_CODES.has(code) ? null : code;
|
|
44427
|
+
}
|
|
44428
|
+
|
|
44429
|
+
// packages/daemon/src/platform/process/read-host-load.ts
|
|
44430
|
+
function readHostLoad(sources) {
|
|
44431
|
+
const readProc = (...names) => readProcFile(sources, join22(sources.procRoot, ...names));
|
|
44432
|
+
return {
|
|
44433
|
+
cpuStallUs: parsePressureTotal(readProc("pressure", "cpu")),
|
|
44434
|
+
ioStallUs: parsePressureTotal(readProc("pressure", "io")),
|
|
44435
|
+
memoryStallUs: parsePressureTotal(readProc("pressure", "memory")),
|
|
44436
|
+
stealUs: parseStealUs(readProc("stat"))
|
|
44437
|
+
};
|
|
44438
|
+
}
|
|
44439
|
+
function readProcFile(sources, path) {
|
|
44440
|
+
try {
|
|
44441
|
+
return sources.readFile(path);
|
|
44442
|
+
} catch (error) {
|
|
44443
|
+
const code = findUnexpectedReadCode(error);
|
|
44444
|
+
if (code !== null) {
|
|
44445
|
+
sources.logger.warning("cannot read {path} for the host stall: {code}", { path, code });
|
|
44446
|
+
}
|
|
44447
|
+
return null;
|
|
44448
|
+
}
|
|
44449
|
+
}
|
|
44450
|
+
function parsePressureTotal(pressure) {
|
|
44451
|
+
const total = pressure === null ? undefined : /^some .*total=(?<us>\d+)$/mv.exec(pressure);
|
|
44452
|
+
return total?.groups?.["us"] === undefined ? null : Number(total.groups["us"]);
|
|
44453
|
+
}
|
|
44454
|
+
var STEAL_FIELD = 8;
|
|
44455
|
+
var US_PER_TICK = 1e4;
|
|
44456
|
+
function parseStealUs(stat) {
|
|
44457
|
+
const fields = stat?.split(`
|
|
44458
|
+
`).find((line) => line.startsWith("cpu "))?.split(/\s+/v);
|
|
44459
|
+
const steal = fields?.[STEAL_FIELD];
|
|
44460
|
+
return steal === undefined ? null : Number(steal) * US_PER_TICK;
|
|
44461
|
+
}
|
|
44462
|
+
|
|
44463
|
+
// packages/daemon/src/platform/process/read-text.ts
|
|
44464
|
+
import { readFileSync as readFileSync22 } from "fs";
|
|
44465
|
+
function readText(path) {
|
|
44466
|
+
return readFileSync22(path, "utf8");
|
|
44467
|
+
}
|
|
44468
|
+
|
|
44397
44469
|
// packages/daemon/src/platform/telemetry/imp-telemetry.ts
|
|
44398
44470
|
import { ROOT_CONTEXT, metrics as metrics2, trace } from "@opentelemetry/api";
|
|
44399
44471
|
var SPAN_NAMES = {
|
|
@@ -44770,12 +44842,12 @@ function createMemoryController(deps) {
|
|
|
44770
44842
|
import {
|
|
44771
44843
|
existsSync as existsSync14,
|
|
44772
44844
|
mkdirSync as mkdirSync16,
|
|
44773
|
-
readFileSync as
|
|
44845
|
+
readFileSync as readFileSync23,
|
|
44774
44846
|
readdirSync as readdirSync8,
|
|
44775
44847
|
rmdirSync as rmdirSync2,
|
|
44776
44848
|
writeFileSync as writeFileSync5
|
|
44777
44849
|
} from "fs";
|
|
44778
|
-
import { join as
|
|
44850
|
+
import { join as join23 } from "path";
|
|
44779
44851
|
var PERIOD_US = 1e5;
|
|
44780
44852
|
var MEMORY_MIN_OVERHEAD_MIB = 256;
|
|
44781
44853
|
var MEMORY_OVERHEAD_DIVISOR = 8;
|
|
@@ -44803,18 +44875,18 @@ function parseOomKills(text) {
|
|
|
44803
44875
|
return match?.groups === undefined ? null : Number(match.groups["count"]);
|
|
44804
44876
|
}
|
|
44805
44877
|
function createCpuCgroups(options) {
|
|
44806
|
-
const imps =
|
|
44878
|
+
const imps = join23(options.root, "imps");
|
|
44807
44879
|
const procRoot = options.procRoot ?? "/proc";
|
|
44808
44880
|
const rmdir = options.rmdir ?? rmdirSync2;
|
|
44809
44881
|
const sleep = options.sleep ?? Bun.sleep;
|
|
44810
44882
|
const isEnforced = probeControllerDelegated(imps, "cpu");
|
|
44811
44883
|
const isMemoryEnforced = isEnforced && probeControllerDelegated(imps, "memory");
|
|
44812
|
-
const getDir = (impId) =>
|
|
44884
|
+
const getDir = (impId) => join23(imps, impId);
|
|
44813
44885
|
const guestMibs = new Map;
|
|
44814
44886
|
const oomBaselines = new Map;
|
|
44815
44887
|
const readOomKills = (impId) => {
|
|
44816
44888
|
try {
|
|
44817
|
-
const events =
|
|
44889
|
+
const events = readFileSync23(join23(getDir(impId), "memory.events"), "utf8");
|
|
44818
44890
|
return parseOomKills(events);
|
|
44819
44891
|
} catch {
|
|
44820
44892
|
return null;
|
|
@@ -44824,8 +44896,8 @@ function createCpuCgroups(options) {
|
|
|
44824
44896
|
oomBaselines.set(impId, readOomKills(impId) ?? 0);
|
|
44825
44897
|
};
|
|
44826
44898
|
const writeSettings = (impId, cpu, limit) => {
|
|
44827
|
-
writeFileSync5(
|
|
44828
|
-
writeFileSync5(
|
|
44899
|
+
writeFileSync5(join23(getDir(impId), "cpu.weight"), String(cpu.weight));
|
|
44900
|
+
writeFileSync5(join23(getDir(impId), "cpu.max"), formatCpuMax(limit));
|
|
44829
44901
|
};
|
|
44830
44902
|
const writeMemory = (impId) => {
|
|
44831
44903
|
const guestMib = guestMibs.get(impId);
|
|
@@ -44833,10 +44905,10 @@ function createCpuCgroups(options) {
|
|
|
44833
44905
|
return;
|
|
44834
44906
|
}
|
|
44835
44907
|
const directory = getDir(impId);
|
|
44836
|
-
writeFileSync5(
|
|
44837
|
-
writeFileSync5(
|
|
44838
|
-
writeFileSync5(
|
|
44839
|
-
writeFileSync5(
|
|
44908
|
+
writeFileSync5(join23(directory, "memory.max"), buildMemoryMax(guestMib));
|
|
44909
|
+
writeFileSync5(join23(directory, "memory.high"), "max");
|
|
44910
|
+
writeFileSync5(join23(directory, "memory.swap.max"), "0");
|
|
44911
|
+
writeFileSync5(join23(directory, "memory.oom.group"), "1");
|
|
44840
44912
|
};
|
|
44841
44913
|
const setup = (impId, cpu, memoryMib) => {
|
|
44842
44914
|
if (!isEnforced) {
|
|
@@ -44858,7 +44930,7 @@ function createCpuCgroups(options) {
|
|
|
44858
44930
|
return null;
|
|
44859
44931
|
}
|
|
44860
44932
|
return {
|
|
44861
|
-
procsPath:
|
|
44933
|
+
procsPath: join23(getDir(impId), "cgroup.procs"),
|
|
44862
44934
|
liftLimit: () => {
|
|
44863
44935
|
tryWrite(impId, "lift the limit", () => {
|
|
44864
44936
|
writeSettings(impId, cpu, null);
|
|
@@ -44942,7 +45014,7 @@ function createCpuCgroups(options) {
|
|
|
44942
45014
|
kill: (impId) => {
|
|
44943
45015
|
if (isEnforced && existsSync14(getDir(impId))) {
|
|
44944
45016
|
tryWrite(impId, "kill", () => {
|
|
44945
|
-
writeFileSync5(
|
|
45017
|
+
writeFileSync5(join23(getDir(impId), "cgroup.kill"), "1");
|
|
44946
45018
|
});
|
|
44947
45019
|
}
|
|
44948
45020
|
},
|
|
@@ -44953,7 +45025,7 @@ function createCpuCgroups(options) {
|
|
|
44953
45025
|
},
|
|
44954
45026
|
readCpuStat: (impId) => {
|
|
44955
45027
|
try {
|
|
44956
|
-
const stat =
|
|
45028
|
+
const stat = readFileSync23(join23(getDir(impId), "cpu.stat"), "utf8");
|
|
44957
45029
|
return parseCpuStat(stat);
|
|
44958
45030
|
} catch {
|
|
44959
45031
|
return null;
|
|
@@ -44963,7 +45035,7 @@ function createCpuCgroups(options) {
|
|
|
44963
45035
|
}
|
|
44964
45036
|
function probeControllerDelegated(imps, controller) {
|
|
44965
45037
|
try {
|
|
44966
|
-
const delegated =
|
|
45038
|
+
const delegated = readFileSync23(join23(imps, "cgroup.subtree_control"), "utf8");
|
|
44967
45039
|
return delegated.split(/\s+/u).includes(controller);
|
|
44968
45040
|
} catch {
|
|
44969
45041
|
return false;
|
|
@@ -44996,13 +45068,13 @@ function probeUffdDevice(path = "/dev/userfaultfd") {
|
|
|
44996
45068
|
}
|
|
44997
45069
|
|
|
44998
45070
|
// packages/daemon/src/vm/vmm/read-huge-page-pool.ts
|
|
44999
|
-
import { readFileSync as
|
|
45000
|
-
import { join as
|
|
45071
|
+
import { readFileSync as readFileSync24 } from "fs";
|
|
45072
|
+
import { join as join24 } from "path";
|
|
45001
45073
|
var HUGE_PAGE_MIB = 2;
|
|
45002
45074
|
function readHugePagePool(sysRoot = "/sys") {
|
|
45003
|
-
const directory =
|
|
45075
|
+
const directory = join24(sysRoot, "kernel", "mm", "hugepages", "hugepages-2048kB");
|
|
45004
45076
|
try {
|
|
45005
|
-
const readCount = (name) => Number(
|
|
45077
|
+
const readCount = (name) => Number(readFileSync24(join24(directory, name), "utf8").trim());
|
|
45006
45078
|
const total = readCount("nr_hugepages");
|
|
45007
45079
|
const free = readCount("free_hugepages") - readCount("resv_hugepages");
|
|
45008
45080
|
if (!Number.isSafeInteger(total) || !Number.isSafeInteger(free)) {
|
|
@@ -45581,6 +45653,7 @@ function resolveImpBoundaries(boundaries) {
|
|
|
45581
45653
|
kernelOops: boundaries.kernelOops ?? createKernelOopsWatch(),
|
|
45582
45654
|
readThreadIds: boundaries.readThreadIds ?? ((pid) => readThreadIds(pid)),
|
|
45583
45655
|
readNetBytes: boundaries.readNetBytes ?? ((tap) => readGuestNetBytes(tap)),
|
|
45656
|
+
readHostLoad: boundaries.readHostLoad ?? (() => readHostLoad({ procRoot: "/proc", readFile: readText, logger: getImpdLogger("imps") })),
|
|
45584
45657
|
...boundaries.openTap !== undefined && { openTap: boundaries.openTap },
|
|
45585
45658
|
...boundaries.now !== undefined && { now: boundaries.now }
|
|
45586
45659
|
};
|
|
@@ -45595,7 +45668,7 @@ function makeStandInVmRam(readRam) {
|
|
|
45595
45668
|
|
|
45596
45669
|
// packages/daemon/src/imp-ops/moves/move-receiver.ts
|
|
45597
45670
|
import { existsSync as existsSync16, rmSync as rmSync24 } from "fs";
|
|
45598
|
-
import { join as
|
|
45671
|
+
import { join as join26 } from "path";
|
|
45599
45672
|
|
|
45600
45673
|
// packages/daemon/src/platform/db/probe-slot-free.ts
|
|
45601
45674
|
async function probeSlotFree(db, slot, now) {
|
|
@@ -45920,7 +45993,7 @@ function readReceipt(receipt, secret) {
|
|
|
45920
45993
|
// packages/daemon/src/imp-ops/moves/read-move-stream.ts
|
|
45921
45994
|
import { mkdirSync as mkdirSync19, rmSync as rmSync23 } from "fs";
|
|
45922
45995
|
import { open as open7 } from "fs/promises";
|
|
45923
|
-
import { join as
|
|
45996
|
+
import { join as join25 } from "path";
|
|
45924
45997
|
import invariant5 from "tiny-invariant";
|
|
45925
45998
|
|
|
45926
45999
|
// packages/daemon/src/imp-ops/moves/build-received-digest.ts
|
|
@@ -46545,7 +46618,7 @@ async function readMoveStream(deps, options) {
|
|
|
46545
46618
|
const count = createByteCounter(row.bytes);
|
|
46546
46619
|
const files = [];
|
|
46547
46620
|
mkdirSync19(options.tempDir, { recursive: true, mode: 448 });
|
|
46548
|
-
const temp =
|
|
46621
|
+
const temp = join25(options.tempDir, `${row.id}.part`);
|
|
46549
46622
|
const writeDisk = async (impId) => {
|
|
46550
46623
|
if (header.streams !== null) {
|
|
46551
46624
|
await writeMoveStreams(deps, {
|
|
@@ -46760,7 +46833,7 @@ async function requireMoveTicket(db, request) {
|
|
|
46760
46833
|
// packages/daemon/src/imp-ops/moves/move-receiver.ts
|
|
46761
46834
|
var STREAM_WINDOW_MS = 10 * 60 * 1000;
|
|
46762
46835
|
function createMoveReceiver(deps) {
|
|
46763
|
-
const tempDir =
|
|
46836
|
+
const tempDir = join26(deps.dataDir, "moves");
|
|
46764
46837
|
const sessions = new Map;
|
|
46765
46838
|
const writeTicketRow = async (name, bytes, fields, write = (row) => writeMoveTicket(deps.db, row)) => {
|
|
46766
46839
|
const created = mintOpaqueToken(MOVE_TICKET_PREFIX);
|
|
@@ -47935,12 +48008,12 @@ function toPeerError2(procedure, error) {
|
|
|
47935
48008
|
// packages/daemon/src/vm/storage/write-image-files.ts
|
|
47936
48009
|
import { writeFileSync as writeFileSync6 } from "fs";
|
|
47937
48010
|
import { copyFile } from "fs/promises";
|
|
47938
|
-
import { join as
|
|
48011
|
+
import { join as join27 } from "path";
|
|
47939
48012
|
async function writeImageFiles(files, directory) {
|
|
47940
|
-
const rootfs =
|
|
48013
|
+
const rootfs = join27(directory, "rootfs.ext4");
|
|
47941
48014
|
writeFileSync6(rootfs, "");
|
|
47942
48015
|
await writeChangedBlocks(files.rootfsPath, rootfs);
|
|
47943
|
-
await copyFile(files.configPath,
|
|
48016
|
+
await copyFile(files.configPath, join27(directory, "config.json"));
|
|
47944
48017
|
}
|
|
47945
48018
|
|
|
47946
48019
|
// packages/daemon/src/create-impd-moves.ts
|
|
@@ -47980,7 +48053,7 @@ function createImpdMoves(config, deps, parts, hooks) {
|
|
|
47980
48053
|
|
|
47981
48054
|
// packages/daemon/src/imps/images/template-service.ts
|
|
47982
48055
|
import { copyFileSync as copyFileSync3, existsSync as existsSync17, statSync as statSync11, writeFileSync as writeFileSync7 } from "fs";
|
|
47983
|
-
import { join as
|
|
48056
|
+
import { join as join28 } from "path";
|
|
47984
48057
|
|
|
47985
48058
|
// packages/daemon/src/imps/images/read-held-image.ts
|
|
47986
48059
|
async function readHeldImage(db, name, at) {
|
|
@@ -48268,7 +48341,7 @@ function createTemplateService(deps) {
|
|
|
48268
48341
|
});
|
|
48269
48342
|
const writeConfig = async (imageId, directory) => {
|
|
48270
48343
|
const image = await readImageById(deps.db, imageId);
|
|
48271
|
-
const target =
|
|
48344
|
+
const target = join28(directory, "config.json");
|
|
48272
48345
|
const config = image === undefined ? undefined : buildImagePaths(deps.config.dataDir, image.digest).config;
|
|
48273
48346
|
if (config !== undefined && existsSync17(config)) {
|
|
48274
48347
|
copyFileSync3(config, target);
|
|
@@ -48656,7 +48729,7 @@ function createImpdServices(config, deps, parts) {
|
|
|
48656
48729
|
|
|
48657
48730
|
// packages/daemon/src/imps/images/build/create-image-builds.ts
|
|
48658
48731
|
import { existsSync as existsSync19, mkdirSync as mkdirSync20, rmSync as rmSync25, statSync as statSync12 } from "fs";
|
|
48659
|
-
import { join as
|
|
48732
|
+
import { join as join30, posix as posix3 } from "path";
|
|
48660
48733
|
|
|
48661
48734
|
// packages/local-tar/src/extract-local.ts
|
|
48662
48735
|
import tar from "tar-stream";
|
|
@@ -48664,7 +48737,7 @@ import * as z83 from "zod";
|
|
|
48664
48737
|
// packages/local-tar/src/pack-build-context.ts
|
|
48665
48738
|
import { existsSync as existsSync18 } from "fs";
|
|
48666
48739
|
import { lstat, readFile as readFile4, readdir } from "fs/promises";
|
|
48667
|
-
import { join as
|
|
48740
|
+
import { join as join29, posix as posix2 } from "path";
|
|
48668
48741
|
import ignore from "@balena/dockerignore";
|
|
48669
48742
|
|
|
48670
48743
|
// packages/local-tar/src/write-build-context.ts
|
|
@@ -48948,7 +49021,7 @@ class MissingDockerfileError extends Error {
|
|
|
48948
49021
|
name = "MissingDockerfileError";
|
|
48949
49022
|
}
|
|
48950
49023
|
function listContextEntries(root, dockerfile) {
|
|
48951
|
-
const found = listDockerfileCandidates(posix2.normalize(dockerfile)).find((candidate) => existsSync18(
|
|
49024
|
+
const found = listDockerfileCandidates(posix2.normalize(dockerfile)).find((candidate) => existsSync18(join29(root, candidate)));
|
|
48952
49025
|
if (found === undefined) {
|
|
48953
49026
|
return Promise.reject(new MissingDockerfileError(`there is no ${dockerfile} in ${root}`));
|
|
48954
49027
|
}
|
|
@@ -48960,8 +49033,8 @@ var ENTRY_KINDS = [
|
|
|
48960
49033
|
["file", "isFile"]
|
|
48961
49034
|
];
|
|
48962
49035
|
async function listEntries(root, dockerfile) {
|
|
48963
|
-
const ignoreName = existsSync18(
|
|
48964
|
-
const patterns = existsSync18(
|
|
49036
|
+
const ignoreName = existsSync18(join29(root, `${dockerfile}.dockerignore`)) ? `${dockerfile}.dockerignore` : ".dockerignore";
|
|
49037
|
+
const patterns = existsSync18(join29(root, ignoreName)) ? await readFile4(join29(root, ignoreName), "utf8") : "";
|
|
48965
49038
|
const matcher = ignore().add(patterns);
|
|
48966
49039
|
const hasExceptions = patterns.split(`
|
|
48967
49040
|
`).some((line) => line.trim().startsWith("!"));
|
|
@@ -48971,7 +49044,7 @@ async function listEntries(root, dockerfile) {
|
|
|
48971
49044
|
const entries = [];
|
|
48972
49045
|
const children = await readdir(directory);
|
|
48973
49046
|
for (const child of children.toSorted()) {
|
|
48974
|
-
const path =
|
|
49047
|
+
const path = join29(directory, child);
|
|
48975
49048
|
const name = prefix === "" ? child : `${prefix}/${child}`;
|
|
48976
49049
|
const stats = await lstat(path);
|
|
48977
49050
|
const ignored = matcher.ignores(name) && name !== dockerfileName;
|
|
@@ -50026,7 +50099,7 @@ function planRootfsOverhead(treeBytes) {
|
|
|
50026
50099
|
}
|
|
50027
50100
|
|
|
50028
50101
|
// packages/daemon/src/imps/images/rootfs/unpack-export.ts
|
|
50029
|
-
import { readFileSync as
|
|
50102
|
+
import { readFileSync as readFileSync25 } from "fs";
|
|
50030
50103
|
var CAP_SETFCAP_BIT = 31n;
|
|
50031
50104
|
var SETFCAP_HELP = "imp-host needs CAP_SETFCAP (docs/architecture/host.md#privileges)";
|
|
50032
50105
|
var UNPACK_TAR_ARGS = [
|
|
@@ -50068,7 +50141,7 @@ function findXattrFailure(stderr) {
|
|
|
50068
50141
|
});
|
|
50069
50142
|
return failures.find((failure) => failure.missingSetfcap) ?? failures[0] ?? null;
|
|
50070
50143
|
}
|
|
50071
|
-
function readSetfcapWarning(status =
|
|
50144
|
+
function readSetfcapWarning(status = readFileSync25("/proc/self/status", "utf8")) {
|
|
50072
50145
|
const effective = /^CapEff:\s*(?<mask>[0-9a-f]+)$/mu.exec(status)?.groups?.["mask"] ?? "0";
|
|
50073
50146
|
if (BigInt(`0x${effective}`) >> CAP_SETFCAP_BIT & 1n) {
|
|
50074
50147
|
return null;
|
|
@@ -50492,7 +50565,7 @@ function createImageBuilds(deps, writer) {
|
|
|
50492
50565
|
});
|
|
50493
50566
|
}
|
|
50494
50567
|
const uploadsDir = buildUploadsDir(deps.config.dataDir);
|
|
50495
|
-
const tarPath =
|
|
50568
|
+
const tarPath = join30(uploadsDir, `${Bun.randomUUIDv7()}.tar`);
|
|
50496
50569
|
mkdirSync20(uploadsDir, { recursive: true, mode: 448 });
|
|
50497
50570
|
return deps.diskBudget.withRoom(tarBytes, async () => {
|
|
50498
50571
|
try {
|
|
@@ -50649,7 +50722,7 @@ function buildImageRuntimeConfig(ociConfig) {
|
|
|
50649
50722
|
|
|
50650
50723
|
// packages/daemon/src/imps/images/rootfs/create-image-writer.ts
|
|
50651
50724
|
import { existsSync as existsSync20, mkdirSync as mkdirSync22, rmSync as rmSync27, statSync as statSync13, writeFileSync as writeFileSync8 } from "fs";
|
|
50652
|
-
import { join as
|
|
50725
|
+
import { join as join32 } from "path";
|
|
50653
50726
|
|
|
50654
50727
|
// packages/daemon/src/imps/images/rootfs/read-oci-config.ts
|
|
50655
50728
|
import * as z88 from "zod";
|
|
@@ -50669,13 +50742,13 @@ async function readOciConfig(ref, signal, run) {
|
|
|
50669
50742
|
|
|
50670
50743
|
// packages/daemon/src/imps/images/rootfs/write-image-config.ts
|
|
50671
50744
|
import { closeSync as closeSync11, constants as constants6, lstatSync as lstatSync5, mkdirSync as mkdirSync21, openSync as openSync9, rmSync as rmSync26, writeSync as writeSync3 } from "fs";
|
|
50672
|
-
import { join as
|
|
50745
|
+
import { join as join31 } from "path";
|
|
50673
50746
|
function writeImageConfig(root, contents) {
|
|
50674
|
-
const etc =
|
|
50675
|
-
const directory =
|
|
50747
|
+
const etc = join31(root, "etc");
|
|
50748
|
+
const directory = join31(etc, "imp");
|
|
50676
50749
|
createDirectory(etc, "/etc");
|
|
50677
50750
|
createDirectory(directory, "/etc/imp");
|
|
50678
|
-
const file =
|
|
50751
|
+
const file = join31(directory, "image.json");
|
|
50679
50752
|
rmSync26(file, { recursive: true, force: true });
|
|
50680
50753
|
const fd = openSync9(file, constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW, 420);
|
|
50681
50754
|
try {
|
|
@@ -50722,8 +50795,8 @@ function createImageWriter(deps) {
|
|
|
50722
50795
|
const guestRootfsLock = buildKeyedMutex();
|
|
50723
50796
|
const makeWorkDir = () => {
|
|
50724
50797
|
const images = buildImagesDir(deps.config.dataDir);
|
|
50725
|
-
const work =
|
|
50726
|
-
const root =
|
|
50798
|
+
const work = join32(images, `.build-${Bun.randomUUIDv7()}`);
|
|
50799
|
+
const root = join32(work, "root");
|
|
50727
50800
|
mkdirSync22(images, { recursive: true });
|
|
50728
50801
|
mkdirSync22(work, { mode: 448 });
|
|
50729
50802
|
mkdirSync22(root, { mode: 493 });
|
|
@@ -50734,7 +50807,7 @@ function createImageWriter(deps) {
|
|
|
50734
50807
|
const usage = await readTreeUsage(root);
|
|
50735
50808
|
const plan = planRootfs(usage);
|
|
50736
50809
|
await deps.storage.createImage(digest, async (directory) => {
|
|
50737
|
-
const image =
|
|
50810
|
+
const image = join32(directory, "rootfs.ext4");
|
|
50738
50811
|
await runChecked(["truncate", "-s", String(plan.bytes), image]);
|
|
50739
50812
|
await runChecked([
|
|
50740
50813
|
"mkfs.ext4",
|
|
@@ -50747,7 +50820,7 @@ function createImageWriter(deps) {
|
|
|
50747
50820
|
root,
|
|
50748
50821
|
image
|
|
50749
50822
|
]);
|
|
50750
|
-
writeFileSync8(
|
|
50823
|
+
writeFileSync8(join32(directory, "config.json"), JSON.stringify(ociConfig ?? {}, null, 2));
|
|
50751
50824
|
});
|
|
50752
50825
|
return readDiskUsage(buildImagePaths(deps.config.dataDir, digest).rootfs);
|
|
50753
50826
|
};
|
|
@@ -51298,7 +51371,7 @@ async function runStreamed(argv, onStdout, signal) {
|
|
|
51298
51371
|
|
|
51299
51372
|
// packages/daemon/src/vm/storage/count-tree-bytes.ts
|
|
51300
51373
|
import { lstat as lstat3, readdir as readdir3 } from "fs/promises";
|
|
51301
|
-
import { join as
|
|
51374
|
+
import { join as join33 } from "path";
|
|
51302
51375
|
async function countTreeBytes(root, deps = {}) {
|
|
51303
51376
|
const readDir = deps.readDir ?? readDirEntries;
|
|
51304
51377
|
const inodes = new Map;
|
|
@@ -51307,11 +51380,11 @@ async function countTreeBytes(root, deps = {}) {
|
|
|
51307
51380
|
const entries = await readEntries2(readDir, directory);
|
|
51308
51381
|
for (const entry of entries) {
|
|
51309
51382
|
if (entry.isDirectory()) {
|
|
51310
|
-
dirs.push(
|
|
51383
|
+
dirs.push(join33(directory, entry.name));
|
|
51311
51384
|
}
|
|
51312
51385
|
}
|
|
51313
51386
|
const files = entries.filter((entry) => entry.isFile());
|
|
51314
|
-
const stats = await Promise.all(files.map((entry) => readFileStats(
|
|
51387
|
+
const stats = await Promise.all(files.map((entry) => readFileStats(join33(directory, entry.name))));
|
|
51315
51388
|
for (const stat of stats) {
|
|
51316
51389
|
if (stat !== undefined) {
|
|
51317
51390
|
inodes.set(`${String(stat.dev)}:${String(stat.ino)}`, Math.max(0, stat.blocks - 1) * 512);
|
|
@@ -51554,12 +51627,12 @@ function createTailnetAccess(config, deps, readStatus) {
|
|
|
51554
51627
|
}
|
|
51555
51628
|
|
|
51556
51629
|
// packages/daemon/src/identity/token.ts
|
|
51557
|
-
import { existsSync as existsSync21, readFileSync as
|
|
51558
|
-
import { join as
|
|
51630
|
+
import { existsSync as existsSync21, readFileSync as readFileSync26, writeFileSync as writeFileSync9 } from "fs";
|
|
51631
|
+
import { join as join34 } from "path";
|
|
51559
51632
|
function loadOrCreateToken(dataDir) {
|
|
51560
|
-
const path =
|
|
51633
|
+
const path = join34(dataDir, "token");
|
|
51561
51634
|
if (existsSync21(path)) {
|
|
51562
|
-
return
|
|
51635
|
+
return readFileSync26(path, "utf8").trim();
|
|
51563
51636
|
}
|
|
51564
51637
|
const token = mintSecret();
|
|
51565
51638
|
writeFileSync9(path, `${token}
|
|
@@ -51681,13 +51754,13 @@ import { basename as basename4 } from "path";
|
|
|
51681
51754
|
|
|
51682
51755
|
// packages/daemon/src/vm/storage/remove-unused-system-drives.ts
|
|
51683
51756
|
import { readdirSync as readdirSync9, rmSync as rmSync28 } from "fs";
|
|
51684
|
-
import { join as
|
|
51757
|
+
import { join as join35 } from "path";
|
|
51685
51758
|
function removeUnusedSystemDrives(dataDir, keep) {
|
|
51686
51759
|
const directory = buildSystemDrivesDir(dataDir);
|
|
51687
51760
|
const removed = [];
|
|
51688
51761
|
for (const name of readNames(directory)) {
|
|
51689
51762
|
if (!keep.has(name)) {
|
|
51690
|
-
rmSync28(
|
|
51763
|
+
rmSync28(join35(directory, name), { force: true });
|
|
51691
51764
|
removed.push(name);
|
|
51692
51765
|
}
|
|
51693
51766
|
}
|
|
@@ -52896,13 +52969,13 @@ function createPublicRecordsLink() {
|
|
|
52896
52969
|
|
|
52897
52970
|
// packages/daemon/src/network/tailnet-names/host-id.ts
|
|
52898
52971
|
import { randomBytes as randomBytes11 } from "crypto";
|
|
52899
|
-
import { existsSync as existsSync22, mkdirSync as mkdirSync23, readFileSync as
|
|
52900
|
-
import { join as
|
|
52972
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync23, readFileSync as readFileSync27, writeFileSync as writeFileSync10 } from "fs";
|
|
52973
|
+
import { join as join36 } from "path";
|
|
52901
52974
|
function loadOrCreateHostId(dataDir) {
|
|
52902
|
-
const directory =
|
|
52903
|
-
const path =
|
|
52975
|
+
const directory = join36(dataDir, "tailnet-names");
|
|
52976
|
+
const path = join36(directory, "host-id");
|
|
52904
52977
|
if (existsSync22(path)) {
|
|
52905
|
-
return
|
|
52978
|
+
return readFileSync27(path, "utf8").trim();
|
|
52906
52979
|
}
|
|
52907
52980
|
mkdirSync23(directory, { recursive: true });
|
|
52908
52981
|
const id = randomBytes11(16).toString("hex");
|
|
@@ -52912,7 +52985,7 @@ function loadOrCreateHostId(dataDir) {
|
|
|
52912
52985
|
}
|
|
52913
52986
|
|
|
52914
52987
|
// packages/daemon/src/network/tailnet-names/oauth-credential.ts
|
|
52915
|
-
import { readFileSync as
|
|
52988
|
+
import { readFileSync as readFileSync28, statSync as statSync14 } from "fs";
|
|
52916
52989
|
import * as z92 from "zod";
|
|
52917
52990
|
var CredentialSchema = z92.object({ clientId: z92.string().min(1), clientSecret: z92.string().min(1) });
|
|
52918
52991
|
function readOAuthCredential(path) {
|
|
@@ -52928,7 +53001,7 @@ function readOAuthCredential(path) {
|
|
|
52928
53001
|
}
|
|
52929
53002
|
function readJson(path) {
|
|
52930
53003
|
try {
|
|
52931
|
-
return JSON.parse(
|
|
53004
|
+
return JSON.parse(readFileSync28(path, "utf8"));
|
|
52932
53005
|
} catch {
|
|
52933
53006
|
return null;
|
|
52934
53007
|
}
|
|
@@ -53325,7 +53398,7 @@ async function startOtlpExport(env, version) {
|
|
|
53325
53398
|
}
|
|
53326
53399
|
|
|
53327
53400
|
// packages/daemon/src/network/https/wire-https-service.ts
|
|
53328
|
-
import { readFileSync as
|
|
53401
|
+
import { readFileSync as readFileSync30 } from "fs";
|
|
53329
53402
|
|
|
53330
53403
|
// packages/daemon/src/platform/db/exposure.ts
|
|
53331
53404
|
async function readPublicImp(db, name) {
|
|
@@ -53520,8 +53593,8 @@ function formatAcmeError(error) {
|
|
|
53520
53593
|
}
|
|
53521
53594
|
|
|
53522
53595
|
// packages/daemon/src/network/https/acme/cert-store.ts
|
|
53523
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync24, readFileSync as
|
|
53524
|
-
import { join as
|
|
53596
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync24, readFileSync as readFileSync29, rmSync as rmSync29 } from "fs";
|
|
53597
|
+
import { join as join37 } from "path";
|
|
53525
53598
|
import * as z95 from "zod";
|
|
53526
53599
|
var AttemptStateSchema = z95.object({
|
|
53527
53600
|
failures: z95.int().nonnegative(),
|
|
@@ -53532,11 +53605,11 @@ var AccountSchema = z95.object({ directoryUrl: z95.string(), url: z95.string(),
|
|
|
53532
53605
|
var LegacyAccountSchema = z95.object({ directoryUrl: z95.string(), url: z95.string() });
|
|
53533
53606
|
var NO_ATTEMPTS = { failures: 0, lastAttemptAt: null, lastError: null };
|
|
53534
53607
|
function createCertStore(dataDir) {
|
|
53535
|
-
const directory =
|
|
53536
|
-
const certificatePath =
|
|
53537
|
-
const attemptsPath =
|
|
53538
|
-
const accountPath =
|
|
53539
|
-
const legacyKeyPath =
|
|
53608
|
+
const directory = join37(dataDir, "tls");
|
|
53609
|
+
const certificatePath = join37(directory, "certificate.pem");
|
|
53610
|
+
const attemptsPath = join37(directory, "attempts.json");
|
|
53611
|
+
const accountPath = join37(directory, "account.json");
|
|
53612
|
+
const legacyKeyPath = join37(directory, "account.key");
|
|
53540
53613
|
const warned = { account: false };
|
|
53541
53614
|
const write = (path, content) => {
|
|
53542
53615
|
mkdirSync24(directory, { recursive: true, mode: 448 });
|
|
@@ -53602,7 +53675,7 @@ ${certificate.chainPem.trimEnd()}
|
|
|
53602
53675
|
};
|
|
53603
53676
|
}
|
|
53604
53677
|
function readIfExists(path) {
|
|
53605
|
-
return existsSync23(path) ?
|
|
53678
|
+
return existsSync23(path) ? readFileSync29(path, "utf8") : null;
|
|
53606
53679
|
}
|
|
53607
53680
|
function parseJson(text) {
|
|
53608
53681
|
try {
|
|
@@ -54408,7 +54481,7 @@ function wireHttpsService(options) {
|
|
|
54408
54481
|
const issue = createAcmeIssuer({
|
|
54409
54482
|
directoryUrl: config.acmeDirectory,
|
|
54410
54483
|
email: config.acmeEmail,
|
|
54411
|
-
caPem: config.acmeCaFile === null ? null :
|
|
54484
|
+
caPem: config.acmeCaFile === null ? null : readFileSync30(config.acmeCaFile, "utf8"),
|
|
54412
54485
|
store,
|
|
54413
54486
|
dns
|
|
54414
54487
|
});
|
|
@@ -54995,17 +55068,17 @@ function buildTooMany() {
|
|
|
54995
55068
|
|
|
54996
55069
|
// packages/daemon/src/surface/ssh/host-key.ts
|
|
54997
55070
|
var import_ssh22 = __toESM(require_lib2(), 1);
|
|
54998
|
-
import { existsSync as existsSync24, mkdirSync as mkdirSync25, readFileSync as
|
|
54999
|
-
import { join as
|
|
55071
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync25, readFileSync as readFileSync31, writeFileSync as writeFileSync11 } from "fs";
|
|
55072
|
+
import { join as join38 } from "path";
|
|
55000
55073
|
function setupSshDir(dataDir) {
|
|
55001
|
-
const directory =
|
|
55074
|
+
const directory = join38(dataDir, "ssh");
|
|
55002
55075
|
mkdirSync25(directory, { recursive: true, mode: 448 });
|
|
55003
55076
|
return directory;
|
|
55004
55077
|
}
|
|
55005
55078
|
function loadOrCreateHostKey(sshDir) {
|
|
55006
|
-
const path =
|
|
55079
|
+
const path = join38(sshDir, "host_key");
|
|
55007
55080
|
if (existsSync24(path)) {
|
|
55008
|
-
return
|
|
55081
|
+
return readFileSync31(path, "utf8");
|
|
55009
55082
|
}
|
|
55010
55083
|
const pair = generateEd25519Key();
|
|
55011
55084
|
writeFileSync11(path, pair.private, { mode: 384, flag: "wx" });
|
|
@@ -56170,8 +56243,8 @@ async function stopImpd(parts, options) {
|
|
|
56170
56243
|
}
|
|
56171
56244
|
|
|
56172
56245
|
// packages/daemon/src/vm/storage/create-storage-backend.ts
|
|
56173
|
-
import { existsSync as existsSync31, readFileSync as
|
|
56174
|
-
import { join as
|
|
56246
|
+
import { existsSync as existsSync31, readFileSync as readFileSync35, readdirSync as readdirSync14, writeFileSync as writeFileSync14 } from "fs";
|
|
56247
|
+
import { join as join47 } from "path";
|
|
56175
56248
|
|
|
56176
56249
|
// packages/daemon/src/vm/storage/xfs-backend.ts
|
|
56177
56250
|
import {
|
|
@@ -56184,7 +56257,7 @@ import {
|
|
|
56184
56257
|
statfsSync as statfsSync2,
|
|
56185
56258
|
writeFileSync as writeFileSync12
|
|
56186
56259
|
} from "fs";
|
|
56187
|
-
import { basename as basename6, dirname as dirname13, join as
|
|
56260
|
+
import { basename as basename6, dirname as dirname13, join as join42 } from "path";
|
|
56188
56261
|
|
|
56189
56262
|
// packages/daemon/src/vm/storage/count-owner-bytes.ts
|
|
56190
56263
|
function countOwnerBytes(files) {
|
|
@@ -56241,13 +56314,13 @@ import {
|
|
|
56241
56314
|
copyFileSync as copyFileSync4,
|
|
56242
56315
|
existsSync as existsSync25,
|
|
56243
56316
|
mkdirSync as mkdirSync26,
|
|
56244
|
-
readFileSync as
|
|
56317
|
+
readFileSync as readFileSync32,
|
|
56245
56318
|
readdirSync as readdirSync10,
|
|
56246
56319
|
renameSync as renameSync6,
|
|
56247
56320
|
rmSync as rmSync30,
|
|
56248
56321
|
statSync as statSync15
|
|
56249
56322
|
} from "fs";
|
|
56250
|
-
import { basename as basename5, dirname as dirname11, join as
|
|
56323
|
+
import { basename as basename5, dirname as dirname11, join as join39 } from "path";
|
|
56251
56324
|
import * as z97 from "zod";
|
|
56252
56325
|
var CopiesSchema = z97.record(z97.string(), z97.object({ ino: z97.string(), ctimeNs: z97.string(), size: z97.string() }));
|
|
56253
56326
|
function createXfsBackups(ctx) {
|
|
@@ -56255,7 +56328,7 @@ function createXfsBackups(ctx) {
|
|
|
56255
56328
|
const freshCopies = new Set;
|
|
56256
56329
|
const readCopies = () => {
|
|
56257
56330
|
try {
|
|
56258
|
-
return CopiesSchema.parse(JSON.parse(
|
|
56331
|
+
return CopiesSchema.parse(JSON.parse(readFileSync32(backup.copies, "utf8")));
|
|
56259
56332
|
} catch {
|
|
56260
56333
|
return {};
|
|
56261
56334
|
}
|
|
@@ -56278,7 +56351,7 @@ function createXfsBackups(ctx) {
|
|
|
56278
56351
|
return {
|
|
56279
56352
|
createBackupCopy: async (impId, _runId, options) => {
|
|
56280
56353
|
const source = ctx.resolveImpPaths(impId).disk;
|
|
56281
|
-
const target =
|
|
56354
|
+
const target = join39(backup.tree, BACKUP_TREE.buildDisk(impId));
|
|
56282
56355
|
const stats = statSync15(source, { bigint: true });
|
|
56283
56356
|
const record = {
|
|
56284
56357
|
ino: String(stats.ino),
|
|
@@ -56306,34 +56379,34 @@ function createXfsBackups(ctx) {
|
|
|
56306
56379
|
const checkpointIds = new Set;
|
|
56307
56380
|
const imageDigests = new Set;
|
|
56308
56381
|
for (const imp of request.imps) {
|
|
56309
|
-
if (!existsSync25(
|
|
56382
|
+
if (!existsSync25(join39(backup.tree, BACKUP_TREE.buildDisk(imp.impId)))) {
|
|
56310
56383
|
continue;
|
|
56311
56384
|
}
|
|
56312
56385
|
impIds.add(imp.impId);
|
|
56313
56386
|
for (const checkpointId of imp.checkpointIds) {
|
|
56314
|
-
const isCopied = await createTreeClone(ctx.buildCheckpointDisk(imp.impId, checkpointId),
|
|
56387
|
+
const isCopied = await createTreeClone(ctx.buildCheckpointDisk(imp.impId, checkpointId), join39(backup.tree, BACKUP_TREE.buildCheckpointDisk(imp.impId, checkpointId)));
|
|
56315
56388
|
if (isCopied) {
|
|
56316
56389
|
checkpointIds.add(checkpointId);
|
|
56317
56390
|
}
|
|
56318
56391
|
}
|
|
56319
|
-
removeUnlisted(
|
|
56392
|
+
removeUnlisted(join39(backup.tree, BACKUP_TREE.buildImpDir(imp.impId), "checkpoints"), new Set(imp.checkpointIds.filter((id) => checkpointIds.has(id))));
|
|
56320
56393
|
}
|
|
56321
56394
|
for (const digest of request.imageDigests) {
|
|
56322
56395
|
const source = buildImagePaths(ctx.dataDir, digest);
|
|
56323
|
-
const directory =
|
|
56324
|
-
const isCopied = await createTreeClone(source.rootfs,
|
|
56396
|
+
const directory = join39(backup.tree, BACKUP_TREE.buildImageDir(digest));
|
|
56397
|
+
const isCopied = await createTreeClone(source.rootfs, join39(directory, "rootfs.ext4"));
|
|
56325
56398
|
if (isCopied) {
|
|
56326
|
-
copyFileSync4(source.config,
|
|
56399
|
+
copyFileSync4(source.config, join39(directory, "config.json"));
|
|
56327
56400
|
imageDigests.add(digest);
|
|
56328
56401
|
}
|
|
56329
56402
|
}
|
|
56330
|
-
removeUnlisted(
|
|
56331
|
-
removeUnlisted(
|
|
56403
|
+
removeUnlisted(join39(backup.tree, "imps"), impIds);
|
|
56404
|
+
removeUnlisted(join39(backup.tree, "images"), new Set([...imageDigests].map((digest) => basename5(BACKUP_TREE.buildImageDir(digest)))));
|
|
56332
56405
|
const copies = readCopies();
|
|
56333
56406
|
writeCopies(Object.fromEntries(Object.entries(copies).filter(([id]) => impIds.has(id))));
|
|
56334
56407
|
const removeFreshCopies = () => {
|
|
56335
56408
|
for (const impId of freshCopies) {
|
|
56336
|
-
rmSync30(
|
|
56409
|
+
rmSync30(join39(backup.tree, BACKUP_TREE.buildDisk(impId)), { force: true });
|
|
56337
56410
|
}
|
|
56338
56411
|
freshCopies.clear();
|
|
56339
56412
|
return Promise.resolve();
|
|
@@ -56345,18 +56418,18 @@ function createXfsBackups(ctx) {
|
|
|
56345
56418
|
function removeUnlisted(directory, keep) {
|
|
56346
56419
|
const names = existsSync25(directory) ? readdirSync10(directory) : [];
|
|
56347
56420
|
for (const name of names.filter((entry) => !keep.has(entry))) {
|
|
56348
|
-
rmSync30(
|
|
56421
|
+
rmSync30(join39(directory, name), { recursive: true, force: true });
|
|
56349
56422
|
}
|
|
56350
56423
|
}
|
|
56351
56424
|
|
|
56352
56425
|
// packages/daemon/src/vm/storage/loop-backing-file.ts
|
|
56353
|
-
import { readFileSync as
|
|
56354
|
-
import { dirname as dirname12, join as
|
|
56426
|
+
import { readFileSync as readFileSync33, realpathSync, statfsSync } from "fs";
|
|
56427
|
+
import { dirname as dirname12, join as join40 } from "path";
|
|
56355
56428
|
var HOST_DIRS = { procDir: "/proc", sysDir: "/sys" };
|
|
56356
56429
|
function readLoopBackingFile(directory, hostDirs = HOST_DIRS) {
|
|
56357
56430
|
try {
|
|
56358
56431
|
const target = realpathSync(directory);
|
|
56359
|
-
const mountInfo =
|
|
56432
|
+
const mountInfo = readFileSync33(join40(hostDirs.procDir, "self", "mountinfo"), "utf8");
|
|
56360
56433
|
for (const line of mountInfo.split(`
|
|
56361
56434
|
`)) {
|
|
56362
56435
|
const [mounts = "", fields = ""] = line.split(" - ");
|
|
@@ -56364,8 +56437,8 @@ function readLoopBackingFile(directory, hostDirs = HOST_DIRS) {
|
|
|
56364
56437
|
const [, source = ""] = fields.split(" ");
|
|
56365
56438
|
const loop = /^\/dev\/(?<name>loop\d+)$/u.exec(source)?.groups?.["name"];
|
|
56366
56439
|
if (mountPoint === target && loop !== undefined) {
|
|
56367
|
-
const backing =
|
|
56368
|
-
return
|
|
56440
|
+
const backing = join40(hostDirs.sysDir, "block", loop, "loop", "backing_file");
|
|
56441
|
+
return readFileSync33(backing, "utf8").trim();
|
|
56369
56442
|
}
|
|
56370
56443
|
}
|
|
56371
56444
|
} catch {}
|
|
@@ -56386,7 +56459,7 @@ function readLoopHostFreeBytes(directory, hostDirs = HOST_DIRS) {
|
|
|
56386
56459
|
|
|
56387
56460
|
// packages/daemon/src/vm/storage/orphan-files.ts
|
|
56388
56461
|
import { existsSync as existsSync26, readdirSync as readdirSync11, statSync as statSync16 } from "fs";
|
|
56389
|
-
import { join as
|
|
56462
|
+
import { join as join41 } from "path";
|
|
56390
56463
|
function probeHoldingFiles(directory) {
|
|
56391
56464
|
return existsSync26(directory) && readdirSync11(directory, { recursive: true, withFileTypes: true }).some((entry) => !entry.isDirectory());
|
|
56392
56465
|
}
|
|
@@ -56394,7 +56467,7 @@ function listFilesUnder(directory) {
|
|
|
56394
56467
|
if (!existsSync26(directory)) {
|
|
56395
56468
|
return [];
|
|
56396
56469
|
}
|
|
56397
|
-
return readdirSync11(directory, { recursive: true, withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) =>
|
|
56470
|
+
return readdirSync11(directory, { recursive: true, withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => join41(entry.parentPath, entry.name));
|
|
56398
56471
|
}
|
|
56399
56472
|
function readDirectoryOrphan(kind, id, directory, snapshots) {
|
|
56400
56473
|
const birth = statSync16(directory).birthtimeMs;
|
|
@@ -56420,7 +56493,7 @@ function createXfsBackend(deps) {
|
|
|
56420
56493
|
const cloneFile = deps.cloneFile ?? createReflinkClone;
|
|
56421
56494
|
const readFileExtents = deps.readFileExtents ?? readExtents;
|
|
56422
56495
|
const resolveImpPaths = (impId) => buildImpPaths(deps.dataDir, impId);
|
|
56423
|
-
const buildCheckpointDisk = (impId, checkpointId) =>
|
|
56496
|
+
const buildCheckpointDisk = (impId, checkpointId) => join42(resolveImpPaths(impId).checkpointsDir, checkpointId, "disk.ext4");
|
|
56424
56497
|
const getSourceFile = (source) => {
|
|
56425
56498
|
if (source.kind === "image") {
|
|
56426
56499
|
return buildImagePaths(deps.dataDir, source.digest).rootfs;
|
|
@@ -56435,7 +56508,7 @@ function createXfsBackend(deps) {
|
|
|
56435
56508
|
};
|
|
56436
56509
|
const createImage = async (digest, write) => {
|
|
56437
56510
|
const paths = buildImagePaths(deps.dataDir, digest);
|
|
56438
|
-
const staged =
|
|
56511
|
+
const staged = join42(buildImagesDir(deps.dataDir), `${STAGING_PREFIX}${Bun.randomUUIDv7()}`);
|
|
56439
56512
|
mkdirSync27(staged, { recursive: true });
|
|
56440
56513
|
try {
|
|
56441
56514
|
await write(staged);
|
|
@@ -56456,13 +56529,13 @@ function createXfsBackend(deps) {
|
|
|
56456
56529
|
return listEntries2(directory).map((id) => ({
|
|
56457
56530
|
kind: "checkpoint",
|
|
56458
56531
|
id,
|
|
56459
|
-
directory:
|
|
56532
|
+
directory: join42(directory, id)
|
|
56460
56533
|
}));
|
|
56461
56534
|
}).filter((checkpoint) => !live.checkpointIds.has(checkpoint.id));
|
|
56462
56535
|
const unknownImages = listEntries2(buildImagesDir(deps.dataDir)).filter((name) => !name.startsWith(".") && !liveDigests.has(name)).map((name) => ({
|
|
56463
56536
|
kind: "image",
|
|
56464
56537
|
id: name,
|
|
56465
|
-
directory:
|
|
56538
|
+
directory: join42(buildImagesDir(deps.dataDir), name)
|
|
56466
56539
|
}));
|
|
56467
56540
|
const unknownImps = impIds.filter((impId) => !live.impIds.has(impId)).map((impId) => ({
|
|
56468
56541
|
kind: "imp",
|
|
@@ -56482,14 +56555,14 @@ function createXfsBackend(deps) {
|
|
|
56482
56555
|
};
|
|
56483
56556
|
const removeLeftover = (dropped, live) => {
|
|
56484
56557
|
if (dropped.kind === "image") {
|
|
56485
|
-
rmSync31(
|
|
56558
|
+
rmSync31(join42(buildImagesDir(deps.dataDir), dropped.id), { recursive: true, force: true });
|
|
56486
56559
|
}
|
|
56487
56560
|
if (dropped.kind === "imp") {
|
|
56488
56561
|
rmSync31(resolveImpPaths(dropped.id).directory, { recursive: true, force: true });
|
|
56489
56562
|
}
|
|
56490
56563
|
if (dropped.kind === "checkpoint") {
|
|
56491
56564
|
for (const impId of live.impIds) {
|
|
56492
|
-
rmSync31(
|
|
56565
|
+
rmSync31(join42(resolveImpPaths(impId).checkpointsDir, dropped.id), {
|
|
56493
56566
|
recursive: true,
|
|
56494
56567
|
force: true
|
|
56495
56568
|
});
|
|
@@ -56504,7 +56577,7 @@ function createXfsBackend(deps) {
|
|
|
56504
56577
|
const listOtherFiles = () => {
|
|
56505
56578
|
const images = listEntries2(buildImagesDir(deps.dataDir)).filter((name) => !name.startsWith(".")).map((name) => ({
|
|
56506
56579
|
owner: `image:${name}`,
|
|
56507
|
-
path:
|
|
56580
|
+
path: join42(buildImagesDir(deps.dataDir), name, "rootfs.ext4")
|
|
56508
56581
|
}));
|
|
56509
56582
|
const tree = listFilesUnder(backup.tree).map((path) => ({ owner: "backup", path }));
|
|
56510
56583
|
return [...images, ...tree].filter((file) => existsSync27(file.path));
|
|
@@ -56512,7 +56585,7 @@ function createXfsBackend(deps) {
|
|
|
56512
56585
|
const usageState = { resumeImpId: null };
|
|
56513
56586
|
const setupReserveFile = async () => {
|
|
56514
56587
|
const bytes = deps.reserveFileBytes ?? 0;
|
|
56515
|
-
const file =
|
|
56588
|
+
const file = join42(deps.dataDir, "reserve");
|
|
56516
56589
|
if (bytes === 0 || existsSync27(file)) {
|
|
56517
56590
|
return;
|
|
56518
56591
|
}
|
|
@@ -56542,7 +56615,7 @@ function createXfsBackend(deps) {
|
|
|
56542
56615
|
start: (live) => {
|
|
56543
56616
|
const imagesDir = buildImagesDir(deps.dataDir);
|
|
56544
56617
|
for (const name of listEntries2(imagesDir).filter((entry) => entry.startsWith("."))) {
|
|
56545
|
-
rmSync31(
|
|
56618
|
+
rmSync31(join42(imagesDir, name), { recursive: true, force: true });
|
|
56546
56619
|
}
|
|
56547
56620
|
const swept = removeUnnamed(live, { isDryRun: false, isOrphans: false });
|
|
56548
56621
|
printSweep(getImpdLogger("storage"), swept, "each");
|
|
@@ -56564,7 +56637,7 @@ function createXfsBackend(deps) {
|
|
|
56564
56637
|
receiveMoveSnapshots: () => Promise.reject(new Error("xfs: only a ZFS host receives ZFS streams")),
|
|
56565
56638
|
createImage,
|
|
56566
56639
|
createImageFromImp: (digest, impId, steps) => createImage(digest, async (directory) => {
|
|
56567
|
-
await steps.hold(() => cloneFile(resolveImpPaths(impId).disk,
|
|
56640
|
+
await steps.hold(() => cloneFile(resolveImpPaths(impId).disk, join42(directory, "rootfs.ext4")));
|
|
56568
56641
|
await steps.write(directory);
|
|
56569
56642
|
}),
|
|
56570
56643
|
removeImage: (digest) => {
|
|
@@ -56706,8 +56779,8 @@ function isSharedExtent(extent) {
|
|
|
56706
56779
|
}
|
|
56707
56780
|
|
|
56708
56781
|
// packages/daemon/src/vm/storage/zfs/zfs-backend.ts
|
|
56709
|
-
import { existsSync as existsSync30, mkdirSync as mkdirSync28, readFileSync as
|
|
56710
|
-
import { join as
|
|
56782
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync28, readFileSync as readFileSync34, rmdirSync as rmdirSync3, writeFileSync as writeFileSync13 } from "fs";
|
|
56783
|
+
import { join as join46 } from "path";
|
|
56711
56784
|
|
|
56712
56785
|
// packages/daemon/src/platform/process/run-stream.ts
|
|
56713
56786
|
function createStreamRunner() {
|
|
@@ -56996,7 +57069,7 @@ function formatUiomoveWarning(version) {
|
|
|
56996
57069
|
|
|
56997
57070
|
// packages/daemon/src/vm/storage/zfs/create-zfs-backups.ts
|
|
56998
57071
|
import { rmSync as rmSync32 } from "fs";
|
|
56999
|
-
import { dirname as dirname14, join as
|
|
57072
|
+
import { dirname as dirname14, join as join43 } from "path";
|
|
57000
57073
|
function createZfsBackups(ctx) {
|
|
57001
57074
|
return {
|
|
57002
57075
|
createBackupCopy: (impId, runId) => ctx.runSnapshot(() => ctx.zfs.snapshot(`${ctx.buildDiskName(impId)}@bk-${runId}-${impId}`)),
|
|
@@ -57023,7 +57096,7 @@ function createZfsBackups(ctx) {
|
|
|
57023
57096
|
ctx.startReclaim();
|
|
57024
57097
|
};
|
|
57025
57098
|
const createTreeClone = async (snapshot, name, relativeDir) => {
|
|
57026
|
-
const directory =
|
|
57099
|
+
const directory = join43(tree, relativeDir);
|
|
57027
57100
|
await ctx.zfs.clone(snapshot, name, { readonly: "on" });
|
|
57028
57101
|
clones.push({ name, directory });
|
|
57029
57102
|
await ctx.setupMount(name, directory, true);
|
|
@@ -57033,8 +57106,8 @@ function createZfsBackups(ctx) {
|
|
|
57033
57106
|
if (mounted !== undefined) {
|
|
57034
57107
|
throw new Error(`zfs: ${mounted} in the backup tree is still mounted`);
|
|
57035
57108
|
}
|
|
57036
|
-
rmSync32(
|
|
57037
|
-
rmSync32(
|
|
57109
|
+
rmSync32(join43(tree, "imps"), { recursive: true, force: true });
|
|
57110
|
+
rmSync32(join43(tree, "images"), { recursive: true, force: true });
|
|
57038
57111
|
const entries = await ctx.listAll();
|
|
57039
57112
|
for (const imp of request.imps) {
|
|
57040
57113
|
const copy = entries.find((entry) => entry.type === "snapshot" && entry.name.endsWith(`@bk-${request.runId}-${imp.impId}`));
|
|
@@ -57167,7 +57240,7 @@ function createZfsCheckpoints(ctx) {
|
|
|
57167
57240
|
}
|
|
57168
57241
|
|
|
57169
57242
|
// packages/daemon/src/vm/storage/zfs/create-zfs-moves.ts
|
|
57170
|
-
import { join as
|
|
57243
|
+
import { join as join44 } from "path";
|
|
57171
57244
|
function createZfsMoves(ctx) {
|
|
57172
57245
|
const openMoveFiles = async (snapshots, removeMoveSnapshot) => {
|
|
57173
57246
|
const moveId = Bun.randomUUIDv7();
|
|
@@ -57196,7 +57269,7 @@ function createZfsMoves(ctx) {
|
|
|
57196
57269
|
await removeClones();
|
|
57197
57270
|
throw error;
|
|
57198
57271
|
}
|
|
57199
|
-
const paths = clones.map((clone) =>
|
|
57272
|
+
const paths = clones.map((clone) => join44(clone.directory, ctx.rootfsFile));
|
|
57200
57273
|
return {
|
|
57201
57274
|
kind: "files",
|
|
57202
57275
|
checkpointPaths: paths.slice(0, -1),
|
|
@@ -57452,7 +57525,7 @@ function createZfsReclaim(ctx) {
|
|
|
57452
57525
|
|
|
57453
57526
|
// packages/daemon/src/vm/storage/zfs/create-zfs-sweep.ts
|
|
57454
57527
|
import { existsSync as existsSync28, readdirSync as readdirSync13, rmSync as rmSync33 } from "fs";
|
|
57455
|
-
import { join as
|
|
57528
|
+
import { join as join45 } from "path";
|
|
57456
57529
|
var FORK_SNAPSHOT = /@fork-[^@]+$/u;
|
|
57457
57530
|
var BACKUP_SNAPSHOT = /@bk-[^@]+$/u;
|
|
57458
57531
|
var MOVE_SNAPSHOT = /@mv-[^@]+$/u;
|
|
@@ -57477,10 +57550,10 @@ function createZfsSweep(ctx) {
|
|
|
57477
57550
|
const orphanCheckpoints = isOrphans ? [] : unmarked.filter((entry) => !isOnOrphan(entry) && isOrphanCheckpoint(entry));
|
|
57478
57551
|
const keptDisks = isOrphans ? [] : unknownDisks;
|
|
57479
57552
|
const keptImpIds = new Set(keptDisks.map((disk) => getChildId(disk.name, ctx.datasets.disks)));
|
|
57480
|
-
const listUnknownDirs = (kind, parent) => (existsSync28(parent) ? readdirSync13(parent).toSorted() : []).filter((id) => !live.impIds.has(id) && !keptImpIds.has(id)).map((id) => ({ kind, id, directory:
|
|
57553
|
+
const listUnknownDirs = (kind, parent) => (existsSync28(parent) ? readdirSync13(parent).toSorted() : []).filter((id) => !live.impIds.has(id) && !keptImpIds.has(id)).map((id) => ({ kind, id, directory: join45(parent, id) }));
|
|
57481
57554
|
const unknownDirs = [
|
|
57482
57555
|
...listUnknownDirs("imp", buildImpsDir(ctx.dataDir)),
|
|
57483
|
-
...listUnknownDirs("memory",
|
|
57556
|
+
...listUnknownDirs("memory", join45(ctx.dataDir, "mem"))
|
|
57484
57557
|
];
|
|
57485
57558
|
const probeDirDropped = (entry) => isOrphans || !probeHoldingFiles(entry.directory);
|
|
57486
57559
|
const droppedDirs = unknownDirs.filter((entry) => probeDirDropped(entry));
|
|
@@ -57569,7 +57642,7 @@ function createZfsSweep(ctx) {
|
|
|
57569
57642
|
}
|
|
57570
57643
|
}
|
|
57571
57644
|
for (const impId of plan.memDirs) {
|
|
57572
|
-
rmSync33(
|
|
57645
|
+
rmSync33(join45(ctx.dataDir, "mem", impId), { recursive: true, force: true });
|
|
57573
57646
|
}
|
|
57574
57647
|
return { dropped: toDropped(plan), kept };
|
|
57575
57648
|
};
|
|
@@ -57657,13 +57730,13 @@ function createZfsBackend(deps) {
|
|
|
57657
57730
|
const buildDiskName = (impId) => `${datasets.disks}/${impId}`;
|
|
57658
57731
|
const buildImageName = (digest) => `${datasets.images}/${toDigestHex(digest)}`;
|
|
57659
57732
|
const buildRestoreName = (impId) => `${datasets.staging}/restore-${impId}`;
|
|
57660
|
-
const buildDiskDir = (impId) =>
|
|
57733
|
+
const buildDiskDir = (impId) => join46(buildImpPaths(deps.dataDir, impId).directory, "disk");
|
|
57661
57734
|
const buildImageDir = (digest) => buildImagePaths(deps.dataDir, digest).directory;
|
|
57662
|
-
const buildStagingDir = (name) =>
|
|
57735
|
+
const buildStagingDir = (name) => join46(deps.dataDir, "staging", name.slice(datasets.staging.length + 1));
|
|
57663
57736
|
const resolveImpPaths = (impId) => ({
|
|
57664
57737
|
...buildImpPaths(deps.dataDir, impId),
|
|
57665
|
-
disk:
|
|
57666
|
-
...buildSnapshotPaths(
|
|
57738
|
+
disk: join46(buildDiskDir(impId), ROOTFS_FILE),
|
|
57739
|
+
...buildSnapshotPaths(join46(deps.dataDir, "mem", impId))
|
|
57667
57740
|
});
|
|
57668
57741
|
const listAll = () => zfs.list(deps.root);
|
|
57669
57742
|
const setupMount = async (name, directory, isReadOnly = false) => {
|
|
@@ -57806,7 +57879,7 @@ function createZfsBackend(deps) {
|
|
|
57806
57879
|
throw new Error(`zfs: ${deps.root} is not mounted on ${deps.dataDir} (host/scripts/setup-storage.sh mounts it)`);
|
|
57807
57880
|
}
|
|
57808
57881
|
await createMissingDatasets();
|
|
57809
|
-
await setupMount(datasets.mem,
|
|
57882
|
+
await setupMount(datasets.mem, join46(deps.dataDir, "mem"));
|
|
57810
57883
|
await resolveStaging();
|
|
57811
57884
|
const swept = await sweep.removeLeftovers(live, { isDryRun: false, isOrphans: false });
|
|
57812
57885
|
printSweep(getImpdLogger("storage"), swept, "each");
|
|
@@ -57891,7 +57964,7 @@ function createZfsBackend(deps) {
|
|
|
57891
57964
|
await zfs.create(target);
|
|
57892
57965
|
await setupMount(target, buildDiskDir(impId));
|
|
57893
57966
|
});
|
|
57894
|
-
writeFileSync13(
|
|
57967
|
+
writeFileSync13(join46(buildDiskDir(impId), ROOTFS_FILE), "");
|
|
57895
57968
|
return;
|
|
57896
57969
|
}
|
|
57897
57970
|
await runSerial(async () => {
|
|
@@ -57968,7 +58041,7 @@ function createZfsBackend(deps) {
|
|
|
57968
58041
|
}
|
|
57969
58042
|
function readZfsModuleVersion() {
|
|
57970
58043
|
try {
|
|
57971
|
-
return
|
|
58044
|
+
return readFileSync34("/sys/module/zfs/version", "utf8").trim();
|
|
57972
58045
|
} catch {
|
|
57973
58046
|
return null;
|
|
57974
58047
|
}
|
|
@@ -58011,14 +58084,14 @@ function createBackend(config, boundaries) {
|
|
|
58011
58084
|
});
|
|
58012
58085
|
}
|
|
58013
58086
|
function checkStorageMarker(dataDir, kind) {
|
|
58014
|
-
const marker =
|
|
58015
|
-
const recorded = existsSync31(marker) ?
|
|
58087
|
+
const marker = join47(dataDir, MARKER_FILE);
|
|
58088
|
+
const recorded = existsSync31(marker) ? readFileSync35(marker, "utf8").trim() : readUnmarked(dataDir);
|
|
58016
58089
|
if (recorded !== null && recorded !== kind) {
|
|
58017
58090
|
throw new Error(`${dataDir} holds ${recorded} storage, but IMP_STORAGE_BACKEND is ${kind}; moving imps between backends is not supported`);
|
|
58018
58091
|
}
|
|
58019
58092
|
}
|
|
58020
58093
|
function writeStorageMarker(dataDir, kind) {
|
|
58021
|
-
const marker =
|
|
58094
|
+
const marker = join47(dataDir, MARKER_FILE);
|
|
58022
58095
|
if (!existsSync31(marker)) {
|
|
58023
58096
|
writeFileSync14(marker, `${kind}
|
|
58024
58097
|
`);
|
|
@@ -58031,7 +58104,7 @@ function readUnmarked(dataDir) {
|
|
|
58031
58104
|
}
|
|
58032
58105
|
|
|
58033
58106
|
// packages/daemon/src/vm/storage/setup-system-files.ts
|
|
58034
|
-
import { existsSync as existsSync32, mkdirSync as mkdirSync29, readFileSync as
|
|
58107
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync29, readFileSync as readFileSync36 } from "fs";
|
|
58035
58108
|
import { dirname as dirname15 } from "path";
|
|
58036
58109
|
|
|
58037
58110
|
// packages/daemon/src/vm/storage/system-file-info.ts
|
|
@@ -58067,7 +58140,7 @@ async function setupSystemFiles(config) {
|
|
|
58067
58140
|
const missing = config.kernelSource === null ? " and no source is configured" : "";
|
|
58068
58141
|
throw new Error(`${kernelSource} does not exist${missing}`);
|
|
58069
58142
|
}
|
|
58070
|
-
const kernel =
|
|
58143
|
+
const kernel = readFileSync36(kernelSource);
|
|
58071
58144
|
const guestKernel = readKernelInfo(kernel);
|
|
58072
58145
|
if (config.kernelSource !== null && !probeContent(config.kernelPath, kernel)) {
|
|
58073
58146
|
writeCopy(config.kernelSource, config.kernelPath);
|
|
@@ -58087,7 +58160,7 @@ async function setupSystemFiles(config) {
|
|
|
58087
58160
|
};
|
|
58088
58161
|
}
|
|
58089
58162
|
function probeContent(path, content) {
|
|
58090
|
-
return existsSync32(path) && Buffer.from(content).equals(
|
|
58163
|
+
return existsSync32(path) && Buffer.from(content).equals(readFileSync36(path));
|
|
58091
58164
|
}
|
|
58092
58165
|
function writeCopy(source, target) {
|
|
58093
58166
|
mkdirSync29(dirname15(target), { recursive: true });
|
|
@@ -58139,7 +58212,7 @@ async function startImpdParts(config, boundaries, plan) {
|
|
|
58139
58212
|
}
|
|
58140
58213
|
return files;
|
|
58141
58214
|
});
|
|
58142
|
-
const db = await runStep("database", () => boundaries.db ?? openDatabase(
|
|
58215
|
+
const db = await runStep("database", () => boundaries.db ?? openDatabase(join48(config.dataDir, "db", "imp.sqlite")));
|
|
58143
58216
|
plan.db = boundaries.db === undefined ? db : null;
|
|
58144
58217
|
const kernelOops = boundaries.imps?.kernelOops ?? createKernelOopsWatch();
|
|
58145
58218
|
const storage = boundaries.storage ?? createStorageBackend(config, { zfs: { isKernelOopsed: kernelOops.isOopsed } });
|
|
@@ -58246,7 +58319,7 @@ async function startImpdParts(config, boundaries, plan) {
|
|
|
58246
58319
|
secretFiles
|
|
58247
58320
|
});
|
|
58248
58321
|
const state = { ready: false };
|
|
58249
|
-
const authorizedKeys = createAuthorizedKeys(
|
|
58322
|
+
const authorizedKeys = createAuthorizedKeys(join48(setupSshDir(config.dataDir), "authorized_keys"));
|
|
58250
58323
|
const access = await runStep("access", () => loadImpdAccess(config, deps, authorizedKeys.probeListed));
|
|
58251
58324
|
const backups = config.backup === null ? null : createBackupService({
|
|
58252
58325
|
dataDir: config.dataDir,
|
|
@@ -58312,7 +58385,7 @@ async function startImpdParts(config, boundaries, plan) {
|
|
|
58312
58385
|
readTailnetNames: tailnetNames === null ? null : tailnetNames.readStatus,
|
|
58313
58386
|
hostReaders: {
|
|
58314
58387
|
readKernel: () => deps.hostKernelRelease ?? release2(),
|
|
58315
|
-
readCpuInfo: deps.readCpuInfo ?? (() =>
|
|
58388
|
+
readCpuInfo: deps.readCpuInfo ?? (() => readFileSync37("/proc/cpuinfo", "utf8")),
|
|
58316
58389
|
readHugePagePool: deps.imps?.readHugePagePool ?? (() => readHugePagePool())
|
|
58317
58390
|
},
|
|
58318
58391
|
isReady: () => state.ready,
|
|
@@ -58431,6 +58504,11 @@ function buildStubTickerTimer() {
|
|
|
58431
58504
|
};
|
|
58432
58505
|
}
|
|
58433
58506
|
|
|
58507
|
+
// packages/daemon/testing/platform/format-run-prefix.ts
|
|
58508
|
+
function formatRunPrefix(owner) {
|
|
58509
|
+
return `pid${String(owner.pid)}-ns${owner.namespace}-`;
|
|
58510
|
+
}
|
|
58511
|
+
|
|
58434
58512
|
// packages/daemon/testing/platform/open-migrated-copy.ts
|
|
58435
58513
|
import { Database as Database4 } from "bun:sqlite";
|
|
58436
58514
|
var TEMPLATE = {};
|
|
@@ -58453,6 +58531,15 @@ function pickImpdPort(draw) {
|
|
|
58453
58531
|
return FIRST_PORT + Math.floor(draw * PORT_SPAN);
|
|
58454
58532
|
}
|
|
58455
58533
|
|
|
58534
|
+
// packages/daemon/testing/platform/read-run-owner.ts
|
|
58535
|
+
import { readlinkSync as readlinkSync2 } from "fs";
|
|
58536
|
+
function readRunOwner() {
|
|
58537
|
+
return {
|
|
58538
|
+
pid: process.pid,
|
|
58539
|
+
namespace: readlinkSync2("/proc/self/ns/pid").replaceAll(/\D/gu, "")
|
|
58540
|
+
};
|
|
58541
|
+
}
|
|
58542
|
+
|
|
58456
58543
|
// packages/daemon/testing/platform/start-impd-log-capture.ts
|
|
58457
58544
|
import { resetSync } from "@logtape/logtape";
|
|
58458
58545
|
|
|
@@ -58918,7 +59005,7 @@ var NO_FREEZER = { freeze: () => Promise.resolve(), thaw: () => Promise.resolve(
|
|
|
58918
59005
|
var KSM_KERNEL = "6.12.0";
|
|
58919
59006
|
var IDLE_KSM = { running: true, sharedMib: 0, profitMib: 0, zeroMib: 0 };
|
|
58920
59007
|
async function startTestImpd(stack, options = {}) {
|
|
58921
|
-
const dataDir = options.dataDir ?? mkdtempSync(`${tmpdir()}
|
|
59008
|
+
const dataDir = options.dataDir ?? mkdtempSync(`${tmpdir()}/${formatRunPrefix(readRunOwner())}impd-test-`);
|
|
58922
59009
|
if (options.dataDir === undefined) {
|
|
58923
59010
|
stack.defer(() => rm2(dataDir, { recursive: true, force: true }));
|
|
58924
59011
|
}
|
|
@@ -58989,6 +59076,7 @@ async function startTestImpd(stack, options = {}) {
|
|
|
58989
59076
|
});
|
|
58990
59077
|
const cgroups = options.cgroups ?? createCpuCgroups({ root: "/nonexistent" });
|
|
58991
59078
|
const extra = options.boundaries ?? {};
|
|
59079
|
+
const procRoot = options.procRoot;
|
|
58992
59080
|
const buildBoundaries = (identity, runner, storage) => {
|
|
58993
59081
|
const jails = options.jails;
|
|
58994
59082
|
return {
|
|
@@ -59088,6 +59176,9 @@ async function startTestImpd(stack, options = {}) {
|
|
|
59088
59176
|
hostCpus: options.hostCpus ?? 8,
|
|
59089
59177
|
kernelOops,
|
|
59090
59178
|
readThreadIds: (pid) => options.procRoot === undefined ? null : readThreadIds(pid, options.procRoot),
|
|
59179
|
+
...procRoot !== undefined && {
|
|
59180
|
+
readHostLoad: () => readHostLoad({ procRoot, readFile: readText, logger: getImpdLogger("imps") })
|
|
59181
|
+
},
|
|
59091
59182
|
...options.readUnsharedRamMib !== undefined && {
|
|
59092
59183
|
readUnsharedRamMib: options.readUnsharedRamMib
|
|
59093
59184
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@impz/testing",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.5.0",
|
|
4
4
|
"description": "A real impd on stand-ins, for Bun tests of code that drives impd through @impz/client",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"ts-pattern": "^5.9.2",
|
|
44
44
|
"xstate": "^5.33.3",
|
|
45
45
|
"zod": "^4.6.7",
|
|
46
|
-
"@impz/client": "6.
|
|
46
|
+
"@impz/client": "6.5.0"
|
|
47
47
|
},
|
|
48
48
|
"engines": {
|
|
49
49
|
"bun": ">=1.4.3"
|