Skip to content

Instantly share code, notes, and snippets.

@joseivanlopez
Last active May 27, 2024 09:20
Show Gist options
  • Save joseivanlopez/25c49ac7e3b9b94afdb2f488dcf80148 to your computer and use it in GitHub Desktop.
Save joseivanlopez/25c49ac7e3b9b94afdb2f488dcf80148 to your computer and use it in GitHub Desktop.

Agama Auto-installation (Storage Settings)

Format specification

Storage
  disk <Disk[]>
  md <MD[]>
  lvm <VolumeGroup[]>
  bcache <BCache[]>
  nfs <NFS[]>
  multidevice_btrfs <MultideviceBtrfs[]>

Disk
  name <string>
  wipe [<boolean=false>]
  encryption [<Encryption>]
  filesystem [<Filesystem>]
  mount_point [<MountPoint>]
  partition_table [<PartitionTable>]

Encryption
  method <string>
  key [<string>]
  pdkdf [<string>]
  label [<string>]
  cipher [<string>]
  key_size [<number>]

Filesystem
  type <string>
  label [<string>]
  mkfs_options [<string[]>]
  mount_by [<string>]
  btrfs [<Btrfs>]

Btrfs
  subvolume_prefix <string>
  subvolumes <Subvolume[]>
  snapshots <boolean>
  quotas <boolean>

MountPoint
  path <string>
  mount_options [<string[]>]

PartitionTable
  type <string>
  partitions [<Partition[]>]

Partition
  alias [<string>]
  uuid [<string>]
  partition_number [<string>]
  id [<string>]
  type [<string>]
  size [<number>]
  filesystem [<Filesystem>]
  mount_point [<MountPoint>]

VolumeGroup
  name [<string>]
  pesize [<number>]
  physical_volumes [<string[]>]
  logical_volumes [<LogicalVolume[]>]

LogicalVolume
  name [<string>]
  size [<number>]
  pool [<boolean>]
  used_pool [<string>]
  stripes [<number>]
  strip_size [<number>]
  filesystem [<Filesystem>]
  mount_point [<MountPoint>]

MD
  name <string>
  level [<string>]
  chunk_size [<number>]
  devices [<string[]>]
  wipe [<boolean=false>]
  encryption [<Encryption>]
  filesystem [<Filesystem>]
  mount_point [<MountPoint>]
  partition_table [<PartitionTable>]

MultideviceBtrfs
  uuid  [<string>]
  data_raid_level <string>
  metadata_raid_level <string>
  devices <string[]>
  btrfs: [<Btrfs>]

Examples

  • Partition table

    • create
    • reuse if conditions (e.g., type matches) or create
    • reuse if any or create
    • create from scratch
    • reuse
  • Filesystem

    • create
    • reuse if conditions (e.g., type matches) or create
storage: {
  drive: [
    {
      conditions: {
        all: [{ fact: 'size_gib', value: 5, operator: 'bigger_or_equal' }]
      },
      format: {
        type: xfs
      },
      mount: {
        path: '/home',
        options: []
      },
      encrypt: {},
      partition_table: {
        conditions: {
          any: [{ self: null }, { type: 'gpt' }]
        },
        type: 'msdos',
        ...


        partitions: [
          delete: [

          ],
          reuse: [

          ],
          create: [

          ],

          {
            conditions: {
              name: '/dev/vda1'
            },
            format: {
              filesystem: xfs
            }
          },
          {
            create: {
              size: 10GiB
            },
            format: {
              type: xfs
            }
          }
        ]
      }
    }
  ]
}

Examples using jsonnet

Select a device

storage: {
  disk: [
    {
      device: {
        name: /dev/vda,
        uuid: 244445555
      },
      wipe: true
    }
  ]
}

Dynamically select a device

// This can belong to agama library.
findDisks() =
  agama.selectClass(agama.lshw, 'disk'),

// This can belong to agama library.
findDevices(fn, devices) =
  local result = std.filter(fn, devices);

// This can belong to agama library.
findDevice(fn, devices) =
  local result = findDevices(fn, devices);

  if std.length(result) > 0 then
    result[0]
  else
    error 'No device found',

