Skip to content

Instantly share code, notes, and snippets.

@joseivanlopez
Last active October 14, 2024 10:04
Show Gist options
  • Save joseivanlopez/c09b36fcf7abe5485a5f66d6884770ea to your computer and use it in GitHub Desktop.
Save joseivanlopez/c09b36fcf7abe5485a5f66d6884770ea to your computer and use it in GitHub Desktop.

Guided Settings VS Storage Config

Comparison between the guided settings and the storage config formats to decide whether to finally kill the guided settings.

The so called guided settings is a JSON format defined to cover the Agama storage use cases. The storage service translates the guided settings to Y2Storage settings and calculates a proposal by calling to the Y2Storage guided proposal.

The storage config is a new and more powerful JSON format introduced for auto-installation. Agama also defines its own proposal, and both the storage config and the Agama proposal are able to cover all the use cases supported by the guided settings and the Y2Storage guided proposal.

Agama is going to stop using the Y2Storage guided proposal in favor of the new Agama proposal. Note that the guided proposal was originally designed to support an small set of use cases. Independently on the client (CLI, UI, auto-install, ...), Agama will always call to its own proposal.

Regarding the settings, the current UI is very attached to the guided settings. The initial plan was to keep the UI working with the guided settings, making the backend service to translate that settings to a storage config before calling to the Agama proposal. But we have received some feedback pointing to some issues with the current UI approach. Now we are planning a revamp of the UI in order to solve that problems and to support more use cases like RAID.

Making the new UI to directly manage a storage config seems to be a better approach.

              Service                       HTTP
Product
config  -->  Storage::Config     <-- storage/set_config (JSON)
                  |              --> storage/get_config (JSON)
                  |
             AgamaProposal

Goal: A New UI Concept

The current UI is going to drastically change, adding support for more scenarios like RAID. Keeping the UI using the guided settings implies to adapt such a settings to the new uses cases, duplicating the effort of maintaining two different formats. Ideally, the UI should directly work with a storage config. At least with a subset of options.

Adapting the current UI to directly use the storage settitng implies too many changes. So the plan is to somehow downgrade the current UI in order to support the basic scenarios:

  • Install in a single disk.
  • Install in a new LVM volume group (over one or several disks).
  • Define space actions (remove, resize as needed) over the partitions of the installation disks.
  • Select boot device.

And the following use cases will be dropped and reintroduced in a different way with the new UI:

  • Mounting an existing file system.
  • Reformat an existing device.
  • Create a partition in any disk.
  • Create a dedicated LVM volume group.

Use Case: Install in a Single Disk

Guided Settings

{
  boot: {
    configure: true,
    device: "/dev/vda"
  },
  target: {
    disk: "/dev/vda"
  },
  encryption: {
    method: "luks2",
    password: "12345",
    pbkdFunction: "argon2i"
  },
  space: {
    policy: "delete"
  },
  volumes: [
    {
      target: "default",
      mount: {
        path: "/"
      },
      filesystem: {
        btrfs: {
          snapshots: true
        }
      }
    },
    {
      target: "default",
      mount: {
        path: "swap"
      },
      filesystem: "swap"
    }
  ]
}

Storage Config

  • Requires to explicitly delete or resize each partition.
  • Requires to repeat the encrytion in all the new partitions.
{
  boot: {
    configure: true,
    device: "/dev/vda"
  },
  drives: [
    {
      search: "/dev/vda",
      partitions: [
        {
          search: "/dev/vda1",
          delete: true
        },
        {
          search: "/dev/vda2",
          delete: true
        },
        {
          filesystem: {
            path: "/",
            type: {
              btrfs: {
                snapshots: true
              }
            }
          },
          encryption: {
            method: "luks2",
            password: "12345",
            pbkdFunction: "argon2i"
          }
        },
        {
          filesystem: {
            path: "swap",
            type: "swap"
          },
          encryption: {
            method: "luks2",
            password: "12345",
            pbkdFunction: "argon2i"
          }
        }
      ]
    }
  ]
}

Use Case: Install in a LVM Volume Group

Guided Settings

{
  boot: {
    configure: true,
    device: "/dev/vda"
  },
  target: {
    newLvmVg: ["/dev/vda", "/dev/vdb"]
  },
  encryption: {
    method: "luks2",
    password: "12345",
    pbkdFunction: "argon2i"
  },
  space: {
    policy: "delete"
  },
  volumes: [
    {
      target: "default",
      mount: {
        path: "/"
      },
      filesystem: {
        btrfs: {
          snapshots: true
        }
      }
    },
    {
      target: "default",
      mount: {
        path: "swap"
      },
      filesystem: "swap"
    }
  ]
}

Storage Config

  • Requires to explicitly delete or resize each partition.
  • Requires to repeat the encrytion in all the new partitions.
{
  boot: {
    configure: true,
    device: "/dev/vda"
  },
  drives: [
    {
      search: "/dev/vda",
      alias: "vda",
      partitions: [
        {
          search: "/dev/vda1",
          delete: true
        },
        {
          search: "/dev/vda2",
          delete: true
        }
      ]
    },
    {
      search: "/dev/vdb",
      alias: "vdb",
      partitions: [
        {
          search: "/dev/vdb1",
          delete: true
        }
      ]
    }
  ],
  volumeGroups: [
    physicalVolumes: [
      {
        generate: ["vda", "vdb"]
      }
    ],
    logicalVolumes: [
      {
        filesystem: {
          path: "/",
          type: {
            btrfs: {
              snapshots: true
            }
          }
        },
        encryption: {
          method: "luks2",
          password: "12345",
          pbkdFunction: "argon2i"
        }
      },
      {
        filesystem: {
          path: "swap",
          type: "swap"
        },
        encryption: {
          method: "luks2",
          password: "12345",
          pbkdFunction: "argon2i"
        }
      }
    ]
  ]
}

