1

I'm trying to install Ubuntu 22.04 using Autoinstall. My generated ISO that includes userdata.yml (main autoinstall's file) has storage section, that should support both EFI and Legacy boot, but I cannot find a way to implement it.

Storage section in userdata.yml that supports only EFI boot:

  storage:
    config:
    - ptable: gpt
      path: /dev/sda
      wipe: superblock-recursive
      preserve: false
      name: ''
      grub_device: false
      type: disk
      id: disk-sda
    - device: disk-sda
      size: 1127219200
      wipe: superblock
      flag: boot
      number: 1
      preserve: false
      grub_device: true
      type: partition
      id: partition-0
    - fstype: fat32
      volume: partition-0
      preserve: false
      type: format
      id: format-0
    - device: disk-sda
      size: 1073741824
      wipe: superblock
      flag: ''
      number: 2
      preserve: false
      grub_device: false
      type: partition
      id: partition-1
    - fstype: ext4
      volume: partition-1
      preserve: false
      type: format
      id: format-1
    - device: disk-sda
      size: 54760833024
      wipe: superblock
      flag: ''
      number: 3
      preserve: false
      grub_device: false
      type: partition
      id: partition-2
    - name: myvg
      devices:
      - partition-2
      preserve: false
      type: lvm_volgroup
      id: lvm_volgroup-0
    - name: slashlv
      volgroup: lvm_volgroup-0
      size: 53687091200B
      wipe: superblock
      preserve: false
      type: lvm_partition
      id: lvm_partition-0
    - fstype: ext4
      volume: lvm_partition-0
      preserve: false
      type: format
      id: format-2
    - path: /
      device: format-2
      type: mount
      id: mount-2
    - path: /boot
      device: format-1
      type: mount
      id: mount-1
    - path: /boot/efi
      device: format-0
      type: mount
      id: mount-0

Storage section in userdata.yml that supports only Legacy boot:

  storage:
    config:
    - ptable: gpt
      path: /dev/sda
      wipe: superblock-recursive
      preserve: false
      name: ''
      grub_device: true
      type: disk
      id: disk-sda
    - device: disk-sda
      size: 1048576
      flag: bios_grub
      number: 1
      preserve: false
      grub_device: false
      type: partition
      id: partition-0
    - device: disk-sda
      size: 1073741824
      wipe: superblock
      flag: ''
      number: 2
      preserve: false
      grub_device: false
      type: partition
      id: partition-1
    - fstype: ext4
      volume: partition-1
      preserve: false
      type: format
      id: format-1
    - device: disk-sda
      size: 54760833024
      wipe: superblock
      flag: ''
      number: 3
      preserve: false
      grub_device: false
      type: partition
      id: partition-2
    - name: myvg
      devices:
      - partition-2
      preserve: false
      type: lvm_volgroup
      id: lvm_volgroup-0
    - name: slashlv
      volgroup: lvm_volgroup-0
      size: 53687091200B
      wipe: superblock
      preserve: false
      type: lvm_partition
      id: lvm_partition-0
    - fstype: ext4
      volume: lvm_partition-0
      preserve: false
      type: format
      id: format-2
    - path: /
      device: format-2
      type: mount
      id: mount-1
    - path: /boot
      device: format-1
      type: mount
      id: mount-0

My failure when I'm trying to install EFI with userdata.yml that supports only legacy boot (and the opposite) -

2022-11-03 09:48:37,448 ERROR root:39 finish: subiquity/Filesystem/apply_autoinstall_config: FAIL: autoinstall config did not create needed bootloader partition
2022-11-03 09:48:37,448 ERROR root:39 finish: subiquity/apply_autoinstall_config: FAIL: autoinstall config did not create needed bootloader partition

Again, I need to support both EFI and Legacy boot, in the same userdata.yml file.

Thanks!

mook765
  • 18,644
Utz
  • 139
  • 3
  • 15

3 Answers3

5

Officially, you can't create a single storage config that supports both BIOS and UEFI. The grub_device settings are incompatible. Quoting from one of the installer (subiquity) developers