// This can belong to agama library.
local used_devices = [];

// This can belong to agama library.
findUnusedDevice(fn, devices) =
  local isUnused_(device) =
    !std.contains(used_devices, device["name"])

  local unused = findDevices(isUnused_, findDevices(fn, devices));

  if std.length(unused) > 0 then
    local name = unused[0]["name"];
    used_devices = used_devices + [name];
    name
  else
    error 'No unused device found',

findRootDisk() =
  local isSuitable_(device) =
    device.size_gib > 5,

  findUnusedDisks(isSuitable_),

storage: {
  disk: [
    {
      device: {
        name: findRootDisk()
      },
      wipe: true
    }
  ]
}

Dynamically select partitions

storage: {
  disk: [
    {
      device: {
        name: select_devices([
          { key: size_gib, value: 5, matcher: "bigger_or_equal" }
        ])
      },
      filesystem: {
        type: xfs
      }
    },
    {
      device: {
        name: /dev/vda
      },
      partition_table: {
        delete: [
          {
            device: {
              name: select_partitions([
                { key: filesystem_label, value: DELETEME, matcher: "equal" }
              ])
            }
          }
        ],
        partitions: [
          {
            device: {
              name: select_partition(
                { key: name, value: /dev/vda1, matcher: equal }
              )
            },
            filesystem: {
              type: xfs
            }
          },
          {
            size: 10GiB,
            fileystem: {
              type: xfs
            }
          }
        ]
      }
    }
  ]
}

Wipe a disk and create partitions

storage: {
  disk: [
    {
      name: /dev/vda,
      wipe: true,
      partition_table: {
        type: gpt,
        partitions: [
          {
            size: 15GiB,
            filesystem:
              type: btrfs
            btrfs:
              subvolume_prefix: @,
              snapshots: true
            mount_point:
              path: /
          },
          {
            size: 50 GiB,
            filesystem:
              type: xfs
            mount_point:
              path: /home
          }
        ]
      }
    }
  ]
}

Resuse partition for root and create partition for home (removing any other partition)

storage: {
  disk: [
    {
      name: /dev/vda,
      partition_table: {
        partitions: [
          {
            uuid: 2344234r44,
            filesystem: {
              type: btrfs
            }
            btrfs: {
              subvolume_prefix: @,
              snapshots: true
            },
            mount_point: {
              path: /
            }
          },
          {
            size: 50 GiB,
            filesystem: {
              type: xfs
            },
            mount_point: {
              path: /home
            }
          }
        ]
      }
    }
  ]
}

Reuse and resize partition

storage: {
  disk: [
    {
      name: /dev/vda,
      partition_table: {
        partitions: [
          {
            uuid: 2344234r44,
            size: 10GiB,
            filesystem: {
              type: ext4
            },
            mount_point: {
              path: /
            }
          }
        ]
      }
    }
  ]
}

Reuse and mount partition

storage: {
  disk: [
    {
      name: /dev/vda,
      partition_table: {
        partitions: [
          {
            uuid: 2344234r44,
            mount_point: {
              path: /home
            }
          }
        ]
      }
    }
  ]
}

Create and encrypt a partition

storage: {
  disk: [
    {
      name: /dev/vda,
      partition_table: {
        partitions: [
          {
            size: 10GiB,
            encryption: {
              method: luks2,
              key: secret
            }
            mount_point: {
              path: /home
            }
          }
        ]
      }
    }
  ]
}

Directly format a disk

storage: {
  disk: [
    {
      name: /dev/vda,
      filesystem: {
        type: ext4
      },
      mount_point: {
        path: /data
      }
    }
  ]
}

Create a volume group over partitions

storage: {
  disk: [
    {
      name: /dev/vda,
      partition_table: {
        type: gpt,
        partitions: [
          {
            alias: vda-part1,
            size: 10GiB
          },
          {
            alias: vda-part2,
            uuid: 22323434343
          }
        ]
      }
    },
    {
      name: /dev/vdb,
      partition_table: {
        type: gpt,
        partitions: [
          {
            alias: vdb-part1,
            size: 10GiB
          }
        ]
      }
    }
  ],
  lvm: [
    {
      name: vg0,
      physical_volumes: [vda-part1, vda-part2, vdb-part1],
      logical_volumes: [
        {
          size: 5GiB,
          filesystem: {
            type: ext4
          },
          mount_point: {
            path: /home
          }
        }
      ]
    }
  ]
}

