nix-community / disko

Declarative disk partitioning and formatting using nix [maintainers=@Lassulus @Enzime @iFreilicht]
MIT License
1.73k stars 191 forks source link

Cannot declare 50% size on "gpt" type #816

Open yajo opened 3 days ago

yajo commented 3 days ago

I'm in the process to migrate an old system disk declaration to the new format, just like explained in https://github.com/nix-community/disko/blob/master/docs/table-to-gpt.md.

I find out a feature that the table type had, but the gpt type doesn't have: declaring a partition as 50% size. This is the legacy format I'm using now:

{disko, ...}: {
  imports = [
    disko.nixosModules.disko
  ];

  disko.devices.disk.main = {
    type = "disk";
    device = "/dev/sda";
    content = {
      # TODO Migrate to new "gpt" type
      # DOCS https://github.com/nix-community/disko/blob/master/docs/table-to-gpt.md
      type = "table";
      format = "gpt";
      partitions = [
        {
          name = "boot";
          part-type = "primary";
          start = "1MB";
          end = "512MB";
          flags = ["bios_grub"];
        }
        {
          name = "nixos";
          start = "512MB";
          end = "50%";
          bootable = true;
          content = {
            type = "filesystem";
            format = "xfs";
            extraArgs = "-fm bigtime=1";
            mountpoint = "/";
          };
        }
        {
          name = "storage-raw";
          start = "50%";
          end = "100%";
        }
      ];
    };
  };
}

As you can see, there are 2 partitions with 50% size.

Now, when trying to do the same with the gpt type, this configuration fails:

{disko, ...}: {
  imports = [
    disko.nixosModules.disko
  ];

  disko.devices.disk.main = {
    type = "disk";
    device = "/dev/sda"; # With disko-install, we can overwrite this value from the commandline
    content = {
      type = "gpt";
      partitions = {
        boot = {
          size = "512M";
          type = "EF00";
          content = {
            type = "filesystem";
            format = "vfat";
            mountpoint = "/boot";
          };
        };
        nixos = {
          size = "50%";
          content = {
            type = "filesystem";
            format = "xfs";
            extraArgs = "-fm bigtime=1";
            mountpoint = "/";
          };
        };
        storage-raw = {
          size = "50%";
        };
      };
    };
  };
}

The error:

error:
       … while calling the 'head' builtin

         at /nix/store/5cypwijbjdxmr4i7ckpq1in7f09547fc-source/lib/attrsets.nix:1575:11:

         1574|         || pred here (elemAt values 1) (head values) then
         1575|           head values
             |           ^
         1576|         else

       … while evaluating the attribute 'optionalValue.value'

         at /nix/store/5cypwijbjdxmr4i7ckpq1in7f09547fc-source/lib/modules.nix:856:5:

          855|
          856|     optionalValue =
             |     ^
          857|       if isDefined then { value = mergedValue; }

       (stack trace truncated; use '--show-trace' to show the full trace)

       error: A definition for option `disko.devices.disk.main.content.partitions.nixos.size' is not of type `value "100%" (singular enum) or string matching the pattern [0-9]+[KMGTP]?'. Definition values:
       - In `/nix/store/i85v05nhhmhsq95f1mp91j3ixkk2jwkr-source/nix/nixos-modules/disk-layout.nix': "50%"

The ability to specify some partition to start at 50% was very useful to me, and the main problem seems to be that the gpt tool uses sgdisk (which expects absolute values) instead of parted.

Is it possible to move again to parted for gpt type, so we can specify more dynamic values? Or fix this somehow?

@moduon MT-7504

iFreilicht commented 3 days ago

Your assessment is correct, this is caused by using sgdisk (or more broadly, gptfdisk) instead of parted. However, I don't know what the reasoning was for moving from parted to sgdisk. Maybe @Mic92 or @Lassulus know more about that?

There is another related feature request to allow for more flexibility in partition sizes (#600), but I realize that this is more about restoring a feature that already existed.

Lassulus commented 3 days ago

parted is horrible for scripting and arguments are sometimes ignored on mandatory depending on other arguments passed. sgdisk provides a saner interface for using inside a script.

iFreilicht commented 3 days ago

Thank you! Then I think it's clear that we won't be going back to parted. However, it should be possible to re-implement this feature after #789