diff --git a/packages/grid_client/src/helpers/index.ts b/packages/grid_client/src/helpers/index.ts index ef382c8e77..df0e217c10 100644 --- a/packages/grid_client/src/helpers/index.ts +++ b/packages/grid_client/src/helpers/index.ts @@ -4,3 +4,4 @@ export * from "./events"; export * from "./validator"; export * from "./expose"; export * from "./migration"; +export * from "./root_fs"; diff --git a/packages/grid_client/src/helpers/root_fs.ts b/packages/grid_client/src/helpers/root_fs.ts new file mode 100644 index 0000000000..6988b959be --- /dev/null +++ b/packages/grid_client/src/helpers/root_fs.ts @@ -0,0 +1,39 @@ +import { Decimal } from "decimal.js"; + +const GB = 1024; + +interface RootFSOptions { + /** The machine CPU, should be in cores e.g. 5 cores*/ + CPUCores: number; + /** The machine memory, should be in megabytes e.g. 1024 or 2048 MG*/ + RAMInMegaBytes: number; +} + +/** + * Calculate the root filesystem size (CU - Compute Units) based on provided options. + * + * This function calculates the compute units (CU) required based on the CPU cores and RAM in megabytes. + * If both CPU cores and RAM are provided in the `options` parameter, it calculates CU by multiplying + * the CPU cores with RAM and dividing by 8 * GB, then converting the result to an integer. If the + * calculated CU is zero, it returns 500 / GB; otherwise, it returns 2. + * + * @param {RootFSOptions} [options] - Optional configuration object. + * @param {number} [options.CPUCores] - The number of CPU cores. + * @param {number} [options.RAMInMegaBytes] - The RAM size in megabytes. + * + * @returns {number} - The calculated compute units (CU) based on the provided options. + */ +function calculateRootFileSystem(options?: RootFSOptions): number { + let cu = 0; + + if (options && options.CPUCores && options.RAMInMegaBytes) { + cu = new Decimal(options.CPUCores) + .mul(options.RAMInMegaBytes) + .divToInt(8 * GB) + .toNumber(); + } + + return cu === 0 ? 500 / GB : 2; +} + +export { calculateRootFileSystem, RootFSOptions }; diff --git a/packages/grid_client/src/high_level/machine.ts b/packages/grid_client/src/high_level/machine.ts index d01821d906..0de7b154c1 100644 --- a/packages/grid_client/src/high_level/machine.ts +++ b/packages/grid_client/src/high_level/machine.ts @@ -2,6 +2,7 @@ import { GridClientErrors, ValidationError } from "@threefold/types"; import { Addr } from "netaddr"; import { events } from "../helpers/events"; +import { calculateRootFileSystem } from "../helpers/root_fs"; import { randomChoice, zeroPadding } from "../helpers/utils"; import { validateHexSeed } from "../helpers/validator"; import { DiskModel, MyceliumNetworkModel, QSFSDiskModel } from "../modules/models"; @@ -53,6 +54,12 @@ class VMHL extends HighLevelBase { zlogsOutput?: string, gpus: string[] = [], ): Promise<[TwinDeployment[], string]> { + if (!rootfs_size) { + rootfs_size = calculateRootFileSystem({ + CPUCores: cpu, + RAMInMegaBytes: memory, + }); + } const deployments: TwinDeployment[] = []; const workloads: Workload[] = []; let totalDisksSize = rootfs_size; diff --git a/packages/grid_client/tests/unittests/root_fs.test.ts b/packages/grid_client/tests/unittests/root_fs.test.ts new file mode 100644 index 0000000000..f4e07a1e79 --- /dev/null +++ b/packages/grid_client/tests/unittests/root_fs.test.ts @@ -0,0 +1,15 @@ +import { calculateRootFileSystem } from "../../src/helpers/root_fs"; + +describe("Calculate the rootFS size based on the machine specs", () => { + it("should return 2GB when the options are provided", () => { + const options = { CPUCores: 5, RAMInMegaBytes: 2048 }; + const result = calculateRootFileSystem(options); + expect(result).toEqual(2); + }); + + it("should return 0.48828125 when CPU cores and RAM are zero", () => { + const options = { CPUCores: 0, RAMInMegaBytes: 0 }; + const result = calculateRootFileSystem(options); + expect(result).toEqual(0.48828125); + }); +}); diff --git a/packages/playground/src/components/caprover_worker.vue b/packages/playground/src/components/caprover_worker.vue index 542bc4f715..cbc2a8073c 100644 --- a/packages/playground/src/components/caprover_worker.vue +++ b/packages/playground/src/components/caprover_worker.vue @@ -47,13 +47,13 @@ diff --git a/packages/playground/src/components/manage_caprover_worker_dialog.vue b/packages/playground/src/components/manage_caprover_worker_dialog.vue index 80e0581631..3904d7faae 100644 --- a/packages/playground/src/components/manage_caprover_worker_dialog.vue +++ b/packages/playground/src/components/manage_caprover_worker_dialog.vue @@ -82,7 +82,6 @@ import { ref } from "vue"; import { useGrid } from "../stores"; import { addMachine, deleteMachine, loadVM } from "../utils/deploy_vm"; -import rootFs from "../utils/root_fs"; const props = defineProps<{ master: any; data: any[]; projectName: string }>(); const emits = defineEmits<{ (event: "close"): void; (event: "update:caprover", data: any): void }>(); @@ -139,7 +138,10 @@ async function deploy(layout: any) { { key: "SWM_NODE_MODE", value: "worker" }, { key: "PUBLIC_KEY", value: props.master.env.PUBLIC_KEY }, ], - rootFilesystemSize: rootFs(worker.value.solution!.cpu, worker.value.solution!.memory), + rootFilesystemSize: calculateRootFileSystem({ + CPUCores: worker.value.solution!.cpu, + RAMInMegaBytes: worker.value.solution!.memory, + }), }); const [leader, ...workers] = vm; @@ -181,7 +183,7 @@ async function onDelete(cb: (workers: any[]) => void) {