@impz/testing 6.4.1 → 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 +252 -155
- 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",
|
|
@@ -22487,9 +22488,9 @@ async function updateImpCommitted(db, id, committedAt, isWarm = false) {
|
|
|
22487
22488
|
db.writes.publish({ kind: "changed", imp, reason: "updated" });
|
|
22488
22489
|
return imp;
|
|
22489
22490
|
}
|
|
22490
|
-
async function
|
|
22491
|
-
const
|
|
22492
|
-
return
|
|
22491
|
+
async function removeTrustPending(db, id) {
|
|
22492
|
+
const row = await db.updateTable("imps").set({ trust_pending: 0 }).where("id", "=", id).returningAll().executeTakeFirstOrThrow();
|
|
22493
|
+
return toImpRecord(row);
|
|
22493
22494
|
}
|
|
22494
22495
|
async function updateImpMove(db, id, moveState) {
|
|
22495
22496
|
const row = await db.transaction().execute(async (trx) => {
|
|
@@ -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,
|
|
@@ -42658,14 +42660,17 @@ function makeWakeImpVm(deps) {
|
|
|
42658
42660
|
};
|
|
42659
42661
|
const applyPendingTrust = async (imp, paths) => {
|
|
42660
42662
|
try {
|
|
42661
|
-
|
|
42663
|
+
const env = await context.readExecEnv(imp, paths.vsockSocket);
|
|
42664
|
+
if (env.kind === "untrusted") {
|
|
42665
|
+
logTrustFailure(imp, env.detail);
|
|
42662
42666
|
return imp;
|
|
42663
42667
|
}
|
|
42664
|
-
await context.
|
|
42668
|
+
const trusted = await removeTrustPending(context.db, imp.id);
|
|
42669
|
+
return toLockedImp(imp, trusted);
|
|
42665
42670
|
} catch (error) {
|
|
42666
|
-
|
|
42671
|
+
logTrustFailure(imp, getErrorMessage(error));
|
|
42672
|
+
return imp;
|
|
42667
42673
|
}
|
|
42668
|
-
return toLockedImp(imp, { ...imp, isTrustPending: false });
|
|
42669
42674
|
};
|
|
42670
42675
|
const canBootOnPool = (imp) => pickHugePages(context.config.hugePages !== null, imp) === "2M";
|
|
42671
42676
|
const writeHostPagesIdentity = (imp, paths) => {
|
|
@@ -42727,6 +42732,9 @@ ${failure.message}`, { cause: failure }) : failure;
|
|
|
42727
42732
|
};
|
|
42728
42733
|
return wakeImpVm;
|
|
42729
42734
|
}
|
|
42735
|
+
function logTrustFailure(imp, error) {
|
|
42736
|
+
getImpdLogger("imps").with({ imp: imp.name }).warning("broker CA after the wake: {error}", { error });
|
|
42737
|
+
}
|
|
42730
42738
|
|
|
42731
42739
|
// packages/daemon/src/imps/imps/start-cold-vm.ts
|
|
42732
42740
|
import { randomBytes as randomBytes9 } from "crypto";
|
|
@@ -43491,6 +43499,22 @@ ${readLogTail(plan.paths.logFile, 5)}`, step.fault, error);
|
|
|
43491
43499
|
}
|
|
43492
43500
|
}
|
|
43493
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
|
+
|
|
43494
43518
|
// packages/daemon/src/imps/imps/start-cold-vm.ts
|
|
43495
43519
|
var CLAIM_SEED_BYTES = 64;
|
|
43496
43520
|
async function startColdVm(context, start) {
|
|
@@ -43546,11 +43570,12 @@ async function startColdVm(context, start) {
|
|
|
43546
43570
|
}
|
|
43547
43571
|
});
|
|
43548
43572
|
context.templates?.reportRestored(template);
|
|
43549
|
-
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}", {
|
|
43550
43574
|
key: template.key.slice(0, 12),
|
|
43551
43575
|
pid: String(vm.pid),
|
|
43552
43576
|
timings: formatTimings({ ...hostSteps, ...vm.timings }),
|
|
43553
|
-
guestSteps: formatGuestSteps(vm.guestSteps)
|
|
43577
|
+
guestSteps: formatGuestSteps(vm.guestSteps),
|
|
43578
|
+
hostStall: formatHostStall(start.loadBefore, context.readHostLoad())
|
|
43554
43579
|
});
|
|
43555
43580
|
return vm;
|
|
43556
43581
|
} catch (error) {
|
|
@@ -43583,10 +43608,11 @@ async function startColdVm(context, start) {
|
|
|
43583
43608
|
isIdentityReset: imp.isIdentityResetPending,
|
|
43584
43609
|
jail: context.findJailUser(imp)
|
|
43585
43610
|
});
|
|
43586
|
-
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}", {
|
|
43587
43612
|
pid: String(vm.pid),
|
|
43588
43613
|
timings: formatTimings({ ...hostSteps, ...vm.timings }),
|
|
43589
|
-
guestSteps: formatGuestSteps(vm.guestSteps)
|
|
43614
|
+
guestSteps: formatGuestSteps(vm.guestSteps),
|
|
43615
|
+
hostStall: formatHostStall(start.loadBefore, context.readHostLoad())
|
|
43590
43616
|
});
|
|
43591
43617
|
return vm;
|
|
43592
43618
|
}
|
|
@@ -43667,6 +43693,7 @@ function createImpVmOps(host) {
|
|
|
43667
43693
|
hugePagesMib: hugePages === "2M" ? imp.memoryMib : 0
|
|
43668
43694
|
});
|
|
43669
43695
|
const setupStarted = performance.now();
|
|
43696
|
+
const loadBefore = context.readHostLoad();
|
|
43670
43697
|
try {
|
|
43671
43698
|
removeSnapshot(paths);
|
|
43672
43699
|
await context.egress.requireImp(imp.id);
|
|
@@ -43684,6 +43711,7 @@ function createImpVmOps(host) {
|
|
|
43684
43711
|
cgroup,
|
|
43685
43712
|
hugePages,
|
|
43686
43713
|
hostSteps,
|
|
43714
|
+
loadBefore,
|
|
43687
43715
|
diskReady
|
|
43688
43716
|
});
|
|
43689
43717
|
startCounting(context, imp, vm.pid);
|
|
@@ -44388,6 +44416,56 @@ function createImpService(deps, createWatchdog) {
|
|
|
44388
44416
|
};
|
|
44389
44417
|
}
|
|
44390
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
|
+
|
|
44391
44469
|
// packages/daemon/src/platform/telemetry/imp-telemetry.ts
|
|
44392
44470
|
import { ROOT_CONTEXT, metrics as metrics2, trace } from "@opentelemetry/api";
|
|
44393
44471
|
var SPAN_NAMES = {
|
|
@@ -44764,12 +44842,12 @@ function createMemoryController(deps) {
|
|
|
44764
44842
|
import {
|
|
44765
44843
|
existsSync as existsSync14,
|
|
44766
44844
|
mkdirSync as mkdirSync16,
|
|
44767
|
-
readFileSync as
|
|
44845
|
+
readFileSync as readFileSync23,
|
|
44768
44846
|
readdirSync as readdirSync8,
|
|
44769
44847
|
rmdirSync as rmdirSync2,
|
|
44770
44848
|
writeFileSync as writeFileSync5
|
|
44771
44849
|
} from "fs";
|
|
44772
|
-
import { join as
|
|
44850
|
+
import { join as join23 } from "path";
|
|
44773
44851
|
var PERIOD_US = 1e5;
|
|
44774
44852
|
var MEMORY_MIN_OVERHEAD_MIB = 256;
|
|
44775
44853
|
var MEMORY_OVERHEAD_DIVISOR = 8;
|
|
@@ -44797,18 +44875,18 @@ function parseOomKills(text) {
|
|
|
44797
44875
|
return match?.groups === undefined ? null : Number(match.groups["count"]);
|
|
44798
44876
|
}
|
|
44799
44877
|
function createCpuCgroups(options) {
|
|
44800
|
-
const imps =
|
|
44878
|
+
const imps = join23(options.root, "imps");
|
|
44801
44879
|
const procRoot = options.procRoot ?? "/proc";
|
|
44802
44880
|
const rmdir = options.rmdir ?? rmdirSync2;
|
|
44803
44881
|
const sleep = options.sleep ?? Bun.sleep;
|
|
44804
44882
|
const isEnforced = probeControllerDelegated(imps, "cpu");
|
|
44805
44883
|
const isMemoryEnforced = isEnforced && probeControllerDelegated(imps, "memory");
|
|
44806
|
-
const getDir = (impId) =>
|
|
44884
|
+
const getDir = (impId) => join23(imps, impId);
|
|
44807
44885
|
const guestMibs = new Map;
|
|
44808
44886
|
const oomBaselines = new Map;
|
|
44809
44887
|
const readOomKills = (impId) => {
|
|
44810
44888
|
try {
|
|
44811
|
-
const events =
|
|
44889
|
+
const events = readFileSync23(join23(getDir(impId), "memory.events"), "utf8");
|
|
44812
44890
|
return parseOomKills(events);
|
|
44813
44891
|
} catch {
|
|
44814
44892
|
return null;
|
|
@@ -44818,8 +44896,8 @@ function createCpuCgroups(options) {
|
|
|
44818
44896
|
oomBaselines.set(impId, readOomKills(impId) ?? 0);
|
|
44819
44897
|
};
|
|
44820
44898
|
const writeSettings = (impId, cpu, limit) => {
|
|
44821
|
-
writeFileSync5(
|
|
44822
|
-
writeFileSync5(
|
|
44899
|
+
writeFileSync5(join23(getDir(impId), "cpu.weight"), String(cpu.weight));
|
|
44900
|
+
writeFileSync5(join23(getDir(impId), "cpu.max"), formatCpuMax(limit));
|
|
44823
44901
|
};
|
|
44824
44902
|
const writeMemory = (impId) => {
|
|
44825
44903
|
const guestMib = guestMibs.get(impId);
|
|
@@ -44827,10 +44905,10 @@ function createCpuCgroups(options) {
|
|
|
44827
44905
|
return;
|
|
44828
44906
|
}
|
|
44829
44907
|
const directory = getDir(impId);
|
|
44830
|
-
writeFileSync5(
|
|
44831
|
-
writeFileSync5(
|
|
44832
|
-
writeFileSync5(
|
|
44833
|
-
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");
|
|
44834
44912
|
};
|
|
44835
44913
|
const setup = (impId, cpu, memoryMib) => {
|
|
44836
44914
|
if (!isEnforced) {
|
|
@@ -44852,7 +44930,7 @@ function createCpuCgroups(options) {
|
|
|
44852
44930
|
return null;
|
|
44853
44931
|
}
|
|
44854
44932
|
return {
|
|
44855
|
-
procsPath:
|
|
44933
|
+
procsPath: join23(getDir(impId), "cgroup.procs"),
|
|
44856
44934
|
liftLimit: () => {
|
|
44857
44935
|
tryWrite(impId, "lift the limit", () => {
|
|
44858
44936
|
writeSettings(impId, cpu, null);
|
|
@@ -44936,7 +45014,7 @@ function createCpuCgroups(options) {
|
|
|
44936
45014
|
kill: (impId) => {
|
|
44937
45015
|
if (isEnforced && existsSync14(getDir(impId))) {
|
|
44938
45016
|
tryWrite(impId, "kill", () => {
|
|
44939
|
-
writeFileSync5(
|
|
45017
|
+
writeFileSync5(join23(getDir(impId), "cgroup.kill"), "1");
|
|
44940
45018
|
});
|
|
44941
45019
|
}
|
|
44942
45020
|
},
|
|
@@ -44947,7 +45025,7 @@ function createCpuCgroups(options) {
|
|
|
44947
45025
|
},
|
|
44948
45026
|
readCpuStat: (impId) => {
|
|
44949
45027
|
try {
|
|
44950
|
-
const stat =
|
|
45028
|
+
const stat = readFileSync23(join23(getDir(impId), "cpu.stat"), "utf8");
|
|
44951
45029
|
return parseCpuStat(stat);
|
|
44952
45030
|
} catch {
|
|
44953
45031
|
return null;
|
|
@@ -44957,7 +45035,7 @@ function createCpuCgroups(options) {
|
|
|
44957
45035
|
}
|
|
44958
45036
|
function probeControllerDelegated(imps, controller) {
|
|
44959
45037
|
try {
|
|
44960
|
-
const delegated =
|
|
45038
|
+
const delegated = readFileSync23(join23(imps, "cgroup.subtree_control"), "utf8");
|
|
44961
45039
|
return delegated.split(/\s+/u).includes(controller);
|
|
44962
45040
|
} catch {
|
|
44963
45041
|
return false;
|
|
@@ -44990,13 +45068,13 @@ function probeUffdDevice(path = "/dev/userfaultfd") {
|
|
|
44990
45068
|
}
|
|
44991
45069
|
|
|
44992
45070
|
// packages/daemon/src/vm/vmm/read-huge-page-pool.ts
|
|
44993
|
-
import { readFileSync as
|
|
44994
|
-
import { join as
|
|
45071
|
+
import { readFileSync as readFileSync24 } from "fs";
|
|
45072
|
+
import { join as join24 } from "path";
|
|
44995
45073
|
var HUGE_PAGE_MIB = 2;
|
|
44996
45074
|
function readHugePagePool(sysRoot = "/sys") {
|
|
44997
|
-
const directory =
|
|
45075
|
+
const directory = join24(sysRoot, "kernel", "mm", "hugepages", "hugepages-2048kB");
|
|
44998
45076
|
try {
|
|
44999
|
-
const readCount = (name) => Number(
|
|
45077
|
+
const readCount = (name) => Number(readFileSync24(join24(directory, name), "utf8").trim());
|
|
45000
45078
|
const total = readCount("nr_hugepages");
|
|
45001
45079
|
const free = readCount("free_hugepages") - readCount("resv_hugepages");
|
|
45002
45080
|
if (!Number.isSafeInteger(total) || !Number.isSafeInteger(free)) {
|
|
@@ -45575,6 +45653,7 @@ function resolveImpBoundaries(boundaries) {
|
|
|
45575
45653
|
kernelOops: boundaries.kernelOops ?? createKernelOopsWatch(),
|
|
45576
45654
|
readThreadIds: boundaries.readThreadIds ?? ((pid) => readThreadIds(pid)),
|
|
45577
45655
|
readNetBytes: boundaries.readNetBytes ?? ((tap) => readGuestNetBytes(tap)),
|
|
45656
|
+
readHostLoad: boundaries.readHostLoad ?? (() => readHostLoad({ procRoot: "/proc", readFile: readText, logger: getImpdLogger("imps") })),
|
|
45578
45657
|
...boundaries.openTap !== undefined && { openTap: boundaries.openTap },
|
|
45579
45658
|
...boundaries.now !== undefined && { now: boundaries.now }
|
|
45580
45659
|
};
|
|
@@ -45589,7 +45668,7 @@ function makeStandInVmRam(readRam) {
|
|
|
45589
45668
|
|
|
45590
45669
|
// packages/daemon/src/imp-ops/moves/move-receiver.ts
|
|
45591
45670
|
import { existsSync as existsSync16, rmSync as rmSync24 } from "fs";
|
|
45592
|
-
import { join as
|
|
45671
|
+
import { join as join26 } from "path";
|
|
45593
45672
|
|
|
45594
45673
|
// packages/daemon/src/platform/db/probe-slot-free.ts
|
|
45595
45674
|
async function probeSlotFree(db, slot, now) {
|
|
@@ -45914,7 +45993,7 @@ function readReceipt(receipt, secret) {
|
|
|
45914
45993
|
// packages/daemon/src/imp-ops/moves/read-move-stream.ts
|
|
45915
45994
|
import { mkdirSync as mkdirSync19, rmSync as rmSync23 } from "fs";
|
|
45916
45995
|
import { open as open7 } from "fs/promises";
|
|
45917
|
-
import { join as
|
|
45996
|
+
import { join as join25 } from "path";
|
|
45918
45997
|
import invariant5 from "tiny-invariant";
|
|
45919
45998
|
|
|
45920
45999
|
// packages/daemon/src/imp-ops/moves/build-received-digest.ts
|
|
@@ -46539,7 +46618,7 @@ async function readMoveStream(deps, options) {
|
|
|
46539
46618
|
const count = createByteCounter(row.bytes);
|
|
46540
46619
|
const files = [];
|
|
46541
46620
|
mkdirSync19(options.tempDir, { recursive: true, mode: 448 });
|
|
46542
|
-
const temp =
|
|
46621
|
+
const temp = join25(options.tempDir, `${row.id}.part`);
|
|
46543
46622
|
const writeDisk = async (impId) => {
|
|
46544
46623
|
if (header.streams !== null) {
|
|
46545
46624
|
await writeMoveStreams(deps, {
|
|
@@ -46754,7 +46833,7 @@ async function requireMoveTicket(db, request) {
|
|
|
46754
46833
|
// packages/daemon/src/imp-ops/moves/move-receiver.ts
|
|
46755
46834
|
var STREAM_WINDOW_MS = 10 * 60 * 1000;
|
|
46756
46835
|
function createMoveReceiver(deps) {
|
|
46757
|
-
const tempDir =
|
|
46836
|
+
const tempDir = join26(deps.dataDir, "moves");
|
|
46758
46837
|
const sessions = new Map;
|
|
46759
46838
|
const writeTicketRow = async (name, bytes, fields, write = (row) => writeMoveTicket(deps.db, row)) => {
|
|
46760
46839
|
const created = mintOpaqueToken(MOVE_TICKET_PREFIX);
|
|
@@ -47929,12 +48008,12 @@ function toPeerError2(procedure, error) {
|
|
|
47929
48008
|
// packages/daemon/src/vm/storage/write-image-files.ts
|
|
47930
48009
|
import { writeFileSync as writeFileSync6 } from "fs";
|
|
47931
48010
|
import { copyFile } from "fs/promises";
|
|
47932
|
-
import { join as
|
|
48011
|
+
import { join as join27 } from "path";
|
|
47933
48012
|
async function writeImageFiles(files, directory) {
|
|
47934
|
-
const rootfs =
|
|
48013
|
+
const rootfs = join27(directory, "rootfs.ext4");
|
|
47935
48014
|
writeFileSync6(rootfs, "");
|
|
47936
48015
|
await writeChangedBlocks(files.rootfsPath, rootfs);
|
|
47937
|
-
await copyFile(files.configPath,
|
|
48016
|
+
await copyFile(files.configPath, join27(directory, "config.json"));
|
|
47938
48017
|
}
|
|
47939
48018
|
|
|
47940
48019
|
// packages/daemon/src/create-impd-moves.ts
|
|
@@ -47974,7 +48053,7 @@ function createImpdMoves(config, deps, parts, hooks) {
|
|
|
47974
48053
|
|
|
47975
48054
|
// packages/daemon/src/imps/images/template-service.ts
|
|
47976
48055
|
import { copyFileSync as copyFileSync3, existsSync as existsSync17, statSync as statSync11, writeFileSync as writeFileSync7 } from "fs";
|
|
47977
|
-
import { join as
|
|
48056
|
+
import { join as join28 } from "path";
|
|
47978
48057
|
|
|
47979
48058
|
// packages/daemon/src/imps/images/read-held-image.ts
|
|
47980
48059
|
async function readHeldImage(db, name, at) {
|
|
@@ -48262,7 +48341,7 @@ function createTemplateService(deps) {
|
|
|
48262
48341
|
});
|
|
48263
48342
|
const writeConfig = async (imageId, directory) => {
|
|
48264
48343
|
const image = await readImageById(deps.db, imageId);
|
|
48265
|
-
const target =
|
|
48344
|
+
const target = join28(directory, "config.json");
|
|
48266
48345
|
const config = image === undefined ? undefined : buildImagePaths(deps.config.dataDir, image.digest).config;
|
|
48267
48346
|
if (config !== undefined && existsSync17(config)) {
|
|
48268
48347
|
copyFileSync3(config, target);
|
|
@@ -48650,7 +48729,7 @@ function createImpdServices(config, deps, parts) {
|
|
|
48650
48729
|
|
|
48651
48730
|
// packages/daemon/src/imps/images/build/create-image-builds.ts
|
|
48652
48731
|
import { existsSync as existsSync19, mkdirSync as mkdirSync20, rmSync as rmSync25, statSync as statSync12 } from "fs";
|
|
48653
|
-
import { join as
|
|
48732
|
+
import { join as join30, posix as posix3 } from "path";
|
|
48654
48733
|
|
|
48655
48734
|
// packages/local-tar/src/extract-local.ts
|
|
48656
48735
|
import tar from "tar-stream";
|
|
@@ -48658,7 +48737,7 @@ import * as z83 from "zod";
|
|
|
48658
48737
|
// packages/local-tar/src/pack-build-context.ts
|
|
48659
48738
|
import { existsSync as existsSync18 } from "fs";
|
|
48660
48739
|
import { lstat, readFile as readFile4, readdir } from "fs/promises";
|
|
48661
|
-
import { join as
|
|
48740
|
+
import { join as join29, posix as posix2 } from "path";
|
|
48662
48741
|
import ignore from "@balena/dockerignore";
|
|
48663
48742
|
|
|
48664
48743
|
// packages/local-tar/src/write-build-context.ts
|
|
@@ -48942,7 +49021,7 @@ class MissingDockerfileError extends Error {
|
|
|
48942
49021
|
name = "MissingDockerfileError";
|
|
48943
49022
|
}
|
|
48944
49023
|
function listContextEntries(root, dockerfile) {
|
|
48945
|
-
const found = listDockerfileCandidates(posix2.normalize(dockerfile)).find((candidate) => existsSync18(
|
|
49024
|
+
const found = listDockerfileCandidates(posix2.normalize(dockerfile)).find((candidate) => existsSync18(join29(root, candidate)));
|
|
48946
49025
|
if (found === undefined) {
|
|
48947
49026
|
return Promise.reject(new MissingDockerfileError(`there is no ${dockerfile} in ${root}`));
|
|
48948
49027
|
}
|
|
@@ -48954,8 +49033,8 @@ var ENTRY_KINDS = [
|
|
|
48954
49033
|
["file", "isFile"]
|
|
48955
49034
|
];
|
|
48956
49035
|
async function listEntries(root, dockerfile) {
|
|
48957
|
-
const ignoreName = existsSync18(
|
|
48958
|
-
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") : "";
|
|
48959
49038
|
const matcher = ignore().add(patterns);
|
|
48960
49039
|
const hasExceptions = patterns.split(`
|
|
48961
49040
|
`).some((line) => line.trim().startsWith("!"));
|
|
@@ -48965,7 +49044,7 @@ async function listEntries(root, dockerfile) {
|
|
|
48965
49044
|
const entries = [];
|
|
48966
49045
|
const children = await readdir(directory);
|
|
48967
49046
|
for (const child of children.toSorted()) {
|
|
48968
|
-
const path =
|
|
49047
|
+
const path = join29(directory, child);
|
|
48969
49048
|
const name = prefix === "" ? child : `${prefix}/${child}`;
|
|
48970
49049
|
const stats = await lstat(path);
|
|
48971
49050
|
const ignored = matcher.ignores(name) && name !== dockerfileName;
|
|
@@ -50020,7 +50099,7 @@ function planRootfsOverhead(treeBytes) {
|
|
|
50020
50099
|
}
|
|
50021
50100
|
|
|
50022
50101
|
// packages/daemon/src/imps/images/rootfs/unpack-export.ts
|
|
50023
|
-
import { readFileSync as
|
|
50102
|
+
import { readFileSync as readFileSync25 } from "fs";
|
|
50024
50103
|
var CAP_SETFCAP_BIT = 31n;
|
|
50025
50104
|
var SETFCAP_HELP = "imp-host needs CAP_SETFCAP (docs/architecture/host.md#privileges)";
|
|
50026
50105
|
var UNPACK_TAR_ARGS = [
|
|
@@ -50062,7 +50141,7 @@ function findXattrFailure(stderr) {
|
|
|
50062
50141
|
});
|
|
50063
50142
|
return failures.find((failure) => failure.missingSetfcap) ?? failures[0] ?? null;
|
|
50064
50143
|
}
|
|
50065
|
-
function readSetfcapWarning(status =
|
|
50144
|
+
function readSetfcapWarning(status = readFileSync25("/proc/self/status", "utf8")) {
|
|
50066
50145
|
const effective = /^CapEff:\s*(?<mask>[0-9a-f]+)$/mu.exec(status)?.groups?.["mask"] ?? "0";
|
|
50067
50146
|
if (BigInt(`0x${effective}`) >> CAP_SETFCAP_BIT & 1n) {
|
|
50068
50147
|
return null;
|
|
@@ -50486,7 +50565,7 @@ function createImageBuilds(deps, writer) {
|
|
|
50486
50565
|
});
|
|
50487
50566
|
}
|
|
50488
50567
|
const uploadsDir = buildUploadsDir(deps.config.dataDir);
|
|
50489
|
-
const tarPath =
|
|
50568
|
+
const tarPath = join30(uploadsDir, `${Bun.randomUUIDv7()}.tar`);
|
|
50490
50569
|
mkdirSync20(uploadsDir, { recursive: true, mode: 448 });
|
|
50491
50570
|
return deps.diskBudget.withRoom(tarBytes, async () => {
|
|
50492
50571
|
try {
|
|
@@ -50643,7 +50722,7 @@ function buildImageRuntimeConfig(ociConfig) {
|
|
|
50643
50722
|
|
|
50644
50723
|
// packages/daemon/src/imps/images/rootfs/create-image-writer.ts
|
|
50645
50724
|
import { existsSync as existsSync20, mkdirSync as mkdirSync22, rmSync as rmSync27, statSync as statSync13, writeFileSync as writeFileSync8 } from "fs";
|
|
50646
|
-
import { join as
|
|
50725
|
+
import { join as join32 } from "path";
|
|
50647
50726
|
|
|
50648
50727
|
// packages/daemon/src/imps/images/rootfs/read-oci-config.ts
|
|
50649
50728
|
import * as z88 from "zod";
|
|
@@ -50663,13 +50742,13 @@ async function readOciConfig(ref, signal, run) {
|
|
|
50663
50742
|
|
|
50664
50743
|
// packages/daemon/src/imps/images/rootfs/write-image-config.ts
|
|
50665
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";
|
|
50666
|
-
import { join as
|
|
50745
|
+
import { join as join31 } from "path";
|
|
50667
50746
|
function writeImageConfig(root, contents) {
|
|
50668
|
-
const etc =
|
|
50669
|
-
const directory =
|
|
50747
|
+
const etc = join31(root, "etc");
|
|
50748
|
+
const directory = join31(etc, "imp");
|
|
50670
50749
|
createDirectory(etc, "/etc");
|
|
50671
50750
|
createDirectory(directory, "/etc/imp");
|
|
50672
|
-
const file =
|
|
50751
|
+
const file = join31(directory, "image.json");
|
|
50673
50752
|
rmSync26(file, { recursive: true, force: true });
|
|
50674
50753
|
const fd = openSync9(file, constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW, 420);
|
|
50675
50754
|
try {
|
|
@@ -50716,8 +50795,8 @@ function createImageWriter(deps) {
|
|
|
50716
50795
|
const guestRootfsLock = buildKeyedMutex();
|
|
50717
50796
|
const makeWorkDir = () => {
|
|
50718
50797
|
const images = buildImagesDir(deps.config.dataDir);
|
|
50719
|
-
const work =
|
|
50720
|
-
const root =
|
|
50798
|
+
const work = join32(images, `.build-${Bun.randomUUIDv7()}`);
|
|
50799
|
+
const root = join32(work, "root");
|
|
50721
50800
|
mkdirSync22(images, { recursive: true });
|
|
50722
50801
|
mkdirSync22(work, { mode: 448 });
|
|
50723
50802
|
mkdirSync22(root, { mode: 493 });
|
|
@@ -50728,7 +50807,7 @@ function createImageWriter(deps) {
|
|
|
50728
50807
|
const usage = await readTreeUsage(root);
|
|
50729
50808
|
const plan = planRootfs(usage);
|
|
50730
50809
|
await deps.storage.createImage(digest, async (directory) => {
|
|
50731
|
-
const image =
|
|
50810
|
+
const image = join32(directory, "rootfs.ext4");
|
|
50732
50811
|
await runChecked(["truncate", "-s", String(plan.bytes), image]);
|
|
50733
50812
|
await runChecked([
|
|
50734
50813
|
"mkfs.ext4",
|
|
@@ -50741,7 +50820,7 @@ function createImageWriter(deps) {
|
|
|
50741
50820
|
root,
|
|
50742
50821
|
image
|
|
50743
50822
|
]);
|
|
50744
|
-
writeFileSync8(
|
|
50823
|
+
writeFileSync8(join32(directory, "config.json"), JSON.stringify(ociConfig ?? {}, null, 2));
|
|
50745
50824
|
});
|
|
50746
50825
|
return readDiskUsage(buildImagePaths(deps.config.dataDir, digest).rootfs);
|
|
50747
50826
|
};
|
|
@@ -51292,7 +51371,7 @@ async function runStreamed(argv, onStdout, signal) {
|
|
|
51292
51371
|
|
|
51293
51372
|
// packages/daemon/src/vm/storage/count-tree-bytes.ts
|
|
51294
51373
|
import { lstat as lstat3, readdir as readdir3 } from "fs/promises";
|
|
51295
|
-
import { join as
|
|
51374
|
+
import { join as join33 } from "path";
|
|
51296
51375
|
async function countTreeBytes(root, deps = {}) {
|
|
51297
51376
|
const readDir = deps.readDir ?? readDirEntries;
|
|
51298
51377
|
const inodes = new Map;
|
|
@@ -51301,11 +51380,11 @@ async function countTreeBytes(root, deps = {}) {
|
|
|
51301
51380
|
const entries = await readEntries2(readDir, directory);
|
|
51302
51381
|
for (const entry of entries) {
|
|
51303
51382
|
if (entry.isDirectory()) {
|
|
51304
|
-
dirs.push(
|
|
51383
|
+
dirs.push(join33(directory, entry.name));
|
|
51305
51384
|
}
|
|
51306
51385
|
}
|
|
51307
51386
|
const files = entries.filter((entry) => entry.isFile());
|
|
51308
|
-
const stats = await Promise.all(files.map((entry) => readFileStats(
|
|
51387
|
+
const stats = await Promise.all(files.map((entry) => readFileStats(join33(directory, entry.name))));
|
|
51309
51388
|
for (const stat of stats) {
|
|
51310
51389
|
if (stat !== undefined) {
|
|
51311
51390
|
inodes.set(`${String(stat.dev)}:${String(stat.ino)}`, Math.max(0, stat.blocks - 1) * 512);
|
|
@@ -51548,12 +51627,12 @@ function createTailnetAccess(config, deps, readStatus) {
|
|
|
51548
51627
|
}
|
|
51549
51628
|
|
|
51550
51629
|
// packages/daemon/src/identity/token.ts
|
|
51551
|
-
import { existsSync as existsSync21, readFileSync as
|
|
51552
|
-
import { join as
|
|
51630
|
+
import { existsSync as existsSync21, readFileSync as readFileSync26, writeFileSync as writeFileSync9 } from "fs";
|
|
51631
|
+
import { join as join34 } from "path";
|
|
51553
51632
|
function loadOrCreateToken(dataDir) {
|
|
51554
|
-
const path =
|
|
51633
|
+
const path = join34(dataDir, "token");
|
|
51555
51634
|
if (existsSync21(path)) {
|
|
51556
|
-
return
|
|
51635
|
+
return readFileSync26(path, "utf8").trim();
|
|
51557
51636
|
}
|
|
51558
51637
|
const token = mintSecret();
|
|
51559
51638
|
writeFileSync9(path, `${token}
|
|
@@ -51675,13 +51754,13 @@ import { basename as basename4 } from "path";
|
|
|
51675
51754
|
|
|
51676
51755
|
// packages/daemon/src/vm/storage/remove-unused-system-drives.ts
|
|
51677
51756
|
import { readdirSync as readdirSync9, rmSync as rmSync28 } from "fs";
|
|
51678
|
-
import { join as
|
|
51757
|
+
import { join as join35 } from "path";
|
|
51679
51758
|
function removeUnusedSystemDrives(dataDir, keep) {
|
|
51680
51759
|
const directory = buildSystemDrivesDir(dataDir);
|
|
51681
51760
|
const removed = [];
|
|
51682
51761
|
for (const name of readNames(directory)) {
|
|
51683
51762
|
if (!keep.has(name)) {
|
|
51684
|
-
rmSync28(
|
|
51763
|
+
rmSync28(join35(directory, name), { force: true });
|
|
51685
51764
|
removed.push(name);
|
|
51686
51765
|
}
|
|
51687
51766
|
}
|
|
@@ -52890,13 +52969,13 @@ function createPublicRecordsLink() {
|
|
|
52890
52969
|
|
|
52891
52970
|
// packages/daemon/src/network/tailnet-names/host-id.ts
|
|
52892
52971
|
import { randomBytes as randomBytes11 } from "crypto";
|
|
52893
|
-
import { existsSync as existsSync22, mkdirSync as mkdirSync23, readFileSync as
|
|
52894
|
-
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";
|
|
52895
52974
|
function loadOrCreateHostId(dataDir) {
|
|
52896
|
-
const directory =
|
|
52897
|
-
const path =
|
|
52975
|
+
const directory = join36(dataDir, "tailnet-names");
|
|
52976
|
+
const path = join36(directory, "host-id");
|
|
52898
52977
|
if (existsSync22(path)) {
|
|
52899
|
-
return
|
|
52978
|
+
return readFileSync27(path, "utf8").trim();
|
|
52900
52979
|
}
|
|
52901
52980
|
mkdirSync23(directory, { recursive: true });
|
|
52902
52981
|
const id = randomBytes11(16).toString("hex");
|
|
@@ -52906,7 +52985,7 @@ function loadOrCreateHostId(dataDir) {
|
|
|
52906
52985
|
}
|
|
52907
52986
|
|
|
52908
52987
|
// packages/daemon/src/network/tailnet-names/oauth-credential.ts
|
|
52909
|
-
import { readFileSync as
|
|
52988
|
+
import { readFileSync as readFileSync28, statSync as statSync14 } from "fs";
|
|
52910
52989
|
import * as z92 from "zod";
|
|
52911
52990
|
var CredentialSchema = z92.object({ clientId: z92.string().min(1), clientSecret: z92.string().min(1) });
|
|
52912
52991
|
function readOAuthCredential(path) {
|
|
@@ -52922,7 +53001,7 @@ function readOAuthCredential(path) {
|
|
|
52922
53001
|
}
|
|
52923
53002
|
function readJson(path) {
|
|
52924
53003
|
try {
|
|
52925
|
-
return JSON.parse(
|
|
53004
|
+
return JSON.parse(readFileSync28(path, "utf8"));
|
|
52926
53005
|
} catch {
|
|
52927
53006
|
return null;
|
|
52928
53007
|
}
|
|
@@ -53319,7 +53398,7 @@ async function startOtlpExport(env, version) {
|
|
|
53319
53398
|
}
|
|
53320
53399
|
|
|
53321
53400
|
// packages/daemon/src/network/https/wire-https-service.ts
|
|
53322
|
-
import { readFileSync as
|
|
53401
|
+
import { readFileSync as readFileSync30 } from "fs";
|
|
53323
53402
|
|
|
53324
53403
|
// packages/daemon/src/platform/db/exposure.ts
|
|
53325
53404
|
async function readPublicImp(db, name) {
|
|
@@ -53514,8 +53593,8 @@ function formatAcmeError(error) {
|
|
|
53514
53593
|
}
|
|
53515
53594
|
|
|
53516
53595
|
// packages/daemon/src/network/https/acme/cert-store.ts
|
|
53517
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync24, readFileSync as
|
|
53518
|
-
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";
|
|
53519
53598
|
import * as z95 from "zod";
|
|
53520
53599
|
var AttemptStateSchema = z95.object({
|
|
53521
53600
|
failures: z95.int().nonnegative(),
|
|
@@ -53526,11 +53605,11 @@ var AccountSchema = z95.object({ directoryUrl: z95.string(), url: z95.string(),
|
|
|
53526
53605
|
var LegacyAccountSchema = z95.object({ directoryUrl: z95.string(), url: z95.string() });
|
|
53527
53606
|
var NO_ATTEMPTS = { failures: 0, lastAttemptAt: null, lastError: null };
|
|
53528
53607
|
function createCertStore(dataDir) {
|
|
53529
|
-
const directory =
|
|
53530
|
-
const certificatePath =
|
|
53531
|
-
const attemptsPath =
|
|
53532
|
-
const accountPath =
|
|
53533
|
-
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");
|
|
53534
53613
|
const warned = { account: false };
|
|
53535
53614
|
const write = (path, content) => {
|
|
53536
53615
|
mkdirSync24(directory, { recursive: true, mode: 448 });
|
|
@@ -53596,7 +53675,7 @@ ${certificate.chainPem.trimEnd()}
|
|
|
53596
53675
|
};
|
|
53597
53676
|
}
|
|
53598
53677
|
function readIfExists(path) {
|
|
53599
|
-
return existsSync23(path) ?
|
|
53678
|
+
return existsSync23(path) ? readFileSync29(path, "utf8") : null;
|
|
53600
53679
|
}
|
|
53601
53680
|
function parseJson(text) {
|
|
53602
53681
|
try {
|
|
@@ -54402,7 +54481,7 @@ function wireHttpsService(options) {
|
|
|
54402
54481
|
const issue = createAcmeIssuer({
|
|
54403
54482
|
directoryUrl: config.acmeDirectory,
|
|
54404
54483
|
email: config.acmeEmail,
|
|
54405
|
-
caPem: config.acmeCaFile === null ? null :
|
|
54484
|
+
caPem: config.acmeCaFile === null ? null : readFileSync30(config.acmeCaFile, "utf8"),
|
|
54406
54485
|
store,
|
|
54407
54486
|
dns
|
|
54408
54487
|
});
|
|
@@ -54989,17 +55068,17 @@ function buildTooMany() {
|
|
|
54989
55068
|
|
|
54990
55069
|
// packages/daemon/src/surface/ssh/host-key.ts
|
|
54991
55070
|
var import_ssh22 = __toESM(require_lib2(), 1);
|
|
54992
|
-
import { existsSync as existsSync24, mkdirSync as mkdirSync25, readFileSync as
|
|
54993
|
-
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";
|
|
54994
55073
|
function setupSshDir(dataDir) {
|
|
54995
|
-
const directory =
|
|
55074
|
+
const directory = join38(dataDir, "ssh");
|
|
54996
55075
|
mkdirSync25(directory, { recursive: true, mode: 448 });
|
|
54997
55076
|
return directory;
|
|
54998
55077
|
}
|
|
54999
55078
|
function loadOrCreateHostKey(sshDir) {
|
|
55000
|
-
const path =
|
|
55079
|
+
const path = join38(sshDir, "host_key");
|
|
55001
55080
|
if (existsSync24(path)) {
|
|
55002
|
-
return
|
|
55081
|
+
return readFileSync31(path, "utf8");
|
|
55003
55082
|
}
|
|
55004
55083
|
const pair = generateEd25519Key();
|
|
55005
55084
|
writeFileSync11(path, pair.private, { mode: 384, flag: "wx" });
|
|
@@ -56164,8 +56243,8 @@ async function stopImpd(parts, options) {
|
|
|
56164
56243
|
}
|
|
56165
56244
|
|
|
56166
56245
|
// packages/daemon/src/vm/storage/create-storage-backend.ts
|
|
56167
|
-
import { existsSync as existsSync31, readFileSync as
|
|
56168
|
-
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";
|
|
56169
56248
|
|
|
56170
56249
|
// packages/daemon/src/vm/storage/xfs-backend.ts
|
|
56171
56250
|
import {
|
|
@@ -56178,7 +56257,7 @@ import {
|
|
|
56178
56257
|
statfsSync as statfsSync2,
|
|
56179
56258
|
writeFileSync as writeFileSync12
|
|
56180
56259
|
} from "fs";
|
|
56181
|
-
import { basename as basename6, dirname as dirname13, join as
|
|
56260
|
+
import { basename as basename6, dirname as dirname13, join as join42 } from "path";
|
|
56182
56261
|
|
|
56183
56262
|
// packages/daemon/src/vm/storage/count-owner-bytes.ts
|
|
56184
56263
|
function countOwnerBytes(files) {
|
|
@@ -56235,13 +56314,13 @@ import {
|
|
|
56235
56314
|
copyFileSync as copyFileSync4,
|
|
56236
56315
|
existsSync as existsSync25,
|
|
56237
56316
|
mkdirSync as mkdirSync26,
|
|
56238
|
-
readFileSync as
|
|
56317
|
+
readFileSync as readFileSync32,
|
|
56239
56318
|
readdirSync as readdirSync10,
|
|
56240
56319
|
renameSync as renameSync6,
|
|
56241
56320
|
rmSync as rmSync30,
|
|
56242
56321
|
statSync as statSync15
|
|
56243
56322
|
} from "fs";
|
|
56244
|
-
import { basename as basename5, dirname as dirname11, join as
|
|
56323
|
+
import { basename as basename5, dirname as dirname11, join as join39 } from "path";
|
|
56245
56324
|
import * as z97 from "zod";
|
|
56246
56325
|
var CopiesSchema = z97.record(z97.string(), z97.object({ ino: z97.string(), ctimeNs: z97.string(), size: z97.string() }));
|
|
56247
56326
|
function createXfsBackups(ctx) {
|
|
@@ -56249,7 +56328,7 @@ function createXfsBackups(ctx) {
|
|
|
56249
56328
|
const freshCopies = new Set;
|
|
56250
56329
|
const readCopies = () => {
|
|
56251
56330
|
try {
|
|
56252
|
-
return CopiesSchema.parse(JSON.parse(
|
|
56331
|
+
return CopiesSchema.parse(JSON.parse(readFileSync32(backup.copies, "utf8")));
|
|
56253
56332
|
} catch {
|
|
56254
56333
|
return {};
|
|
56255
56334
|
}
|
|
@@ -56272,7 +56351,7 @@ function createXfsBackups(ctx) {
|
|
|
56272
56351
|
return {
|
|
56273
56352
|
createBackupCopy: async (impId, _runId, options) => {
|
|
56274
56353
|
const source = ctx.resolveImpPaths(impId).disk;
|
|
56275
|
-
const target =
|
|
56354
|
+
const target = join39(backup.tree, BACKUP_TREE.buildDisk(impId));
|
|
56276
56355
|
const stats = statSync15(source, { bigint: true });
|
|
56277
56356
|
const record = {
|
|
56278
56357
|
ino: String(stats.ino),
|
|
@@ -56300,34 +56379,34 @@ function createXfsBackups(ctx) {
|
|
|
56300
56379
|
const checkpointIds = new Set;
|
|
56301
56380
|
const imageDigests = new Set;
|
|
56302
56381
|
for (const imp of request.imps) {
|
|
56303
|
-
if (!existsSync25(
|
|
56382
|
+
if (!existsSync25(join39(backup.tree, BACKUP_TREE.buildDisk(imp.impId)))) {
|
|
56304
56383
|
continue;
|
|
56305
56384
|
}
|
|
56306
56385
|
impIds.add(imp.impId);
|
|
56307
56386
|
for (const checkpointId of imp.checkpointIds) {
|
|
56308
|
-
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)));
|
|
56309
56388
|
if (isCopied) {
|
|
56310
56389
|
checkpointIds.add(checkpointId);
|
|
56311
56390
|
}
|
|
56312
56391
|
}
|
|
56313
|
-
removeUnlisted(
|
|
56392
|
+
removeUnlisted(join39(backup.tree, BACKUP_TREE.buildImpDir(imp.impId), "checkpoints"), new Set(imp.checkpointIds.filter((id) => checkpointIds.has(id))));
|
|
56314
56393
|
}
|
|
56315
56394
|
for (const digest of request.imageDigests) {
|
|
56316
56395
|
const source = buildImagePaths(ctx.dataDir, digest);
|
|
56317
|
-
const directory =
|
|
56318
|
-
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"));
|
|
56319
56398
|
if (isCopied) {
|
|
56320
|
-
copyFileSync4(source.config,
|
|
56399
|
+
copyFileSync4(source.config, join39(directory, "config.json"));
|
|
56321
56400
|
imageDigests.add(digest);
|
|
56322
56401
|
}
|
|
56323
56402
|
}
|
|
56324
|
-
removeUnlisted(
|
|
56325
|
-
removeUnlisted(
|
|
56403
|
+
removeUnlisted(join39(backup.tree, "imps"), impIds);
|
|
56404
|
+
removeUnlisted(join39(backup.tree, "images"), new Set([...imageDigests].map((digest) => basename5(BACKUP_TREE.buildImageDir(digest)))));
|
|
56326
56405
|
const copies = readCopies();
|
|
56327
56406
|
writeCopies(Object.fromEntries(Object.entries(copies).filter(([id]) => impIds.has(id))));
|
|
56328
56407
|
const removeFreshCopies = () => {
|
|
56329
56408
|
for (const impId of freshCopies) {
|
|
56330
|
-
rmSync30(
|
|
56409
|
+
rmSync30(join39(backup.tree, BACKUP_TREE.buildDisk(impId)), { force: true });
|
|
56331
56410
|
}
|
|
56332
56411
|
freshCopies.clear();
|
|
56333
56412
|
return Promise.resolve();
|
|
@@ -56339,18 +56418,18 @@ function createXfsBackups(ctx) {
|
|
|
56339
56418
|
function removeUnlisted(directory, keep) {
|
|
56340
56419
|
const names = existsSync25(directory) ? readdirSync10(directory) : [];
|
|
56341
56420
|
for (const name of names.filter((entry) => !keep.has(entry))) {
|
|
56342
|
-
rmSync30(
|
|
56421
|
+
rmSync30(join39(directory, name), { recursive: true, force: true });
|
|
56343
56422
|
}
|
|
56344
56423
|
}
|
|
56345
56424
|
|
|
56346
56425
|
// packages/daemon/src/vm/storage/loop-backing-file.ts
|
|
56347
|
-
import { readFileSync as
|
|
56348
|
-
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";
|
|
56349
56428
|
var HOST_DIRS = { procDir: "/proc", sysDir: "/sys" };
|
|
56350
56429
|
function readLoopBackingFile(directory, hostDirs = HOST_DIRS) {
|
|
56351
56430
|
try {
|
|
56352
56431
|
const target = realpathSync(directory);
|
|
56353
|
-
const mountInfo =
|
|
56432
|
+
const mountInfo = readFileSync33(join40(hostDirs.procDir, "self", "mountinfo"), "utf8");
|
|
56354
56433
|
for (const line of mountInfo.split(`
|
|
56355
56434
|
`)) {
|
|
56356
56435
|
const [mounts = "", fields = ""] = line.split(" - ");
|
|
@@ -56358,8 +56437,8 @@ function readLoopBackingFile(directory, hostDirs = HOST_DIRS) {
|
|
|
56358
56437
|
const [, source = ""] = fields.split(" ");
|
|
56359
56438
|
const loop = /^\/dev\/(?<name>loop\d+)$/u.exec(source)?.groups?.["name"];
|
|
56360
56439
|
if (mountPoint === target && loop !== undefined) {
|
|
56361
|
-
const backing =
|
|
56362
|
-
return
|
|
56440
|
+
const backing = join40(hostDirs.sysDir, "block", loop, "loop", "backing_file");
|
|
56441
|
+
return readFileSync33(backing, "utf8").trim();
|
|
56363
56442
|
}
|
|
56364
56443
|
}
|
|
56365
56444
|
} catch {}
|
|
@@ -56380,7 +56459,7 @@ function readLoopHostFreeBytes(directory, hostDirs = HOST_DIRS) {
|
|
|
56380
56459
|
|
|
56381
56460
|
// packages/daemon/src/vm/storage/orphan-files.ts
|
|
56382
56461
|
import { existsSync as existsSync26, readdirSync as readdirSync11, statSync as statSync16 } from "fs";
|
|
56383
|
-
import { join as
|
|
56462
|
+
import { join as join41 } from "path";
|
|
56384
56463
|
function probeHoldingFiles(directory) {
|
|
56385
56464
|
return existsSync26(directory) && readdirSync11(directory, { recursive: true, withFileTypes: true }).some((entry) => !entry.isDirectory());
|
|
56386
56465
|
}
|
|
@@ -56388,7 +56467,7 @@ function listFilesUnder(directory) {
|
|
|
56388
56467
|
if (!existsSync26(directory)) {
|
|
56389
56468
|
return [];
|
|
56390
56469
|
}
|
|
56391
|
-
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));
|
|
56392
56471
|
}
|
|
56393
56472
|
function readDirectoryOrphan(kind, id, directory, snapshots) {
|
|
56394
56473
|
const birth = statSync16(directory).birthtimeMs;
|
|
@@ -56414,7 +56493,7 @@ function createXfsBackend(deps) {
|
|
|
56414
56493
|
const cloneFile = deps.cloneFile ?? createReflinkClone;
|
|
56415
56494
|
const readFileExtents = deps.readFileExtents ?? readExtents;
|
|
56416
56495
|
const resolveImpPaths = (impId) => buildImpPaths(deps.dataDir, impId);
|
|
56417
|
-
const buildCheckpointDisk = (impId, checkpointId) =>
|
|
56496
|
+
const buildCheckpointDisk = (impId, checkpointId) => join42(resolveImpPaths(impId).checkpointsDir, checkpointId, "disk.ext4");
|
|
56418
56497
|
const getSourceFile = (source) => {
|
|
56419
56498
|
if (source.kind === "image") {
|
|
56420
56499
|
return buildImagePaths(deps.dataDir, source.digest).rootfs;
|
|
@@ -56429,7 +56508,7 @@ function createXfsBackend(deps) {
|
|
|
56429
56508
|
};
|
|
56430
56509
|
const createImage = async (digest, write) => {
|
|
56431
56510
|
const paths = buildImagePaths(deps.dataDir, digest);
|
|
56432
|
-
const staged =
|
|
56511
|
+
const staged = join42(buildImagesDir(deps.dataDir), `${STAGING_PREFIX}${Bun.randomUUIDv7()}`);
|
|
56433
56512
|
mkdirSync27(staged, { recursive: true });
|
|
56434
56513
|
try {
|
|
56435
56514
|
await write(staged);
|
|
@@ -56450,13 +56529,13 @@ function createXfsBackend(deps) {
|
|
|
56450
56529
|
return listEntries2(directory).map((id) => ({
|
|
56451
56530
|
kind: "checkpoint",
|
|
56452
56531
|
id,
|
|
56453
|
-
directory:
|
|
56532
|
+
directory: join42(directory, id)
|
|
56454
56533
|
}));
|
|
56455
56534
|
}).filter((checkpoint) => !live.checkpointIds.has(checkpoint.id));
|
|
56456
56535
|
const unknownImages = listEntries2(buildImagesDir(deps.dataDir)).filter((name) => !name.startsWith(".") && !liveDigests.has(name)).map((name) => ({
|
|
56457
56536
|
kind: "image",
|
|
56458
56537
|
id: name,
|
|
56459
|
-
directory:
|
|
56538
|
+
directory: join42(buildImagesDir(deps.dataDir), name)
|
|
56460
56539
|
}));
|
|
56461
56540
|
const unknownImps = impIds.filter((impId) => !live.impIds.has(impId)).map((impId) => ({
|
|
56462
56541
|
kind: "imp",
|
|
@@ -56476,14 +56555,14 @@ function createXfsBackend(deps) {
|
|
|
56476
56555
|
};
|
|
56477
56556
|
const removeLeftover = (dropped, live) => {
|
|
56478
56557
|
if (dropped.kind === "image") {
|
|
56479
|
-
rmSync31(
|
|
56558
|
+
rmSync31(join42(buildImagesDir(deps.dataDir), dropped.id), { recursive: true, force: true });
|
|
56480
56559
|
}
|
|
56481
56560
|
if (dropped.kind === "imp") {
|
|
56482
56561
|
rmSync31(resolveImpPaths(dropped.id).directory, { recursive: true, force: true });
|
|
56483
56562
|
}
|
|
56484
56563
|
if (dropped.kind === "checkpoint") {
|
|
56485
56564
|
for (const impId of live.impIds) {
|
|
56486
|
-
rmSync31(
|
|
56565
|
+
rmSync31(join42(resolveImpPaths(impId).checkpointsDir, dropped.id), {
|
|
56487
56566
|
recursive: true,
|
|
56488
56567
|
force: true
|
|
56489
56568
|
});
|
|
@@ -56498,7 +56577,7 @@ function createXfsBackend(deps) {
|
|
|
56498
56577
|
const listOtherFiles = () => {
|
|
56499
56578
|
const images = listEntries2(buildImagesDir(deps.dataDir)).filter((name) => !name.startsWith(".")).map((name) => ({
|
|
56500
56579
|
owner: `image:${name}`,
|
|
56501
|
-
path:
|
|
56580
|
+
path: join42(buildImagesDir(deps.dataDir), name, "rootfs.ext4")
|
|
56502
56581
|
}));
|
|
56503
56582
|
const tree = listFilesUnder(backup.tree).map((path) => ({ owner: "backup", path }));
|
|
56504
56583
|
return [...images, ...tree].filter((file) => existsSync27(file.path));
|
|
@@ -56506,7 +56585,7 @@ function createXfsBackend(deps) {
|
|
|
56506
56585
|
const usageState = { resumeImpId: null };
|
|
56507
56586
|
const setupReserveFile = async () => {
|
|
56508
56587
|
const bytes = deps.reserveFileBytes ?? 0;
|
|
56509
|
-
const file =
|
|
56588
|
+
const file = join42(deps.dataDir, "reserve");
|
|
56510
56589
|
if (bytes === 0 || existsSync27(file)) {
|
|
56511
56590
|
return;
|
|
56512
56591
|
}
|
|
@@ -56536,7 +56615,7 @@ function createXfsBackend(deps) {
|
|
|
56536
56615
|
start: (live) => {
|
|
56537
56616
|
const imagesDir = buildImagesDir(deps.dataDir);
|
|
56538
56617
|
for (const name of listEntries2(imagesDir).filter((entry) => entry.startsWith("."))) {
|
|
56539
|
-
rmSync31(
|
|
56618
|
+
rmSync31(join42(imagesDir, name), { recursive: true, force: true });
|
|
56540
56619
|
}
|
|
56541
56620
|
const swept = removeUnnamed(live, { isDryRun: false, isOrphans: false });
|
|
56542
56621
|
printSweep(getImpdLogger("storage"), swept, "each");
|
|
@@ -56558,7 +56637,7 @@ function createXfsBackend(deps) {
|
|
|
56558
56637
|
receiveMoveSnapshots: () => Promise.reject(new Error("xfs: only a ZFS host receives ZFS streams")),
|
|
56559
56638
|
createImage,
|
|
56560
56639
|
createImageFromImp: (digest, impId, steps) => createImage(digest, async (directory) => {
|
|
56561
|
-
await steps.hold(() => cloneFile(resolveImpPaths(impId).disk,
|
|
56640
|
+
await steps.hold(() => cloneFile(resolveImpPaths(impId).disk, join42(directory, "rootfs.ext4")));
|
|
56562
56641
|
await steps.write(directory);
|
|
56563
56642
|
}),
|
|
56564
56643
|
removeImage: (digest) => {
|
|
@@ -56700,8 +56779,8 @@ function isSharedExtent(extent) {
|
|
|
56700
56779
|
}
|
|
56701
56780
|
|
|
56702
56781
|
// packages/daemon/src/vm/storage/zfs/zfs-backend.ts
|
|
56703
|
-
import { existsSync as existsSync30, mkdirSync as mkdirSync28, readFileSync as
|
|
56704
|
-
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";
|
|
56705
56784
|
|
|
56706
56785
|
// packages/daemon/src/platform/process/run-stream.ts
|
|
56707
56786
|
function createStreamRunner() {
|
|
@@ -56990,7 +57069,7 @@ function formatUiomoveWarning(version) {
|
|
|
56990
57069
|
|
|
56991
57070
|
// packages/daemon/src/vm/storage/zfs/create-zfs-backups.ts
|
|
56992
57071
|
import { rmSync as rmSync32 } from "fs";
|
|
56993
|
-
import { dirname as dirname14, join as
|
|
57072
|
+
import { dirname as dirname14, join as join43 } from "path";
|
|
56994
57073
|
function createZfsBackups(ctx) {
|
|
56995
57074
|
return {
|
|
56996
57075
|
createBackupCopy: (impId, runId) => ctx.runSnapshot(() => ctx.zfs.snapshot(`${ctx.buildDiskName(impId)}@bk-${runId}-${impId}`)),
|
|
@@ -57017,7 +57096,7 @@ function createZfsBackups(ctx) {
|
|
|
57017
57096
|
ctx.startReclaim();
|
|
57018
57097
|
};
|
|
57019
57098
|
const createTreeClone = async (snapshot, name, relativeDir) => {
|
|
57020
|
-
const directory =
|
|
57099
|
+
const directory = join43(tree, relativeDir);
|
|
57021
57100
|
await ctx.zfs.clone(snapshot, name, { readonly: "on" });
|
|
57022
57101
|
clones.push({ name, directory });
|
|
57023
57102
|
await ctx.setupMount(name, directory, true);
|
|
@@ -57027,8 +57106,8 @@ function createZfsBackups(ctx) {
|
|
|
57027
57106
|
if (mounted !== undefined) {
|
|
57028
57107
|
throw new Error(`zfs: ${mounted} in the backup tree is still mounted`);
|
|
57029
57108
|
}
|
|
57030
|
-
rmSync32(
|
|
57031
|
-
rmSync32(
|
|
57109
|
+
rmSync32(join43(tree, "imps"), { recursive: true, force: true });
|
|
57110
|
+
rmSync32(join43(tree, "images"), { recursive: true, force: true });
|
|
57032
57111
|
const entries = await ctx.listAll();
|
|
57033
57112
|
for (const imp of request.imps) {
|
|
57034
57113
|
const copy = entries.find((entry) => entry.type === "snapshot" && entry.name.endsWith(`@bk-${request.runId}-${imp.impId}`));
|
|
@@ -57161,7 +57240,7 @@ function createZfsCheckpoints(ctx) {
|
|
|
57161
57240
|
}
|
|
57162
57241
|
|
|
57163
57242
|
// packages/daemon/src/vm/storage/zfs/create-zfs-moves.ts
|
|
57164
|
-
import { join as
|
|
57243
|
+
import { join as join44 } from "path";
|
|
57165
57244
|
function createZfsMoves(ctx) {
|
|
57166
57245
|
const openMoveFiles = async (snapshots, removeMoveSnapshot) => {
|
|
57167
57246
|
const moveId = Bun.randomUUIDv7();
|
|
@@ -57190,7 +57269,7 @@ function createZfsMoves(ctx) {
|
|
|
57190
57269
|
await removeClones();
|
|
57191
57270
|
throw error;
|
|
57192
57271
|
}
|
|
57193
|
-
const paths = clones.map((clone) =>
|
|
57272
|
+
const paths = clones.map((clone) => join44(clone.directory, ctx.rootfsFile));
|
|
57194
57273
|
return {
|
|
57195
57274
|
kind: "files",
|
|
57196
57275
|
checkpointPaths: paths.slice(0, -1),
|
|
@@ -57446,7 +57525,7 @@ function createZfsReclaim(ctx) {
|
|
|
57446
57525
|
|
|
57447
57526
|
// packages/daemon/src/vm/storage/zfs/create-zfs-sweep.ts
|
|
57448
57527
|
import { existsSync as existsSync28, readdirSync as readdirSync13, rmSync as rmSync33 } from "fs";
|
|
57449
|
-
import { join as
|
|
57528
|
+
import { join as join45 } from "path";
|
|
57450
57529
|
var FORK_SNAPSHOT = /@fork-[^@]+$/u;
|
|
57451
57530
|
var BACKUP_SNAPSHOT = /@bk-[^@]+$/u;
|
|
57452
57531
|
var MOVE_SNAPSHOT = /@mv-[^@]+$/u;
|
|
@@ -57471,10 +57550,10 @@ function createZfsSweep(ctx) {
|
|
|
57471
57550
|
const orphanCheckpoints = isOrphans ? [] : unmarked.filter((entry) => !isOnOrphan(entry) && isOrphanCheckpoint(entry));
|
|
57472
57551
|
const keptDisks = isOrphans ? [] : unknownDisks;
|
|
57473
57552
|
const keptImpIds = new Set(keptDisks.map((disk) => getChildId(disk.name, ctx.datasets.disks)));
|
|
57474
|
-
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) }));
|
|
57475
57554
|
const unknownDirs = [
|
|
57476
57555
|
...listUnknownDirs("imp", buildImpsDir(ctx.dataDir)),
|
|
57477
|
-
...listUnknownDirs("memory",
|
|
57556
|
+
...listUnknownDirs("memory", join45(ctx.dataDir, "mem"))
|
|
57478
57557
|
];
|
|
57479
57558
|
const probeDirDropped = (entry) => isOrphans || !probeHoldingFiles(entry.directory);
|
|
57480
57559
|
const droppedDirs = unknownDirs.filter((entry) => probeDirDropped(entry));
|
|
@@ -57563,7 +57642,7 @@ function createZfsSweep(ctx) {
|
|
|
57563
57642
|
}
|
|
57564
57643
|
}
|
|
57565
57644
|
for (const impId of plan.memDirs) {
|
|
57566
|
-
rmSync33(
|
|
57645
|
+
rmSync33(join45(ctx.dataDir, "mem", impId), { recursive: true, force: true });
|
|
57567
57646
|
}
|
|
57568
57647
|
return { dropped: toDropped(plan), kept };
|
|
57569
57648
|
};
|
|
@@ -57651,13 +57730,13 @@ function createZfsBackend(deps) {
|
|
|
57651
57730
|
const buildDiskName = (impId) => `${datasets.disks}/${impId}`;
|
|
57652
57731
|
const buildImageName = (digest) => `${datasets.images}/${toDigestHex(digest)}`;
|
|
57653
57732
|
const buildRestoreName = (impId) => `${datasets.staging}/restore-${impId}`;
|
|
57654
|
-
const buildDiskDir = (impId) =>
|
|
57733
|
+
const buildDiskDir = (impId) => join46(buildImpPaths(deps.dataDir, impId).directory, "disk");
|
|
57655
57734
|
const buildImageDir = (digest) => buildImagePaths(deps.dataDir, digest).directory;
|
|
57656
|
-
const buildStagingDir = (name) =>
|
|
57735
|
+
const buildStagingDir = (name) => join46(deps.dataDir, "staging", name.slice(datasets.staging.length + 1));
|
|
57657
57736
|
const resolveImpPaths = (impId) => ({
|
|
57658
57737
|
...buildImpPaths(deps.dataDir, impId),
|
|
57659
|
-
disk:
|
|
57660
|
-
...buildSnapshotPaths(
|
|
57738
|
+
disk: join46(buildDiskDir(impId), ROOTFS_FILE),
|
|
57739
|
+
...buildSnapshotPaths(join46(deps.dataDir, "mem", impId))
|
|
57661
57740
|
});
|
|
57662
57741
|
const listAll = () => zfs.list(deps.root);
|
|
57663
57742
|
const setupMount = async (name, directory, isReadOnly = false) => {
|
|
@@ -57800,7 +57879,7 @@ function createZfsBackend(deps) {
|
|
|
57800
57879
|
throw new Error(`zfs: ${deps.root} is not mounted on ${deps.dataDir} (host/scripts/setup-storage.sh mounts it)`);
|
|
57801
57880
|
}
|
|
57802
57881
|
await createMissingDatasets();
|
|
57803
|
-
await setupMount(datasets.mem,
|
|
57882
|
+
await setupMount(datasets.mem, join46(deps.dataDir, "mem"));
|
|
57804
57883
|
await resolveStaging();
|
|
57805
57884
|
const swept = await sweep.removeLeftovers(live, { isDryRun: false, isOrphans: false });
|
|
57806
57885
|
printSweep(getImpdLogger("storage"), swept, "each");
|
|
@@ -57885,7 +57964,7 @@ function createZfsBackend(deps) {
|
|
|
57885
57964
|
await zfs.create(target);
|
|
57886
57965
|
await setupMount(target, buildDiskDir(impId));
|
|
57887
57966
|
});
|
|
57888
|
-
writeFileSync13(
|
|
57967
|
+
writeFileSync13(join46(buildDiskDir(impId), ROOTFS_FILE), "");
|
|
57889
57968
|
return;
|
|
57890
57969
|
}
|
|
57891
57970
|
await runSerial(async () => {
|
|
@@ -57962,7 +58041,7 @@ function createZfsBackend(deps) {
|
|
|
57962
58041
|
}
|
|
57963
58042
|
function readZfsModuleVersion() {
|
|
57964
58043
|
try {
|
|
57965
|
-
return
|
|
58044
|
+
return readFileSync34("/sys/module/zfs/version", "utf8").trim();
|
|
57966
58045
|
} catch {
|
|
57967
58046
|
return null;
|
|
57968
58047
|
}
|
|
@@ -58005,14 +58084,14 @@ function createBackend(config, boundaries) {
|
|
|
58005
58084
|
});
|
|
58006
58085
|
}
|
|
58007
58086
|
function checkStorageMarker(dataDir, kind) {
|
|
58008
|
-
const marker =
|
|
58009
|
-
const recorded = existsSync31(marker) ?
|
|
58087
|
+
const marker = join47(dataDir, MARKER_FILE);
|
|
58088
|
+
const recorded = existsSync31(marker) ? readFileSync35(marker, "utf8").trim() : readUnmarked(dataDir);
|
|
58010
58089
|
if (recorded !== null && recorded !== kind) {
|
|
58011
58090
|
throw new Error(`${dataDir} holds ${recorded} storage, but IMP_STORAGE_BACKEND is ${kind}; moving imps between backends is not supported`);
|
|
58012
58091
|
}
|
|
58013
58092
|
}
|
|
58014
58093
|
function writeStorageMarker(dataDir, kind) {
|
|
58015
|
-
const marker =
|
|
58094
|
+
const marker = join47(dataDir, MARKER_FILE);
|
|
58016
58095
|
if (!existsSync31(marker)) {
|
|
58017
58096
|
writeFileSync14(marker, `${kind}
|
|
58018
58097
|
`);
|
|
@@ -58025,7 +58104,7 @@ function readUnmarked(dataDir) {
|
|
|
58025
58104
|
}
|
|
58026
58105
|
|
|
58027
58106
|
// packages/daemon/src/vm/storage/setup-system-files.ts
|
|
58028
|
-
import { existsSync as existsSync32, mkdirSync as mkdirSync29, readFileSync as
|
|
58107
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync29, readFileSync as readFileSync36 } from "fs";
|
|
58029
58108
|
import { dirname as dirname15 } from "path";
|
|
58030
58109
|
|
|
58031
58110
|
// packages/daemon/src/vm/storage/system-file-info.ts
|
|
@@ -58061,7 +58140,7 @@ async function setupSystemFiles(config) {
|
|
|
58061
58140
|
const missing = config.kernelSource === null ? " and no source is configured" : "";
|
|
58062
58141
|
throw new Error(`${kernelSource} does not exist${missing}`);
|
|
58063
58142
|
}
|
|
58064
|
-
const kernel =
|
|
58143
|
+
const kernel = readFileSync36(kernelSource);
|
|
58065
58144
|
const guestKernel = readKernelInfo(kernel);
|
|
58066
58145
|
if (config.kernelSource !== null && !probeContent(config.kernelPath, kernel)) {
|
|
58067
58146
|
writeCopy(config.kernelSource, config.kernelPath);
|
|
@@ -58081,7 +58160,7 @@ async function setupSystemFiles(config) {
|
|
|
58081
58160
|
};
|
|
58082
58161
|
}
|
|
58083
58162
|
function probeContent(path, content) {
|
|
58084
|
-
return existsSync32(path) && Buffer.from(content).equals(
|
|
58163
|
+
return existsSync32(path) && Buffer.from(content).equals(readFileSync36(path));
|
|
58085
58164
|
}
|
|
58086
58165
|
function writeCopy(source, target) {
|
|
58087
58166
|
mkdirSync29(dirname15(target), { recursive: true });
|
|
@@ -58133,7 +58212,7 @@ async function startImpdParts(config, boundaries, plan) {
|
|
|
58133
58212
|
}
|
|
58134
58213
|
return files;
|
|
58135
58214
|
});
|
|
58136
|
-
const db = await runStep("database", () => boundaries.db ?? openDatabase(
|
|
58215
|
+
const db = await runStep("database", () => boundaries.db ?? openDatabase(join48(config.dataDir, "db", "imp.sqlite")));
|
|
58137
58216
|
plan.db = boundaries.db === undefined ? db : null;
|
|
58138
58217
|
const kernelOops = boundaries.imps?.kernelOops ?? createKernelOopsWatch();
|
|
58139
58218
|
const storage = boundaries.storage ?? createStorageBackend(config, { zfs: { isKernelOopsed: kernelOops.isOopsed } });
|
|
@@ -58240,7 +58319,7 @@ async function startImpdParts(config, boundaries, plan) {
|
|
|
58240
58319
|
secretFiles
|
|
58241
58320
|
});
|
|
58242
58321
|
const state = { ready: false };
|
|
58243
|
-
const authorizedKeys = createAuthorizedKeys(
|
|
58322
|
+
const authorizedKeys = createAuthorizedKeys(join48(setupSshDir(config.dataDir), "authorized_keys"));
|
|
58244
58323
|
const access = await runStep("access", () => loadImpdAccess(config, deps, authorizedKeys.probeListed));
|
|
58245
58324
|
const backups = config.backup === null ? null : createBackupService({
|
|
58246
58325
|
dataDir: config.dataDir,
|
|
@@ -58306,7 +58385,7 @@ async function startImpdParts(config, boundaries, plan) {
|
|
|
58306
58385
|
readTailnetNames: tailnetNames === null ? null : tailnetNames.readStatus,
|
|
58307
58386
|
hostReaders: {
|
|
58308
58387
|
readKernel: () => deps.hostKernelRelease ?? release2(),
|
|
58309
|
-
readCpuInfo: deps.readCpuInfo ?? (() =>
|
|
58388
|
+
readCpuInfo: deps.readCpuInfo ?? (() => readFileSync37("/proc/cpuinfo", "utf8")),
|
|
58310
58389
|
readHugePagePool: deps.imps?.readHugePagePool ?? (() => readHugePagePool())
|
|
58311
58390
|
},
|
|
58312
58391
|
isReady: () => state.ready,
|
|
@@ -58425,6 +58504,11 @@ function buildStubTickerTimer() {
|
|
|
58425
58504
|
};
|
|
58426
58505
|
}
|
|
58427
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
|
+
|
|
58428
58512
|
// packages/daemon/testing/platform/open-migrated-copy.ts
|
|
58429
58513
|
import { Database as Database4 } from "bun:sqlite";
|
|
58430
58514
|
var TEMPLATE = {};
|
|
@@ -58447,6 +58531,15 @@ function pickImpdPort(draw) {
|
|
|
58447
58531
|
return FIRST_PORT + Math.floor(draw * PORT_SPAN);
|
|
58448
58532
|
}
|
|
58449
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
|
+
|
|
58450
58543
|
// packages/daemon/testing/platform/start-impd-log-capture.ts
|
|
58451
58544
|
import { resetSync } from "@logtape/logtape";
|
|
58452
58545
|
|
|
@@ -58912,7 +59005,7 @@ var NO_FREEZER = { freeze: () => Promise.resolve(), thaw: () => Promise.resolve(
|
|
|
58912
59005
|
var KSM_KERNEL = "6.12.0";
|
|
58913
59006
|
var IDLE_KSM = { running: true, sharedMib: 0, profitMib: 0, zeroMib: 0 };
|
|
58914
59007
|
async function startTestImpd(stack, options = {}) {
|
|
58915
|
-
const dataDir = options.dataDir ?? mkdtempSync(`${tmpdir()}
|
|
59008
|
+
const dataDir = options.dataDir ?? mkdtempSync(`${tmpdir()}/${formatRunPrefix(readRunOwner())}impd-test-`);
|
|
58916
59009
|
if (options.dataDir === undefined) {
|
|
58917
59010
|
stack.defer(() => rm2(dataDir, { recursive: true, force: true }));
|
|
58918
59011
|
}
|
|
@@ -58983,6 +59076,7 @@ async function startTestImpd(stack, options = {}) {
|
|
|
58983
59076
|
});
|
|
58984
59077
|
const cgroups = options.cgroups ?? createCpuCgroups({ root: "/nonexistent" });
|
|
58985
59078
|
const extra = options.boundaries ?? {};
|
|
59079
|
+
const procRoot = options.procRoot;
|
|
58986
59080
|
const buildBoundaries = (identity, runner, storage) => {
|
|
58987
59081
|
const jails = options.jails;
|
|
58988
59082
|
return {
|
|
@@ -59082,6 +59176,9 @@ async function startTestImpd(stack, options = {}) {
|
|
|
59082
59176
|
hostCpus: options.hostCpus ?? 8,
|
|
59083
59177
|
kernelOops,
|
|
59084
59178
|
readThreadIds: (pid) => options.procRoot === undefined ? null : readThreadIds(pid, options.procRoot),
|
|
59179
|
+
...procRoot !== undefined && {
|
|
59180
|
+
readHostLoad: () => readHostLoad({ procRoot, readFile: readText, logger: getImpdLogger("imps") })
|
|
59181
|
+
},
|
|
59085
59182
|
...options.readUnsharedRamMib !== undefined && {
|
|
59086
59183
|
readUnsharedRamMib: options.readUnsharedRamMib
|
|
59087
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"
|