Create a MD over partitions

storage: {
  disk: [
    {
      name: /dev/vda,
      partition_table: {
        type: gpt,
        partitions: [
          {
            alias: vda-part1,
            size: 10GiB
          }
        ]
      }
    },
    {
      name: /dev/vdb,
      partition_table: {
        type: gpt,
        partitions: [
          {
            alias: vdb-part1,
            size: 10GiB
          }
        ]
      }
    }
  ],
  md: [
    {
      name: md1,
      devices: [vda-part1, vdb-part1]
    }
  ]
}

Reuse a MD

storage: {
  md: [
    {
      name: md1,
      filesystem: {
        type: ext4
      }
    }
  ]
}

Create a multidevice Btrfs

storage: {
  disk: [
    {
      name: /dev/vda,
      partition_table: {
        type: gpt,
        partitions: [
          {
            alias: vda-part1,
            size: 10GiB
          }
        ]
      }
    },
    {
      name: /dev/vdb,
      partition_table: {
        type: gpt,
        partitions: [
          {
            alias: vdb-part1,
            size: 10GiB
          }
        ]
      }
    }
  ],
  multidevice_btrfs: [
    {
      data_raid_level: raid0,
      metadata_raid_level: raid0,
      devices: [vda-part1, vdb-part1]
    }
  ]
}

Examples using jnsonnet

Select a device

storage: {
  disk: [
    {
      device: {
        name: /dev/vda,
        uuid: 244445555
      },
      wipe: true
    }
  ]
}

Dynamically select a device

storage: {
  disk: [
    {
      device: {
        name: select_device([
          { key: size_gib, value: 10, condition: greatest_or_equal }
        ])
      },
      wipe: true
    }
  ]
}

Dynamically select several devices

storage: {
  disk: [
    {
      device: {
        name: select_devices([
          { key: size_gib, value: 5, condition: equal },
          { key: name, value: /dev/vdb, condition: not_equal }
        ])
      },
      filesystem: {
        type: xfs
      }
    }
  ]
}

Dynamically delete partitions

storage: {
  disk: [
    {
      device: {
        name: /dev/vda
      },
      partition_table: {
        delete: [
          {
            device: {
              name: select_partitions([
                { key: name, value: /dev/vda\d+, condition: match },
                { key: filesystem_label, value: DELETEME }
              ])
            }
          }
        ],
        partitions: [
          {
            device: {
              name: select_partitions([
                { key: name, value: /dev/vda\d+, condition: match },
                { key: filesystem_label, value: DELETEME }
              ])
            },
            delete: true
          }
        ]
      }
    }
  ]
}

Dynamically select partitions

storage: {
  disk: [
    {
      device: {
        name: /dev/vda
      },
      partition_table: {
        delete: [
          {
            device: {
              name: select_partitions([
                { key: name, value: /dev/vda\d+, condition: match },
                { key: filesystem_label, value: DELETEME }
              ])
            }
          }
        ],
        partitions: [
          {
            device: {
              name: select_partition([
                { key: name, value: /dev/vda1 }
              ])
            },
            filesystem: {
              type: xfs
            }
          },
          {
            size: 10GiB,
            fileystem: {
              type: xfs
            }
          }
        ]
      }
    }
  ]
}

Reuse and resize a partition

storage: {
  disk: [
    {
      device: {
        name: /dev/vda
      }
      partition_table: {
        partitions: [
          {
            device: {
              uuid: 2344234r44
            },
            size: 10GiB
          }
        ]
      }
    }
  ]
}

Reuse, format and mount a partition

storage: {
  disk: [
    {
      device: {
        name: /dev/vda
      }
      partition_table: {
        partitions: [
          {
            device: {
              name: /dev/vda1
            },
            filesystem: {
              type: xfs
            },
            mount_point: {
              path: /home
            }
          }
        ]
      }
    }
  ]
}

