Search code examples
salt-project

Correct way to manage block devices in SaltStack


I would like to be able provision block devices using SaltStack. In this specific case on Ubuntu 20.04. There doesn't seem to be much documentation on the subject.

The goal is to partition and format a new block device as GPT with a single EXT4 filesystem, then mount it. If the block device already has a filesystem it will just be mounted. An entry should be added to /etc/fstab so that the device is automatically mounted on boot using it's partition label.

I was able to pull together a state file that seems to have gotten the job done, volume.sls:

disk_label_mysql:
  module.run:
    - name: partition.mklabel
    - device: /dev/nvme2n1
    - label_type: gpt
    - unless: "parted /dev/nvme2n1 print | grep -i '^Partition Table: gpt'"

disk_partition_mysql:
  module.run:
    - name: parted_partition.mkpart
    - device: /dev/nvme2n1
    - fs_type: ext4
    - part_type: primary
    - start: 0%
    - end: 100%
    - unless: parted /dev/nvme2n1 print 1
    - require:
      - module: disk_label_mysql

disk_name_mysql:
  module.run:
    - name: partition.name
    - device: /dev/nvme2n1
    - partition: 1
    - m_name: mysql
    - unless: parted /dev/nvme2n1 print | grep mysql
    - require:
      - module: disk_partition_mysql

disk_format_mysql:
  module.run:
    - name: extfs.mkfs
    - device: /dev/nvme2n1p1
    - fs_type: ext4
    - label: mysql
    - unless: blkid --label mysql
    - require:
      - module: disk_name_mysql

disk_mount_mysql:
  file.directory:
    - name: /var/db/mysql
    - user: root
    - group: root
    - file_mode: 644
    - dir_mode: 777
    - makedirs: True
  mount.fstab_present:
    - name: /dev/nvme2n1p1
    - fs_file: /var/db/mysql
    - fs_vfstype: ext4
    - mount: True
    - fs_mntops:
      - defaults
    - mount_by: label
    - require:
      - module: disk_format_mysql

After applying the sate I do see the device gets partitioned and a file system formatted.

parted /dev/nvme2n1 print
Model: Amazon Elastic Block Store (nvme)
Disk /dev/nvme2n1: 53.7GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: 

Number  Start   End     Size    File system  Name    Flags
 1      1049kB  53.7GB  53.7GB  ext4         mysql

It also gets added to /etc/fstab and mounted.

# cat /etc/fstab
LABEL=cloudimg-rootfs   /    ext4   defaults,discard    0 1
LABEL=mysql     /var/db/mysql   ext4    defaults    0 0

# df -h /var/db/mysql
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme2n1p1   49G   53M   47G   1% /var/db/mysql

I would like to know if there is a "more correct way" to do this. The current approach looks very complicated. In my experience that usually means I'm doing it wrong.


Solution

  • There is a Salt state to manage block devices and it is called blockdev.

    If there is no need to explicitly create and manage partitions on a disk, using this state could eliminate the need to label, partition, name, etc. the disk.

    Example below will format the entire disk /dev/sdb with ext4 filesystem and mount it. If you have a partition, you could specify it instead of the disk.

    disk_create:
      blockdev.formatted:
        - name: /dev/sdb
        - fs_type: ext4
    
    disk_mount:
      file.directory:
        - name: /mnt/newdisk
    
      mount.mounted:
        - name: /mnt/newdisk
        - device: /dev/sdb
        - fstype: ext4