Use Case: Custom Space Actions

Guided Settings

{
  boot: {
    configure: true,
    device: "/dev/vda"
  },
  target: {
    disk: "/dev/vda"
  }
  space: {
    policy: {
      forceDelete: "/dev/vda1",
      forceDelete: "/dev/vda2",
      resize: "/dev/vda3"
    }
  },
  volumes: [
    {
      target: "default",
      mount: {
        path: "/"
      },
      filesystem: {
        btrfs: {
          snapshots: true
        }
      }
    }
  ]
}

Storage Config

  • Resize implies to set a size with min 0.
{
  boot: {
    configure: true,
    device: "/dev/vda"
  },
  drives: [
    {
      search: "/dev/vda",
      partitions: [
        {
          search: "/dev/vda1",
          delete: true
        },
        {
          search: "/dev/vda2",
          delete: true
        },
        {
          search: "/dev/vda3",
          size: { min: 0 }
        },
        {
          filesystem: {
            path: "/",
            type: {
              btrfs: {
                snapshots: true
              }
            }
          }
        }
      ]
    }
  ]
}

Steps for Killing the Guided Settings

  • Generate Config from the product definition (default proposal).
  • Add Config conversion to JSON.
  • Extend D-Bus API to provide product data (e.g., default encryption, default paths, etc).
  • Adapt UI to basic use cases.

And then:

  • Drop ProposalSettings reader.
  • Drop ProposalSettings conversion from/to D-Bus.
  • Drop ProposalSettings conversion from/to JSON.
  • Drop ProposalSettings.
  • Drop rust conversion from D-Bus to JSON.
  • Drop rust conversion from JSON to D-Bus.
  • Drop D-Bus proposal object.
  • Adapt D-Bus API to stop accepting guided settings (e.g., #GetConfig, #SetConfig).

Questions

  • If a config is given with partitions or logical volumes generators (e.g., generate: "default"), should #GetConfig report the solved config? Note that the UI requires a solved config.

Tentative PBIs

PBI: Introduce a product definition

There are some classes that needs to recover certain information from the product, for example: the definition of a volume for a specificic mount path, the default encryption data, etc. At least the following classes require some kind of information from the product: ConfigJSONSolver, ConfigSolver, ConfigChecker.

And right now there are 3 different classes providing the required product information: Agama::Config, Agama::Storage::VolumeTemplatesBuilder and Agama::Storage::ConfigBuilder.

A new class (e.g., ProductDefinition) should be used for getting the product info. This new class could make useless some of the current classes like ConfigBuilder.

The D-Bus API should have a way to report the product information, making use of that ProductDefinition class.

Question: how should the D-Bus API look like? A new API with several methods? Or adding a single method to the storage API?

org.opensuse.Agama.Storage1.Product
  #Transactional
  #Volumes --> JSON list
  #EncryptionMethods
  #DefaultEncryption
  #...
org.opensuse.Agama.Storage1
  #ProductInfo --> JSON ({ transactional: false, volumes: [...] })

PBI: Generate config for initial proposal

The initial proposal is still calculated by the guided proposal. The guided settings are generated from the product definition (ProposalSettingsReader).

Stop using the guided proposal in favor of the agama proposal. For that, the default storage config should be generated from the product definition.

PBI: Export config to JSON

The storage config used by the agama proposal has to be reported in the D-Bus API. Cases to consiser:

  • The default proposal calculated from the product definition:

    • The storage config is generated from the product definition.
    • The storage config has to be converted to JSON.
  • A proposal calculated from the UI:

    • The UI gives the storage config in JSON format.
    • The UI always uses a "solved" config (i.e., without generate sections for partitions or lvs, with the filesystem section, etc).
  • A proposal calculated from the CLI:

    • The given config could be an "unsolved" config (i.e., with generate sections, omitting some information like the file system type, etc).
    • The result solved config has to be reported for the UI.

Question: de we need separate D-Bus methods to get the raw (unsolved) config and the solved one?

Note: The current UI is only able to manage a subset of use cases. The reported config could be unintelligible by the UI.

Nothe: There are some information that has to be reported for calculating or showing a proposal: usable devices, size range calculated for a volume, default boot device.

PBI: Adapt UI to storage config

The UI is able to understand and generate a storage config instead of the guided settings. The current UI will be downgraded, and it will only support:

  • Select boot device.
  • Install in a single disk.
  • Install in a new LVM volume group (over one or several disks).
  • Add, delete and edit volumes.
  • Define space actions (remove, resize as needed) over the partitions of the installation disks.

The UI should complain if the storage config is unintelligible, for example:

  • Install over more than one drive.
  • Install over more than one VG.
  • Contains generators for partitions or lvs.
  • Contains PV without generator.
  • Conatins unsupported encryption scenarios (volumes with different encryption config, only encrypt a subset of volumes, etc).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment