rightsize 0.7.8 → 0.7.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backend-docker/backend.d.ts +4 -1
- package/dist/backend-docker/backend.d.ts.map +1 -1
- package/dist/backend-docker/backend.js +4 -0
- package/dist/backend-docker/backend.js.map +1 -1
- package/dist/backend-msb/backend.d.ts +618 -68
- package/dist/backend-msb/backend.d.ts.map +1 -1
- package/dist/backend-msb/backend.js +1236 -133
- package/dist/backend-msb/backend.js.map +1 -1
- package/dist/backend-msb/commands.d.ts +160 -16
- package/dist/backend-msb/commands.d.ts.map +1 -1
- package/dist/backend-msb/commands.js +197 -31
- package/dist/backend-msb/commands.js.map +1 -1
- package/dist/backend-msb/provisioner.d.ts +1 -1
- package/dist/backend-msb/provisioner.d.ts.map +1 -1
- package/dist/backend-msb/provisioner.js +1 -1
- package/dist/backend-msb/provisioner.js.map +1 -1
- package/dist/backend-msb/restore-access-denied.d.ts +50 -0
- package/dist/backend-msb/restore-access-denied.d.ts.map +1 -0
- package/dist/backend-msb/restore-access-denied.js +52 -0
- package/dist/backend-msb/restore-access-denied.js.map +1 -0
- package/dist/backend-msb/restore-broker.d.ts +181 -0
- package/dist/backend-msb/restore-broker.d.ts.map +1 -0
- package/dist/backend-msb/restore-broker.js +264 -0
- package/dist/backend-msb/restore-broker.js.map +1 -0
- package/dist/backend-msb/sandbox-already-exists.d.ts +32 -0
- package/dist/backend-msb/sandbox-already-exists.d.ts.map +1 -0
- package/dist/backend-msb/sandbox-already-exists.js +35 -0
- package/dist/backend-msb/sandbox-already-exists.js.map +1 -0
- package/dist/backend-msb/snapshot-create.d.ts +22 -0
- package/dist/backend-msb/snapshot-create.d.ts.map +1 -0
- package/dist/backend-msb/snapshot-create.js +33 -0
- package/dist/backend-msb/snapshot-create.js.map +1 -0
- package/dist/backend-msb/snapshot-import.d.ts +30 -14
- package/dist/backend-msb/snapshot-import.d.ts.map +1 -1
- package/dist/backend-msb/snapshot-import.js +35 -17
- package/dist/backend-msb/snapshot-import.js.map +1 -1
- package/dist/backend-msb/snapshot-rm.d.ts +28 -0
- package/dist/backend-msb/snapshot-rm.d.ts.map +1 -0
- package/dist/backend-msb/snapshot-rm.js +30 -0
- package/dist/backend-msb/snapshot-rm.js.map +1 -0
- package/dist/core/backend.d.ts +53 -22
- package/dist/core/backend.d.ts.map +1 -1
- package/dist/core/checkpoint/api.d.ts +2 -2
- package/dist/core/checkpoint/api.js +2 -2
- package/dist/core/checkpoint/registry.d.ts +34 -0
- package/dist/core/checkpoint/registry.d.ts.map +1 -1
- package/dist/core/checkpoint/registry.js +20 -1
- package/dist/core/checkpoint/registry.js.map +1 -1
- package/dist/core/errors.d.ts +49 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +61 -0
- package/dist/core/errors.js.map +1 -1
- package/dist/core/generic-container.d.ts +58 -10
- package/dist/core/generic-container.d.ts.map +1 -1
- package/dist/core/generic-container.js +222 -27
- package/dist/core/generic-container.js.map +1 -1
- package/dist/core/model.d.ts +3 -2
- package/dist/core/model.d.ts.map +1 -1
- package/dist/core/sandbox-name.d.ts +3 -0
- package/dist/core/sandbox-name.d.ts.map +1 -0
- package/dist/core/sandbox-name.js +19 -0
- package/dist/core/sandbox-name.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modules/minio.d.ts +5 -3
- package/dist/modules/minio.d.ts.map +1 -1
- package/dist/modules/minio.js +14 -4
- package/dist/modules/minio.js.map +1 -1
- package/package.json +1 -1
- package/dist/backend-msb/snapshot-list.d.ts +0 -43
- package/dist/backend-msb/snapshot-list.d.ts.map +0 -1
- package/dist/backend-msb/snapshot-list.js +0 -53
- package/dist/backend-msb/snapshot-list.js.map +0 -1
package/dist/core/errors.js
CHANGED
|
@@ -158,6 +158,40 @@ export class ReuseFromCheckpointError extends Error {
|
|
|
158
158
|
this.name = "ReuseFromCheckpointError";
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Thrown at `start()` when a container built via `GenericContainer.fromCheckpoint()`
|
|
163
|
+
* carries an env that no longer matches the checkpoint's own captured env —
|
|
164
|
+
* an extra `withEnv()` call, or one overriding a key the checkpoint already
|
|
165
|
+
* set — and the active backend has no way to apply that at restore time.
|
|
166
|
+
*
|
|
167
|
+
* msb is the one backend this affects: 0.7.1 replaced `run --from-snapshot`
|
|
168
|
+
* with a dedicated `msb restore` command that has no `-e`/`--env` flag at
|
|
169
|
+
* all (a disk-only restore replays the sandbox's own captured
|
|
170
|
+
* configuration). Before 0.7.1, an overridden or extended env silently
|
|
171
|
+
* reached the restored guest via `run -e`; since there is now no msb
|
|
172
|
+
* invocation this library could emit that would honor it, silently dropping
|
|
173
|
+
* it would let the workload boot with env the caller never asked for and
|
|
174
|
+
* without env it did ask for — a correctness bug, not a graceful
|
|
175
|
+
* degradation — so this throws instead, before any backend call. Restoring
|
|
176
|
+
* with the checkpoint's own env completely unchanged never hits this: only
|
|
177
|
+
* a call that actually changes what would be sent does. docker is
|
|
178
|
+
* unaffected — restoring there is an ordinary `docker create`/`run` against
|
|
179
|
+
* the committed image with a fresh env array, so this is never thrown when
|
|
180
|
+
* the active backend is `"docker"`.
|
|
181
|
+
*/
|
|
182
|
+
export class CheckpointRestoreEnvOverrideError extends Error {
|
|
183
|
+
backend;
|
|
184
|
+
constructor(
|
|
185
|
+
/** The active backend's name — always `"microsandbox"` today, the one backend this affects. */
|
|
186
|
+
backend) {
|
|
187
|
+
super(`fromCheckpoint(...).withEnv(...) cannot override or extend a checkpoint's captured env when restoring ` +
|
|
188
|
+
`on the '${backend}' backend — its restore command has no way to inject env at boot time, so an ` +
|
|
189
|
+
`overridden or extended env would be silently dropped instead of reaching the restored workload. ` +
|
|
190
|
+
`Restore with the checkpoint's own env unchanged, or bake the desired env into a fresh checkpoint instead.`);
|
|
191
|
+
this.backend = backend;
|
|
192
|
+
this.name = "CheckpointRestoreEnvOverrideError";
|
|
193
|
+
}
|
|
194
|
+
}
|
|
161
195
|
/**
|
|
162
196
|
* Thrown by `copyFileToContainer`/`copyContentToContainer`/
|
|
163
197
|
* `copyFileFromContainer` when `containerPath` is not absolute — both
|
|
@@ -326,4 +360,31 @@ export class TmpfsRootCheckpointError extends Error {
|
|
|
326
360
|
this.name = "TmpfsRootCheckpointError";
|
|
327
361
|
}
|
|
328
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* Thrown restoring a microsandbox checkpoint whose source container had no
|
|
365
|
+
* explicit command (the image's own default entrypoint was running) and
|
|
366
|
+
* whose registry entry carries no captured workload cmdline either —
|
|
367
|
+
* `msb restore` boots a restored sandbox with only its guest agent inside
|
|
368
|
+
* and never re-runs anything on its own (EMPIRICALLY VERIFIED against msb
|
|
369
|
+
* 0.7.1 — see `MsbCliBackend.bootRestoreOnce`'s own doc), so without EITHER
|
|
370
|
+
* source this library has no workload argv left to revive. Thrown instead of
|
|
371
|
+
* silently booting the sandbox idle — the checkpoint either predates
|
|
372
|
+
* workload-cmdline capture, or its capture attempt failed at checkpoint time
|
|
373
|
+
* (see `CheckpointRegistryEntry.capturedCommand`'s own doc on why a capture
|
|
374
|
+
* failure never fails the checkpoint that created it, only a later restore
|
|
375
|
+
* of it). Only ever thrown by the microsandbox backend.
|
|
376
|
+
*/
|
|
377
|
+
export class CheckpointWorkloadCommandMissingError extends Error {
|
|
378
|
+
ref;
|
|
379
|
+
constructor(
|
|
380
|
+
/** The checkpoint ref being restored. */
|
|
381
|
+
ref) {
|
|
382
|
+
super(`sandbox restore from checkpoint '${ref}' has no explicit command and no captured workload cmdline in ` +
|
|
383
|
+
"its registry entry — this checkpoint predates workload-cmdline capture, or its capture attempt " +
|
|
384
|
+
"failed at checkpoint time, so there is no workload argv left to revive. Re-checkpoint the source " +
|
|
385
|
+
"container under a build that captures one.");
|
|
386
|
+
this.ref = ref;
|
|
387
|
+
this.name = "CheckpointWorkloadCommandMissingError";
|
|
388
|
+
}
|
|
389
|
+
}
|
|
329
390
|
//# sourceMappingURL=errors.js.map
|
package/dist/core/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -40,6 +40,15 @@ export declare class GenericContainer implements AsyncDisposable, NetworkMember
|
|
|
40
40
|
private requireIsolationRequested;
|
|
41
41
|
private checkpointRef;
|
|
42
42
|
private checkpointSourceBackend;
|
|
43
|
+
/**
|
|
44
|
+
* `cp.spec.env` exactly as captured, set once by `fromCheckpoint()` and
|
|
45
|
+
* never touched again — kept separate from the mutable `envPairs` so
|
|
46
|
+
* `start()` can tell "the caller re-applied the checkpoint's own env
|
|
47
|
+
* unchanged" from "the caller actually overrode or extended it" (see
|
|
48
|
+
* `CheckpointRestoreEnvOverrideError`). `undefined` for every container
|
|
49
|
+
* not built via `fromCheckpoint()`.
|
|
50
|
+
*/
|
|
51
|
+
private checkpointCapturedEnv;
|
|
43
52
|
private handle;
|
|
44
53
|
private backend;
|
|
45
54
|
private mappedPorts;
|
|
@@ -61,7 +70,14 @@ export declare class GenericContainer implements AsyncDisposable, NetworkMember
|
|
|
61
70
|
* captures. `start()` throws `CheckpointBackendMismatchError` before any
|
|
62
71
|
* backend call if the active backend isn't the one that created `cp`, and
|
|
63
72
|
* `ReuseFromCheckpointError` if this container is also marked
|
|
64
|
-
* `withReuse()` — reuse's identity hash never covers a checkpoint ref.
|
|
73
|
+
* `withReuse()` — reuse's identity hash never covers a checkpoint ref. On
|
|
74
|
+
* msb specifically, `start()` also throws `CheckpointRestoreEnvOverrideError`
|
|
75
|
+
* before any backend call if a further `withEnv()` call actually changes
|
|
76
|
+
* the env beyond what `cp.spec.env` captured — msb's restore command has
|
|
77
|
+
* no way to inject env at boot time (see that error's own doc); re-calling
|
|
78
|
+
* `withEnv()` with the checkpoint's own captured values, unchanged, never
|
|
79
|
+
* throws. docker is unaffected — an overridden/extended env reaches a
|
|
80
|
+
* docker restore normally.
|
|
65
81
|
* Once started, a restored container is ordinary in every other respect:
|
|
66
82
|
* fresh host ports, normal reaping-ledger tracking, normal stop.
|
|
67
83
|
*/
|
|
@@ -292,21 +308,48 @@ export declare class GenericContainer implements AsyncDisposable, NetworkMember
|
|
|
292
308
|
* state error (same shape as `exec`/`logs`) if this container isn't
|
|
293
309
|
* currently running.
|
|
294
310
|
*
|
|
295
|
-
* Passing `name` makes this checkpoint NAMED and durable: the ref
|
|
296
|
-
* deterministic (
|
|
297
|
-
* on microsandbox, `rightsize/checkpoint:<name>` on docker — see
|
|
311
|
+
* Passing `name` makes this checkpoint NAMED and durable: on docker the ref
|
|
312
|
+
* becomes deterministic (`rightsize/checkpoint:<name>` — see
|
|
298
313
|
* `checkpointRef` — instead of a random 12-hex suffix), and — only once
|
|
299
314
|
* the backend call below has actually succeeded — a registry entry is written under
|
|
300
315
|
* `<cacheDir>/checkpoints/<name>.json` that `Checkpoints.find`/`list`/
|
|
301
316
|
* `remove` can rediscover later, in this process or a different one. `name`
|
|
302
317
|
* must match `^[a-z0-9][a-z0-9-]{0,40}$`; an invalid name throws
|
|
303
318
|
* `InvalidCheckpointNameError` before any backend call. Checkpointing under
|
|
304
|
-
* a name that already has a registry entry REPLACES it:
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
319
|
+
* a name that already has a registry entry REPLACES it: this best-effort
|
|
320
|
+
* clears whatever artifact the PRIOR checkpoint under `name` actually left
|
|
321
|
+
* behind, then overwrites the registry entry with the BACKEND'S OWN
|
|
322
|
+
* EFFECTIVE ref for the fresh checkpoint — the latest checkpoint under a
|
|
323
|
+
* name always wins. The prior artifact's real location comes from the
|
|
324
|
+
* existing registry entry itself (when one exists for a backend matching
|
|
325
|
+
* the currently active one) rather than a recomputed nominal ref: on
|
|
326
|
+
* docker the two are always the same deterministic value anyway, but on
|
|
327
|
+
* microsandbox (since 0.7.1) the effective ref is a content-addressed
|
|
328
|
+
* artifact path the nominal one never predicts (see
|
|
329
|
+
* `SandboxBackend.createCheckpoint`'s own doc), so reading it back from the
|
|
330
|
+
* registry is what makes this reliable there too — the same lookup
|
|
331
|
+
* `Checkpoints.remove(name)` itself uses.
|
|
332
|
+
*
|
|
333
|
+
* The PRIOR entry's real ref is only ever removed once the fresh
|
|
334
|
+
* checkpoint below has actually been created successfully (and, on a
|
|
335
|
+
* backend whose checkpoint reboots the workload, once the post-checkpoint
|
|
336
|
+
* re-wait below has succeeded too) — never before. When the prior ref and
|
|
337
|
+
* the freshly-minted nominal one are the SAME deterministic value (always
|
|
338
|
+
* true on docker), removing it earlier would just be removing the nominal
|
|
339
|
+
* ref that `createCheckpoint` is about to reuse anyway, so this method
|
|
340
|
+
* best-effort clears the nominal ref up front instead (a harmless no-op on
|
|
341
|
+
* microsandbox, where a name never predicts a real artifact); when the two
|
|
342
|
+
* differ (microsandbox's content-addressed case, or the rare coincidence
|
|
343
|
+
* of the two colliding on any backend), the prior ref is left completely
|
|
344
|
+
* untouched until the new one is confirmed both real and reachable. That
|
|
345
|
+
* ordering is what keeps a FAILED same-name re-checkpoint from destroying
|
|
346
|
+
* an otherwise-good, previously-restorable checkpoint: on any backend, a
|
|
347
|
+
* `createCheckpoint()` (or post-checkpoint re-wait) that throws leaves both
|
|
348
|
+
* the prior artifact and its registry entry completely untouched, exactly
|
|
349
|
+
* as if the failed call had never been attempted. Omitting `name` keeps
|
|
350
|
+
* the original behavior byte-for-byte: an ephemeral checkpoint with no
|
|
351
|
+
* registry entry, whose `Checkpoint.ref` is always the backend's own
|
|
352
|
+
* effective ref.
|
|
310
353
|
*
|
|
311
354
|
* On a backend whose `capabilities.checkpointRestartsWorkload` is `true`
|
|
312
355
|
* (microsandbox: the stop/snapshot/reboot cycle boots a fresh microVM),
|
|
@@ -323,6 +366,11 @@ export declare class GenericContainer implements AsyncDisposable, NetworkMember
|
|
|
323
366
|
* BEFORE the wait-strategy re-run — the wait must gate a container that is
|
|
324
367
|
* fully re-linked, not just booted.
|
|
325
368
|
*
|
|
369
|
+
* If that re-wait (or the link re-install before it) fails, this container
|
|
370
|
+
* is torn down to completion via `stop()` — same as a failed `start()` —
|
|
371
|
+
* before the rejection propagates, so a revived-but-never-ready workload
|
|
372
|
+
* never sits around as an orphan.
|
|
373
|
+
*
|
|
326
374
|
* Checkpoints are never auto-reaped (a committed image or a disk snapshot
|
|
327
375
|
* is not a container) — see the checkpoints guide for the manual cleanup
|
|
328
376
|
* one-liners and the `Checkpoints.remove` cleanup affordance.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generic-container.d.ts","sourceRoot":"","sources":["../../src/core/generic-container.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generic-container.d.ts","sourceRoot":"","sources":["../../src/core/generic-container.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,11 +4,12 @@ import * as os from "node:os";
|
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
import { FreePorts } from "./free-ports.js";
|
|
6
6
|
import { RunId } from "./run-id.js";
|
|
7
|
+
import { nextSandboxName } from "./sandbox-name.js";
|
|
7
8
|
import { Network } from "./network.js";
|
|
8
|
-
import { PortBindConflictError, IsolationRequiredError, CheckpointUnsupportedError, CheckpointBackendMismatchError, ReuseFromCheckpointError, RelativeContainerPathError, BackendError, RootDiskConflictError, TmpfsRootExceedsMemoryError, NetworkDisabledConflictError, TmpfsRootCheckpointError, } from "./errors.js";
|
|
9
|
+
import { PortBindConflictError, IsolationRequiredError, CheckpointUnsupportedError, CheckpointBackendMismatchError, ReuseFromCheckpointError, CheckpointRestoreEnvOverrideError, RelativeContainerPathError, BackendError, RootDiskConflictError, TmpfsRootExceedsMemoryError, NetworkDisabledConflictError, TmpfsRootCheckpointError, } from "./errors.js";
|
|
9
10
|
import { requireValidCheckpointName } from "./checkpoint/name.js";
|
|
10
11
|
import { checkpointRef } from "./checkpoint/ref.js";
|
|
11
|
-
import { toCheckpointRegistrySpec, writeCheckpointRegistryAtomic } from "./checkpoint/registry.js";
|
|
12
|
+
import { toCheckpointRegistrySpec, writeCheckpointRegistryAtomic, readCheckpointRegistry } from "./checkpoint/registry.js";
|
|
12
13
|
import { Wait } from "./wait.js";
|
|
13
14
|
import { registerSyncCleanup, unregisterSyncCleanup } from "./cleanup.js";
|
|
14
15
|
import { Backends } from "./backends.js";
|
|
@@ -24,12 +25,29 @@ function requireAbsoluteContainerPath(containerPath) {
|
|
|
24
25
|
throw new RelativeContainerPathError(containerPath);
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Order-insensitive equality for env pairs — `start()`'s only use is telling
|
|
30
|
+
* "the checkpoint's own captured env, re-applied unchanged" from "the caller
|
|
31
|
+
* actually changed it" (see `CheckpointRestoreEnvOverrideError`). Compared as
|
|
32
|
+
* key/value sets rather than positionally: `withEnv()` re-setting an
|
|
33
|
+
* existing key moves it to the end of `envPairs` (last-write-wins,
|
|
34
|
+
* insertion-ordered — see `withEnv()`'s own doc), which must not by itself
|
|
35
|
+
* read as a change.
|
|
36
|
+
*/
|
|
37
|
+
function envPairsEqual(a, b) {
|
|
38
|
+
const aMap = new Map(a);
|
|
39
|
+
const bMap = new Map(b);
|
|
40
|
+
if (aMap.size !== bMap.size) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
for (const [key, value] of aMap) {
|
|
44
|
+
if (bMap.get(key) !== value) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return true;
|
|
32
49
|
}
|
|
50
|
+
const MAX_START_ATTEMPTS = 5;
|
|
33
51
|
/** Typed-first, string-fallback classification: walk the cause chain for a typed conflict, else match the daemon's own wording. */
|
|
34
52
|
function isPortBindConflict(err) {
|
|
35
53
|
let current = err;
|
|
@@ -111,6 +129,15 @@ export class GenericContainer {
|
|
|
111
129
|
requireIsolationRequested = false;
|
|
112
130
|
checkpointRef;
|
|
113
131
|
checkpointSourceBackend;
|
|
132
|
+
/**
|
|
133
|
+
* `cp.spec.env` exactly as captured, set once by `fromCheckpoint()` and
|
|
134
|
+
* never touched again — kept separate from the mutable `envPairs` so
|
|
135
|
+
* `start()` can tell "the caller re-applied the checkpoint's own env
|
|
136
|
+
* unchanged" from "the caller actually overrode or extended it" (see
|
|
137
|
+
* `CheckpointRestoreEnvOverrideError`). `undefined` for every container
|
|
138
|
+
* not built via `fromCheckpoint()`.
|
|
139
|
+
*/
|
|
140
|
+
checkpointCapturedEnv;
|
|
114
141
|
handle;
|
|
115
142
|
backend;
|
|
116
143
|
mappedPorts = new Map();
|
|
@@ -136,7 +163,14 @@ export class GenericContainer {
|
|
|
136
163
|
* captures. `start()` throws `CheckpointBackendMismatchError` before any
|
|
137
164
|
* backend call if the active backend isn't the one that created `cp`, and
|
|
138
165
|
* `ReuseFromCheckpointError` if this container is also marked
|
|
139
|
-
* `withReuse()` — reuse's identity hash never covers a checkpoint ref.
|
|
166
|
+
* `withReuse()` — reuse's identity hash never covers a checkpoint ref. On
|
|
167
|
+
* msb specifically, `start()` also throws `CheckpointRestoreEnvOverrideError`
|
|
168
|
+
* before any backend call if a further `withEnv()` call actually changes
|
|
169
|
+
* the env beyond what `cp.spec.env` captured — msb's restore command has
|
|
170
|
+
* no way to inject env at boot time (see that error's own doc); re-calling
|
|
171
|
+
* `withEnv()` with the checkpoint's own captured values, unchanged, never
|
|
172
|
+
* throws. docker is unaffected — an overridden/extended env reaches a
|
|
173
|
+
* docker restore normally.
|
|
140
174
|
* Once started, a restored container is ordinary in every other respect:
|
|
141
175
|
* fresh host ports, normal reaping-ledger tracking, normal stop.
|
|
142
176
|
*/
|
|
@@ -144,6 +178,7 @@ export class GenericContainer {
|
|
|
144
178
|
const container = new GenericContainer(cp.ref);
|
|
145
179
|
container.checkpointRef = cp.ref;
|
|
146
180
|
container.checkpointSourceBackend = cp.backend;
|
|
181
|
+
container.checkpointCapturedEnv = cp.spec.env;
|
|
147
182
|
for (const [key, value] of cp.spec.env) {
|
|
148
183
|
container.withEnv(key, value);
|
|
149
184
|
}
|
|
@@ -466,6 +501,20 @@ export class GenericContainer {
|
|
|
466
501
|
if (this.checkpointSourceBackend !== undefined && this.checkpointSourceBackend !== backend.name) {
|
|
467
502
|
throw new CheckpointBackendMismatchError(this.checkpointSourceBackend, backend.name);
|
|
468
503
|
}
|
|
504
|
+
// Also before any backend work: msb's restore command has no -e/--env
|
|
505
|
+
// flag at all (see CheckpointRestoreEnvOverrideError's own doc) — an env
|
|
506
|
+
// the caller has genuinely changed beyond the checkpoint's own captured
|
|
507
|
+
// values can never reach a restored msb sandbox, so this refuses rather
|
|
508
|
+
// than silently booting it without the env the caller asked for. Only
|
|
509
|
+
// msb is checked: docker's restore is an ordinary create/run against the
|
|
510
|
+
// committed image, so an overridden env reaches it normally. Re-applying
|
|
511
|
+
// the checkpoint's own captured env unchanged never throws — only a call
|
|
512
|
+
// that actually changes what would be sent does.
|
|
513
|
+
if (this.checkpointRef !== undefined &&
|
|
514
|
+
backend.name === "microsandbox" &&
|
|
515
|
+
!envPairsEqual(this.checkpointCapturedEnv ?? [], this.envPairs)) {
|
|
516
|
+
throw new CheckpointRestoreEnvOverrideError(backend.name);
|
|
517
|
+
}
|
|
469
518
|
// Only the env-resolved path (never an explicit withBackend() override)
|
|
470
519
|
// drives the reaper: writes this process's run record, sweeps dead runs
|
|
471
520
|
// on first use, and spawns the watchdog. Skipping it for overrides is
|
|
@@ -516,7 +565,7 @@ export class GenericContainer {
|
|
|
516
565
|
try {
|
|
517
566
|
for (let attempt = 0; attempt < MAX_START_ATTEMPTS; attempt++) {
|
|
518
567
|
const ports = await this.allocatePorts();
|
|
519
|
-
const name =
|
|
568
|
+
const name = nextSandboxName();
|
|
520
569
|
const spec = this.buildSpec(name, ports);
|
|
521
570
|
// Appended BEFORE create() — the ledger's `.sandboxes` file is always
|
|
522
571
|
// a superset of this run's live sandboxes, never a subset. `keepAlive`
|
|
@@ -912,21 +961,48 @@ export class GenericContainer {
|
|
|
912
961
|
* state error (same shape as `exec`/`logs`) if this container isn't
|
|
913
962
|
* currently running.
|
|
914
963
|
*
|
|
915
|
-
* Passing `name` makes this checkpoint NAMED and durable: the ref
|
|
916
|
-
* deterministic (
|
|
917
|
-
* on microsandbox, `rightsize/checkpoint:<name>` on docker — see
|
|
964
|
+
* Passing `name` makes this checkpoint NAMED and durable: on docker the ref
|
|
965
|
+
* becomes deterministic (`rightsize/checkpoint:<name>` — see
|
|
918
966
|
* `checkpointRef` — instead of a random 12-hex suffix), and — only once
|
|
919
967
|
* the backend call below has actually succeeded — a registry entry is written under
|
|
920
968
|
* `<cacheDir>/checkpoints/<name>.json` that `Checkpoints.find`/`list`/
|
|
921
969
|
* `remove` can rediscover later, in this process or a different one. `name`
|
|
922
970
|
* must match `^[a-z0-9][a-z0-9-]{0,40}$`; an invalid name throws
|
|
923
971
|
* `InvalidCheckpointNameError` before any backend call. Checkpointing under
|
|
924
|
-
* a name that already has a registry entry REPLACES it:
|
|
925
|
-
*
|
|
926
|
-
*
|
|
927
|
-
*
|
|
928
|
-
*
|
|
929
|
-
*
|
|
972
|
+
* a name that already has a registry entry REPLACES it: this best-effort
|
|
973
|
+
* clears whatever artifact the PRIOR checkpoint under `name` actually left
|
|
974
|
+
* behind, then overwrites the registry entry with the BACKEND'S OWN
|
|
975
|
+
* EFFECTIVE ref for the fresh checkpoint — the latest checkpoint under a
|
|
976
|
+
* name always wins. The prior artifact's real location comes from the
|
|
977
|
+
* existing registry entry itself (when one exists for a backend matching
|
|
978
|
+
* the currently active one) rather than a recomputed nominal ref: on
|
|
979
|
+
* docker the two are always the same deterministic value anyway, but on
|
|
980
|
+
* microsandbox (since 0.7.1) the effective ref is a content-addressed
|
|
981
|
+
* artifact path the nominal one never predicts (see
|
|
982
|
+
* `SandboxBackend.createCheckpoint`'s own doc), so reading it back from the
|
|
983
|
+
* registry is what makes this reliable there too — the same lookup
|
|
984
|
+
* `Checkpoints.remove(name)` itself uses.
|
|
985
|
+
*
|
|
986
|
+
* The PRIOR entry's real ref is only ever removed once the fresh
|
|
987
|
+
* checkpoint below has actually been created successfully (and, on a
|
|
988
|
+
* backend whose checkpoint reboots the workload, once the post-checkpoint
|
|
989
|
+
* re-wait below has succeeded too) — never before. When the prior ref and
|
|
990
|
+
* the freshly-minted nominal one are the SAME deterministic value (always
|
|
991
|
+
* true on docker), removing it earlier would just be removing the nominal
|
|
992
|
+
* ref that `createCheckpoint` is about to reuse anyway, so this method
|
|
993
|
+
* best-effort clears the nominal ref up front instead (a harmless no-op on
|
|
994
|
+
* microsandbox, where a name never predicts a real artifact); when the two
|
|
995
|
+
* differ (microsandbox's content-addressed case, or the rare coincidence
|
|
996
|
+
* of the two colliding on any backend), the prior ref is left completely
|
|
997
|
+
* untouched until the new one is confirmed both real and reachable. That
|
|
998
|
+
* ordering is what keeps a FAILED same-name re-checkpoint from destroying
|
|
999
|
+
* an otherwise-good, previously-restorable checkpoint: on any backend, a
|
|
1000
|
+
* `createCheckpoint()` (or post-checkpoint re-wait) that throws leaves both
|
|
1001
|
+
* the prior artifact and its registry entry completely untouched, exactly
|
|
1002
|
+
* as if the failed call had never been attempted. Omitting `name` keeps
|
|
1003
|
+
* the original behavior byte-for-byte: an ephemeral checkpoint with no
|
|
1004
|
+
* registry entry, whose `Checkpoint.ref` is always the backend's own
|
|
1005
|
+
* effective ref.
|
|
930
1006
|
*
|
|
931
1007
|
* On a backend whose `capabilities.checkpointRestartsWorkload` is `true`
|
|
932
1008
|
* (microsandbox: the stop/snapshot/reboot cycle boots a fresh microVM),
|
|
@@ -943,6 +1019,11 @@ export class GenericContainer {
|
|
|
943
1019
|
* BEFORE the wait-strategy re-run — the wait must gate a container that is
|
|
944
1020
|
* fully re-linked, not just booted.
|
|
945
1021
|
*
|
|
1022
|
+
* If that re-wait (or the link re-install before it) fails, this container
|
|
1023
|
+
* is torn down to completion via `stop()` — same as a failed `start()` —
|
|
1024
|
+
* before the rejection propagates, so a revived-but-never-ready workload
|
|
1025
|
+
* never sits around as an orphan.
|
|
1026
|
+
*
|
|
946
1027
|
* Checkpoints are never auto-reaped (a committed image or a disk snapshot
|
|
947
1028
|
* is not a container) — see the checkpoints guide for the manual cleanup
|
|
948
1029
|
* one-liners and the `Checkpoints.remove` cleanup affordance.
|
|
@@ -968,33 +1049,147 @@ export class GenericContainer {
|
|
|
968
1049
|
throw new TmpfsRootCheckpointError();
|
|
969
1050
|
}
|
|
970
1051
|
const ref = checkpointRef(backend.name, name);
|
|
1052
|
+
// Replace semantics: a prior checkpoint under this same name — if any —
|
|
1053
|
+
// is cleared once the new one is confirmed to actually exist (see the
|
|
1054
|
+
// deferred removal after `createCheckpoint`/the post-checkpoint re-wait
|
|
1055
|
+
// below), never before — a failed re-checkpoint must never cost this
|
|
1056
|
+
// container its previously-good, restorable checkpoint. The RELIABLE way
|
|
1057
|
+
// to find where the prior checkpoint actually lives is the registry's
|
|
1058
|
+
// own recorded entry (the same lookup `Checkpoints.remove(name)` uses),
|
|
1059
|
+
// not a freshly-minted nominal ref: on docker the ref is deterministic
|
|
1060
|
+
// from `name`, so the registry entry's `ref` and the nominal one below
|
|
1061
|
+
// are always the same value anyway, but on microsandbox (since 0.7.1)
|
|
1062
|
+
// the EFFECTIVE ref `createCheckpoint` returns is a content-addressed
|
|
1063
|
+
// artifact path the nominal one never determines (see
|
|
1064
|
+
// `SandboxBackend.createCheckpoint`'s own doc) — only the registry's
|
|
1065
|
+
// recorded ref points at the real artifact there. Only consulted when
|
|
1066
|
+
// the entry's own recorded backend matches the CURRENTLY active one — a
|
|
1067
|
+
// foreign-backend ref means nothing to this backend's `removeCheckpoint`,
|
|
1068
|
+
// same gate `find`/`remove` apply to the same mismatch. A missing or
|
|
1069
|
+
// corrupt registry read is treated the same as "no entry" (best-effort:
|
|
1070
|
+
// this must never fail the checkpoint itself), leaving only the
|
|
1071
|
+
// nominal-ref removal below to run.
|
|
1072
|
+
let priorRealRef;
|
|
971
1073
|
if (name !== undefined) {
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1074
|
+
try {
|
|
1075
|
+
const registryRead = await readCheckpointRegistry(cacheDir(), name);
|
|
1076
|
+
if (registryRead.kind === "found" && registryRead.entry.backend === backend.name) {
|
|
1077
|
+
priorRealRef = registryRead.entry.ref;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
catch {
|
|
1081
|
+
// Swallowed deliberately — see the comment above.
|
|
1082
|
+
}
|
|
1083
|
+
// Best-effort clear the freshly-minted NOMINAL ref up front, before
|
|
1084
|
+
// creating the new checkpoint — exactly what this method did before
|
|
1085
|
+
// the registry lookup above existed. On docker this nominal ref IS the
|
|
1086
|
+
// prior checkpoint's real recorded ref (deterministic from `name`), so
|
|
1087
|
+
// this is the only removal that ever runs there, and it must run here:
|
|
1088
|
+
// `createCheckpoint` is about to reuse this exact ref, so there is no
|
|
1089
|
+
// "after" at which removing it wouldn't also remove the checkpoint
|
|
1090
|
+
// just created. On microsandbox this is a no-op against a path that
|
|
1091
|
+
// was never real, same as before this method ever read the registry —
|
|
1092
|
+
// so nothing new is destroyed here before the new checkpoint's success
|
|
1093
|
+
// is confirmed.
|
|
975
1094
|
await swallow(() => backend.removeCheckpoint(ref));
|
|
976
1095
|
}
|
|
977
|
-
|
|
1096
|
+
// The EFFECTIVE ref: on docker this is always `ref` itself; on
|
|
1097
|
+
// microsandbox (since 0.7.1) it is whatever real artifact path
|
|
1098
|
+
// `createCheckpoint` discovered from `msb snapshot create`'s own stdout
|
|
1099
|
+
// — never necessarily `ref`. Everything downstream (the registry entry,
|
|
1100
|
+
// the returned `Checkpoint`) uses this, not the working `ref`.
|
|
1101
|
+
//
|
|
1102
|
+
// Captured BEFORE the call: a backend whose checkpoint reboots the
|
|
1103
|
+
// workload under a fresh identity (msb's `createCheckpoint`, see its own
|
|
1104
|
+
// doc) mutates `handle.id` IN PLACE once that reboot succeeds — the same
|
|
1105
|
+
// carve-out `SandboxBackend.createCheckpoint`'s own interface doc
|
|
1106
|
+
// documents. `registerSyncCleanup` (see start(), above) keyed its exit-path
|
|
1107
|
+
// teardown entry by the OLD id; if the id just changed, that registration
|
|
1108
|
+
// must be re-keyed to the new one too, or the old entry leaks in
|
|
1109
|
+
// `cleanup.ts`'s registry forever (stop() below only ever unregisters by
|
|
1110
|
+
// the CURRENT `handle.id`, which after a rename no longer matches what
|
|
1111
|
+
// was registered) — silently breaking both the exit-path teardown for
|
|
1112
|
+
// this container AND `liveContainers()`/diagnostics, which read that same
|
|
1113
|
+
// registry.
|
|
1114
|
+
const preCheckpointHandleId = handle.id;
|
|
1115
|
+
const effectiveRef = await backend.createCheckpoint(handle, ref);
|
|
1116
|
+
if (handle.id !== preCheckpointHandleId && !handle.spec.keepAlive) {
|
|
1117
|
+
// Mirrors start()'s own keepAlive exclusion: a keepAlive container was
|
|
1118
|
+
// never registered in the first place, so there is nothing to re-key.
|
|
1119
|
+
// The cleanup closure below reads `handle.id` dynamically (see
|
|
1120
|
+
// start()'s own registerSyncCleanup call), so re-registering it under
|
|
1121
|
+
// the new id is automatically correct without capturing anything else.
|
|
1122
|
+
unregisterSyncCleanup(preCheckpointHandleId);
|
|
1123
|
+
registerSyncCleanup(handle, backend, () => backend.cleanupSync(handle.id));
|
|
1124
|
+
}
|
|
978
1125
|
if (backend.capabilities.checkpointRestartsWorkload) {
|
|
979
|
-
|
|
980
|
-
|
|
1126
|
+
// The backend checkpoint call above already succeeded — the artifact
|
|
1127
|
+
// exists — but the reboot it triggered can still leave this container
|
|
1128
|
+
// unusable: a revived workload that never becomes ready. Same shape as
|
|
1129
|
+
// start()'s own post-boot wait (line ~722): a failure here must not
|
|
1130
|
+
// leak the freshly-spawned workload (msb's revived `exec` child sits
|
|
1131
|
+
// in `handle`'s attached slot from the moment the reboot reaches
|
|
1132
|
+
// Running, well before this wait ever resolves). Tear this container
|
|
1133
|
+
// down to completion via the same this.stop() start() uses, so the
|
|
1134
|
+
// handle's attached child — and the sandbox itself — never outlive
|
|
1135
|
+
// this rejection, before rethrowing.
|
|
1136
|
+
try {
|
|
1137
|
+
if (this.installedNetworkLinks.length > 0) {
|
|
1138
|
+
await backend.installNetworkLinks(handle, this.installedNetworkLinks);
|
|
1139
|
+
}
|
|
1140
|
+
await this.waitStrategy.waitUntilReady(this.asWaitTarget());
|
|
1141
|
+
}
|
|
1142
|
+
catch (err) {
|
|
1143
|
+
await this.stop();
|
|
1144
|
+
throw err;
|
|
981
1145
|
}
|
|
982
|
-
await this.waitStrategy.waitUntilReady(this.asWaitTarget());
|
|
983
1146
|
}
|
|
1147
|
+
// The workload argv the backend captured from the guest during the
|
|
1148
|
+
// createCheckpoint() call just above, when `handle.spec.command` was
|
|
1149
|
+
// undefined — see `SandboxBackend.capturedWorkloadCommand`'s own doc.
|
|
1150
|
+
// `undefined` on every backend that never captures one (docker, or msb
|
|
1151
|
+
// when the source container already carried an explicit command).
|
|
1152
|
+
const capturedCommand = backend.capturedWorkloadCommand?.(handle);
|
|
984
1153
|
if (name !== undefined) {
|
|
1154
|
+
// Only reached once the fresh checkpoint above is confirmed both real
|
|
1155
|
+
// (createCheckpoint succeeded) and reachable (the post-checkpoint
|
|
1156
|
+
// re-wait above, when applicable, succeeded too) — a failure at either
|
|
1157
|
+
// point already threw and returned above, before any of this ran. The
|
|
1158
|
+
// PRIOR checkpoint's real recorded ref (see the registry lookup
|
|
1159
|
+
// before createCheckpoint) is best-effort removed here, now that it is
|
|
1160
|
+
// safe to: never when it's the SAME ref as the nominal one already
|
|
1161
|
+
// cleared above (docker — clearing it again here would target the
|
|
1162
|
+
// fresh checkpoint `createCheckpoint` just reused that exact ref for),
|
|
1163
|
+
// and never when it happens to equal the fresh checkpoint's own
|
|
1164
|
+
// EFFECTIVE ref (the rare case of two checkpoints content-addressing
|
|
1165
|
+
// to the very same artifact on microsandbox — removing it would delete
|
|
1166
|
+
// the checkpoint this call just created, not a prior one).
|
|
1167
|
+
if (priorRealRef !== undefined && priorRealRef !== ref && priorRealRef !== effectiveRef) {
|
|
1168
|
+
const realRef = priorRealRef;
|
|
1169
|
+
await swallow(() => backend.removeCheckpoint(realRef));
|
|
1170
|
+
}
|
|
985
1171
|
// Only after the backend checkpoint above has actually succeeded — a
|
|
986
1172
|
// failed createCheckpoint() already threw, so a registry entry is
|
|
987
1173
|
// never written for a checkpoint that doesn't exist.
|
|
988
1174
|
const entry = {
|
|
989
1175
|
name,
|
|
990
|
-
ref,
|
|
1176
|
+
ref: effectiveRef,
|
|
991
1177
|
backend: backend.name,
|
|
992
1178
|
createdIso: new Date().toISOString(),
|
|
993
1179
|
spec: toCheckpointRegistrySpec(handle.spec),
|
|
1180
|
+
...(capturedCommand !== undefined ? { capturedCommand } : {}),
|
|
994
1181
|
};
|
|
995
1182
|
await writeCheckpointRegistryAtomic(cacheDir(), name, entry);
|
|
996
1183
|
}
|
|
997
|
-
|
|
1184
|
+
// `handle.spec.command` already covers an explicit command; only
|
|
1185
|
+
// substitute the captured fallback when the source had none, so a later
|
|
1186
|
+
// `fromCheckpoint(cp).start()` on THIS in-memory `Checkpoint` — unnamed
|
|
1187
|
+
// or named, same process or not — already carries the fully-resolved
|
|
1188
|
+
// workload argv a restore-side backend needs to revive it, the same
|
|
1189
|
+
// merge `fromCheckpointRegistryEntry` applies for a registry-mediated
|
|
1190
|
+
// restore.
|
|
1191
|
+
const effectiveSpec = handle.spec.command !== undefined || capturedCommand === undefined ? handle.spec : { ...handle.spec, command: capturedCommand };
|
|
1192
|
+
return { ref: effectiveRef, backend: backend.name, spec: effectiveSpec };
|
|
998
1193
|
}
|
|
999
1194
|
/**
|
|
1000
1195
|
* Copies a host file or directory into this running container at
|