From b513e82d7322a1131fbc6d43e44dca298b32feae Mon Sep 17 00:00:00 2001 From: "andres.suarez" Date: Tue, 29 Jul 2025 14:04:29 +0200 Subject: [PATCH 1/4] feat: add script to mount/unmount disks --- ansible/files/adminapi.sudoers.conf | 1 + ansible/files/mount-volume.sh | 55 ++++++++++++++++++++++++++++ ansible/tasks/internal/admin-api.yml | 1 + 3 files changed, 57 insertions(+) create mode 100644 ansible/files/mount-volume.sh diff --git a/ansible/files/adminapi.sudoers.conf b/ansible/files/adminapi.sudoers.conf index 531d47ca1..569db9410 100644 --- a/ansible/files/adminapi.sudoers.conf +++ b/ansible/files/adminapi.sudoers.conf @@ -5,6 +5,7 @@ Cmnd_Alias GOTRUE = /bin/systemctl start gotrue.service, /bin/systemctl stop got Cmnd_Alias PGBOUNCER = /bin/systemctl start pgbouncer.service, /bin/systemctl stop pgbouncer.service, /bin/systemctl restart pgbouncer.service, /bin/systemctl disable pgbouncer.service, /bin/systemctl enable pgbouncer.service, /bin/systemctl reload pgbouncer.service, /bin/systemctl try-restart pgbouncer.service %adminapi ALL= NOPASSWD: /root/grow_fs.sh +%adminapi ALL= NOPASSWD: /root/mount-volume.sh %adminapi ALL= NOPASSWD: /root/manage_readonly_mode.sh %adminapi ALL= NOPASSWD: /etc/adminapi/pg_upgrade_scripts/prepare.sh %adminapi ALL= NOPASSWD: /etc/adminapi/pg_upgrade_scripts/initiate.sh diff --git a/ansible/files/mount-volume.sh b/ansible/files/mount-volume.sh new file mode 100644 index 000000000..2a514c2e0 --- /dev/null +++ b/ansible/files/mount-volume.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +set -euo pipefail + +DEVICE=${1:-} +MOUNT_POINT=${2:-} + +if [[ -z "$DEVICE" || -z "$MOUNT_POINT" ]]; then + echo "Usage: $0 " + echo "Example: sudo ./mount-volume.sh /dev/nvme1n1 /data/150008" + exit 1 +fi + +OWNER="postgres:postgres" +PERMISSIONS="750" +FSTYPE="ext4" +MOUNT_OPTS="defaults" +FSTAB_FILE="/etc/fstab" + +if [ ! -b "$DEVICE" ]; then + echo "Error: Block device '$DEVICE' does not exist." + exit 2 +fi + +if ! blkid "$DEVICE" >/dev/null 2>&1; then + echo "Device $DEVICE appears unformatted. Formatting as $FSTYPE..." + mkfs."$FSTYPE" -F "$DEVICE" +else + echo "$DEVICE already has a filesystem — skipping format." +fi + +mkdir -p "$MOUNT_POINT" + +if ! mountpoint -q "$MOUNT_POINT"; then + echo "Mounting $DEVICE to $MOUNT_POINT" + mount -t "$FSTYPE" -o "$MOUNT_OPTS" "$DEVICE" "$MOUNT_POINT" +else + echo "$MOUNT_POINT is already mounted" +fi + +echo "Setting ownership and permissions on $MOUNT_POINT" +chown "$OWNER" "$MOUNT_POINT" +chmod "$PERMISSIONS" "$MOUNT_POINT" + +UUID=$(blkid -s UUID -o value "$DEVICE") +FSTAB_LINE="UUID=$UUID $MOUNT_POINT $FSTYPE $MOUNT_OPTS 0 2" + +if ! grep -q "$UUID" "$FSTAB_FILE"; then + echo "Adding $FSTAB_LINE to $FSTAB_FILE" + echo "$FSTAB_LINE" >> "$FSTAB_FILE" +else + echo "UUID $UUID already in $FSTAB_FILE — skipping" +fi + +echo "Mounted $DEVICE at $MOUNT_POINT with postgres:postgres and mode $PERMISSIONS" diff --git a/ansible/tasks/internal/admin-api.yml b/ansible/tasks/internal/admin-api.yml index 5eb6fd276..10da028ea 100644 --- a/ansible/tasks/internal/admin-api.yml +++ b/ansible/tasks/internal/admin-api.yml @@ -14,6 +14,7 @@ - { file: "grow_fs.sh" } - { file: "manage_readonly_mode.sh" } - { file: "pg_egress_collect.pl" } + - { file: "mount-volume.sh" } - name: give adminapi user permissions copy: From b66218fe4d56da621fb5273b061c435d41eaac6c Mon Sep 17 00:00:00 2001 From: "andres.suarez" Date: Tue, 29 Jul 2025 14:29:54 +0200 Subject: [PATCH 2/4] feat: add script to unmount disk --- ansible/files/adminapi.sudoers.conf | 1 + ansible/files/mount-volume.sh | 5 ++++ ansible/files/unmount-volume.sh | 43 ++++++++++++++++++++++++++++ ansible/tasks/internal/admin-api.yml | 1 + 4 files changed, 50 insertions(+) create mode 100644 ansible/files/unmount-volume.sh diff --git a/ansible/files/adminapi.sudoers.conf b/ansible/files/adminapi.sudoers.conf index 569db9410..904377c29 100644 --- a/ansible/files/adminapi.sudoers.conf +++ b/ansible/files/adminapi.sudoers.conf @@ -6,6 +6,7 @@ Cmnd_Alias PGBOUNCER = /bin/systemctl start pgbouncer.service, /bin/systemctl st %adminapi ALL= NOPASSWD: /root/grow_fs.sh %adminapi ALL= NOPASSWD: /root/mount-volume.sh +%adminapi ALL= NOPASSWD: /root/unmount-volume.sh %adminapi ALL= NOPASSWD: /root/manage_readonly_mode.sh %adminapi ALL= NOPASSWD: /etc/adminapi/pg_upgrade_scripts/prepare.sh %adminapi ALL= NOPASSWD: /etc/adminapi/pg_upgrade_scripts/initiate.sh diff --git a/ansible/files/mount-volume.sh b/ansible/files/mount-volume.sh index 2a514c2e0..793f04d6a 100644 --- a/ansible/files/mount-volume.sh +++ b/ansible/files/mount-volume.sh @@ -11,6 +11,11 @@ if [[ -z "$DEVICE" || -z "$MOUNT_POINT" ]]; then exit 1 fi +# Mount a block device to a specified mount point +# If the device is not formatted, format it as ext4 +# Set ownership to postgres:postgres and permissions to 750 +# Add the mount entry to /etc/fstab for persistence across reboots + OWNER="postgres:postgres" PERMISSIONS="750" FSTYPE="ext4" diff --git a/ansible/files/unmount-volume.sh b/ansible/files/unmount-volume.sh new file mode 100644 index 000000000..6250b8c47 --- /dev/null +++ b/ansible/files/unmount-volume.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +set -euo pipefail + +MOUNT_POINT=${1:-} +DELETE_FLAG=${2:-} + +if [[ -z "$MOUNT_POINT" ]]; then + echo "Usage: $0 [--delete-dir]" + echo "Unmount only: sudo ./unmount-volume.sh /data/150008" + echo "Unmount delete dir: sudo ./unmount-volume.sh /data/150008 --delete-dir" + exit 1 +fi + +# Unmount a block device from a specified mount point +# Remove the corresponding entry from /etc/fstab for persistence across reboots + +FSTAB_FILE="/etc/fstab" +BACKUP_FILE="/etc/fstab.bak" + +if mountpoint -q "$MOUNT_POINT"; then + echo "Unmounting $MOUNT_POINT" + umount "$MOUNT_POINT" +else + echo "$MOUNT_POINT is not currently mounted — skipping umount" +fi + +UUID=$(findmnt -no UUID "$MOUNT_POINT" 2>/dev/null || true) + +if [[ -n "$UUID" ]]; then + echo "Removing UUID=$UUID from $FSTAB_FILE" + cp "$FSTAB_FILE" "$BACKUP_FILE" + sed -i "/UUID=${UUID//\//\\/}/d" "$FSTAB_FILE" +else + echo "Could not find UUID for $MOUNT_POINT — skipping fstab cleanup" +fi + +if [[ "$DELETE_FLAG" == "--delete-dir" ]]; then + echo "Deleting mount point directory: $MOUNT_POINT" + rm -rf "$MOUNT_POINT" +fi + +echo "Unmount and cleanup complete for $MOUNT_POINT" diff --git a/ansible/tasks/internal/admin-api.yml b/ansible/tasks/internal/admin-api.yml index 10da028ea..5844b3f54 100644 --- a/ansible/tasks/internal/admin-api.yml +++ b/ansible/tasks/internal/admin-api.yml @@ -15,6 +15,7 @@ - { file: "manage_readonly_mode.sh" } - { file: "pg_egress_collect.pl" } - { file: "mount-volume.sh" } + - { file: "unmount-volume.sh" } - name: give adminapi user permissions copy: From 29cc8245bff940d371821678ebfe6380418f5b09 Mon Sep 17 00:00:00 2001 From: "andres.suarez" Date: Tue, 29 Jul 2025 15:00:53 +0200 Subject: [PATCH 3/4] fix: rmove files to correct path --- ansible/files/{ => admin_api_scripts}/mount-volume.sh | 0 ansible/files/{ => admin_api_scripts}/unmount-volume.sh | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename ansible/files/{ => admin_api_scripts}/mount-volume.sh (100%) rename ansible/files/{ => admin_api_scripts}/unmount-volume.sh (100%) diff --git a/ansible/files/mount-volume.sh b/ansible/files/admin_api_scripts/mount-volume.sh similarity index 100% rename from ansible/files/mount-volume.sh rename to ansible/files/admin_api_scripts/mount-volume.sh diff --git a/ansible/files/unmount-volume.sh b/ansible/files/admin_api_scripts/unmount-volume.sh similarity index 100% rename from ansible/files/unmount-volume.sh rename to ansible/files/admin_api_scripts/unmount-volume.sh From ae19ea54b5e65039933e454f1bca68dc54d3eb11 Mon Sep 17 00:00:00 2001 From: "andres.suarez" Date: Tue, 29 Jul 2025 17:12:40 +0200 Subject: [PATCH 4/4] feat: validating the disk in a state --- ansible/files/admin_api_scripts/mount-volume.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ansible/files/admin_api_scripts/mount-volume.sh b/ansible/files/admin_api_scripts/mount-volume.sh index 793f04d6a..5f4277f2d 100644 --- a/ansible/files/admin_api_scripts/mount-volume.sh +++ b/ansible/files/admin_api_scripts/mount-volume.sh @@ -36,6 +36,8 @@ fi mkdir -p "$MOUNT_POINT" +e2fsck -pf "$DEVICE" + if ! mountpoint -q "$MOUNT_POINT"; then echo "Mounting $DEVICE to $MOUNT_POINT" mount -t "$FSTYPE" -o "$MOUNT_OPTS" "$DEVICE" "$MOUNT_POINT"