Path: blob/master/src/packages/file-server/btrfs/subvolume-quota.ts
1539 views
import { type Subvolume } from "./subvolume";1import { btrfs } from "./util";2import getLogger from "@cocalc/backend/logger";34const logger = getLogger("file-server:btrfs:subvolume-quota");56export class SubvolumeQuota {7constructor(public subvolume: Subvolume) {}89private qgroup = async () => {10const { stdout } = await btrfs({11verbose: false,12args: ["--format=json", "qgroup", "show", "-reF", this.subvolume.path],13});14const x = JSON.parse(stdout);15return x["qgroup-show"][0];16};1718get = async (): Promise<{19size: number;20used: number;21}> => {22let { max_referenced: size, referenced: used } = await this.qgroup();23if (size == "none") {24size = null;25}26return {27used,28size,29};30};3132set = async (size: string | number) => {33if (!size) {34throw Error("size must be specified");35}36logger.debug("setQuota ", this.subvolume.path, size);37await btrfs({38args: ["qgroup", "limit", `${size}`, this.subvolume.path],39});40};4142du = async () => {43return await btrfs({44args: ["filesystem", "du", "-s", this.subvolume.path],45});46};4748usage = async (): Promise<{49// used and free in bytes50used: number;51free: number;52size: number;53}> => {54const { stdout } = await btrfs({55args: ["filesystem", "usage", "-b", this.subvolume.path],56});57let used: number = -1;58let free: number = -1;59let size: number = -1;60for (const x of stdout.split("\n")) {61if (used == -1) {62const i = x.indexOf("Used:");63if (i != -1) {64used = parseInt(x.split(":")[1].trim());65continue;66}67}68if (free == -1) {69const i = x.indexOf("Free (statfs, df):");70if (i != -1) {71free = parseInt(x.split(":")[1].trim());72continue;73}74}75if (size == -1) {76const i = x.indexOf("Device size:");77if (i != -1) {78size = parseInt(x.split(":")[1].trim());79continue;80}81}82}83return { used, free, size };84};85}868788