Yes, probably. I actually wanted to clean this whole area up and make the config saner (for example, it really ought to be possible to install a system that will boot both legacy and UEFI) but it doesn’t look like I’m going to get around to that any time soon…

As a workaround, early-commands can be used to make a single config work. Here is a sample user-data snippet that I have used. It will modify the /autoinstall.yaml file depending on the existence of /sys/firmware/efi.

#cloud-config
autoinstall:
  storage:
    config:
    - type: disk
      match:
        size: largest
      ptable: gpt
      preserve: false
      name: ''
      grub_device: true
      id: disk-sda
    - type: partition
      device: disk-sda
      size: 4194304
      wipe: superblock
      flag: bios_grub
      number: 14
      preserve: false
      grub_device: false
      id: partition-14
    - type: partition
      device: disk-sda
      size: 111149056
      wipe: superblock
      flag: boot
      number: 15
      preserve: false
      grub_device: UEFI
      id: partition-15
    - type: partition
      device: disk-sda
      size: -1
      wipe: superblock
      number: 1
      preserve: false
      grub_device: false
      id: partition-1
    - type: format
      fstype: ext4
      volume: partition-1
      preserve: false
      id: format-1
    - type: mount
      path: /
      device: format-1
      id: mount-1
    - type: format
      fstype: fat32
      volume: partition-15
      preserve: false
      id: format-15
    - type: mount
      path: /boot/efi
      device: format-15
      id: mount-15
  early-commands:
    - |
      if [ -e "/sys/firmware/efi" ]; then
        sed -i -e "s/grub_device: UEFI/grub_device: true/" /autoinstall.yaml
      else
        sed -i -e "s/grub_device: UEFI/grub_device: false/" /autoinstall.yaml
      fi
      true

With this snippet all devices will end up with the same partition layout, which could be confusing. For example, a BIOS based machine will still end up with an unnecessary ESP partition mounted at /boot/efi, and a UEFI based machine will have an unnecessary bios_grub partition.

The cloud images have a partition layout that was used as inspiration for this config. The cloud images support both BIOS and UEFI and I wanted to duplicate that. The resulting partition table looks like this, where the final partition fills the disk.

Partition Table: gpt
Disk Flags:

Number Start End Size File system Name Flags 1 1.00MiB 5.00MiB 4.00MiB bios_grub 2 5.00MiB 111MiB 106MiB fat32 boot, esp 3 111MiB 20479MiB 20368MiB ext4

1

Here is an example I used to create autoinstall for ubuntu22.04:

  early-commands:
- |
  cat << EOF | python3
  import yaml
  import os

