134 lines
5.4 KiB
YAML
134 lines
5.4 KiB
YAML
|
|
---
|
||
|
|
# The 500 GB data disk.
|
||
|
|
#
|
||
|
|
# knots-box does this by hand: /mnt/knots_data holds ~875 GB of blockchain and
|
||
|
|
# appears nowhere in Ansible, so a rebuild of that host would come up with the
|
||
|
|
# chain silently missing. This role does it in code instead.
|
||
|
|
|
||
|
|
- name: Check the Monero data device
|
||
|
|
ansible.builtin.stat:
|
||
|
|
path: "{{ monero_data_device }}"
|
||
|
|
register: monero_device
|
||
|
|
|
||
|
|
- name: Find the device backing the root filesystem
|
||
|
|
ansible.builtin.command: findmnt -no SOURCE /
|
||
|
|
register: monero_root_source
|
||
|
|
changed_when: false
|
||
|
|
check_mode: false
|
||
|
|
|
||
|
|
# A guard, not ceremony. mkfs on the wrong device is unrecoverable, and
|
||
|
|
# /dev/sdX names are assigned by the kernel at boot - the whole reason
|
||
|
|
# everything below this point works by UUID.
|
||
|
|
- name: Assert the data device is a real block device and is not the root disk
|
||
|
|
ansible.builtin.assert:
|
||
|
|
that:
|
||
|
|
- monero_device.stat.exists
|
||
|
|
- monero_device.stat.isblk | default(false)
|
||
|
|
- not monero_root_source.stdout.startswith(monero_data_device)
|
||
|
|
quiet: true
|
||
|
|
fail_msg: >-
|
||
|
|
{{ monero_data_device }} is not a usable data device, or it is the disk
|
||
|
|
the root filesystem lives on ({{ monero_root_source.stdout }}).
|
||
|
|
Refusing to touch it. Check `lsblk` on the host.
|
||
|
|
|
||
|
|
- name: Read any existing filesystem on the data device
|
||
|
|
ansible.builtin.command: "blkid -o value -s TYPE {{ monero_data_device }}"
|
||
|
|
register: monero_existing_fs
|
||
|
|
changed_when: false
|
||
|
|
failed_when: false
|
||
|
|
check_mode: false
|
||
|
|
|
||
|
|
# community.general.filesystem is idempotent and will not rebuild a filesystem
|
||
|
|
# that is already the requested type, but it would happily create one on a disk
|
||
|
|
# holding something it does not recognise. Say so out loud instead.
|
||
|
|
- name: Refuse to reformat a disk that already carries a different filesystem
|
||
|
|
ansible.builtin.assert:
|
||
|
|
that:
|
||
|
|
- monero_existing_fs.stdout | trim in ['', monero_data_fstype]
|
||
|
|
quiet: true
|
||
|
|
fail_msg: >-
|
||
|
|
{{ monero_data_device }} already holds a '{{ monero_existing_fs.stdout | trim }}'
|
||
|
|
filesystem, not '{{ monero_data_fstype }}'. Refusing to overwrite it.
|
||
|
|
|
||
|
|
- name: Create the filesystem on the data device
|
||
|
|
community.general.filesystem:
|
||
|
|
fstype: "{{ monero_data_fstype }}"
|
||
|
|
dev: "{{ monero_data_device }}"
|
||
|
|
opts: "{{ monero_data_mkfs_opts }}"
|
||
|
|
|
||
|
|
- name: Read the filesystem UUID
|
||
|
|
ansible.builtin.command: "blkid -o value -s UUID {{ monero_data_device }}"
|
||
|
|
register: monero_fs_uuid
|
||
|
|
changed_when: false
|
||
|
|
failed_when: false
|
||
|
|
check_mode: false
|
||
|
|
|
||
|
|
# Everything past this point mounts by UUID, so there is nothing sensible to do
|
||
|
|
# without one. On a --check run against a disk that has no filesystem yet this
|
||
|
|
# is expected and unavoidable: check mode did not create the filesystem, so
|
||
|
|
# there is no UUID to read. Say that, rather than leaving a bare blkid rc=2.
|
||
|
|
- name: Assert the UUID looks like a UUID
|
||
|
|
ansible.builtin.assert:
|
||
|
|
that:
|
||
|
|
- monero_fs_uuid.stdout | trim | length == 36
|
||
|
|
quiet: true
|
||
|
|
fail_msg: >-
|
||
|
|
No filesystem UUID on {{ monero_data_device }}.
|
||
|
|
{% if ansible_check_mode %}This is expected under --check when the disk
|
||
|
|
has not been formatted yet - check mode cannot create the filesystem, so
|
||
|
|
it cannot dry-run the mount either. Run without --check once, then
|
||
|
|
--check is meaningful from then on.{% else %}mkfs appears to have failed;
|
||
|
|
check `lsblk` and `blkid` on the host.{% endif %}
|
||
|
|
|
||
|
|
# Same owner and mode as the "Own the mounted data directory" task below, and
|
||
|
|
# that is deliberate rather than duplication. Before the disk is mounted this
|
||
|
|
# creates the mount point; afterwards it targets the mounted filesystem and is a
|
||
|
|
# no-op. Giving it root:root 0755 here - the obvious thing to write - made the
|
||
|
|
# two tasks disagree, and each run flipped the directory back and forth.
|
||
|
|
- name: Create the Monero data directory as a mount point
|
||
|
|
ansible.builtin.file:
|
||
|
|
path: "{{ monero_data_dir }}"
|
||
|
|
state: directory
|
||
|
|
owner: "{{ monero_user }}"
|
||
|
|
group: "{{ monero_group }}"
|
||
|
|
mode: '0750'
|
||
|
|
|
||
|
|
# By UUID, never by /dev/sdb. nofail so a missing disk does not drop a headless
|
||
|
|
# VM into an emergency shell - monerod is stopped from starting by
|
||
|
|
# RequiresMountsFor= in its unit instead, which the systemd monitor then reports.
|
||
|
|
# noatime because LMDB touches a lot of pages and none of it wants an atime write.
|
||
|
|
- name: Mount the data disk by UUID
|
||
|
|
ansible.posix.mount:
|
||
|
|
path: "{{ monero_data_dir }}"
|
||
|
|
src: "UUID={{ monero_fs_uuid.stdout | trim }}"
|
||
|
|
fstype: "{{ monero_data_fstype }}"
|
||
|
|
opts: defaults,noatime,nofail
|
||
|
|
state: mounted
|
||
|
|
|
||
|
|
# AFTER the mount, never before: chowning the mount point first sets permissions
|
||
|
|
# on the directory the mount then hides, and the blockchain lands on a root-owned
|
||
|
|
# filesystem that monerod cannot write to.
|
||
|
|
- name: Own the mounted data directory
|
||
|
|
ansible.builtin.file:
|
||
|
|
path: "{{ monero_data_dir }}"
|
||
|
|
state: directory
|
||
|
|
owner: "{{ monero_user }}"
|
||
|
|
group: "{{ monero_group }}"
|
||
|
|
mode: '0750'
|
||
|
|
|
||
|
|
- name: Confirm the data directory is a mount point and not the root filesystem
|
||
|
|
ansible.builtin.command: "findmnt -no SOURCE --target {{ monero_data_dir }}"
|
||
|
|
register: monero_mounted_source
|
||
|
|
changed_when: false
|
||
|
|
check_mode: false
|
||
|
|
|
||
|
|
- name: Assert the blockchain will land on the data disk
|
||
|
|
ansible.builtin.assert:
|
||
|
|
that:
|
||
|
|
- monero_mounted_source.stdout | trim != monero_root_source.stdout | trim
|
||
|
|
quiet: true
|
||
|
|
fail_msg: >-
|
||
|
|
{{ monero_data_dir }} resolves to {{ monero_mounted_source.stdout | trim }},
|
||
|
|
which is the root filesystem. The 500 GB disk is not mounted and a full
|
||
|
|
sync would fill the 10 GB root disk.
|