@rallycry/conveyor-k3 0.1.7 → 0.1.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/cli.js +29 -2
- package/dist/index.d.ts +4 -1
- package/dist/index.js +9 -0
- package/dist/vm-qemu.js +24 -5
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -127,6 +127,21 @@ var init_exec = __esm({
|
|
|
127
127
|
}
|
|
128
128
|
});
|
|
129
129
|
|
|
130
|
+
// src/vm/memory-budget.ts
|
|
131
|
+
function vmHostMemoryGiB(guestGiB) {
|
|
132
|
+
return guestGiB + Math.max(1, guestGiB / 4);
|
|
133
|
+
}
|
|
134
|
+
function maximumGuestMemoryGiB(hostBytes) {
|
|
135
|
+
if (!Number.isFinite(hostBytes) || hostBytes <= 0) return 0;
|
|
136
|
+
const budget = hostBytes / 1024 ** 3 * 0.75;
|
|
137
|
+
return Math.max(0, Math.floor(Math.min(budget - 1, budget / 1.25)));
|
|
138
|
+
}
|
|
139
|
+
var init_memory_budget = __esm({
|
|
140
|
+
"src/vm/memory-budget.ts"() {
|
|
141
|
+
"use strict";
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
130
145
|
// src/vm/config.ts
|
|
131
146
|
import { cpus, freemem, totalmem } from "os";
|
|
132
147
|
import { stringify as stringify2 } from "yaml";
|
|
@@ -139,8 +154,10 @@ function validateResources(resources, host = { cpus: cpus().length, memory: tota
|
|
|
139
154
|
if (!Number.isInteger(count) || count < 1 || count > Math.max(1, host.cpus - 1)) {
|
|
140
155
|
throw new Error("CPU allocation must leave at least one host CPU available.");
|
|
141
156
|
}
|
|
142
|
-
if (!Number.isInteger(memoryGiB) || memoryGiB < 2 || memoryGiB * GIB > host.memory * 0.75) {
|
|
143
|
-
throw new Error(
|
|
157
|
+
if (!Number.isInteger(memoryGiB) || memoryGiB < 2 || vmHostMemoryGiB(memoryGiB) * GIB > host.memory * 0.75) {
|
|
158
|
+
throw new Error(
|
|
159
|
+
"VM memory must be at least 2 GiB and leave 25% of host memory available, including QEMU and relay overhead."
|
|
160
|
+
);
|
|
144
161
|
}
|
|
145
162
|
if (!Number.isInteger(diskGiB) || diskGiB < 20 || diskGiB > 512) {
|
|
146
163
|
throw new Error("VM disk must be between 20 and 512 GiB.");
|
|
@@ -193,10 +210,18 @@ function parseInstallUrl(value) {
|
|
|
193
210
|
throw new Error("Install URL is missing its enrollment token.");
|
|
194
211
|
return url;
|
|
195
212
|
}
|
|
213
|
+
function validateStartupMemory(memoryGiB, hostBytes = totalmem()) {
|
|
214
|
+
if (memoryGiB > maximumGuestMemoryGiB(hostBytes)) {
|
|
215
|
+
throw new Error(
|
|
216
|
+
"VM memory plus host overhead must leave 25% of host RAM available. Reduce the memory allocation before starting."
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
196
220
|
var VM_NAME, GIB, IMAGES;
|
|
197
221
|
var init_config = __esm({
|
|
198
222
|
"src/vm/config.ts"() {
|
|
199
223
|
"use strict";
|
|
224
|
+
init_memory_budget();
|
|
200
225
|
VM_NAME = "conveyor";
|
|
201
226
|
GIB = 1024 ** 3;
|
|
202
227
|
IMAGES = {
|
|
@@ -1198,6 +1223,7 @@ async function createVm(ports, resources, installUrl) {
|
|
|
1198
1223
|
async function startVm(ports, state) {
|
|
1199
1224
|
ports.log("Checking VM configuration and current state\u2026");
|
|
1200
1225
|
await assertTemplateUnchanged(ports.paths, state);
|
|
1226
|
+
validateStartupMemory(state.resources.memoryGiB, ports.hostMemory?.());
|
|
1201
1227
|
const status = await vmStatus(ports, state);
|
|
1202
1228
|
const stopped = status.status === "Stopped";
|
|
1203
1229
|
if (!stopped && status.status !== "Running") {
|
|
@@ -9274,6 +9300,7 @@ Documentation=https://conveyor.rallycryapp.com/docs/guides/managed-personal-comp
|
|
|
9274
9300
|
|
|
9275
9301
|
[Service]
|
|
9276
9302
|
Type=oneshot
|
|
9303
|
+
User=root
|
|
9277
9304
|
EnvironmentFile=${ENV_FILE}
|
|
9278
9305
|
ExecStart=${options.cliBin} update
|
|
9279
9306
|
StandardOutput=journal
|
package/dist/index.d.ts
CHANGED
|
@@ -774,4 +774,7 @@ interface QemuPolicyContext {
|
|
|
774
774
|
/** Rewrites only a complete, known Lima QEMU profile; every unknown input fails closed. */
|
|
775
775
|
declare function rewriteQemuArgs(args: string[], network: QemuNetworkPolicy, ncPath?: string, context?: QemuPolicyContext): string[];
|
|
776
776
|
|
|
777
|
-
|
|
777
|
+
/** Reserve 25% of physical host RAM after accounting for VM overhead. */
|
|
778
|
+
declare function maximumGuestMemoryGiB(hostBytes: number): number;
|
|
779
|
+
|
|
780
|
+
export { ClusterConnection, type ClusterConnectionConfig, ClusterDaemon, CommandError, type CrictlImage, type DaemonPorts, type Executor, type FileSystemPort$1 as FileSystemPort, type GuestDnsProvision, type GuestSrvRecord, HELP, type ImageInventory, K3S_DISABLED_COMPONENTS, K3S_INSTALL_EXEC, type K3sUpgradeDecision, type MachineState, type NetworkEndpoint, type NetworkPolicy, type QemuNetworkPolicy, type ReconcileContext, type ReconcileResult, type RegistriesFile, type ResolvedNetwork, type ResolvedNetworkHost, type SRVLookup, type UninstallResult, type UnitRenderOptions, VERBS, type Verb, cloudflaredSrvRecords, collectHeartbeat, configuredAuthHosts, countRunningConveyorPods, createMemoryFileSystem, decideK3sUpgrade, isGloballyRoutableIPv4, isVerb, maximumGuestMemoryGiB, meetsK3sMinimum, missingAuthHosts, nodeFileSystem, ownerConfiguredKeys, ownerConfiguredKubeletFlags, parseArgs, parseK3sVersion, parseRegistries, pruneStrandedImages, readImageInventory, readState, reconcile, registryAdd, registryList, renderAllUnits, renderGuestDnsProvision, renderK3sDropIn, renderKubeletDropIn, renderRegistryAuthSummary, resolveCloudflaredSrvRecords, resolveNetwork, rewriteQemuArgs, runOrThrow, runUpdate, selectStrandedImages, serializeRegistries, spawnExecutor, uninstall, upsertRegistryAuth, warmImages, writeState };
|
package/dist/index.js
CHANGED
|
@@ -7723,6 +7723,7 @@ Documentation=https://conveyor.rallycryapp.com/docs/guides/managed-personal-comp
|
|
|
7723
7723
|
|
|
7724
7724
|
[Service]
|
|
7725
7725
|
Type=oneshot
|
|
7726
|
+
User=root
|
|
7726
7727
|
EnvironmentFile=${ENV_FILE}
|
|
7727
7728
|
ExecStart=${options.cliBin} update
|
|
7728
7729
|
StandardOutput=journal
|
|
@@ -8850,6 +8851,13 @@ function rewriteQemuArgs(args, network, ncPath = "/usr/bin/nc", context = {}) {
|
|
|
8850
8851
|
assertCompleteProfile(state);
|
|
8851
8852
|
return output;
|
|
8852
8853
|
}
|
|
8854
|
+
|
|
8855
|
+
// src/vm/memory-budget.ts
|
|
8856
|
+
function maximumGuestMemoryGiB(hostBytes) {
|
|
8857
|
+
if (!Number.isFinite(hostBytes) || hostBytes <= 0) return 0;
|
|
8858
|
+
const budget = hostBytes / 1024 ** 3 * 0.75;
|
|
8859
|
+
return Math.max(0, Math.floor(Math.min(budget - 1, budget / 1.25)));
|
|
8860
|
+
}
|
|
8853
8861
|
export {
|
|
8854
8862
|
ClusterConnection,
|
|
8855
8863
|
ClusterDaemon,
|
|
@@ -8866,6 +8874,7 @@ export {
|
|
|
8866
8874
|
decideK3sUpgrade,
|
|
8867
8875
|
isGloballyRoutableIPv4,
|
|
8868
8876
|
isVerb,
|
|
8877
|
+
maximumGuestMemoryGiB,
|
|
8869
8878
|
meetsK3sMinimum,
|
|
8870
8879
|
missingAuthHosts,
|
|
8871
8880
|
nodeFileSystem,
|
package/dist/vm-qemu.js
CHANGED
|
@@ -683,6 +683,17 @@ function runRelayNow(root, invocation, io) {
|
|
|
683
683
|
input: process.stdin,
|
|
684
684
|
output: process.stdout
|
|
685
685
|
};
|
|
686
|
+
const signals = ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
687
|
+
const cleanup = () => {
|
|
688
|
+
try {
|
|
689
|
+
unregisterRelay(root, record);
|
|
690
|
+
} catch {
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
const terminated = (signal) => {
|
|
694
|
+
finish(new Error("VM relay terminated"));
|
|
695
|
+
process.kill(process.pid, signal);
|
|
696
|
+
};
|
|
686
697
|
const finish = (error) => {
|
|
687
698
|
if (finished) return;
|
|
688
699
|
finished = true;
|
|
@@ -690,13 +701,14 @@ function runRelayNow(root, invocation, io) {
|
|
|
690
701
|
if (connectTimer) clearTimeout(connectTimer);
|
|
691
702
|
socket.destroy();
|
|
692
703
|
input.destroy();
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
}
|
|
704
|
+
for (const signal of signals) process.removeListener(signal, terminated);
|
|
705
|
+
process.removeListener("exit", cleanup);
|
|
706
|
+
cleanup();
|
|
697
707
|
if (error) process.exitCode = 1;
|
|
698
708
|
resolve();
|
|
699
709
|
};
|
|
710
|
+
process.once("exit", cleanup);
|
|
711
|
+
for (const signal of signals) process.once(signal, terminated);
|
|
700
712
|
const exceedsLimit = (total) => total > MAX_RELAY_BYTES;
|
|
701
713
|
socket.setTimeout(RELAY_IDLE_MS, () => finish(new Error("VM relay idle timeout")));
|
|
702
714
|
socket.once("connect", () => {
|
|
@@ -732,6 +744,11 @@ function runRelayNow(root, invocation, io) {
|
|
|
732
744
|
});
|
|
733
745
|
}
|
|
734
746
|
|
|
747
|
+
// src/vm/memory-budget.ts
|
|
748
|
+
function vmHostMemoryGiB(guestGiB) {
|
|
749
|
+
return guestGiB + Math.max(1, guestGiB / 4);
|
|
750
|
+
}
|
|
751
|
+
|
|
735
752
|
// src/vm/resource-guard.ts
|
|
736
753
|
var GIB = 1024 ** 3;
|
|
737
754
|
var GUARD_INTERVAL_MS = 2e3;
|
|
@@ -741,7 +758,9 @@ function guardLimits(resources) {
|
|
|
741
758
|
}
|
|
742
759
|
return {
|
|
743
760
|
minFreeBytes: 10 * GIB,
|
|
744
|
-
|
|
761
|
+
// A 24 GiB Mac guest exceeded 27 GiB during image unpacking. Allow 25%
|
|
762
|
+
// overhead (at least 1 GiB); admission reserves host RAM using this same cap.
|
|
763
|
+
maxRssKiB: vmHostMemoryGiB(resources.memoryGiB) * 1024 ** 2,
|
|
745
764
|
maxProcesses: 64,
|
|
746
765
|
maxOutputBytes: 1024 * 1024,
|
|
747
766
|
maxDiskBytes: (resources.diskGiB + 1) * GIB,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rallycry/conveyor-k3",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "Managed personal compute for Conveyor. Installs and maintains a k3s cluster that runs your own card builds, kept converged on Conveyor's desired state.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflared",
|