mbr_disk0 = {'id': 'root-disk', 'ptable': 'gpt', 'type': 'disk', 'match': {'size': 'largest'}, 'wipe': 'superblock-recursive', 'preserve': False, 'grub_device': True, 'name': 'rnxtdisk'} mbr_part0 = {'id': 'partition-0', 'type': 'partition', 'device': 'root-disk', 'size': '1M', 'flag': 'bios_grub', 'number': 1, 'preserve': False} efi_disk0 = {'id': 'root-disk', 'ptable': 'gpt', 'type': 'disk', 'match': {'size': 'largest'}, 'wipe': 'superblock-recursive', 'preserve': False, 'grub_device': False, 'name': 'rnxtdisk'} efi_part0 = {'id': 'partition-0', 'type': 'partition', 'device': 'root-disk', 'grub_device': True, 'size': '1G', 'flag': 'boot', 'number': 1, 'preserve': False} part1 = {'id': 'partition-1', 'type': 'partition', 'device': 'root-disk', 'size': '1G', 'wipe': 'superblock', 'number': 2, 'preserve': False} part2 = {'id': 'partition-2', 'type': 'partition', 'device': 'root-disk', 'size': -1, 'wipe': 'superblock', 'number': 3, 'preserve': False} vg0 = {'name': 'vg0', 'devices': ['partition-2'], 'preserve': False, 'id': 'lvm_volgroup-0', 'type': 'lvm_volgroup'} lv_root = {'name': 'lv-root', 'volgroup': 'lvm_volgroup-0', 'size': '10G', 'wipe': 'superblock', 'preserve': False, 'id': 'lvm_partition-0', 'type': 'lvm_partition'} fmt_root = {'fstype': 'xfs', 'volume': 'lvm_partition-0', 'preserve': False, 'id': 'format-2', 'type': 'format'} mnt_root = {'path': '/', 'device': 'format-2', 'id': 'mount-2', 'type': 'mount'} lv_home = {'name': 'lv-home', 'volgroup': 'lvm_volgroup-0', 'size': '5G', 'wipe': 'superblock', 'preserve': False, 'id': 'lvm_partition-1', 'type': 'lvm_partition'} fmt_home = {'fstype': 'xfs', 'volume': 'lvm_partition-1', 'preserve': False, 'id': 'format-3', 'type': 'format'} mnt_home = {'path': '/home', 'device': 'format-3', 'id': 'mount-3', 'type': 'mount'} lv_data = {'name': 'lv-data', 'volgroup': 'lvm_volgroup-0', 'size': '10G', 'wipe': 'superblock', 'preserve': False, 'id': 'lvm_partition-2', 'type': 'lvm_partition'} fmt_data = {'fstype': 'xfs', 'volume': 'lvm_partition-2', 'preserve': False, 'id': 'format-4', 'type': 'format'} mnt_data = {'path': '/data', 'device': 'format-4', 'id': 'mount-4', 'type': 'mount'} fmt_boot = {'fstype': 'xfs', 'volume': 'partition-1', 'preserve': False, 'id': 'format-1', 'type': 'format'} mnt_boot = {'path': '/boot', 'device': 'format-1', 'id': 'mount-1', 'type': 'mount'} fmt_efi = {'fstype': 'fat32', 'volume': 'partition-0', 'preserve': False, 'id': 'format-0', 'type': 'format'} mnt_efi = {'path': '/boot/efi', 'device': 'format-0', 'id': 'mount-0', 'type': 'mount'} lv_docker = {'name': 'lv-lib-docker', 'volgroup': 'lvm_volgroup-0', 'size': '10G', 'wipe': 'superblock', 'preserve': False, 'id': 'lvm_partition-3', 'type': 'lvm_partition'} fmt_docker = {'fstype': 'xfs', 'volume': 'lvm_partition-3', 'preserve': False, 'id': 'format-6', 'type': 'format'} mnt_docker = {'path': '/var/lib/docker', 'device': 'format-6', 'id': 'mount-6', 'type': 'mount'}

boot_fs = [fmt_boot, mnt_boot] root_fs = [lv_root, fmt_root, mnt_root] home_fs = [lv_home, fmt_home, mnt_home] data_fs = [lv_data, fmt_data, mnt_data] docker_fs = [lv_docker, fmt_docker, mnt_docker]

common_storage_part = [part1, part2, vg0] + boot_fs + root_fs + home_fs + data_fs + rlog_fs + docker_fs

with open('/autoinstall.yaml') as reader: autoinstall = yaml.safe_load(reader)

autoinstall['storage'].clear()

with open('/autoinstall.yaml', 'w') as writer: if os.path.exists('/sys/firmware/efi'): autoinstall['storage'].update({'config': [efi_disk0, efi_part0, fmt_efi, mnt_efi] + common_storage_part }) else: autoinstall['storage'].update({'config': [mbr_disk0, mbr_part0] + common_storage_part }) yaml.dump(autoinstall, writer)

EOF

0

Solution:

I deleted the whole storage section in user-data; The default autoinstall "knows" how to deal with it whether you are running in a UEFI system or a Legacy BIOS.

Note: It creates the following as default -

/boot - 2g
(If UEFI) /boot/efi - 1g±
/ - as LVM - 100g, or if your disk is less than 100g, it creates it with about 70% of the disk's size.
VG name - ubuntu-vg
LV name (that mounted to /) - ubuntu-lv
Utz
  • 139
  • 3
  • 15