Create and encrypt a partition

storage: {
  disk: [
    {
      partition_table: {
        partitions: [
          {
            size: 10GiB,
            encryption: {
              method: luks2,
              key: secret
            }
            filesystem: {
              type: btrfs
            }
          }
        ]
      }
    }
  ]
}

Directly format a disk

storage: {
  disk: [
    {
      device: {
        name: /dev/vda
      },
      filesystem: {
        type: ext4
      },
      mount_point: {
        path: /data
      }
    }
  ]
}

Create a volume group over partitions

storage: {
  disk: [
    {
      device: {
        name: /dev/vda,
      },
      partition_table: {
        type: gpt,
        partitions: [
          {
            alias: vda-part1,
            size: 10GiB
          },
          {
            alias: vda-part2,
            device: {
              uuid: 22323434343
            }
          }
        ]
      }
    },
    {
      device: {
        name: /dev/vdb,
      },
      partition_table: {
        type: gpt,
        partitions: [
          {
            alias: vdb-part1,
            size: 10GiB
          }
        ]
      }
    }
  ],
  lvm: [
    {
      name: vg0,
      physical_volumes: [vda_part1, vda-part2, vdb-part1],
      logical_volumes: [
        {
          size: 5GiB,
          filesystem: {
            type: ext4
          },
          mount_point: {
            path: /home
          }
        }
      ]
    }
  ]
}

Create a MD

storage: {
  disk: [
    {
      device: {
        name: /dev/vda
      },
      partition_table: {
        type: gpt,
        partitions: [
          {
            alias: vda-part1,
            size: 10GiB
          }
        ]
      }
    },
    {
      device: {
        name: /dev/vdb
      },
      wipe: true
    }
  ],
  md: [
    {
      name: md1,
      devices: [vda-part1, /dev/vdb]
    }
  ]
}

Reuse a MD

storage: {
  md: [
    {
      device: {
        name: md1
      },
      filesystem: {
        type: ext4
      }
    }
  ]
}

Create a multi-device Btrfs

storage: {
  disk: [
    {
      device: {
        name: /dev/vda
      },
      wipe: true,
      partition_table: {
        type: gpt,
        partitions: [
          {
            alias: vda-part1,
            size: 10GiB
          }
        ]
      }
    },
    {
      device: {
        name: /dev/vdb
      }
      wipe: true,
      partition_table: {
        type: gpt,
        partitions: [
          {
            alias: vdb-part1,
            size: 10GiB
          }
        ]
      }
    }
  ],
  multidevice_btrfs: [
    {
      data_raid_level: raid0,
      metadata_raid_level: raid0,
      devices: [vda-part1, vdb-part1]
    }
  ]
}

Conditions vs AutoYaST rules

AutoYaST rules

https://doc.opensuse.org/projects/autoyast/#rules

AutoYaST offers rules to configure a system depending on the system attributes. If a rule passes, then a specific profile file is selected. As result, a result profile is generated as combination of all the profiles selected with the rules.

Rules

  • Several rules can be indicated.
  • Once a rule passes:
    • The rest of rules are skipped by default.
    • Allows to indicate whether it should continue checking the rest of rules.
  • A rule can check one or more system attributes.
  • Custom attributes can be defined.
  • A custom property could use the output of a script.
  • By default all attributes have to match, but it can be switch to 'or'.
Rule
  attributeA
  attributeB
  custom1
    script
  custom2
  operator: or
  result
    profile
    continue

Attributes

  • Predefine attributes: disksize, totaldisk, memsize, etc.
  • Match types: exact, greater, lower, range, regex
AttributeName
  match
  match_type

Side notes

Pre-defined rules

NameRule
  name <string>
  operator <Operator>

SizeRule
  size <string|number>
  operator <Operator>

FilesystemRule
  filesystem <string>
  operator <Operator>
storage: {
  drives: [
    {
      conditions: {
        all: [{ size: '10GiB', operator: 'greater' }, { filesystem: 'xfs'}],
        max: 1
      },
      mount: { path: '/home' }
    }
  ]
}

Custom rules

TODO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment