automatic backup disk on/off
This commit is contained in:
12
roles/_handlers/handlers/main.yaml
Normal file
12
roles/_handlers/handlers/main.yaml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
- name: reload systemd
|
||||||
|
command: systemctl daemon-reload
|
||||||
|
|
||||||
|
|
||||||
|
- name: Restart NGINX
|
||||||
|
service:
|
||||||
|
name: nginx
|
||||||
|
state: restarted
|
||||||
|
|
||||||
|
|
||||||
|
- name: Run APT update
|
||||||
|
command: apt update -y
|
||||||
9
roles/backup_server/files/backup-disk-off.timer
Normal file
9
roles/backup_server/files/backup-disk-off.timer
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[Unit]
|
||||||
|
Description="Check Backup mounts and turn Disk off if apropriate"
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnCalendar=*:0/15
|
||||||
|
Unit=backup-disk-onoff@off.service
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=network.target
|
||||||
@@ -1,5 +1,24 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
import subprocess
|
import subprocess
|
||||||
import json
|
import json
|
||||||
|
import sys
|
||||||
|
import paho.mqtt.client as mqtt
|
||||||
|
import time
|
||||||
|
|
||||||
|
def send_mqtt_message(topic, payload):
|
||||||
|
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2) # Use the latest API version
|
||||||
|
client.connect("mqtt.chaos", 1883, 60)
|
||||||
|
client.publish(topic, payload)
|
||||||
|
client.disconnect()
|
||||||
|
|
||||||
|
def get_args(name='default', first='on'):
|
||||||
|
return first
|
||||||
|
|
||||||
|
mode = get_args(*sys.argv)
|
||||||
|
print(f"Mode is: {mode}")
|
||||||
|
if mode not in ["on", "off"]:
|
||||||
|
print("Error: mode must be either 'on' or 'off'")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
# Run the systemctl command and capture the output
|
# Run the systemctl command and capture the output
|
||||||
try:
|
try:
|
||||||
@@ -21,7 +40,7 @@ except json.JSONDecodeError as e:
|
|||||||
print(f"Error parsing JSON: {e}")
|
print(f"Error parsing JSON: {e}")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
# Filter units that are loaded, active, and sub: running
|
# Filter units that are loaded, active, and sub: running, and start with 'backup-'
|
||||||
running_units = []
|
running_units = []
|
||||||
for unit in units:
|
for unit in units:
|
||||||
if (
|
if (
|
||||||
@@ -36,3 +55,46 @@ for unit in units:
|
|||||||
print("Units with load: loaded, active: active, sub: running:")
|
print("Units with load: loaded, active: active, sub: running:")
|
||||||
for unit in running_units:
|
for unit in running_units:
|
||||||
print(f" - {unit['unit']}: {unit['description']}")
|
print(f" - {unit['unit']}: {unit['description']}")
|
||||||
|
|
||||||
|
# Send MQTT message based on mode
|
||||||
|
if mode == "on" or (mode == "off" and running_units):
|
||||||
|
# Send ON MQTT message
|
||||||
|
print(f"Turning backup Disk ON")
|
||||||
|
send_mqtt_message("switch_backup/switch/switch_backup_power/command", "on")
|
||||||
|
time.sleep(15)
|
||||||
|
# ON case: Send ON message after waiting 5 seconds and running vgchange -ay backup if needed
|
||||||
|
if mode == "on":
|
||||||
|
# Check if 'backup' VG is active
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
["vgdisplay", "-cA"],
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
text=True,
|
||||||
|
check=True
|
||||||
|
)
|
||||||
|
vgdisplay_output = result.stdout.strip().split("\n")
|
||||||
|
print(f"vgdisplay: {vgdisplay_output}")
|
||||||
|
backup_present = any(line.split(":")[0].strip() == "backup" for line in vgdisplay_output)
|
||||||
|
print(f"backup VG active? {backup_present}")
|
||||||
|
if not backup_present:
|
||||||
|
try:
|
||||||
|
print(f"Activating VG backup")
|
||||||
|
subprocess.run(["vgchange", "-ay", "backup"], check=True)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error executing vgchange: {e.stderr}")
|
||||||
|
exit(1)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error executing vgdisplay: {e.stderr}")
|
||||||
|
exit(1)
|
||||||
|
else:
|
||||||
|
# OFF case: Only execute if nothing is mounted
|
||||||
|
if not running_units:
|
||||||
|
print(f"Turning backup Disk OFF")
|
||||||
|
subprocess.run(["sync"], check=True)
|
||||||
|
try:
|
||||||
|
subprocess.run(["vgchange", "-an", "backup"], check=True)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"Error executing vgchange: {e.stderr}")
|
||||||
|
exit(1)
|
||||||
|
send_mqtt_message("switch_backup/switch/switch_backup_power/command", "off")
|
||||||
11
roles/backup_server/files/backup-disk-onoff@.service
Normal file
11
roles/backup_server/files/backup-disk-onoff@.service
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Backup Disk %I
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecStart=/usr/local/bin/backup-disk-onoff.py %I
|
||||||
|
RemainAfterExit=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=timers.target
|
||||||
2
roles/backup_server/meta/main.yaml
Normal file
2
roles/backup_server/meta/main.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
dependencies:
|
||||||
|
- _handlers
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
- name: Additional packages
|
||||||
|
apt:
|
||||||
|
state: present
|
||||||
|
name:
|
||||||
|
- python3-paho-mqtt
|
||||||
|
|
||||||
|
|
||||||
- name: Generate Automounts
|
- name: Generate Automounts
|
||||||
include_role:
|
include_role:
|
||||||
@@ -12,7 +18,8 @@
|
|||||||
Type: btrfs
|
Type: btrfs
|
||||||
Options: defaults,compress=lzo,space_cache=v2
|
Options: defaults,compress=lzo,space_cache=v2
|
||||||
Unit:
|
Unit:
|
||||||
After: network.target
|
After: network.target backup-disk-onoff@on.service
|
||||||
|
Requires: backup-disk-onoff@on.service
|
||||||
Install:
|
Install:
|
||||||
WantedBy: network.target
|
WantedBy: network.target
|
||||||
catena_automount:
|
catena_automount:
|
||||||
@@ -35,28 +42,33 @@
|
|||||||
loop_var: mount_point
|
loop_var: mount_point
|
||||||
|
|
||||||
|
|
||||||
|
- name: BackupDisk On/Off service
|
||||||
# [Unit]
|
block:
|
||||||
# Description=Automount /backup/yori
|
- name: Copy Script
|
||||||
# After=network.target
|
copy:
|
||||||
|
src: backup-disk-onoff.py
|
||||||
# [Automount]
|
dest: /usr/local/bin/backup-disk-onoff.py
|
||||||
# Where=/backup/yori
|
mode: 0755
|
||||||
# TimeoutIdleSec=30
|
owner: root
|
||||||
|
group: root
|
||||||
# [Install]
|
- name: Install Unit file
|
||||||
# WantedBy=network.target
|
notify: reload systemd
|
||||||
# [Unit]
|
copy:
|
||||||
# Description=Mount /backup/yori
|
src: backup-disk-onoff@.service
|
||||||
# After=network.target
|
dest: /etc/systemd/system/backup-disk-onoff@.service
|
||||||
# #Requires=backup-yori.automount
|
owner: root
|
||||||
# #After=backup-yori.automount
|
group: root
|
||||||
|
- name: Create a timer to turn OFF the Disk
|
||||||
# [Mount]
|
notify: reload systemd
|
||||||
# What=/dev/backup/yori
|
copy:
|
||||||
# Where=/backup/yori
|
src: backup-disk-off.timer
|
||||||
# Type=btrfs
|
dest: /etc/systemd/system/backup-disk-off.timer
|
||||||
# Options=defaults,compress=lzo,space_cache=v2
|
owner: root
|
||||||
|
group: root
|
||||||
# [Install]
|
- name: Enable timer and start it
|
||||||
# WantedBy=network.target
|
ansible.builtin.systemd_service:
|
||||||
|
name: backup-disk-off.timer
|
||||||
|
enabled: true
|
||||||
|
state: started
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user