@impz/testing 6.4.2 → 6.6.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 +297 -158
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -18834,7 +18834,11 @@ import { createImpClient as createImpClient2, watchEvents } from "@impz/client";
|
|
|
18834
18834
|
// packages/daemon/src/vm/storage/data-layout.ts
|
|
18835
18835
|
import { mkdirSync } from "fs";
|
|
18836
18836
|
import { join } from "path";
|
|
18837
|
-
var UFFD_RUN_FILES = {
|
|
18837
|
+
var UFFD_RUN_FILES = {
|
|
18838
|
+
socket: "uffd.sock",
|
|
18839
|
+
pidFile: "uffd.pid",
|
|
18840
|
+
statsFile: "uffd.stats"
|
|
18841
|
+
};
|
|
18838
18842
|
var DATA_DIRS = ["db", "system", "images", "imps"];
|
|
18839
18843
|
function createDataDirs(dataDir) {
|
|
18840
18844
|
for (const name of DATA_DIRS) {
|
|
@@ -18864,6 +18868,7 @@ function buildImpPaths(dataDir, impId) {
|
|
|
18864
18868
|
pidFile: join(runDir, "pid"),
|
|
18865
18869
|
uffdSocket: join(runDir, UFFD_RUN_FILES.socket),
|
|
18866
18870
|
uffdPidFile: join(runDir, UFFD_RUN_FILES.pidFile),
|
|
18871
|
+
uffdStatsFile: join(runDir, UFFD_RUN_FILES.statsFile),
|
|
18867
18872
|
...buildSnapshotPaths(join(directory, "snapshot")),
|
|
18868
18873
|
vmIdentity: join(directory, "vm.json"),
|
|
18869
18874
|
checkpointsDir: join(directory, "checkpoints"),
|
|
@@ -21961,18 +21966,19 @@ function parseKsmConfig(parsed) {
|
|
|
21961
21966
|
}
|
|
21962
21967
|
|
|
21963
21968
|
// packages/daemon/src/create-impd.ts
|
|
21964
|
-
import { readFileSync as
|
|
21969
|
+
import { readFileSync as readFileSync38 } from "fs";
|
|
21965
21970
|
import { release as release2 } from "os";
|
|
21966
|
-
import { join as
|
|
21971
|
+
import { join as join48 } from "path";
|
|
21967
21972
|
// packages/daemon/package.json
|
|
21968
21973
|
var package_default = {
|
|
21969
21974
|
name: "@impz/daemon",
|
|
21970
|
-
version: "6.
|
|
21975
|
+
version: "6.6.0",
|
|
21971
21976
|
private: true,
|
|
21972
21977
|
description: "impd: the imp host daemon",
|
|
21973
21978
|
type: "module",
|
|
21974
21979
|
exports: {
|
|
21975
21980
|
".": "./src/index.ts",
|
|
21981
|
+
"./read-text": "./src/platform/process/read-text.ts",
|
|
21976
21982
|
"./real-clock": "./src/platform/process/real-clock.ts",
|
|
21977
21983
|
"./testing": "./testing/index.ts",
|
|
21978
21984
|
"./testing/build-stub-clock": "./testing/platform/build-stub-clock.ts",
|
|
@@ -24140,6 +24146,12 @@ function writeRegularFile(path, text) {
|
|
|
24140
24146
|
closeSync2(fd);
|
|
24141
24147
|
}
|
|
24142
24148
|
}
|
|
24149
|
+
function createZeroedFile(path, sizeBytes) {
|
|
24150
|
+
const fd = openRegularFile(path, constants.O_RDWR, 420);
|
|
24151
|
+
ftruncateSync(fd, 0);
|
|
24152
|
+
ftruncateSync(fd, sizeBytes);
|
|
24153
|
+
return fd;
|
|
24154
|
+
}
|
|
24143
24155
|
function readRegularFile(path) {
|
|
24144
24156
|
const fd = openSync2(path, constants.O_RDONLY | SAFE_FLAGS);
|
|
24145
24157
|
try {
|
|
@@ -37525,6 +37537,7 @@ async function createImpdFirewall(config, deps, secretFiles, plan) {
|
|
|
37525
37537
|
}
|
|
37526
37538
|
|
|
37527
37539
|
// packages/daemon/src/create-impd-imps.ts
|
|
37540
|
+
import { readFileSync as readFileSync25 } from "fs";
|
|
37528
37541
|
import { availableParallelism } from "os";
|
|
37529
37542
|
|
|
37530
37543
|
// packages/daemon/src/host-net/net/tap-bytes.ts
|
|
@@ -41112,7 +41125,8 @@ function createImpContext(deps) {
|
|
|
41112
41125
|
const records = {
|
|
41113
41126
|
config: deps.config,
|
|
41114
41127
|
db: deps.db,
|
|
41115
|
-
identity: deps.identity
|
|
41128
|
+
identity: deps.identity,
|
|
41129
|
+
readHostLoad: deps.readHostLoad
|
|
41116
41130
|
};
|
|
41117
41131
|
const clock = {
|
|
41118
41132
|
now,
|
|
@@ -42545,6 +42559,11 @@ function readDiskMib(path) {
|
|
|
42545
42559
|
}
|
|
42546
42560
|
}
|
|
42547
42561
|
|
|
42562
|
+
// packages/daemon/src/imps/imps/format-page-handler.ts
|
|
42563
|
+
function formatPageHandler(stats) {
|
|
42564
|
+
return stats === undefined ? "" : `; page handler faults=${String(stats.faults)} blocks=${String(stats.blocks)} serve=${String(stats.serveMs)}ms`;
|
|
42565
|
+
}
|
|
42566
|
+
|
|
42548
42567
|
// packages/daemon/src/imps/imps/pick-huge-pages.ts
|
|
42549
42568
|
function pickHugePages(isOn, imp) {
|
|
42550
42569
|
return isOn && imp.maxMemoryMib <= imp.memoryMib && imp.memoryMib % 2 === 0 ? "2M" : "None";
|
|
@@ -42626,10 +42645,11 @@ function makeWakeImpVm(deps) {
|
|
|
42626
42645
|
return startAfterFailedWake(imp, paths, wrong);
|
|
42627
42646
|
}
|
|
42628
42647
|
const wakeMs = Math.round(performance.now() - started);
|
|
42629
|
-
getImpdLogger("imps").with({ imp: imp.name }).info("woke pid {pid} in {wakeMs}ms {timings}", {
|
|
42648
|
+
getImpdLogger("imps").with({ imp: imp.name }).info("woke pid {pid} in {wakeMs}ms {timings}{pageHandler}", {
|
|
42630
42649
|
pid: String(woken.pid),
|
|
42631
42650
|
wakeMs: String(wakeMs),
|
|
42632
|
-
timings: formatTimings(woken.timings)
|
|
42651
|
+
timings: formatTimings(woken.timings),
|
|
42652
|
+
pageHandler: formatPageHandler(woken.pageHandler)
|
|
42633
42653
|
});
|
|
42634
42654
|
if (hugePages === "None") {
|
|
42635
42655
|
writeHostPagesIdentity(imp, paths);
|
|
@@ -43204,10 +43224,11 @@ function probeSealedEntry(paths, path) {
|
|
|
43204
43224
|
const entry = lstatSync3(path);
|
|
43205
43225
|
const uffdSocket = join21(paths.runDir, UFFD_RUN_FILES.socket);
|
|
43206
43226
|
const uffdPidFile = join21(paths.runDir, UFFD_RUN_FILES.pidFile);
|
|
43227
|
+
const uffdStatsFile = join21(paths.runDir, UFFD_RUN_FILES.statsFile);
|
|
43207
43228
|
if (path === paths.apiSocket || path === paths.vsockSocket || path === uffdSocket) {
|
|
43208
43229
|
return entry.isSocket();
|
|
43209
43230
|
}
|
|
43210
|
-
return (path === paths.logFile || path === paths.pidFile || path === uffdPidFile) && entry.isFile() && entry.uid === IMPD_USER.uid && entry.nlink === 1;
|
|
43231
|
+
return (path === paths.logFile || path === paths.pidFile || path === uffdPidFile || path === uffdStatsFile) && entry.isFile() && entry.uid === IMPD_USER.uid && entry.nlink === 1;
|
|
43211
43232
|
}
|
|
43212
43233
|
function setupImpdDir(directory) {
|
|
43213
43234
|
setupRealDir(directory);
|
|
@@ -43252,6 +43273,16 @@ function readOwnerUid(path) {
|
|
|
43252
43273
|
|
|
43253
43274
|
// packages/daemon/src/vm/vmm/uffd-handler.ts
|
|
43254
43275
|
import { closeSync as closeSync10, existsSync as existsSync13, openSync as openSync8, rmSync as rmSync20 } from "fs";
|
|
43276
|
+
|
|
43277
|
+
// packages/daemon/src/vm/vmm/uffd-stats-layout.ts
|
|
43278
|
+
var UFFD_STATS_OFFSETS = {
|
|
43279
|
+
faults: 0,
|
|
43280
|
+
blocks: 8,
|
|
43281
|
+
serveNs: 16
|
|
43282
|
+
};
|
|
43283
|
+
var UFFD_STATS_BYTES = 24;
|
|
43284
|
+
|
|
43285
|
+
// packages/daemon/src/vm/vmm/uffd-handler.ts
|
|
43255
43286
|
var MEM_FILE_FD = 3;
|
|
43256
43287
|
var SOCKET_WAIT_MS2 = 3000;
|
|
43257
43288
|
async function startUffdHandler(plan) {
|
|
@@ -43264,11 +43295,13 @@ async function startUffdHandler(plan) {
|
|
|
43264
43295
|
...plan.jail === null ? [] : ["--uid", String(plan.jail.uid), "--gid", String(plan.jail.gid)]
|
|
43265
43296
|
];
|
|
43266
43297
|
const memFd = openSync8(plan.memFile, "r");
|
|
43298
|
+
const statsFd = createZeroedFile(paths.uffdStatsFile, UFFD_STATS_BYTES);
|
|
43267
43299
|
const log = setupLogFile(paths.logFile);
|
|
43268
43300
|
const child = Bun.spawn(buildSpawnArgv(command, plan.cgroup?.procsPath ?? null, null), {
|
|
43269
|
-
stdio: ["ignore", log, log, memFd]
|
|
43301
|
+
stdio: ["ignore", log, log, memFd, statsFd]
|
|
43270
43302
|
});
|
|
43271
43303
|
closeSync10(memFd);
|
|
43304
|
+
closeSync10(statsFd);
|
|
43272
43305
|
closeSync10(log);
|
|
43273
43306
|
child.unref();
|
|
43274
43307
|
writeRegularFile(paths.uffdPidFile, `${String(child.pid)}
|
|
@@ -43287,6 +43320,15 @@ function removeUffdFiles(paths) {
|
|
|
43287
43320
|
rmSync20(paths.uffdSocket, { force: true });
|
|
43288
43321
|
rmSync20(`${paths.uffdSocket}.new`, { force: true });
|
|
43289
43322
|
rmSync20(paths.uffdPidFile, { force: true });
|
|
43323
|
+
rmSync20(paths.uffdStatsFile, { force: true });
|
|
43324
|
+
}
|
|
43325
|
+
function readUffdStats(paths, readFile) {
|
|
43326
|
+
const raw = readFile(paths.uffdStatsFile);
|
|
43327
|
+
return {
|
|
43328
|
+
faults: Number(raw.readBigUInt64LE(UFFD_STATS_OFFSETS.faults)),
|
|
43329
|
+
blocks: Number(raw.readBigUInt64LE(UFFD_STATS_OFFSETS.blocks)),
|
|
43330
|
+
serveMs: Math.round(Number(raw.readBigUInt64LE(UFFD_STATS_OFFSETS.serveNs)) / 1e6)
|
|
43331
|
+
};
|
|
43290
43332
|
}
|
|
43291
43333
|
function readHandlerState(paths, procRoot = "/proc") {
|
|
43292
43334
|
if (!existsSync13(paths.uffdPidFile)) {
|
|
@@ -43497,6 +43539,22 @@ ${readLogTail(plan.paths.logFile, 5)}`, step.fault, error);
|
|
|
43497
43539
|
}
|
|
43498
43540
|
}
|
|
43499
43541
|
|
|
43542
|
+
// packages/daemon/src/imps/imps/format-host-stall.ts
|
|
43543
|
+
var STALL_FIGURES = [
|
|
43544
|
+
["cpu", "cpuStallUs"],
|
|
43545
|
+
["io", "ioStallUs"],
|
|
43546
|
+
["memory", "memoryStallUs"],
|
|
43547
|
+
["steal", "stealUs"]
|
|
43548
|
+
];
|
|
43549
|
+
function formatHostStall(before, after) {
|
|
43550
|
+
const figures = STALL_FIGURES.flatMap(([name, field]) => {
|
|
43551
|
+
const startUs = before[field];
|
|
43552
|
+
const endUs = after[field];
|
|
43553
|
+
return startUs === null || endUs === null ? [] : [`${name}=${String(Math.round((endUs - startUs) / 1000))}ms`];
|
|
43554
|
+
});
|
|
43555
|
+
return figures.length === 0 ? "" : `; host stall ${figures.join(" ")}`;
|
|
43556
|
+
}
|
|
43557
|
+
|
|
43500
43558
|
// packages/daemon/src/imps/imps/start-cold-vm.ts
|
|
43501
43559
|
var CLAIM_SEED_BYTES = 64;
|
|
43502
43560
|
async function startColdVm(context, start) {
|
|
@@ -43552,11 +43610,12 @@ async function startColdVm(context, start) {
|
|
|
43552
43610
|
}
|
|
43553
43611
|
});
|
|
43554
43612
|
context.templates?.reportRestored(template);
|
|
43555
|
-
getImpdLogger("imps").with({ imp: imp.name }).info("restored boot template {key} as pid {pid} {timings}{guestSteps}", {
|
|
43613
|
+
getImpdLogger("imps").with({ imp: imp.name }).info("restored boot template {key} as pid {pid} {timings}{guestSteps}{hostStall}", {
|
|
43556
43614
|
key: template.key.slice(0, 12),
|
|
43557
43615
|
pid: String(vm.pid),
|
|
43558
43616
|
timings: formatTimings({ ...hostSteps, ...vm.timings }),
|
|
43559
|
-
guestSteps: formatGuestSteps(vm.guestSteps)
|
|
43617
|
+
guestSteps: formatGuestSteps(vm.guestSteps),
|
|
43618
|
+
hostStall: formatHostStall(start.loadBefore, context.readHostLoad())
|
|
43560
43619
|
});
|
|
43561
43620
|
return vm;
|
|
43562
43621
|
} catch (error) {
|
|
@@ -43589,10 +43648,11 @@ async function startColdVm(context, start) {
|
|
|
43589
43648
|
isIdentityReset: imp.isIdentityResetPending,
|
|
43590
43649
|
jail: context.findJailUser(imp)
|
|
43591
43650
|
});
|
|
43592
|
-
getImpdLogger("imps").with({ imp: imp.name }).info("booted pid {pid} {timings}{guestSteps}", {
|
|
43651
|
+
getImpdLogger("imps").with({ imp: imp.name }).info("booted pid {pid} {timings}{guestSteps}{hostStall}", {
|
|
43593
43652
|
pid: String(vm.pid),
|
|
43594
43653
|
timings: formatTimings({ ...hostSteps, ...vm.timings }),
|
|
43595
|
-
guestSteps: formatGuestSteps(vm.guestSteps)
|
|
43654
|
+
guestSteps: formatGuestSteps(vm.guestSteps),
|
|
43655
|
+
hostStall: formatHostStall(start.loadBefore, context.readHostLoad())
|
|
43596
43656
|
});
|
|
43597
43657
|
return vm;
|
|
43598
43658
|
}
|
|
@@ -43673,6 +43733,7 @@ function createImpVmOps(host) {
|
|
|
43673
43733
|
hugePagesMib: hugePages === "2M" ? imp.memoryMib : 0
|
|
43674
43734
|
});
|
|
43675
43735
|
const setupStarted = performance.now();
|
|
43736
|
+
const loadBefore = context.readHostLoad();
|
|
43676
43737
|
try {
|
|
43677
43738
|
removeSnapshot(paths);
|
|
43678
43739
|
await context.egress.requireImp(imp.id);
|
|
@@ -43690,6 +43751,7 @@ function createImpVmOps(host) {
|
|
|
43690
43751
|
cgroup,
|
|
43691
43752
|
hugePages,
|
|
43692
43753
|
hostSteps,
|
|
43754
|
+
loadBefore,
|
|
43693
43755
|
diskReady
|
|
43694
43756
|
});
|
|
43695
43757
|
startCounting(context, imp, vm.pid);
|
|
@@ -44394,6 +44456,56 @@ function createImpService(deps, createWatchdog) {
|
|
|
44394
44456
|
};
|
|
44395
44457
|
}
|
|
44396
44458
|
|
|
44459
|
+
// packages/daemon/src/platform/process/read-host-load.ts
|
|
44460
|
+
import { join as join22 } from "path";
|
|
44461
|
+
|
|
44462
|
+
// packages/daemon/src/platform/process/find-unexpected-read-code.ts
|
|
44463
|
+
var UNSUPPORTED_CODES = new Set(["ENOENT", "EOPNOTSUPP"]);
|
|
44464
|
+
function findUnexpectedReadCode(error) {
|
|
44465
|
+
const code = error instanceof Error && "code" in error ? String(error.code) : "unknown";
|
|
44466
|
+
return UNSUPPORTED_CODES.has(code) ? null : code;
|
|
44467
|
+
}
|
|
44468
|
+
|
|
44469
|
+
// packages/daemon/src/platform/process/read-host-load.ts
|
|
44470
|
+
function readHostLoad(sources) {
|
|
44471
|
+
const readProc = (...names) => readProcFile(sources, join22(sources.procRoot, ...names));
|
|
44472
|
+
return {
|
|
44473
|
+
cpuStallUs: parsePressureTotal(readProc("pressure", "cpu")),
|
|
44474
|
+
ioStallUs: parsePressureTotal(readProc("pressure", "io")),
|
|
44475
|
+
memoryStallUs: parsePressureTotal(readProc("pressure", "memory")),
|
|
44476
|
+
stealUs: parseStealUs(readProc("stat"))
|
|
44477
|
+
};
|
|
44478
|
+
}
|
|
44479
|
+
function readProcFile(sources, path) {
|
|
44480
|
+
try {
|
|
44481
|
+
return sources.readFile(path);
|
|
44482
|
+
} catch (error) {
|
|
44483
|
+
const code = findUnexpectedReadCode(error);
|
|
44484
|
+
if (code !== null) {
|
|
44485
|
+
sources.logger.warning("cannot read {path} for the host stall: {code}", { path, code });
|
|
44486
|
+
}
|
|
44487
|
+
return null;
|
|
44488
|
+
}
|
|
44489
|
+
}
|
|
44490
|
+
function parsePressureTotal(pressure) {
|
|
44491
|
+
const total = pressure === null ? undefined : /^some .*total=(?<us>\d+)$/mv.exec(pressure);
|
|
44492
|
+
return total?.groups?.["us"] === undefined ? null : Number(total.groups["us"]);
|
|
44493
|
+
}
|
|
44494
|
+
var STEAL_FIELD = 8;
|
|
44495
|
+
var US_PER_TICK = 1e4;
|
|
44496
|
+
function parseStealUs(stat) {
|
|
44497
|
+
const fields = stat?.split(`
|
|
44498
|
+
`).find((line) => line.startsWith("cpu "))?.split(/\s+/v);
|
|
44499
|
+
const steal = fields?.[STEAL_FIELD];
|
|
44500
|
+
return steal === undefined ? null : Number(steal) * US_PER_TICK;
|
|
44501
|
+
}
|
|
44502
|
+
|
|
44503
|
+
// packages/daemon/src/platform/process/read-text.ts
|
|
44504
|
+
import { readFileSync as readFileSync22 } from "fs";
|
|
44505
|
+
function readText(path) {
|
|
44506
|
+
return readFileSync22(path, "utf8");
|
|
44507
|
+
}
|
|
44508
|
+
|
|
44397
44509
|
// packages/daemon/src/platform/telemetry/imp-telemetry.ts
|
|
44398
44510
|
import { ROOT_CONTEXT, metrics as metrics2, trace } from "@opentelemetry/api";
|
|
44399
44511
|
var SPAN_NAMES = {
|
|
@@ -44770,12 +44882,12 @@ function createMemoryController(deps) {
|
|
|
44770
44882
|
import {
|
|
44771
44883
|
existsSync as existsSync14,
|
|
44772
44884
|
mkdirSync as mkdirSync16,
|
|
44773
|
-
readFileSync as
|
|
44885
|
+
readFileSync as readFileSync23,
|
|
44774
44886
|
readdirSync as readdirSync8,
|
|
44775
44887
|
rmdirSync as rmdirSync2,
|
|
44776
44888
|
writeFileSync as writeFileSync5
|
|
44777
44889
|
} from "fs";
|
|
44778
|
-
import { join as
|
|
44890
|
+
import { join as join23 } from "path";
|
|
44779
44891
|
var PERIOD_US = 1e5;
|
|
44780
44892
|
var MEMORY_MIN_OVERHEAD_MIB = 256;
|
|
44781
44893
|
var MEMORY_OVERHEAD_DIVISOR = 8;
|
|
@@ -44803,18 +44915,18 @@ function parseOomKills(text) {
|
|
|
44803
44915
|
return match?.groups === undefined ? null : Number(match.groups["count"]);
|
|
44804
44916
|
}
|
|
44805
44917
|
function createCpuCgroups(options) {
|
|
44806
|
-
const imps =
|
|
44918
|
+
const imps = join23(options.root, "imps");
|
|
44807
44919
|
const procRoot = options.procRoot ?? "/proc";
|
|
44808
44920
|
const rmdir = options.rmdir ?? rmdirSync2;
|
|
44809
44921
|
const sleep = options.sleep ?? Bun.sleep;
|
|
44810
44922
|
const isEnforced = probeControllerDelegated(imps, "cpu");
|
|
44811
44923
|
const isMemoryEnforced = isEnforced && probeControllerDelegated(imps, "memory");
|
|
44812
|
-
const getDir = (impId) =>
|
|
44924
|
+
const getDir = (impId) => join23(imps, impId);
|
|
44813
44925
|
const guestMibs = new Map;
|
|
44814
44926
|
const oomBaselines = new Map;
|
|
44815
44927
|
const readOomKills = (impId) => {
|
|
44816
44928
|
try {
|
|
44817
|
-
const events =
|
|
44929
|
+
const events = readFileSync23(join23(getDir(impId), "memory.events"), "utf8");
|
|
44818
44930
|
return parseOomKills(events);
|
|
44819
44931
|
} catch {
|
|
44820
44932
|
return null;
|
|
@@ -44824,8 +44936,8 @@ function createCpuCgroups(options) {
|
|
|
44824
44936
|
oomBaselines.set(impId, readOomKills(impId) ?? 0);
|
|
44825
44937
|
};
|
|
44826
44938
|
const writeSettings = (impId, cpu, limit) => {
|
|
44827
|
-
writeFileSync5(
|
|
44828
|
-
writeFileSync5(
|
|
44939
|
+
writeFileSync5(join23(getDir(impId), "cpu.weight"), String(cpu.weight));
|
|
44940
|
+
writeFileSync5(join23(getDir(impId), "cpu.max"), formatCpuMax(limit));
|
|
44829
44941
|
};
|
|
44830
44942
|
const writeMemory = (impId) => {
|
|
44831
44943
|
const guestMib = guestMibs.get(impId);
|
|
@@ -44833,10 +44945,10 @@ function createCpuCgroups(options) {
|
|
|
44833
44945
|
return;
|
|
44834
44946
|
}
|
|
44835
44947
|
const directory = getDir(impId);
|
|
44836
|
-
writeFileSync5(
|
|
44837
|
-
writeFileSync5(
|
|
44838
|
-
writeFileSync5(
|
|
44839
|
-
writeFileSync5(
|
|
44948
|
+
writeFileSync5(join23(directory, "memory.max"), buildMemoryMax(guestMib));
|
|
44949
|
+
writeFileSync5(join23(directory, "memory.high"), "max");
|
|
44950
|
+
writeFileSync5(join23(directory, "memory.swap.max"), "0");
|
|
44951
|
+
writeFileSync5(join23(directory, "memory.oom.group"), "1");
|
|
44840
44952
|
};
|
|
44841
44953
|
const setup = (impId, cpu, memoryMib) => {
|
|
44842
44954
|
if (!isEnforced) {
|
|
@@ -44858,7 +44970,7 @@ function createCpuCgroups(options) {
|
|
|
44858
44970
|
return null;
|
|
44859
44971
|
}
|
|
44860
44972
|
return {
|
|
44861
|
-
procsPath:
|
|
44973
|
+
procsPath: join23(getDir(impId), "cgroup.procs"),
|
|
44862
44974
|
liftLimit: () => {
|
|
44863
44975
|
tryWrite(impId, "lift the limit", () => {
|
|
44864
44976
|
writeSettings(impId, cpu, null);
|
|
@@ -44942,7 +45054,7 @@ function createCpuCgroups(options) {
|
|
|
44942
45054
|
kill: (impId) => {
|
|
44943
45055
|
if (isEnforced && existsSync14(getDir(impId))) {
|
|
44944
45056
|
tryWrite(impId, "kill", () => {
|
|
44945
|
-
writeFileSync5(
|
|
45057
|
+
writeFileSync5(join23(getDir(impId), "cgroup.kill"), "1");
|
|
44946
45058
|
});
|
|
44947
45059
|
}
|
|
44948
45060
|
},
|
|
@@ -44953,7 +45065,7 @@ function createCpuCgroups(options) {
|
|
|
44953
45065
|
},
|
|
44954
45066
|
readCpuStat: (impId) => {
|
|
44955
45067
|
try {
|
|
44956
|
-
const stat =
|
|
45068
|
+
const stat = readFileSync23(join23(getDir(impId), "cpu.stat"), "utf8");
|
|
44957
45069
|
return parseCpuStat(stat);
|
|
44958
45070
|
} catch {
|
|
44959
45071
|
return null;
|
|
@@ -44963,7 +45075,7 @@ function createCpuCgroups(options) {
|
|
|
44963
45075
|
}
|
|
44964
45076
|
function probeControllerDelegated(imps, controller) {
|
|
44965
45077
|
try {
|
|
44966
|
-
const delegated =
|
|
45078
|
+
const delegated = readFileSync23(join23(imps, "cgroup.subtree_control"), "utf8");
|
|
44967
45079
|
return delegated.split(/\s+/u).includes(controller);
|
|
44968
45080
|
} catch {
|
|
44969
45081
|
return false;
|
|
@@ -44996,13 +45108,13 @@ function probeUffdDevice(path = "/dev/userfaultfd") {
|
|
|
44996
45108
|
}
|
|
44997
45109
|
|
|
44998
45110
|
// packages/daemon/src/vm/vmm/read-huge-page-pool.ts
|
|
44999
|
-
import { readFileSync as
|
|
45000
|
-
import { join as
|
|
45111
|
+
import { readFileSync as readFileSync24 } from "fs";
|
|
45112
|
+
import { join as join24 } from "path";
|
|
45001
45113
|
var HUGE_PAGE_MIB = 2;
|
|
45002
45114
|
function readHugePagePool(sysRoot = "/sys") {
|
|
45003
|
-
const directory =
|
|
45115
|
+
const directory = join24(sysRoot, "kernel", "mm", "hugepages", "hugepages-2048kB");
|
|
45004
45116
|
try {
|
|
45005
|
-
const readCount = (name) => Number(
|
|
45117
|
+
const readCount = (name) => Number(readFileSync24(join24(directory, name), "utf8").trim());
|
|
45006
45118
|
const total = readCount("nr_hugepages");
|
|
45007
45119
|
const free = readCount("free_hugepages") - readCount("resv_hugepages");
|
|
45008
45120
|
if (!Number.isSafeInteger(total) || !Number.isSafeInteger(free)) {
|
|
@@ -45088,11 +45200,12 @@ var UFFD_WATCH_INTERVAL_MS = 100;
|
|
|
45088
45200
|
var WAKE_AGENT_DEADLINE_MS = 1e4;
|
|
45089
45201
|
var GUEST_MEMORY_TIMEOUTS = { requestMs: 1000, snapshotMs: 1000 };
|
|
45090
45202
|
var UPTIME_PING_TIMEOUT_MS = 250;
|
|
45091
|
-
function createVmRunner(jails, options
|
|
45203
|
+
function createVmRunner(jails, options) {
|
|
45092
45204
|
const mergeWrapper = options.mergeWrapper ?? null;
|
|
45093
45205
|
const sendUptimePing = options.sendUptimePing ?? sendPing;
|
|
45094
45206
|
const procRoot = options.procRoot ?? "/proc";
|
|
45095
45207
|
const createClient = options.createClient ?? createFirecrackerClient;
|
|
45208
|
+
const readFile = options.readFile;
|
|
45096
45209
|
const uffdHandlerBin = options.uffdHandlerBin ?? null;
|
|
45097
45210
|
const uffdWatch = createUffdWatch({
|
|
45098
45211
|
probeVmAlive: (pid, paths) => probeProcessAlive(pid, paths.apiSocket, procRoot),
|
|
@@ -45323,7 +45436,8 @@ ${readLogTail(plan.paths.logFile)}`, {
|
|
|
45323
45436
|
firecrackerVersion,
|
|
45324
45437
|
agentVersion: ping.version,
|
|
45325
45438
|
timings: timer.marks,
|
|
45326
|
-
bootId: ping.bootId
|
|
45439
|
+
bootId: ping.bootId,
|
|
45440
|
+
...isUffd && { pageHandler: readUffdStats(plan.paths, readFile) }
|
|
45327
45441
|
};
|
|
45328
45442
|
} catch (error) {
|
|
45329
45443
|
const reason = explainUffdFailure(plan.paths, procRoot, getErrorMessage(error));
|
|
@@ -45422,7 +45536,8 @@ function createImpdImps(config, deps, parts) {
|
|
|
45422
45536
|
killCgroup: cgroups.kill
|
|
45423
45537
|
}), {
|
|
45424
45538
|
mergeWrapper: config.ksm?.execBin ?? null,
|
|
45425
|
-
uffdHandlerBin: config.hugePages?.handlerBin ?? null
|
|
45539
|
+
uffdHandlerBin: config.hugePages?.handlerBin ?? null,
|
|
45540
|
+
readFile: readFileSync25
|
|
45426
45541
|
});
|
|
45427
45542
|
const {
|
|
45428
45543
|
readVmRam,
|
|
@@ -45581,6 +45696,7 @@ function resolveImpBoundaries(boundaries) {
|
|
|
45581
45696
|
kernelOops: boundaries.kernelOops ?? createKernelOopsWatch(),
|
|
45582
45697
|
readThreadIds: boundaries.readThreadIds ?? ((pid) => readThreadIds(pid)),
|
|
45583
45698
|
readNetBytes: boundaries.readNetBytes ?? ((tap) => readGuestNetBytes(tap)),
|
|
45699
|
+
readHostLoad: boundaries.readHostLoad ?? (() => readHostLoad({ procRoot: "/proc", readFile: readText, logger: getImpdLogger("imps") })),
|
|
45584
45700
|
...boundaries.openTap !== undefined && { openTap: boundaries.openTap },
|
|
45585
45701
|
...boundaries.now !== undefined && { now: boundaries.now }
|
|
45586
45702
|
};
|
|
@@ -45595,7 +45711,7 @@ function makeStandInVmRam(readRam) {
|
|
|
45595
45711
|
|
|
45596
45712
|
// packages/daemon/src/imp-ops/moves/move-receiver.ts
|
|
45597
45713
|
import { existsSync as existsSync16, rmSync as rmSync24 } from "fs";
|
|
45598
|
-
import { join as
|
|
45714
|
+
import { join as join26 } from "path";
|
|
45599
45715
|
|
|
45600
45716
|
// packages/daemon/src/platform/db/probe-slot-free.ts
|
|
45601
45717
|
async function probeSlotFree(db, slot, now) {
|
|
@@ -45920,7 +46036,7 @@ function readReceipt(receipt, secret) {
|
|
|
45920
46036
|
// packages/daemon/src/imp-ops/moves/read-move-stream.ts
|
|
45921
46037
|
import { mkdirSync as mkdirSync19, rmSync as rmSync23 } from "fs";
|
|
45922
46038
|
import { open as open7 } from "fs/promises";
|
|
45923
|
-
import { join as
|
|
46039
|
+
import { join as join25 } from "path";
|
|
45924
46040
|
import invariant5 from "tiny-invariant";
|
|
45925
46041
|
|
|
45926
46042
|
// packages/daemon/src/imp-ops/moves/build-received-digest.ts
|
|
@@ -46545,7 +46661,7 @@ async function readMoveStream(deps, options) {
|
|
|
46545
46661
|
const count = createByteCounter(row.bytes);
|
|
46546
46662
|
const files = [];
|
|
46547
46663
|
mkdirSync19(options.tempDir, { recursive: true, mode: 448 });
|
|
46548
|
-
const temp =
|
|
46664
|
+
const temp = join25(options.tempDir, `${row.id}.part`);
|
|
46549
46665
|
const writeDisk = async (impId) => {
|
|
46550
46666
|
if (header.streams !== null) {
|
|
46551
46667
|
await writeMoveStreams(deps, {
|
|
@@ -46760,7 +46876,7 @@ async function requireMoveTicket(db, request) {
|
|
|
46760
46876
|
// packages/daemon/src/imp-ops/moves/move-receiver.ts
|
|
46761
46877
|
var STREAM_WINDOW_MS = 10 * 60 * 1000;
|
|
46762
46878
|
function createMoveReceiver(deps) {
|
|
46763
|
-
const tempDir =
|
|
46879
|
+
const tempDir = join26(deps.dataDir, "moves");
|
|
46764
46880
|
const sessions = new Map;
|
|
46765
46881
|
const writeTicketRow = async (name, bytes, fields, write = (row) => writeMoveTicket(deps.db, row)) => {
|
|
46766
46882
|
const created = mintOpaqueToken(MOVE_TICKET_PREFIX);
|
|
@@ -47935,12 +48051,12 @@ function toPeerError2(procedure, error) {
|
|
|
47935
48051
|
// packages/daemon/src/vm/storage/write-image-files.ts
|
|
47936
48052
|
import { writeFileSync as writeFileSync6 } from "fs";
|
|
47937
48053
|
import { copyFile } from "fs/promises";
|
|
47938
|
-
import { join as
|
|
48054
|
+
import { join as join27 } from "path";
|
|
47939
48055
|
async function writeImageFiles(files, directory) {
|
|
47940
|
-
const rootfs =
|
|
48056
|
+
const rootfs = join27(directory, "rootfs.ext4");
|
|
47941
48057
|
writeFileSync6(rootfs, "");
|
|
47942
48058
|
await writeChangedBlocks(files.rootfsPath, rootfs);
|
|
47943
|
-
await copyFile(files.configPath,
|
|
48059
|
+
await copyFile(files.configPath, join27(directory, "config.json"));
|
|
47944
48060
|
}
|
|
47945
48061
|
|
|
47946
48062
|
// packages/daemon/src/create-impd-moves.ts
|
|
@@ -47980,7 +48096,7 @@ function createImpdMoves(config, deps, parts, hooks) {
|
|
|
47980
48096
|
|
|
47981
48097
|
// packages/daemon/src/imps/images/template-service.ts
|
|
47982
48098
|
import { copyFileSync as copyFileSync3, existsSync as existsSync17, statSync as statSync11, writeFileSync as writeFileSync7 } from "fs";
|
|
47983
|
-
import { join as
|
|
48099
|
+
import { join as join28 } from "path";
|
|
47984
48100
|
|
|
47985
48101
|
// packages/daemon/src/imps/images/read-held-image.ts
|
|
47986
48102
|
async function readHeldImage(db, name, at) {
|
|
@@ -48268,7 +48384,7 @@ function createTemplateService(deps) {
|
|
|
48268
48384
|
});
|
|
48269
48385
|
const writeConfig = async (imageId, directory) => {
|
|
48270
48386
|
const image = await readImageById(deps.db, imageId);
|
|
48271
|
-
const target =
|
|
48387
|
+
const target = join28(directory, "config.json");
|
|
48272
48388
|
const config = image === undefined ? undefined : buildImagePaths(deps.config.dataDir, image.digest).config;
|
|
48273
48389
|
if (config !== undefined && existsSync17(config)) {
|
|
48274
48390
|
copyFileSync3(config, target);
|
|
@@ -48656,7 +48772,7 @@ function createImpdServices(config, deps, parts) {
|
|
|
48656
48772
|
|
|
48657
48773
|
// packages/daemon/src/imps/images/build/create-image-builds.ts
|
|
48658
48774
|
import { existsSync as existsSync19, mkdirSync as mkdirSync20, rmSync as rmSync25, statSync as statSync12 } from "fs";
|
|
48659
|
-
import { join as
|
|
48775
|
+
import { join as join30, posix as posix3 } from "path";
|
|
48660
48776
|
|
|
48661
48777
|
// packages/local-tar/src/extract-local.ts
|
|
48662
48778
|
import tar from "tar-stream";
|
|
@@ -48664,7 +48780,7 @@ import * as z83 from "zod";
|
|
|
48664
48780
|
// packages/local-tar/src/pack-build-context.ts
|
|
48665
48781
|
import { existsSync as existsSync18 } from "fs";
|
|
48666
48782
|
import { lstat, readFile as readFile4, readdir } from "fs/promises";
|
|
48667
|
-
import { join as
|
|
48783
|
+
import { join as join29, posix as posix2 } from "path";
|
|
48668
48784
|
import ignore from "@balena/dockerignore";
|
|
48669
48785
|
|
|
48670
48786
|
// packages/local-tar/src/write-build-context.ts
|
|
@@ -48948,7 +49064,7 @@ class MissingDockerfileError extends Error {
|
|
|
48948
49064
|
name = "MissingDockerfileError";
|
|
48949
49065
|
}
|
|
48950
49066
|
function listContextEntries(root, dockerfile) {
|
|
48951
|
-
const found = listDockerfileCandidates(posix2.normalize(dockerfile)).find((candidate) => existsSync18(
|
|
49067
|
+
const found = listDockerfileCandidates(posix2.normalize(dockerfile)).find((candidate) => existsSync18(join29(root, candidate)));
|
|
48952
49068
|
if (found === undefined) {
|
|
48953
49069
|
return Promise.reject(new MissingDockerfileError(`there is no ${dockerfile} in ${root}`));
|
|
48954
49070
|
}
|
|
@@ -48960,8 +49076,8 @@ var ENTRY_KINDS = [
|
|
|
48960
49076
|
["file", "isFile"]
|
|
48961
49077
|
];
|
|
48962
49078
|
async function listEntries(root, dockerfile) {
|
|
48963
|
-
const ignoreName = existsSync18(
|
|
48964
|
-
const patterns = existsSync18(
|
|
49079
|
+
const ignoreName = existsSync18(join29(root, `${dockerfile}.dockerignore`)) ? `${dockerfile}.dockerignore` : ".dockerignore";
|
|
49080
|
+
const patterns = existsSync18(join29(root, ignoreName)) ? await readFile4(join29(root, ignoreName), "utf8") : "";
|
|
48965
49081
|
const matcher = ignore().add(patterns);
|
|
48966
49082
|
const hasExceptions = patterns.split(`
|
|
48967
49083
|
`).some((line) => line.trim().startsWith("!"));
|
|
@@ -48971,7 +49087,7 @@ async function listEntries(root, dockerfile) {
|
|
|
48971
49087
|
const entries = [];
|
|
48972
49088
|
const children = await readdir(directory);
|
|
48973
49089
|
for (const child of children.toSorted()) {
|
|
48974
|
-
const path =
|
|
49090
|
+
const path = join29(directory, child);
|
|
48975
49091
|
const name = prefix === "" ? child : `${prefix}/${child}`;
|
|
48976
49092
|
const stats = await lstat(path);
|
|
48977
49093
|
const ignored = matcher.ignores(name) && name !== dockerfileName;
|
|
@@ -50026,7 +50142,7 @@ function planRootfsOverhead(treeBytes) {
|
|
|
50026
50142
|
}
|
|
50027
50143
|
|
|
50028
50144
|
// packages/daemon/src/imps/images/rootfs/unpack-export.ts
|
|
50029
|
-
import { readFileSync as
|
|
50145
|
+
import { readFileSync as readFileSync26 } from "fs";
|
|
50030
50146
|
var CAP_SETFCAP_BIT = 31n;
|
|
50031
50147
|
var SETFCAP_HELP = "imp-host needs CAP_SETFCAP (docs/architecture/host.md#privileges)";
|
|
50032
50148
|
var UNPACK_TAR_ARGS = [
|
|
@@ -50068,7 +50184,7 @@ function findXattrFailure(stderr) {
|
|
|
50068
50184
|
});
|
|
50069
50185
|
return failures.find((failure) => failure.missingSetfcap) ?? failures[0] ?? null;
|
|
50070
50186
|
}
|
|
50071
|
-
function readSetfcapWarning(status =
|
|
50187
|
+
function readSetfcapWarning(status = readFileSync26("/proc/self/status", "utf8")) {
|
|
50072
50188
|
const effective = /^CapEff:\s*(?<mask>[0-9a-f]+)$/mu.exec(status)?.groups?.["mask"] ?? "0";
|
|
50073
50189
|
if (BigInt(`0x${effective}`) >> CAP_SETFCAP_BIT & 1n) {
|
|
50074
50190
|
return null;
|
|
@@ -50492,7 +50608,7 @@ function createImageBuilds(deps, writer) {
|
|
|
50492
50608
|
});
|
|
50493
50609
|
}
|
|
50494
50610
|
const uploadsDir = buildUploadsDir(deps.config.dataDir);
|
|
50495
|
-
const tarPath =
|
|
50611
|
+
const tarPath = join30(uploadsDir, `${Bun.randomUUIDv7()}.tar`);
|
|
50496
50612
|
mkdirSync20(uploadsDir, { recursive: true, mode: 448 });
|
|
50497
50613
|
return deps.diskBudget.withRoom(tarBytes, async () => {
|
|
50498
50614
|
try {
|
|
@@ -50649,7 +50765,7 @@ function buildImageRuntimeConfig(ociConfig) {
|
|
|
50649
50765
|
|
|
50650
50766
|
// packages/daemon/src/imps/images/rootfs/create-image-writer.ts
|
|
50651
50767
|
import { existsSync as existsSync20, mkdirSync as mkdirSync22, rmSync as rmSync27, statSync as statSync13, writeFileSync as writeFileSync8 } from "fs";
|
|
50652
|
-
import { join as
|
|
50768
|
+
import { join as join32 } from "path";
|
|
50653
50769
|
|
|
50654
50770
|
// packages/daemon/src/imps/images/rootfs/read-oci-config.ts
|
|
50655
50771
|
import * as z88 from "zod";
|
|
@@ -50669,13 +50785,13 @@ async function readOciConfig(ref, signal, run) {
|
|
|
50669
50785
|
|
|
50670
50786
|
// packages/daemon/src/imps/images/rootfs/write-image-config.ts
|
|
50671
50787
|
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
|
|
50788
|
+
import { join as join31 } from "path";
|
|
50673
50789
|
function writeImageConfig(root, contents) {
|
|
50674
|
-
const etc =
|
|
50675
|
-
const directory =
|
|
50790
|
+
const etc = join31(root, "etc");
|
|
50791
|
+
const directory = join31(etc, "imp");
|
|
50676
50792
|
createDirectory(etc, "/etc");
|
|
50677
50793
|
createDirectory(directory, "/etc/imp");
|
|
50678
|
-
const file =
|
|
50794
|
+
const file = join31(directory, "image.json");
|
|
50679
50795
|
rmSync26(file, { recursive: true, force: true });
|
|
50680
50796
|
const fd = openSync9(file, constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW, 420);
|
|
50681
50797
|
try {
|
|
@@ -50722,8 +50838,8 @@ function createImageWriter(deps) {
|
|
|
50722
50838
|
const guestRootfsLock = buildKeyedMutex();
|
|
50723
50839
|
const makeWorkDir = () => {
|
|
50724
50840
|
const images = buildImagesDir(deps.config.dataDir);
|
|
50725
|
-
const work =
|
|
50726
|
-
const root =
|
|
50841
|
+
const work = join32(images, `.build-${Bun.randomUUIDv7()}`);
|
|
50842
|
+
const root = join32(work, "root");
|
|
50727
50843
|
mkdirSync22(images, { recursive: true });
|
|
50728
50844
|
mkdirSync22(work, { mode: 448 });
|
|
50729
50845
|
mkdirSync22(root, { mode: 493 });
|
|
@@ -50734,7 +50850,7 @@ function createImageWriter(deps) {
|
|
|
50734
50850
|
const usage = await readTreeUsage(root);
|
|
50735
50851
|
const plan = planRootfs(usage);
|
|
50736
50852
|
await deps.storage.createImage(digest, async (directory) => {
|
|
50737
|
-
const image =
|
|
50853
|
+
const image = join32(directory, "rootfs.ext4");
|
|
50738
50854
|
await runChecked(["truncate", "-s", String(plan.bytes), image]);
|
|
50739
50855
|
await runChecked([
|
|
50740
50856
|
"mkfs.ext4",
|
|
@@ -50747,7 +50863,7 @@ function createImageWriter(deps) {
|
|
|
50747
50863
|
root,
|
|
50748
50864
|
image
|
|
50749
50865
|
]);
|
|
50750
|
-
writeFileSync8(
|
|
50866
|
+
writeFileSync8(join32(directory, "config.json"), JSON.stringify(ociConfig ?? {}, null, 2));
|
|
50751
50867
|
});
|
|
50752
50868
|
return readDiskUsage(buildImagePaths(deps.config.dataDir, digest).rootfs);
|
|
50753
50869
|
};
|
|
@@ -51298,7 +51414,7 @@ async function runStreamed(argv, onStdout, signal) {
|
|
|
51298
51414
|
|
|
51299
51415
|
// packages/daemon/src/vm/storage/count-tree-bytes.ts
|
|
51300
51416
|
import { lstat as lstat3, readdir as readdir3 } from "fs/promises";
|
|
51301
|
-
import { join as
|
|
51417
|
+
import { join as join33 } from "path";
|
|
51302
51418
|
async function countTreeBytes(root, deps = {}) {
|
|
51303
51419
|
const readDir = deps.readDir ?? readDirEntries;
|
|
51304
51420
|
const inodes = new Map;
|
|
@@ -51307,11 +51423,11 @@ async function countTreeBytes(root, deps = {}) {
|
|
|
51307
51423
|
const entries = await readEntries2(readDir, directory);
|
|
51308
51424
|
for (const entry of entries) {
|
|
51309
51425
|
if (entry.isDirectory()) {
|
|
51310
|
-
dirs.push(
|
|
51426
|
+
dirs.push(join33(directory, entry.name));
|
|
51311
51427
|
}
|
|
51312
51428
|
}
|
|
51313
51429
|
const files = entries.filter((entry) => entry.isFile());
|
|
51314
|
-
const stats = await Promise.all(files.map((entry) => readFileStats(
|
|
51430
|
+
const stats = await Promise.all(files.map((entry) => readFileStats(join33(directory, entry.name))));
|
|
51315
51431
|
for (const stat of stats) {
|
|
51316
51432
|
if (stat !== undefined) {
|
|
51317
51433
|
inodes.set(`${String(stat.dev)}:${String(stat.ino)}`, Math.max(0, stat.blocks - 1) * 512);
|
|
@@ -51554,12 +51670,12 @@ function createTailnetAccess(config, deps, readStatus) {
|
|
|
51554
51670
|
}
|
|
51555
51671
|
|
|
51556
51672
|
// packages/daemon/src/identity/token.ts
|
|
51557
|
-
import { existsSync as existsSync21, readFileSync as
|
|
51558
|
-
import { join as
|
|
51673
|
+
import { existsSync as existsSync21, readFileSync as readFileSync27, writeFileSync as writeFileSync9 } from "fs";
|
|
51674
|
+
import { join as join34 } from "path";
|
|
51559
51675
|
function loadOrCreateToken(dataDir) {
|
|
51560
|
-
const path =
|
|
51676
|
+
const path = join34(dataDir, "token");
|
|
51561
51677
|
if (existsSync21(path)) {
|
|
51562
|
-
return
|
|
51678
|
+
return readFileSync27(path, "utf8").trim();
|
|
51563
51679
|
}
|
|
51564
51680
|
const token = mintSecret();
|
|
51565
51681
|
writeFileSync9(path, `${token}
|
|
@@ -51681,13 +51797,13 @@ import { basename as basename4 } from "path";
|
|
|
51681
51797
|
|
|
51682
51798
|
// packages/daemon/src/vm/storage/remove-unused-system-drives.ts
|
|
51683
51799
|
import { readdirSync as readdirSync9, rmSync as rmSync28 } from "fs";
|
|
51684
|
-
import { join as
|
|
51800
|
+
import { join as join35 } from "path";
|
|
51685
51801
|
function removeUnusedSystemDrives(dataDir, keep) {
|
|
51686
51802
|
const directory = buildSystemDrivesDir(dataDir);
|
|
51687
51803
|
const removed = [];
|
|
51688
51804
|
for (const name of readNames(directory)) {
|
|
51689
51805
|
if (!keep.has(name)) {
|
|
51690
|
-
rmSync28(
|
|
51806
|
+
rmSync28(join35(directory, name), { force: true });
|
|
51691
51807
|
removed.push(name);
|
|
51692
51808
|
}
|
|
51693
51809
|
}
|
|
@@ -52896,13 +53012,13 @@ function createPublicRecordsLink() {
|
|
|
52896
53012
|
|
|
52897
53013
|
// packages/daemon/src/network/tailnet-names/host-id.ts
|
|
52898
53014
|
import { randomBytes as randomBytes11 } from "crypto";
|
|
52899
|
-
import { existsSync as existsSync22, mkdirSync as mkdirSync23, readFileSync as
|
|
52900
|
-
import { join as
|
|
53015
|
+
import { existsSync as existsSync22, mkdirSync as mkdirSync23, readFileSync as readFileSync28, writeFileSync as writeFileSync10 } from "fs";
|
|
53016
|
+
import { join as join36 } from "path";
|
|
52901
53017
|
function loadOrCreateHostId(dataDir) {
|
|
52902
|
-
const directory =
|
|
52903
|
-
const path =
|
|
53018
|
+
const directory = join36(dataDir, "tailnet-names");
|
|
53019
|
+
const path = join36(directory, "host-id");
|
|
52904
53020
|
if (existsSync22(path)) {
|
|
52905
|
-
return
|
|
53021
|
+
return readFileSync28(path, "utf8").trim();
|
|
52906
53022
|
}
|
|
52907
53023
|
mkdirSync23(directory, { recursive: true });
|
|
52908
53024
|
const id = randomBytes11(16).toString("hex");
|
|
@@ -52912,7 +53028,7 @@ function loadOrCreateHostId(dataDir) {
|
|
|
52912
53028
|
}
|
|
52913
53029
|
|
|
52914
53030
|
// packages/daemon/src/network/tailnet-names/oauth-credential.ts
|
|
52915
|
-
import { readFileSync as
|
|
53031
|
+
import { readFileSync as readFileSync29, statSync as statSync14 } from "fs";
|
|
52916
53032
|
import * as z92 from "zod";
|
|
52917
53033
|
var CredentialSchema = z92.object({ clientId: z92.string().min(1), clientSecret: z92.string().min(1) });
|
|
52918
53034
|
function readOAuthCredential(path) {
|
|
@@ -52928,7 +53044,7 @@ function readOAuthCredential(path) {
|
|
|
52928
53044
|
}
|
|
52929
53045
|
function readJson(path) {
|
|
52930
53046
|
try {
|
|
52931
|
-
return JSON.parse(
|
|
53047
|
+
return JSON.parse(readFileSync29(path, "utf8"));
|
|
52932
53048
|
} catch {
|
|
52933
53049
|
return null;
|
|
52934
53050
|
}
|
|
@@ -53325,7 +53441,7 @@ async function startOtlpExport(env, version) {
|
|
|
53325
53441
|
}
|
|
53326
53442
|
|
|
53327
53443
|
// packages/daemon/src/network/https/wire-https-service.ts
|
|
53328
|
-
import { readFileSync as
|
|
53444
|
+
import { readFileSync as readFileSync31 } from "fs";
|
|
53329
53445
|
|
|
53330
53446
|
// packages/daemon/src/platform/db/exposure.ts
|
|
53331
53447
|
async function readPublicImp(db, name) {
|
|
@@ -53520,8 +53636,8 @@ function formatAcmeError(error) {
|
|
|
53520
53636
|
}
|
|
53521
53637
|
|
|
53522
53638
|
// packages/daemon/src/network/https/acme/cert-store.ts
|
|
53523
|
-
import { existsSync as existsSync23, mkdirSync as mkdirSync24, readFileSync as
|
|
53524
|
-
import { join as
|
|
53639
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync24, readFileSync as readFileSync30, rmSync as rmSync29 } from "fs";
|
|
53640
|
+
import { join as join37 } from "path";
|
|
53525
53641
|
import * as z95 from "zod";
|
|
53526
53642
|
var AttemptStateSchema = z95.object({
|
|
53527
53643
|
failures: z95.int().nonnegative(),
|
|
@@ -53532,11 +53648,11 @@ var AccountSchema = z95.object({ directoryUrl: z95.string(), url: z95.string(),
|
|
|
53532
53648
|
var LegacyAccountSchema = z95.object({ directoryUrl: z95.string(), url: z95.string() });
|
|
53533
53649
|
var NO_ATTEMPTS = { failures: 0, lastAttemptAt: null, lastError: null };
|
|
53534
53650
|
function createCertStore(dataDir) {
|
|
53535
|
-
const directory =
|
|
53536
|
-
const certificatePath =
|
|
53537
|
-
const attemptsPath =
|
|
53538
|
-
const accountPath =
|
|
53539
|
-
const legacyKeyPath =
|
|
53651
|
+
const directory = join37(dataDir, "tls");
|
|
53652
|
+
const certificatePath = join37(directory, "certificate.pem");
|
|
53653
|
+
const attemptsPath = join37(directory, "attempts.json");
|
|
53654
|
+
const accountPath = join37(directory, "account.json");
|
|
53655
|
+
const legacyKeyPath = join37(directory, "account.key");
|
|
53540
53656
|
const warned = { account: false };
|
|
53541
53657
|
const write = (path, content) => {
|
|
53542
53658
|
mkdirSync24(directory, { recursive: true, mode: 448 });
|
|
@@ -53602,7 +53718,7 @@ ${certificate.chainPem.trimEnd()}
|
|
|
53602
53718
|
};
|
|
53603
53719
|
}
|
|
53604
53720
|
function readIfExists(path) {
|
|
53605
|
-
return existsSync23(path) ?
|
|
53721
|
+
return existsSync23(path) ? readFileSync30(path, "utf8") : null;
|
|
53606
53722
|
}
|
|
53607
53723
|
function parseJson(text) {
|
|
53608
53724
|
try {
|
|
@@ -54408,7 +54524,7 @@ function wireHttpsService(options) {
|
|
|
54408
54524
|
const issue = createAcmeIssuer({
|
|
54409
54525
|
directoryUrl: config.acmeDirectory,
|
|
54410
54526
|
email: config.acmeEmail,
|
|
54411
|
-
caPem: config.acmeCaFile === null ? null :
|
|
54527
|
+
caPem: config.acmeCaFile === null ? null : readFileSync31(config.acmeCaFile, "utf8"),
|
|
54412
54528
|
store,
|
|
54413
54529
|
dns
|
|
54414
54530
|
});
|
|
@@ -54995,17 +55111,17 @@ function buildTooMany() {
|
|
|
54995
55111
|
|
|
54996
55112
|
// packages/daemon/src/surface/ssh/host-key.ts
|
|
54997
55113
|
var import_ssh22 = __toESM(require_lib2(), 1);
|
|
54998
|
-
import { existsSync as existsSync24, mkdirSync as mkdirSync25, readFileSync as
|
|
54999
|
-
import { join as
|
|
55114
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync25, readFileSync as readFileSync32, writeFileSync as writeFileSync11 } from "fs";
|
|
55115
|
+
import { join as join38 } from "path";
|
|
55000
55116
|
function setupSshDir(dataDir) {
|
|
55001
|
-
const directory =
|
|
55117
|
+
const directory = join38(dataDir, "ssh");
|
|
55002
55118
|
mkdirSync25(directory, { recursive: true, mode: 448 });
|
|
55003
55119
|
return directory;
|
|
55004
55120
|
}
|
|
55005
55121
|
function loadOrCreateHostKey(sshDir) {
|
|
55006
|
-
const path =
|
|
55122
|
+
const path = join38(sshDir, "host_key");
|
|
55007
55123
|
if (existsSync24(path)) {
|
|
55008
|
-
return
|
|
55124
|
+
return readFileSync32(path, "utf8");
|
|
55009
55125
|
}
|
|
55010
55126
|
const pair = generateEd25519Key();
|
|
55011
55127
|
writeFileSync11(path, pair.private, { mode: 384, flag: "wx" });
|
|
@@ -56170,8 +56286,8 @@ async function stopImpd(parts, options) {
|
|
|
56170
56286
|
}
|
|
56171
56287
|
|
|
56172
56288
|
// packages/daemon/src/vm/storage/create-storage-backend.ts
|
|
56173
|
-
import { existsSync as existsSync31, readFileSync as
|
|
56174
|
-
import { join as
|
|
56289
|
+
import { existsSync as existsSync31, readFileSync as readFileSync36, readdirSync as readdirSync14, writeFileSync as writeFileSync14 } from "fs";
|
|
56290
|
+
import { join as join47 } from "path";
|
|
56175
56291
|
|
|
56176
56292
|
// packages/daemon/src/vm/storage/xfs-backend.ts
|
|
56177
56293
|
import {
|
|
@@ -56184,7 +56300,7 @@ import {
|
|
|
56184
56300
|
statfsSync as statfsSync2,
|
|
56185
56301
|
writeFileSync as writeFileSync12
|
|
56186
56302
|
} from "fs";
|
|
56187
|
-
import { basename as basename6, dirname as dirname13, join as
|
|
56303
|
+
import { basename as basename6, dirname as dirname13, join as join42 } from "path";
|
|
56188
56304
|
|
|
56189
56305
|
// packages/daemon/src/vm/storage/count-owner-bytes.ts
|
|
56190
56306
|
function countOwnerBytes(files) {
|
|
@@ -56241,13 +56357,13 @@ import {
|
|
|
56241
56357
|
copyFileSync as copyFileSync4,
|
|
56242
56358
|
existsSync as existsSync25,
|
|
56243
56359
|
mkdirSync as mkdirSync26,
|
|
56244
|
-
readFileSync as
|
|
56360
|
+
readFileSync as readFileSync33,
|
|
56245
56361
|
readdirSync as readdirSync10,
|
|
56246
56362
|
renameSync as renameSync6,
|
|
56247
56363
|
rmSync as rmSync30,
|
|
56248
56364
|
statSync as statSync15
|
|
56249
56365
|
} from "fs";
|
|
56250
|
-
import { basename as basename5, dirname as dirname11, join as
|
|
56366
|
+
import { basename as basename5, dirname as dirname11, join as join39 } from "path";
|
|
56251
56367
|
import * as z97 from "zod";
|
|
56252
56368
|
var CopiesSchema = z97.record(z97.string(), z97.object({ ino: z97.string(), ctimeNs: z97.string(), size: z97.string() }));
|
|
56253
56369
|
function createXfsBackups(ctx) {
|
|
@@ -56255,7 +56371,7 @@ function createXfsBackups(ctx) {
|
|
|
56255
56371
|
const freshCopies = new Set;
|
|
56256
56372
|
const readCopies = () => {
|
|
56257
56373
|
try {
|
|
56258
|
-
return CopiesSchema.parse(JSON.parse(
|
|
56374
|
+
return CopiesSchema.parse(JSON.parse(readFileSync33(backup.copies, "utf8")));
|
|
56259
56375
|
} catch {
|
|
56260
56376
|
return {};
|
|
56261
56377
|
}
|
|
@@ -56278,7 +56394,7 @@ function createXfsBackups(ctx) {
|
|
|
56278
56394
|
return {
|
|
56279
56395
|
createBackupCopy: async (impId, _runId, options) => {
|
|
56280
56396
|
const source = ctx.resolveImpPaths(impId).disk;
|
|
56281
|
-
const target =
|
|
56397
|
+
const target = join39(backup.tree, BACKUP_TREE.buildDisk(impId));
|
|
56282
56398
|
const stats = statSync15(source, { bigint: true });
|
|
56283
56399
|
const record = {
|
|
56284
56400
|
ino: String(stats.ino),
|
|
@@ -56306,34 +56422,34 @@ function createXfsBackups(ctx) {
|
|
|
56306
56422
|
const checkpointIds = new Set;
|
|
56307
56423
|
const imageDigests = new Set;
|
|
56308
56424
|
for (const imp of request.imps) {
|
|
56309
|
-
if (!existsSync25(
|
|
56425
|
+
if (!existsSync25(join39(backup.tree, BACKUP_TREE.buildDisk(imp.impId)))) {
|
|
56310
56426
|
continue;
|
|
56311
56427
|
}
|
|
56312
56428
|
impIds.add(imp.impId);
|
|
56313
56429
|
for (const checkpointId of imp.checkpointIds) {
|
|
56314
|
-
const isCopied = await createTreeClone(ctx.buildCheckpointDisk(imp.impId, checkpointId),
|
|
56430
|
+
const isCopied = await createTreeClone(ctx.buildCheckpointDisk(imp.impId, checkpointId), join39(backup.tree, BACKUP_TREE.buildCheckpointDisk(imp.impId, checkpointId)));
|
|
56315
56431
|
if (isCopied) {
|
|
56316
56432
|
checkpointIds.add(checkpointId);
|
|
56317
56433
|
}
|
|
56318
56434
|
}
|
|
56319
|
-
removeUnlisted(
|
|
56435
|
+
removeUnlisted(join39(backup.tree, BACKUP_TREE.buildImpDir(imp.impId), "checkpoints"), new Set(imp.checkpointIds.filter((id) => checkpointIds.has(id))));
|
|
56320
56436
|
}
|
|
56321
56437
|
for (const digest of request.imageDigests) {
|
|
56322
56438
|
const source = buildImagePaths(ctx.dataDir, digest);
|
|
56323
|
-
const directory =
|
|
56324
|
-
const isCopied = await createTreeClone(source.rootfs,
|
|
56439
|
+
const directory = join39(backup.tree, BACKUP_TREE.buildImageDir(digest));
|
|
56440
|
+
const isCopied = await createTreeClone(source.rootfs, join39(directory, "rootfs.ext4"));
|
|
56325
56441
|
if (isCopied) {
|
|
56326
|
-
copyFileSync4(source.config,
|
|
56442
|
+
copyFileSync4(source.config, join39(directory, "config.json"));
|
|
56327
56443
|
imageDigests.add(digest);
|
|
56328
56444
|
}
|
|
56329
56445
|
}
|
|
56330
|
-
removeUnlisted(
|
|
56331
|
-
removeUnlisted(
|
|
56446
|
+
removeUnlisted(join39(backup.tree, "imps"), impIds);
|
|
56447
|
+
removeUnlisted(join39(backup.tree, "images"), new Set([...imageDigests].map((digest) => basename5(BACKUP_TREE.buildImageDir(digest)))));
|
|
56332
56448
|
const copies = readCopies();
|
|
56333
56449
|
writeCopies(Object.fromEntries(Object.entries(copies).filter(([id]) => impIds.has(id))));
|
|
56334
56450
|
const removeFreshCopies = () => {
|
|
56335
56451
|
for (const impId of freshCopies) {
|
|
56336
|
-
rmSync30(
|
|
56452
|
+
rmSync30(join39(backup.tree, BACKUP_TREE.buildDisk(impId)), { force: true });
|
|
56337
56453
|
}
|
|
56338
56454
|
freshCopies.clear();
|
|
56339
56455
|
return Promise.resolve();
|
|
@@ -56345,18 +56461,18 @@ function createXfsBackups(ctx) {
|
|
|
56345
56461
|
function removeUnlisted(directory, keep) {
|
|
56346
56462
|
const names = existsSync25(directory) ? readdirSync10(directory) : [];
|
|
56347
56463
|
for (const name of names.filter((entry) => !keep.has(entry))) {
|
|
56348
|
-
rmSync30(
|
|
56464
|
+
rmSync30(join39(directory, name), { recursive: true, force: true });
|
|
56349
56465
|
}
|
|
56350
56466
|
}
|
|
56351
56467
|
|
|
56352
56468
|
// packages/daemon/src/vm/storage/loop-backing-file.ts
|
|
56353
|
-
import { readFileSync as
|
|
56354
|
-
import { dirname as dirname12, join as
|
|
56469
|
+
import { readFileSync as readFileSync34, realpathSync, statfsSync } from "fs";
|
|
56470
|
+
import { dirname as dirname12, join as join40 } from "path";
|
|
56355
56471
|
var HOST_DIRS = { procDir: "/proc", sysDir: "/sys" };
|
|
56356
56472
|
function readLoopBackingFile(directory, hostDirs = HOST_DIRS) {
|
|
56357
56473
|
try {
|
|
56358
56474
|
const target = realpathSync(directory);
|
|
56359
|
-
const mountInfo =
|
|
56475
|
+
const mountInfo = readFileSync34(join40(hostDirs.procDir, "self", "mountinfo"), "utf8");
|
|
56360
56476
|
for (const line of mountInfo.split(`
|
|
56361
56477
|
`)) {
|
|
56362
56478
|
const [mounts = "", fields = ""] = line.split(" - ");
|
|
@@ -56364,8 +56480,8 @@ function readLoopBackingFile(directory, hostDirs = HOST_DIRS) {
|
|
|
56364
56480
|
const [, source = ""] = fields.split(" ");
|
|
56365
56481
|
const loop = /^\/dev\/(?<name>loop\d+)$/u.exec(source)?.groups?.["name"];
|
|
56366
56482
|
if (mountPoint === target && loop !== undefined) {
|
|
56367
|
-
const backing =
|
|
56368
|
-
return
|
|
56483
|
+
const backing = join40(hostDirs.sysDir, "block", loop, "loop", "backing_file");
|
|
56484
|
+
return readFileSync34(backing, "utf8").trim();
|
|
56369
56485
|
}
|
|
56370
56486
|
}
|
|
56371
56487
|
} catch {}
|
|
@@ -56386,7 +56502,7 @@ function readLoopHostFreeBytes(directory, hostDirs = HOST_DIRS) {
|
|
|
56386
56502
|
|
|
56387
56503
|
// packages/daemon/src/vm/storage/orphan-files.ts
|
|
56388
56504
|
import { existsSync as existsSync26, readdirSync as readdirSync11, statSync as statSync16 } from "fs";
|
|
56389
|
-
import { join as
|
|
56505
|
+
import { join as join41 } from "path";
|
|
56390
56506
|
function probeHoldingFiles(directory) {
|
|
56391
56507
|
return existsSync26(directory) && readdirSync11(directory, { recursive: true, withFileTypes: true }).some((entry) => !entry.isDirectory());
|
|
56392
56508
|
}
|
|
@@ -56394,7 +56510,7 @@ function listFilesUnder(directory) {
|
|
|
56394
56510
|
if (!existsSync26(directory)) {
|
|
56395
56511
|
return [];
|
|
56396
56512
|
}
|
|
56397
|
-
return readdirSync11(directory, { recursive: true, withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) =>
|
|
56513
|
+
return readdirSync11(directory, { recursive: true, withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => join41(entry.parentPath, entry.name));
|
|
56398
56514
|
}
|
|
56399
56515
|
function readDirectoryOrphan(kind, id, directory, snapshots) {
|
|
56400
56516
|
const birth = statSync16(directory).birthtimeMs;
|
|
@@ -56420,7 +56536,7 @@ function createXfsBackend(deps) {
|
|
|
56420
56536
|
const cloneFile = deps.cloneFile ?? createReflinkClone;
|
|
56421
56537
|
const readFileExtents = deps.readFileExtents ?? readExtents;
|
|
56422
56538
|
const resolveImpPaths = (impId) => buildImpPaths(deps.dataDir, impId);
|
|
56423
|
-
const buildCheckpointDisk = (impId, checkpointId) =>
|
|
56539
|
+
const buildCheckpointDisk = (impId, checkpointId) => join42(resolveImpPaths(impId).checkpointsDir, checkpointId, "disk.ext4");
|
|
56424
56540
|
const getSourceFile = (source) => {
|
|
56425
56541
|
if (source.kind === "image") {
|
|
56426
56542
|
return buildImagePaths(deps.dataDir, source.digest).rootfs;
|
|
@@ -56435,7 +56551,7 @@ function createXfsBackend(deps) {
|
|
|
56435
56551
|
};
|
|
56436
56552
|
const createImage = async (digest, write) => {
|
|
56437
56553
|
const paths = buildImagePaths(deps.dataDir, digest);
|
|
56438
|
-
const staged =
|
|
56554
|
+
const staged = join42(buildImagesDir(deps.dataDir), `${STAGING_PREFIX}${Bun.randomUUIDv7()}`);
|
|
56439
56555
|
mkdirSync27(staged, { recursive: true });
|
|
56440
56556
|
try {
|
|
56441
56557
|
await write(staged);
|
|
@@ -56456,13 +56572,13 @@ function createXfsBackend(deps) {
|
|
|
56456
56572
|
return listEntries2(directory).map((id) => ({
|
|
56457
56573
|
kind: "checkpoint",
|
|
56458
56574
|
id,
|
|
56459
|
-
directory:
|
|
56575
|
+
directory: join42(directory, id)
|
|
56460
56576
|
}));
|
|
56461
56577
|
}).filter((checkpoint) => !live.checkpointIds.has(checkpoint.id));
|
|
56462
56578
|
const unknownImages = listEntries2(buildImagesDir(deps.dataDir)).filter((name) => !name.startsWith(".") && !liveDigests.has(name)).map((name) => ({
|
|
56463
56579
|
kind: "image",
|
|
56464
56580
|
id: name,
|
|
56465
|
-
directory:
|
|
56581
|
+
directory: join42(buildImagesDir(deps.dataDir), name)
|
|
56466
56582
|
}));
|
|
56467
56583
|
const unknownImps = impIds.filter((impId) => !live.impIds.has(impId)).map((impId) => ({
|
|
56468
56584
|
kind: "imp",
|
|
@@ -56482,14 +56598,14 @@ function createXfsBackend(deps) {
|
|
|
56482
56598
|
};
|
|
56483
56599
|
const removeLeftover = (dropped, live) => {
|
|
56484
56600
|
if (dropped.kind === "image") {
|
|
56485
|
-
rmSync31(
|
|
56601
|
+
rmSync31(join42(buildImagesDir(deps.dataDir), dropped.id), { recursive: true, force: true });
|
|
56486
56602
|
}
|
|
56487
56603
|
if (dropped.kind === "imp") {
|
|
56488
56604
|
rmSync31(resolveImpPaths(dropped.id).directory, { recursive: true, force: true });
|
|
56489
56605
|
}
|
|
56490
56606
|
if (dropped.kind === "checkpoint") {
|
|
56491
56607
|
for (const impId of live.impIds) {
|
|
56492
|
-
rmSync31(
|
|
56608
|
+
rmSync31(join42(resolveImpPaths(impId).checkpointsDir, dropped.id), {
|
|
56493
56609
|
recursive: true,
|
|
56494
56610
|
force: true
|
|
56495
56611
|
});
|
|
@@ -56504,7 +56620,7 @@ function createXfsBackend(deps) {
|
|
|
56504
56620
|
const listOtherFiles = () => {
|
|
56505
56621
|
const images = listEntries2(buildImagesDir(deps.dataDir)).filter((name) => !name.startsWith(".")).map((name) => ({
|
|
56506
56622
|
owner: `image:${name}`,
|
|
56507
|
-
path:
|
|
56623
|
+
path: join42(buildImagesDir(deps.dataDir), name, "rootfs.ext4")
|
|
56508
56624
|
}));
|
|
56509
56625
|
const tree = listFilesUnder(backup.tree).map((path) => ({ owner: "backup", path }));
|
|
56510
56626
|
return [...images, ...tree].filter((file) => existsSync27(file.path));
|
|
@@ -56512,7 +56628,7 @@ function createXfsBackend(deps) {
|
|
|
56512
56628
|
const usageState = { resumeImpId: null };
|
|
56513
56629
|
const setupReserveFile = async () => {
|
|
56514
56630
|
const bytes = deps.reserveFileBytes ?? 0;
|
|
56515
|
-
const file =
|
|
56631
|
+
const file = join42(deps.dataDir, "reserve");
|
|
56516
56632
|
if (bytes === 0 || existsSync27(file)) {
|
|
56517
56633
|
return;
|
|
56518
56634
|
}
|
|
@@ -56542,7 +56658,7 @@ function createXfsBackend(deps) {
|
|
|
56542
56658
|
start: (live) => {
|
|
56543
56659
|
const imagesDir = buildImagesDir(deps.dataDir);
|
|
56544
56660
|
for (const name of listEntries2(imagesDir).filter((entry) => entry.startsWith("."))) {
|
|
56545
|
-
rmSync31(
|
|
56661
|
+
rmSync31(join42(imagesDir, name), { recursive: true, force: true });
|
|
56546
56662
|
}
|
|
56547
56663
|
const swept = removeUnnamed(live, { isDryRun: false, isOrphans: false });
|
|
56548
56664
|
printSweep(getImpdLogger("storage"), swept, "each");
|
|
@@ -56564,7 +56680,7 @@ function createXfsBackend(deps) {
|
|
|
56564
56680
|
receiveMoveSnapshots: () => Promise.reject(new Error("xfs: only a ZFS host receives ZFS streams")),
|
|
56565
56681
|
createImage,
|
|
56566
56682
|
createImageFromImp: (digest, impId, steps) => createImage(digest, async (directory) => {
|
|
56567
|
-
await steps.hold(() => cloneFile(resolveImpPaths(impId).disk,
|
|
56683
|
+
await steps.hold(() => cloneFile(resolveImpPaths(impId).disk, join42(directory, "rootfs.ext4")));
|
|
56568
56684
|
await steps.write(directory);
|
|
56569
56685
|
}),
|
|
56570
56686
|
removeImage: (digest) => {
|
|
@@ -56706,8 +56822,8 @@ function isSharedExtent(extent) {
|
|
|
56706
56822
|
}
|
|
56707
56823
|
|
|
56708
56824
|
// packages/daemon/src/vm/storage/zfs/zfs-backend.ts
|
|
56709
|
-
import { existsSync as existsSync30, mkdirSync as mkdirSync28, readFileSync as
|
|
56710
|
-
import { join as
|
|
56825
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync28, readFileSync as readFileSync35, rmdirSync as rmdirSync3, writeFileSync as writeFileSync13 } from "fs";
|
|
56826
|
+
import { join as join46 } from "path";
|
|
56711
56827
|
|
|
56712
56828
|
// packages/daemon/src/platform/process/run-stream.ts
|
|
56713
56829
|
function createStreamRunner() {
|
|
@@ -56996,7 +57112,7 @@ function formatUiomoveWarning(version) {
|
|
|
56996
57112
|
|
|
56997
57113
|
// packages/daemon/src/vm/storage/zfs/create-zfs-backups.ts
|
|
56998
57114
|
import { rmSync as rmSync32 } from "fs";
|
|
56999
|
-
import { dirname as dirname14, join as
|
|
57115
|
+
import { dirname as dirname14, join as join43 } from "path";
|
|
57000
57116
|
function createZfsBackups(ctx) {
|
|
57001
57117
|
return {
|
|
57002
57118
|
createBackupCopy: (impId, runId) => ctx.runSnapshot(() => ctx.zfs.snapshot(`${ctx.buildDiskName(impId)}@bk-${runId}-${impId}`)),
|
|
@@ -57023,7 +57139,7 @@ function createZfsBackups(ctx) {
|
|
|
57023
57139
|
ctx.startReclaim();
|
|
57024
57140
|
};
|
|
57025
57141
|
const createTreeClone = async (snapshot, name, relativeDir) => {
|
|
57026
|
-
const directory =
|
|
57142
|
+
const directory = join43(tree, relativeDir);
|
|
57027
57143
|
await ctx.zfs.clone(snapshot, name, { readonly: "on" });
|
|
57028
57144
|
clones.push({ name, directory });
|
|
57029
57145
|
await ctx.setupMount(name, directory, true);
|
|
@@ -57033,8 +57149,8 @@ function createZfsBackups(ctx) {
|
|
|
57033
57149
|
if (mounted !== undefined) {
|
|
57034
57150
|
throw new Error(`zfs: ${mounted} in the backup tree is still mounted`);
|
|
57035
57151
|
}
|
|
57036
|
-
rmSync32(
|
|
57037
|
-
rmSync32(
|
|
57152
|
+
rmSync32(join43(tree, "imps"), { recursive: true, force: true });
|
|
57153
|
+
rmSync32(join43(tree, "images"), { recursive: true, force: true });
|
|
57038
57154
|
const entries = await ctx.listAll();
|
|
57039
57155
|
for (const imp of request.imps) {
|
|
57040
57156
|
const copy = entries.find((entry) => entry.type === "snapshot" && entry.name.endsWith(`@bk-${request.runId}-${imp.impId}`));
|
|
@@ -57167,7 +57283,7 @@ function createZfsCheckpoints(ctx) {
|
|
|
57167
57283
|
}
|
|
57168
57284
|
|
|
57169
57285
|
// packages/daemon/src/vm/storage/zfs/create-zfs-moves.ts
|
|
57170
|
-
import { join as
|
|
57286
|
+
import { join as join44 } from "path";
|
|
57171
57287
|
function createZfsMoves(ctx) {
|
|
57172
57288
|
const openMoveFiles = async (snapshots, removeMoveSnapshot) => {
|
|
57173
57289
|
const moveId = Bun.randomUUIDv7();
|
|
@@ -57196,7 +57312,7 @@ function createZfsMoves(ctx) {
|
|
|
57196
57312
|
await removeClones();
|
|
57197
57313
|
throw error;
|
|
57198
57314
|
}
|
|
57199
|
-
const paths = clones.map((clone) =>
|
|
57315
|
+
const paths = clones.map((clone) => join44(clone.directory, ctx.rootfsFile));
|
|
57200
57316
|
return {
|
|
57201
57317
|
kind: "files",
|
|
57202
57318
|
checkpointPaths: paths.slice(0, -1),
|
|
@@ -57452,7 +57568,7 @@ function createZfsReclaim(ctx) {
|
|
|
57452
57568
|
|
|
57453
57569
|
// packages/daemon/src/vm/storage/zfs/create-zfs-sweep.ts
|
|
57454
57570
|
import { existsSync as existsSync28, readdirSync as readdirSync13, rmSync as rmSync33 } from "fs";
|
|
57455
|
-
import { join as
|
|
57571
|
+
import { join as join45 } from "path";
|
|
57456
57572
|
var FORK_SNAPSHOT = /@fork-[^@]+$/u;
|
|
57457
57573
|
var BACKUP_SNAPSHOT = /@bk-[^@]+$/u;
|
|
57458
57574
|
var MOVE_SNAPSHOT = /@mv-[^@]+$/u;
|
|
@@ -57477,10 +57593,10 @@ function createZfsSweep(ctx) {
|
|
|
57477
57593
|
const orphanCheckpoints = isOrphans ? [] : unmarked.filter((entry) => !isOnOrphan(entry) && isOrphanCheckpoint(entry));
|
|
57478
57594
|
const keptDisks = isOrphans ? [] : unknownDisks;
|
|
57479
57595
|
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:
|
|
57596
|
+
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
57597
|
const unknownDirs = [
|
|
57482
57598
|
...listUnknownDirs("imp", buildImpsDir(ctx.dataDir)),
|
|
57483
|
-
...listUnknownDirs("memory",
|
|
57599
|
+
...listUnknownDirs("memory", join45(ctx.dataDir, "mem"))
|
|
57484
57600
|
];
|
|
57485
57601
|
const probeDirDropped = (entry) => isOrphans || !probeHoldingFiles(entry.directory);
|
|
57486
57602
|
const droppedDirs = unknownDirs.filter((entry) => probeDirDropped(entry));
|
|
@@ -57569,7 +57685,7 @@ function createZfsSweep(ctx) {
|
|
|
57569
57685
|
}
|
|
57570
57686
|
}
|
|
57571
57687
|
for (const impId of plan.memDirs) {
|
|
57572
|
-
rmSync33(
|
|
57688
|
+
rmSync33(join45(ctx.dataDir, "mem", impId), { recursive: true, force: true });
|
|
57573
57689
|
}
|
|
57574
57690
|
return { dropped: toDropped(plan), kept };
|
|
57575
57691
|
};
|
|
@@ -57657,13 +57773,13 @@ function createZfsBackend(deps) {
|
|
|
57657
57773
|
const buildDiskName = (impId) => `${datasets.disks}/${impId}`;
|
|
57658
57774
|
const buildImageName = (digest) => `${datasets.images}/${toDigestHex(digest)}`;
|
|
57659
57775
|
const buildRestoreName = (impId) => `${datasets.staging}/restore-${impId}`;
|
|
57660
|
-
const buildDiskDir = (impId) =>
|
|
57776
|
+
const buildDiskDir = (impId) => join46(buildImpPaths(deps.dataDir, impId).directory, "disk");
|
|
57661
57777
|
const buildImageDir = (digest) => buildImagePaths(deps.dataDir, digest).directory;
|
|
57662
|
-
const buildStagingDir = (name) =>
|
|
57778
|
+
const buildStagingDir = (name) => join46(deps.dataDir, "staging", name.slice(datasets.staging.length + 1));
|
|
57663
57779
|
const resolveImpPaths = (impId) => ({
|
|
57664
57780
|
...buildImpPaths(deps.dataDir, impId),
|
|
57665
|
-
disk:
|
|
57666
|
-
...buildSnapshotPaths(
|
|
57781
|
+
disk: join46(buildDiskDir(impId), ROOTFS_FILE),
|
|
57782
|
+
...buildSnapshotPaths(join46(deps.dataDir, "mem", impId))
|
|
57667
57783
|
});
|
|
57668
57784
|
const listAll = () => zfs.list(deps.root);
|
|
57669
57785
|
const setupMount = async (name, directory, isReadOnly = false) => {
|
|
@@ -57806,7 +57922,7 @@ function createZfsBackend(deps) {
|
|
|
57806
57922
|
throw new Error(`zfs: ${deps.root} is not mounted on ${deps.dataDir} (host/scripts/setup-storage.sh mounts it)`);
|
|
57807
57923
|
}
|
|
57808
57924
|
await createMissingDatasets();
|
|
57809
|
-
await setupMount(datasets.mem,
|
|
57925
|
+
await setupMount(datasets.mem, join46(deps.dataDir, "mem"));
|
|
57810
57926
|
await resolveStaging();
|
|
57811
57927
|
const swept = await sweep.removeLeftovers(live, { isDryRun: false, isOrphans: false });
|
|
57812
57928
|
printSweep(getImpdLogger("storage"), swept, "each");
|
|
@@ -57891,7 +58007,7 @@ function createZfsBackend(deps) {
|
|
|
57891
58007
|
await zfs.create(target);
|
|
57892
58008
|
await setupMount(target, buildDiskDir(impId));
|
|
57893
58009
|
});
|
|
57894
|
-
writeFileSync13(
|
|
58010
|
+
writeFileSync13(join46(buildDiskDir(impId), ROOTFS_FILE), "");
|
|
57895
58011
|
return;
|
|
57896
58012
|
}
|
|
57897
58013
|
await runSerial(async () => {
|
|
@@ -57968,7 +58084,7 @@ function createZfsBackend(deps) {
|
|
|
57968
58084
|
}
|
|
57969
58085
|
function readZfsModuleVersion() {
|
|
57970
58086
|
try {
|
|
57971
|
-
return
|
|
58087
|
+
return readFileSync35("/sys/module/zfs/version", "utf8").trim();
|
|
57972
58088
|
} catch {
|
|
57973
58089
|
return null;
|
|
57974
58090
|
}
|
|
@@ -58011,14 +58127,14 @@ function createBackend(config, boundaries) {
|
|
|
58011
58127
|
});
|
|
58012
58128
|
}
|
|
58013
58129
|
function checkStorageMarker(dataDir, kind) {
|
|
58014
|
-
const marker =
|
|
58015
|
-
const recorded = existsSync31(marker) ?
|
|
58130
|
+
const marker = join47(dataDir, MARKER_FILE);
|
|
58131
|
+
const recorded = existsSync31(marker) ? readFileSync36(marker, "utf8").trim() : readUnmarked(dataDir);
|
|
58016
58132
|
if (recorded !== null && recorded !== kind) {
|
|
58017
58133
|
throw new Error(`${dataDir} holds ${recorded} storage, but IMP_STORAGE_BACKEND is ${kind}; moving imps between backends is not supported`);
|
|
58018
58134
|
}
|
|
58019
58135
|
}
|
|
58020
58136
|
function writeStorageMarker(dataDir, kind) {
|
|
58021
|
-
const marker =
|
|
58137
|
+
const marker = join47(dataDir, MARKER_FILE);
|
|
58022
58138
|
if (!existsSync31(marker)) {
|
|
58023
58139
|
writeFileSync14(marker, `${kind}
|
|
58024
58140
|
`);
|
|
@@ -58031,7 +58147,7 @@ function readUnmarked(dataDir) {
|
|
|
58031
58147
|
}
|
|
58032
58148
|
|
|
58033
58149
|
// packages/daemon/src/vm/storage/setup-system-files.ts
|
|
58034
|
-
import { existsSync as existsSync32, mkdirSync as mkdirSync29, readFileSync as
|
|
58150
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync29, readFileSync as readFileSync37 } from "fs";
|
|
58035
58151
|
import { dirname as dirname15 } from "path";
|
|
58036
58152
|
|
|
58037
58153
|
// packages/daemon/src/vm/storage/system-file-info.ts
|
|
@@ -58067,7 +58183,7 @@ async function setupSystemFiles(config) {
|
|
|
58067
58183
|
const missing = config.kernelSource === null ? " and no source is configured" : "";
|
|
58068
58184
|
throw new Error(`${kernelSource} does not exist${missing}`);
|
|
58069
58185
|
}
|
|
58070
|
-
const kernel =
|
|
58186
|
+
const kernel = readFileSync37(kernelSource);
|
|
58071
58187
|
const guestKernel = readKernelInfo(kernel);
|
|
58072
58188
|
if (config.kernelSource !== null && !probeContent(config.kernelPath, kernel)) {
|
|
58073
58189
|
writeCopy(config.kernelSource, config.kernelPath);
|
|
@@ -58087,7 +58203,7 @@ async function setupSystemFiles(config) {
|
|
|
58087
58203
|
};
|
|
58088
58204
|
}
|
|
58089
58205
|
function probeContent(path, content) {
|
|
58090
|
-
return existsSync32(path) && Buffer.from(content).equals(
|
|
58206
|
+
return existsSync32(path) && Buffer.from(content).equals(readFileSync37(path));
|
|
58091
58207
|
}
|
|
58092
58208
|
function writeCopy(source, target) {
|
|
58093
58209
|
mkdirSync29(dirname15(target), { recursive: true });
|
|
@@ -58139,7 +58255,7 @@ async function startImpdParts(config, boundaries, plan) {
|
|
|
58139
58255
|
}
|
|
58140
58256
|
return files;
|
|
58141
58257
|
});
|
|
58142
|
-
const db = await runStep("database", () => boundaries.db ?? openDatabase(
|
|
58258
|
+
const db = await runStep("database", () => boundaries.db ?? openDatabase(join48(config.dataDir, "db", "imp.sqlite")));
|
|
58143
58259
|
plan.db = boundaries.db === undefined ? db : null;
|
|
58144
58260
|
const kernelOops = boundaries.imps?.kernelOops ?? createKernelOopsWatch();
|
|
58145
58261
|
const storage = boundaries.storage ?? createStorageBackend(config, { zfs: { isKernelOopsed: kernelOops.isOopsed } });
|
|
@@ -58246,7 +58362,7 @@ async function startImpdParts(config, boundaries, plan) {
|
|
|
58246
58362
|
secretFiles
|
|
58247
58363
|
});
|
|
58248
58364
|
const state = { ready: false };
|
|
58249
|
-
const authorizedKeys = createAuthorizedKeys(
|
|
58365
|
+
const authorizedKeys = createAuthorizedKeys(join48(setupSshDir(config.dataDir), "authorized_keys"));
|
|
58250
58366
|
const access = await runStep("access", () => loadImpdAccess(config, deps, authorizedKeys.probeListed));
|
|
58251
58367
|
const backups = config.backup === null ? null : createBackupService({
|
|
58252
58368
|
dataDir: config.dataDir,
|
|
@@ -58312,7 +58428,7 @@ async function startImpdParts(config, boundaries, plan) {
|
|
|
58312
58428
|
readTailnetNames: tailnetNames === null ? null : tailnetNames.readStatus,
|
|
58313
58429
|
hostReaders: {
|
|
58314
58430
|
readKernel: () => deps.hostKernelRelease ?? release2(),
|
|
58315
|
-
readCpuInfo: deps.readCpuInfo ?? (() =>
|
|
58431
|
+
readCpuInfo: deps.readCpuInfo ?? (() => readFileSync38("/proc/cpuinfo", "utf8")),
|
|
58316
58432
|
readHugePagePool: deps.imps?.readHugePagePool ?? (() => readHugePagePool())
|
|
58317
58433
|
},
|
|
58318
58434
|
isReady: () => state.ready,
|
|
@@ -58431,6 +58547,11 @@ function buildStubTickerTimer() {
|
|
|
58431
58547
|
};
|
|
58432
58548
|
}
|
|
58433
58549
|
|
|
58550
|
+
// packages/daemon/testing/platform/format-run-prefix.ts
|
|
58551
|
+
function formatRunPrefix(owner) {
|
|
58552
|
+
return `pid${String(owner.pid)}-ns${owner.namespace}-`;
|
|
58553
|
+
}
|
|
58554
|
+
|
|
58434
58555
|
// packages/daemon/testing/platform/open-migrated-copy.ts
|
|
58435
58556
|
import { Database as Database4 } from "bun:sqlite";
|
|
58436
58557
|
var TEMPLATE = {};
|
|
@@ -58453,6 +58574,15 @@ function pickImpdPort(draw) {
|
|
|
58453
58574
|
return FIRST_PORT + Math.floor(draw * PORT_SPAN);
|
|
58454
58575
|
}
|
|
58455
58576
|
|
|
58577
|
+
// packages/daemon/testing/platform/read-run-owner.ts
|
|
58578
|
+
import { readlinkSync as readlinkSync2 } from "fs";
|
|
58579
|
+
function readRunOwner() {
|
|
58580
|
+
return {
|
|
58581
|
+
pid: process.pid,
|
|
58582
|
+
namespace: readlinkSync2("/proc/self/ns/pid").replaceAll(/\D/gu, "")
|
|
58583
|
+
};
|
|
58584
|
+
}
|
|
58585
|
+
|
|
58456
58586
|
// packages/daemon/testing/platform/start-impd-log-capture.ts
|
|
58457
58587
|
import { resetSync } from "@logtape/logtape";
|
|
58458
58588
|
|
|
@@ -58547,7 +58677,8 @@ function buildStubVmm() {
|
|
|
58547
58677
|
uptimeMs: 60000,
|
|
58548
58678
|
identityReset: "ok",
|
|
58549
58679
|
hasBootId: true,
|
|
58550
|
-
bootSteps: {}
|
|
58680
|
+
bootSteps: {},
|
|
58681
|
+
pageHandler: undefined
|
|
58551
58682
|
};
|
|
58552
58683
|
const guestMemory = new Map;
|
|
58553
58684
|
const readFakeGuestMemory = (directory) => {
|
|
@@ -58669,7 +58800,8 @@ log tail`);
|
|
|
58669
58800
|
return {
|
|
58670
58801
|
...vm,
|
|
58671
58802
|
hugePages: plan.hugePages ?? "None",
|
|
58672
|
-
bootId: bootIds.get(plan.paths.apiSocket)
|
|
58803
|
+
bootId: bootIds.get(plan.paths.apiSocket),
|
|
58804
|
+
...plan.hugePages === "2M" && { pageHandler: guest.pageHandler }
|
|
58673
58805
|
};
|
|
58674
58806
|
} finally {
|
|
58675
58807
|
usedSnapshots.add(plan.paths.snapshotDir);
|
|
@@ -58879,6 +59011,9 @@ log tail`);
|
|
|
58879
59011
|
setGuestBootSteps: (steps) => {
|
|
58880
59012
|
guest.bootSteps = steps;
|
|
58881
59013
|
},
|
|
59014
|
+
setPageHandlerStats: (stats) => {
|
|
59015
|
+
guest.pageHandler = stats;
|
|
59016
|
+
},
|
|
58882
59017
|
setIdentityReset: (result) => {
|
|
58883
59018
|
guest.identityReset = result;
|
|
58884
59019
|
},
|
|
@@ -58918,7 +59053,7 @@ var NO_FREEZER = { freeze: () => Promise.resolve(), thaw: () => Promise.resolve(
|
|
|
58918
59053
|
var KSM_KERNEL = "6.12.0";
|
|
58919
59054
|
var IDLE_KSM = { running: true, sharedMib: 0, profitMib: 0, zeroMib: 0 };
|
|
58920
59055
|
async function startTestImpd(stack, options = {}) {
|
|
58921
|
-
const dataDir = options.dataDir ?? mkdtempSync(`${tmpdir()}
|
|
59056
|
+
const dataDir = options.dataDir ?? mkdtempSync(`${tmpdir()}/${formatRunPrefix(readRunOwner())}impd-test-`);
|
|
58922
59057
|
if (options.dataDir === undefined) {
|
|
58923
59058
|
stack.defer(() => rm2(dataDir, { recursive: true, force: true }));
|
|
58924
59059
|
}
|
|
@@ -58989,6 +59124,7 @@ async function startTestImpd(stack, options = {}) {
|
|
|
58989
59124
|
});
|
|
58990
59125
|
const cgroups = options.cgroups ?? createCpuCgroups({ root: "/nonexistent" });
|
|
58991
59126
|
const extra = options.boundaries ?? {};
|
|
59127
|
+
const procRoot = options.procRoot;
|
|
58992
59128
|
const buildBoundaries = (identity, runner, storage) => {
|
|
58993
59129
|
const jails = options.jails;
|
|
58994
59130
|
return {
|
|
@@ -59088,6 +59224,9 @@ async function startTestImpd(stack, options = {}) {
|
|
|
59088
59224
|
hostCpus: options.hostCpus ?? 8,
|
|
59089
59225
|
kernelOops,
|
|
59090
59226
|
readThreadIds: (pid) => options.procRoot === undefined ? null : readThreadIds(pid, options.procRoot),
|
|
59227
|
+
...procRoot !== undefined && {
|
|
59228
|
+
readHostLoad: () => readHostLoad({ procRoot, readFile: readText, logger: getImpdLogger("imps") })
|
|
59229
|
+
},
|
|
59091
59230
|
...options.readUnsharedRamMib !== undefined && {
|
|
59092
59231
|
readUnsharedRamMib: options.readUnsharedRamMib
|
|
59093
59232
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@impz/testing",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.6.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.6.0"
|
|
47
47
|
},
|
|
48
48
|
"engines": {
|
|
49
49
|
"bun": ">=1.4.3"
|