Repeatable Deployments 5 – NVMe Base Duo
Monday, October 21st, 2024
A few weeks ago we looked at using the Pimoroni NVMe Base to add 500 GBytes of storage to a Raspberry Pi, first manually and then using Ansible.
- Repeatable Deployments (Part 1)
- Adding NVMe Base Manually
- Adding NVMe Base using Ansible
- Variables and Samba
A few days ago I started to look at doing the same but this time with the NVMe Base Duo. This would allow the addition of two drives to the Raspberry Pi. Should be simple, right?
TL;DR The scripts and instructions for running them can be found in the AnsibleNVMe GitHub repository.
Setting up the Hardware
As with the NVMe Base, setting up the NVMe Base Duo was simple, just follow the installation instructions on theproduct page. Again, the most difficult part was connecting the NVMe Base Duo board to the Raspberry Pi using the flat flex connector.
A quick check of the /dev directory shows the two drives as devices:
clusteruser@TestServer:~ $ ls /dev/nv* /dev/nvme0 /dev/nvme0n1 /dev/nvme1 /dev/nvme1n1
Setting up the two drives should be a case of running the configuration script from the previous post with two different device / mount point names, namely:
- nvme0 / nvme0n1
- nvme1 / nvme1n1
Ansible tasks should allow us to reuse the commands used to mount a single drive on the NVMe Base without repeating the instructions with copy/paste.
Ansible Tasks
First thing to do is identify the tasks that should be executed on both drives. These are found in the ConfigureNVMeBase.yml file. They make up the bulk of the file. These tasks are:
- name: Format the NVMe drive {{ nvmebase_device_name }} command: mkfs.ext4 /dev/{{ nvmebase_device_name }} -L Data when: format_nvmebase | bool - name: Make the mount point for {{ nvmebase_device_name }} command: mkdir /mnt/{{ nvmebase_device_name }} - name: Mount the newly formatted drive ({{ nvmebase_device_name }}) command: mount /dev/{{ nvmebase_device_name }} /mnt/{{ nvmebase_device_name }} - name: Make sure that {{ ansible_user }} can read and write to the mount point command: chown -R {{ ansible_user }}:{{ ansible_user }} /mnt/{{ nvmebase_device_name }} - name: Get the UUID of {{ nvmebase_device_name }} command: blkid /dev/{{ nvmebase_device_name }} register: blkid_output - name: Extract UUID from blkid output set_fact: device_uuid: "{{ blkid_output.stdout | regex_search('UUID=\"([^\"]+)\"', '\\1') }}" - name: Clean the extracted UUID set_fact: clean_uuid: "{{ device_uuid | regex_replace('\\[', '') | regex_replace(']', '') | regex_replace(\"'\" '') }}" - name: Add UUID entry for {{ nvmebase_device_name }} to /etc/fstab lineinfile: path: /etc/fstab line: "UUID={{ clean_uuid }} /mnt/{{ nvmebase_device_name }} ext4 defaults,auto,users,rw,nofail,noatime 0 0" state: present create: yes
Breaking these instruction out into a new file, ConfigureNVMeBaseTasks.yml file gives us the consolidated tasks list. The device and drive mount point are derived from the Ansible variable nvmebase_device_name which is set in the calling script as follows:
- include_tasks: ConfigureNVMeDriveTasks.yml vars: nvmebase_device_name: nvme0n1
The ansible_user variable (used in the chown command in the tasks file) is taken from the group_vars/all.yml file.
And for the second drive we would use:
- include_tasks: ConfigureNVMeDriveTasks.yml vars: nvmebase_device_name: nvme1n1 when: nvme_duo == true
Note the addition of the when clause to only execute the tasks in the ConfigureNVMeDriveTasks.yml if the nvme_duo variable is true. This clause will also be used when Samba is configured.
Install Samba (Optional)
The installation of Samba follows similar steps as detailed in the Adding NVMe Base using Ansible post. The only addition is to add the second drive to the configuration section of the script.
Change Hostname (Optional)
One final, optional step is to change the name of the Raspberry Pi. This is useful when a number of devices are being configured. This step requires the hostname variable being set in the group_vars/all.yml file. Execute the ChangeHostname.yml script once the variable has been changed. Note that the script may fail following the reboot step as Ansible tries to reconnect with the Raspberry Pi using the old host name.
Lessons Learned
For some reason which was never tracked down, the installation of the sometimes failed on the NVMe Base Duo with access permission issues. The access issue presents itself on the Samba shares and also when attempting to use the drive when logged into the Raspberry Pi. This was resolved by setting the ansible_user variable in the group_vars/all.yml file.
The first installation of the NVMe Base Duo added the PCIe Generation 3 support. This caused some issues accessing the devices in the /dev directory. Removing this support allowed both of the drives to be accessed.
Conclusion
Breaking the drive installation and configuration into a new tasks file allows Ansible to reuse the same steps for two different devices. Couple this with when clauses allows changes to the control flow when deploying to two different types of devices.