mirror of
https://gitlab.sectorq.eu/jaydee/omv_backup.git
synced 2025-09-13 12:10:12 +02:00
Compare commits
94 Commits
169d43a75c
...
main
Author | SHA1 | Date | |
---|---|---|---|
122ef64ad7 | |||
99f673996e | |||
68e23da03b | |||
1c30fb9995 | |||
b94b61ba5d | |||
26c3245cf3 | |||
1510dc2e8d | |||
d949188a34 | |||
298c9aee23 | |||
808f92c4d1 | |||
43f6d2abcb | |||
81c7ead7b2 | |||
cd818da774 | |||
a1dfbd664c | |||
571219881d | |||
0c07fde85a | |||
f46eacf627 | |||
92226734ef | |||
d3359e9a68 | |||
fdbe4eebe1 | |||
3a3faad97e | |||
8be3e20523 | |||
126ab1813b | |||
28efc95b4d | |||
f6a106fd91 | |||
bbe4d72666 | |||
b536c8ecb1 | |||
7a8130c3f0 | |||
5756798269 | |||
d6af0c24b5 | |||
6f9a2bba67 | |||
11bc56ecb3 | |||
b4032eca7e | |||
f75ac2eb79 | |||
a555567c4b | |||
de63a1e9aa | |||
d3eab9f50e | |||
72a2fa5710 | |||
b3be50bfdd | |||
f32ada9ad5 | |||
d6492ebf80 | |||
7cee7570b4 | |||
ce7c855808 | |||
d3e15e973a | |||
cee1cf353c | |||
f9e7654c47 | |||
1816bd516c | |||
dad1c49409 | |||
66644b6bb9 | |||
781a74ba20 | |||
29cb028c5c | |||
1667ce0079 | |||
984b3e09a0 | |||
64bea0a833 | |||
dd51f14699 | |||
35aa35a3b5 | |||
4f868047be | |||
ba09aeb502 | |||
8e9e915cdc | |||
1714817673 | |||
9cf123382e | |||
ad5e9e698f | |||
017653d34c | |||
cb2e06684b | |||
57ae295d22 | |||
27d0e121cd | |||
de97d2574a | |||
ca1c3a563f | |||
0d6ec1fbc1 | |||
a11076ef04 | |||
d6a3d3765b | |||
eababc2f7c | |||
528995cf75 | |||
695219f6e0 | |||
d6e41e2ceb | |||
0e6ebc0516 | |||
7c2c99fbef | |||
425f9aebaa | |||
f8ae15d195 | |||
c5d915ad87 | |||
9e7b774601 | |||
0eb8cc4afe | |||
ea1d933386 | |||
a407ee9339 | |||
1768fe1369 | |||
2c7dba48da | |||
bcd2b5de9e | |||
986f75e1dc | |||
2af8758261 | |||
fd94729a05 | |||
fb4acad563 | |||
a57c73cc74 | |||
4327d7490b | |||
c72aa231c7 |
@@ -25,6 +25,6 @@ build-job: # This job runs in the build stage, which runs first.
|
|||||||
script:
|
script:
|
||||||
- column=":"
|
- column=":"
|
||||||
- echo "${flow_id}"
|
- echo "${flow_id}"
|
||||||
- curl -X POST https://kestra.sectorq.eu/api/v1/executions/webhook/jaydee/ansible-all/${flow_id} -d '{"tag":["setup","omv_backup"],"target":["servers"]}' -H "Content-Type${column} application/json"
|
- curl -X POST https://kestra.sectorq.eu/api/v1/executions/webhook/jaydee/ansible-all/${flow_id} -d '{"tag":["omv_backup"],"target":["servers"]}' -H "Content-Type${column} application/json"
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_MESSAGE =~ /build/'
|
- if: '$CI_COMMIT_MESSAGE =~ /build/'
|
||||||
|
@@ -47,6 +47,13 @@ cmnd = f"zip -P {PASSWORD} authentik_{DATETIME}.sql.zip authentik_{DATETIME}.sql
|
|||||||
status, output = subprocess.getstatusoutput(cmnd)
|
status, output = subprocess.getstatusoutput(cmnd)
|
||||||
os.remove(f"authentik_{DATETIME}.sql")
|
os.remove(f"authentik_{DATETIME}.sql")
|
||||||
|
|
||||||
|
print("Backup Zabbix")
|
||||||
|
cmnd = f"docker exec zabbix-server-db-server-1 sh -c 'pg_dump -h localhost -p 5432 -U zabbix -d zabbix' > /share/docker_data/__backups/zabbix_{DATETIME}.sql"
|
||||||
|
status, output = subprocess.getstatusoutput(cmnd)
|
||||||
|
cmnd = f"zip -P {PASSWORD} zabbix_{DATETIME}.sql.zip zabbix_{DATETIME}.sql"
|
||||||
|
status, output = subprocess.getstatusoutput(cmnd)
|
||||||
|
os.remove(f"zabbix_{DATETIME}.sql")
|
||||||
|
|
||||||
|
|
||||||
print("Backup portainer")
|
print("Backup portainer")
|
||||||
headers = {
|
headers = {
|
||||||
|
15
exclude.txt
Normal file
15
exclude.txt
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
ha/home-assistant_v2.db
|
||||||
|
jellyfin/cache/transcodes
|
||||||
|
.@__thumb/*
|
||||||
|
ha/home-assistant.log
|
||||||
|
gitlab/logs/*
|
||||||
|
esphome/config/.esphome
|
||||||
|
.cache
|
||||||
|
.git
|
||||||
|
var_lib_motioneye/*
|
||||||
|
*/.esphome/build/*
|
||||||
|
nextcloud/mariadb/*
|
||||||
|
zabbix-server/postgres-data/*
|
||||||
|
gitea-runner/*
|
||||||
|
immich/library/*
|
685
omv_backup.py
685
omv_backup.py
@@ -17,11 +17,21 @@ import fnmatch
|
|||||||
import yaml
|
import yaml
|
||||||
import paramiko
|
import paramiko
|
||||||
import shutil
|
import shutil
|
||||||
|
import signal
|
||||||
|
import paho.mqtt.client as mqtt
|
||||||
#import numpy as np
|
#import numpy as np
|
||||||
|
|
||||||
|
def signal_handler(sig, frame):
|
||||||
|
print('You pressed Ctrl+C!')
|
||||||
|
conn.close()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
file_path = os.path.realpath(__file__)
|
file_path = os.path.realpath(__file__)
|
||||||
dir_path = os.path.dirname(file_path)
|
dir_path = os.path.dirname(file_path)
|
||||||
VERSION="1.0.9"
|
VERSION="1.0.10"
|
||||||
# print(file_path)
|
# print(file_path)
|
||||||
# print(dir_path)
|
# print(dir_path)
|
||||||
os.chdir(dir_path)
|
os.chdir(dir_path)
|
||||||
@@ -42,6 +52,7 @@ status, output = subprocess.getstatusoutput(cmnd)
|
|||||||
if int(output) > 0:
|
if int(output) > 0:
|
||||||
print("Running already!")
|
print("Running already!")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
def is_port_open(host, port):
|
def is_port_open(host, port):
|
||||||
try:
|
try:
|
||||||
sock = socket.create_connection((host, port))
|
sock = socket.create_connection((host, port))
|
||||||
@@ -99,9 +110,6 @@ for o, a in opts:
|
|||||||
elif o in ("-r", "--restore"):
|
elif o in ("-r", "--restore"):
|
||||||
_RESTORE = True
|
_RESTORE = True
|
||||||
_APP = a
|
_APP = a
|
||||||
print("RESTORE")
|
|
||||||
elif o in ("-b", "--backup"):
|
|
||||||
_BACKUP = True
|
|
||||||
elif o in ("-D", "--dry"):
|
elif o in ("-D", "--dry"):
|
||||||
_EXECUTE = False
|
_EXECUTE = False
|
||||||
elif o in ("-T", "--dry"):
|
elif o in ("-T", "--dry"):
|
||||||
@@ -125,13 +133,23 @@ logging.info("script started")
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
client_id = "dasdasdasd333"
|
client_id = "dasdasdasd333"
|
||||||
try:
|
# try:
|
||||||
client = mqtt_client.Client(mqtt_client.CallbackAPIVersion.VERSION1, client_id)
|
# client = mqtt_client.Client(mqtt_client.CallbackAPIVersion.VERSION1, client_id)
|
||||||
except:
|
# except:
|
||||||
client = mqtt_client.Client()
|
# client = mqtt_client.Client()
|
||||||
client.username_pw_set(mqtt_username, mqtt_password)
|
# client.username_pw_set(mqtt_username, mqtt_password)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
logging.info(f"Start OMV Backup")
|
||||||
|
BROKER = 'mqtt.home.lan' # e.g., 'mqtt.example.com'
|
||||||
|
PORT = 1883 # Typically 8883 for secure MQTT
|
||||||
|
TOPIC = 'sectorq/backups/start'
|
||||||
|
USERNAME = 'jaydee'
|
||||||
|
PASSWORD = 'jaydee1'
|
||||||
|
USE_TLS = False # Set to False if not using TLS
|
||||||
backups = {
|
backups = {
|
||||||
"nas": {
|
"nas": {
|
||||||
"login": "admin@nas.home.lan",
|
"login": "admin@nas.home.lan",
|
||||||
@@ -185,11 +203,14 @@ logging.info("Test connection")
|
|||||||
hm = socket.gethostbyaddr(BACKUP_HOST)
|
hm = socket.gethostbyaddr(BACKUP_HOST)
|
||||||
|
|
||||||
logging.info(_RESTORE)
|
logging.info(_RESTORE)
|
||||||
def send_mqtt_message(msg):
|
def send_mqtt_message(topic,msg,qos=0,retain=False):
|
||||||
|
client2 = mqtt.Client()
|
||||||
|
client2.username_pw_set("jaydee", "jaydee1")
|
||||||
try:
|
try:
|
||||||
client.connect(broker,1883,60)
|
client2.connect("mqtt.home.lan",1883,60)
|
||||||
client.publish(topic, json.dumps(msg))
|
client2.publish(topic, json.dumps(msg), qos=qos, retain=retain)
|
||||||
client.disconnect()
|
client2.disconnect()
|
||||||
|
logging.info(f"Message1 sent {topic}, {msg}")
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logging.error("Failed to send")
|
logging.error("Failed to send")
|
||||||
print("Failed to send")
|
print("Failed to send")
|
||||||
@@ -218,11 +239,13 @@ if _STOP:
|
|||||||
continue
|
continue
|
||||||
cmnd = f"docker stop {c.split()[-1]}"
|
cmnd = f"docker stop {c.split()[-1]}"
|
||||||
status, running_containers = subprocess.getstatusoutput(cmnd)
|
status, running_containers = subprocess.getstatusoutput(cmnd)
|
||||||
if _RESTORE:
|
def restore_job(_APP):
|
||||||
|
#global VERSION
|
||||||
logging.info("Starting Restore")
|
logging.info("Starting Restore")
|
||||||
print("Starting Restore")
|
print(f"Starting restore : {VERSION}")
|
||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
STARTTIME = now.strftime("%Y-%m-%d_%H:%M:%S")
|
STARTTIME = now.strftime("%Y-%m-%d_%H:%M:%S")
|
||||||
|
_DATE = "pick"
|
||||||
if _APP == "all":
|
if _APP == "all":
|
||||||
_DATE = "latest"
|
_DATE = "latest"
|
||||||
if host == "rpi5.home.lan" or host == "rpi5":
|
if host == "rpi5.home.lan" or host == "rpi5":
|
||||||
@@ -235,6 +258,7 @@ if _RESTORE:
|
|||||||
#input("????")
|
#input("????")
|
||||||
else:
|
else:
|
||||||
_APP = _APP.split(",")
|
_APP = _APP.split(",")
|
||||||
|
|
||||||
PROGRESS = 0
|
PROGRESS = 0
|
||||||
topic = "sectorq/amd/restore"
|
topic = "sectorq/amd/restore"
|
||||||
step = 100 / len(_APP)
|
step = 100 / len(_APP)
|
||||||
@@ -244,7 +268,7 @@ if _RESTORE:
|
|||||||
logging.info(msg)
|
logging.info(msg)
|
||||||
|
|
||||||
|
|
||||||
send_mqtt_message(msg)
|
send_mqtt_message(topic,msg)
|
||||||
PROGRESS = PROGRESS + step
|
PROGRESS = PROGRESS + step
|
||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
DATETIME = now.strftime("%Y-%m-%d_%H-%M-%S")
|
DATETIME = now.strftime("%Y-%m-%d_%H-%M-%S")
|
||||||
@@ -256,7 +280,7 @@ if _RESTORE:
|
|||||||
if _DATE == "pick":
|
if _DATE == "pick":
|
||||||
cmnd = f"ssh root@amd.home.lan 'ls {BACKUP_DEVICE}/backup/m-server/docker_data'"
|
cmnd = f"ssh root@amd.home.lan 'ls {BACKUP_DEVICE}/backup/m-server/docker_data'"
|
||||||
status, output = subprocess.getstatusoutput(cmnd)
|
status, output = subprocess.getstatusoutput(cmnd)
|
||||||
print(output)
|
# print(output)
|
||||||
dates = output.splitlines()
|
dates = output.splitlines()
|
||||||
n = 1
|
n = 1
|
||||||
for i in dates:
|
for i in dates:
|
||||||
@@ -283,7 +307,7 @@ if _RESTORE:
|
|||||||
LATEST_LINK = f"/{host}/{app}/{_DATE}"
|
LATEST_LINK = f"/{host}/{app}/{_DATE}"
|
||||||
|
|
||||||
logging.info("Create backup dir")
|
logging.info("Create backup dir")
|
||||||
logging.info(cmnd)
|
#logging.info(cmnd)
|
||||||
|
|
||||||
|
|
||||||
#cmnd = "rsync -av --delete {}/ --link-dest {} --exclude=\".cache\" {}".format(SOURCE_DIR, LATEST_LINK, BACKUP_PATH)
|
#cmnd = "rsync -av --delete {}/ --link-dest {} --exclude=\".cache\" {}".format(SOURCE_DIR, LATEST_LINK, BACKUP_PATH)
|
||||||
@@ -452,293 +476,305 @@ if _RESTORE:
|
|||||||
|
|
||||||
msg = {"mode":_MODE, "status":"restore","bak_name":"Restore","host":host,"cur_job":app,"start_time":STARTTIME,"end_time":"","progress":100,"finished":ENDJOB,"used_space":1}
|
msg = {"mode":_MODE, "status":"restore","bak_name":"Restore","host":host,"cur_job":app,"start_time":STARTTIME,"end_time":"","progress":100,"finished":ENDJOB,"used_space":1}
|
||||||
logging.info(msg)
|
logging.info(msg)
|
||||||
|
send_mqtt_message(topic,msg)
|
||||||
send_mqtt_message(msg)
|
|
||||||
if _MODE == "auto":
|
if _MODE == "auto":
|
||||||
cmnd = "ssh root@amd.home.lan 'systemctl suspend &'"
|
cmnd = "ssh root@amd.home.lan 'systemctl suspend &'"
|
||||||
status, output = subprocess.getstatusoutput(cmnd)
|
status, output = subprocess.getstatusoutput(cmnd)
|
||||||
|
|
||||||
if _BACKUP:
|
def backup_job(pl):
|
||||||
last = 1
|
client2 = mqtt.Client()
|
||||||
while True:
|
client2.username_pw_set("jaydee", "jaydee1")
|
||||||
directory = '/backups/'
|
client2.connect("mqtt.home.lan",1883,60)
|
||||||
count = len(fnmatch.filter(os.listdir(directory), '*'))
|
if "log" in pl:
|
||||||
if last != count:
|
if pl["log"] == "debug":
|
||||||
logging.info(f'File Count: {count}')
|
logging.info(f'Debug enabled')
|
||||||
last = count
|
LOG_FILE = "omv_backup.log"
|
||||||
if count == 0:
|
logging.basicConfig(filename=LOG_FILE, level=logging.DEBUG, format='%(asctime)s : %(levelname)s : %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
|
||||||
time.sleep(10)
|
logging.info(f'starting backup job')
|
||||||
continue
|
|
||||||
else:
|
|
||||||
finished = []
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
STARTTIME = now.strftime("%Y-%m-%d_%H:%M:%S")
|
|
||||||
topic = "sectorq/amd/restore"
|
|
||||||
msg = {"mode":"restore", "status":"restore","bak_name":"s","host":0,"cur_job":"aaa","start_time":1,"end_time":1,"progress":0,"finished":0,"used_space":0}
|
|
||||||
send_mqtt_message(msg)
|
|
||||||
topic = "sectorq/amd/backups"
|
|
||||||
msg = {"mode":_MODE, "status":"started","bak_name":"complete","host":"","cur_job":"","start_time":STARTTIME,"end_time":"in progress","progress":0,"finished":",".join(finished)}
|
|
||||||
send_mqtt_message(msg)
|
|
||||||
|
|
||||||
# iterate over files in
|
|
||||||
# that directory
|
|
||||||
|
|
||||||
for filename in os.scandir(directory):
|
|
||||||
if filename.is_file():
|
|
||||||
logging.info(filename.path)
|
|
||||||
logging.info(filename.name)
|
|
||||||
if filename.name == "restore":
|
|
||||||
break
|
|
||||||
host = filename.name
|
|
||||||
logging.info("Backup")
|
|
||||||
for b in backups[host]["jobs"]:
|
|
||||||
|
|
||||||
if not backups[host]["jobs"][b]["active"]:
|
|
||||||
logging.info("Backup {} is not active!".format(b))
|
|
||||||
msg = {"status":"inactive","bak_name":b,"start_time":"inactive","end_time":"inactive","progress":0}
|
|
||||||
send_mqtt_message(msg)
|
|
||||||
continue
|
|
||||||
|
|
||||||
SOURCE_DIR = backups[host]["jobs"][b]["source"]
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
BACKUP_HOST = backups[host]["login"]
|
|
||||||
BACKUP_DEVICE = "/mnt/raid"
|
|
||||||
BACKUP_DIR = f"{BACKUP_HOST}:{SOURCE_DIR}"
|
|
||||||
BACKUP_ROOT = f"{BACKUP_DEVICE}/backup/{host}/{b}"
|
|
||||||
DATETIME = now.strftime("%Y-%m-%d_%H-%M-%S")
|
|
||||||
|
|
||||||
if _FIRST:
|
|
||||||
NEW_BACKUP_DIR = f"{BACKUP_ROOT}/initial"
|
|
||||||
else:
|
|
||||||
NEW_BACKUP_DIR = f"{BACKUP_ROOT}/{DATETIME}_running"
|
|
||||||
|
|
||||||
FULL_BACKUP_LATEST = f"{BACKUP_ROOT}/latest"
|
|
||||||
|
|
||||||
# msg = {"status":"started","bak_name":b,"start_time":DATETIME,"end_time":"in progress", "progress":0}
|
|
||||||
msg = {"mode":_MODE, "status":"started","bak_name":"complete","host":host,"cur_job":b,"start_time":STARTTIME,"end_time":"in progress","progress":0,"finished":",".join(finished)}
|
|
||||||
client.connect(broker,1883,60)
|
|
||||||
client.publish(topic, json.dumps(msg),qos=0, retain=True)
|
|
||||||
client.disconnect()
|
|
||||||
|
|
||||||
|
|
||||||
cmnd = "mkdir -p " + NEW_BACKUP_DIR
|
|
||||||
logging.info(cmnd)
|
|
||||||
|
|
||||||
if _EXECUTE:
|
|
||||||
status, output = subprocess.getstatusoutput(cmnd)
|
|
||||||
logging.info(output)
|
|
||||||
logging.info(status)
|
|
||||||
logging.info("Create backup dir")
|
|
||||||
|
|
||||||
cmnd = f"ssh {BACKUP_HOST} 'ls {SOURCE_DIR}'"
|
|
||||||
logger.debug(cmnd)
|
|
||||||
status, output = subprocess.getstatusoutput(cmnd)
|
|
||||||
logger.debug(output)
|
|
||||||
apps = output.splitlines()
|
|
||||||
c = len(apps)
|
|
||||||
print(apps)
|
|
||||||
print(len(apps))
|
|
||||||
|
|
||||||
step = round(100 / c,1)
|
|
||||||
progress = 0
|
|
||||||
#cmd = f"rsync -avz --delete {BACKUP_DIR} --link-dest {FULL_BACKUP_LATEST}/ --exclude=\"jellyfin/cache/transcodes\" --exclude=\"gitlab/logs/prometheus\" --exclude=\"home-assistant.log\" --exclude=\"gitlab/logs/*\" --exclude=\"esphome/config/.esphome\" --exclude=\".cache\" --exclude=\".git\" --exclude=\"var_lib_motioneye\" {NEW_BACKUP_DIR}"
|
|
||||||
#cmd = [ 'rsync', '-avz','--info=progress2', BACKUP_DIR , NEW_BACKUP_DIR]
|
|
||||||
|
|
||||||
cmd = ['rsync', '-avz', '--delete', BACKUP_DIR, '--link-dest', FULL_BACKUP_LATEST, '--exclude="jellyfin/cache/transcodes"', '--exclude=".@__thumb/"', '--exclude="gitlab/logs/prometheus"', '--exclude="home-assistant.log"', '--exclude="gitlab/logs/*"', '--exclude="esphome/config/.esphome"', '--exclude=".cache"', '--exclude=".git"', '--exclude="var_lib_motioneye"', '--exclude="/.esphome/build"', NEW_BACKUP_DIR]
|
|
||||||
logging.info(" ".join(cmd))
|
|
||||||
process = subprocess.Popen(cmd,
|
|
||||||
stdout=subprocess.PIPE)
|
|
||||||
while process.poll() is None:
|
|
||||||
line = process.stdout.readline().decode("utf-8").split("/")
|
|
||||||
print(line[0])
|
|
||||||
if line[0] in apps:
|
|
||||||
logging.info(f"Working on app {line[0]}")
|
|
||||||
while True:
|
|
||||||
if line[0] != apps[0]:
|
|
||||||
del apps[0]
|
|
||||||
progress = progress + step
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
apps.remove(line[0])
|
|
||||||
#print(len(apps))
|
|
||||||
topic = "sectorq/amd/backups"
|
|
||||||
msg = {"mode":_MODE, "status":"started","bak_name":"complete","host":host,"cur_job":b,"sub":line[0],"start_time":STARTTIME,"end_time":"in progress","progress":str(round(progress)) + "%","finished":",".join(finished)}
|
|
||||||
send_mqtt_message(msg)
|
|
||||||
progress = progress + step
|
|
||||||
# input(apps)
|
|
||||||
|
|
||||||
|
|
||||||
# for a in apps:
|
|
||||||
# logging.info(f"App {a}")
|
|
||||||
# topic = "sectorq/amd/backups"
|
|
||||||
# msg = {"mode":_MODE, "status":"started","bak_name":"complete","host":host,"cur_job":b,"sub":a,"start_time":STARTTIME,"end_time":"in progress","progress":round(progress),"finished":",".join(finished)}
|
|
||||||
# send_mqtt_message(msg)
|
|
||||||
# logger.debug(cmnd)
|
|
||||||
# if _FIRST:
|
|
||||||
# cmnd = f"rsync -avz --delete {SOURCE_DIR} --exclude=\"jellyfin/cache/transcodes\" --exclude=\"gitlab/logs/prometheus\" --exclude=\"home-assistant.log\" --exclude=\"gitlab/logs/*\" --exclude=\"esphome/config/.esphome\" --exclude=\".cache\" --exclude=\".git\" --exclude=\"var_lib_motioneye\" rsync://{BACKUP_HOST}{BACKUP_PATH}"
|
|
||||||
# else:
|
|
||||||
# cmnd = f"rsync -avz --delete {BACKUP_DIR}{a} --link-dest {FULL_BACKUP_LATEST}/{a} --exclude=\"jellyfin/cache/transcodes\" --exclude=\"gitlab/logs/prometheus\" --exclude=\"home-assistant.log\" --exclude=\"gitlab/logs/*\" --exclude=\"esphome/config/.esphome\" --exclude=\".cache\" --exclude=\".git\" --exclude=\"var_lib_motioneye\" {NEW_BACKUP_DIR}"
|
|
||||||
|
|
||||||
# ans = "y"
|
|
||||||
# logging.info(cmnd)
|
|
||||||
# logging.info("Sync files1")
|
|
||||||
# #input("??????")
|
|
||||||
# if _TEST:
|
|
||||||
# ans = input("continue?") or "n"
|
|
||||||
# if ans == "y" and _EXECUTE:
|
|
||||||
# status, output = subprocess.getstatusoutput(cmnd)
|
|
||||||
# #proc = subprocess.Popen(cmnd,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,cwd = "/myapps/",shell=True)
|
|
||||||
# progress = progress + step
|
|
||||||
# topic = "sectorq/amd/backups"
|
|
||||||
# msg = {"mode":_MODE, "status":"started","bak_name":"complete","host":host,"cur_job":b,"sub":a,"start_time":STARTTIME,"end_time":"in progress","progress":round(progress),"finished":",".join(finished)}
|
|
||||||
# send_mqtt_message(msg)
|
|
||||||
|
|
||||||
|
|
||||||
cmnd = f"rm -rf {FULL_BACKUP_LATEST}"
|
|
||||||
|
|
||||||
logging.info(cmnd)
|
|
||||||
logging.info("Removing latest link")
|
|
||||||
# input("????")
|
|
||||||
if _EXECUTE:
|
|
||||||
status, output = subprocess.getstatusoutput(cmnd)
|
|
||||||
if _FIRST:
|
|
||||||
cmnd = f"cd {BACKUP_ROOT}; ln -s initial latest"
|
|
||||||
else:
|
|
||||||
cmnd = f"cd {BACKUP_ROOT}; mv {DATETIME}_running {DATETIME};ln -s {DATETIME} latest"
|
|
||||||
logging.info("Creating new latest link")
|
|
||||||
#print(cmnd)
|
|
||||||
# input("????")
|
|
||||||
if _EXECUTE:
|
|
||||||
status, output = subprocess.getstatusoutput(cmnd)
|
|
||||||
|
|
||||||
|
|
||||||
#Remove old
|
|
||||||
logging.info("Removing old dirs")
|
|
||||||
# input("????")
|
|
||||||
#cmnd = "find {} -maxdepth 1 -type d -mtime +30 -exec rm -rf {{}} \;".format(BACKUP_DIR)
|
|
||||||
cmnd = f"cd {BACKUP_ROOT} find ./ -maxdepth 1 -type d -mmin +30 -exec rm -rf {{}} \\;"
|
|
||||||
|
|
||||||
cmnd = "ls {BACKUP_ROOT}"
|
|
||||||
|
|
||||||
|
|
||||||
#print(cmnd)
|
|
||||||
# input("????")
|
|
||||||
if _EXECUTE:
|
|
||||||
status, output = subprocess.getstatusoutput(cmnd)
|
|
||||||
for f in output.splitlines():
|
|
||||||
pattern = r"^[0-9]{4}.*" # regex pattern: string starts with 'abc'
|
|
||||||
|
|
||||||
if re.match(pattern, f):
|
|
||||||
logging.info("Match!")
|
|
||||||
dt = datetime.datetime.strptime(f, "%Y-%m-%d_%H-%M-%S")
|
|
||||||
epoch_time = int(dt.timestamp())
|
|
||||||
now_epoch = int(datetime.datetime.now().timestamp())
|
|
||||||
x = now_epoch - epoch_time
|
|
||||||
logging.info(epoch_time) # Output: 45
|
|
||||||
if x > "2592000":
|
|
||||||
dir_path = "{BACKUP_ROOT}/{f}"
|
|
||||||
logging.info(f"removing {dir_path}")
|
|
||||||
#shutil.rmtree(dir_path)
|
|
||||||
else:
|
|
||||||
print("No match.")
|
|
||||||
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
ENDTIME = now.strftime("%Y-%m-%d_%H:%M:%S")
|
|
||||||
#msg = {"status":"finished","bak_name":b,"start_time":DATETIME,"end_time":ENDTIME,"progress":0}
|
|
||||||
finished.append(b)
|
|
||||||
msg = {"mode":_MODE, "status":"finished","bak_name":"complete","host":host,"cur_job":b,"start_time":ENDTIME,"end_time":"in progress","progress":0,"finished":",".join(finished)}
|
|
||||||
send_mqtt_message(msg)
|
|
||||||
|
|
||||||
logging.info("Getting size of FS")
|
|
||||||
cmnd = "df -h /mnt/raid|awk '{ print $3 }'|tail -1"
|
|
||||||
logging.info(cmnd)
|
|
||||||
status, output = subprocess.getstatusoutput(cmnd)
|
|
||||||
used_space = (output.split())[0]
|
|
||||||
now = datetime.datetime.now()
|
|
||||||
ENDJOB = now.strftime("%Y-%m-%d_%H:%M:%S")
|
|
||||||
logging.info("Size : {}".format(used_space))
|
|
||||||
logging.info("Sending finished status")
|
|
||||||
#msg = {"mode":_MODE,"status":"finished","bak_name":"complete","start_time":STARTTIME,"end_time":ENDJOB,"progress":0,"used_space":used_space}
|
|
||||||
msg = {"mode":_MODE, "status":"finished","bak_name":"complete","host":host,"cur_job":b,"start_time":STARTTIME,"end_time":ENDTIME,"progress":0,"finished":",".join(finished),"used_space":used_space}
|
|
||||||
logging.info(msg)
|
|
||||||
|
|
||||||
send_mqtt_message(msg)
|
|
||||||
os.remove(filename.path)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
server = pl["host"]
|
||||||
|
if pl["mode"] == "dry":
|
||||||
|
_DRYRUN = True
|
||||||
|
logging.info("Dry run active")
|
||||||
|
else:
|
||||||
|
_DRYRUN = False
|
||||||
|
logging.info("Full mode active")
|
||||||
|
|
||||||
|
finished = []
|
||||||
|
sub_finished = []
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
STARTTIME = now.strftime("%Y-%m-%d_%H:%M:%S")
|
||||||
|
topic = "sectorq/amd/restore"
|
||||||
|
msg = {"mode":"restore", "status":"restore","bak_name":"s","host":0,"cur_job":"aaa","start_time":1,"end_time":1,"progress":0,"finished":0,"used_space":0}
|
||||||
|
|
||||||
|
client2.publish(topic, json.dumps(msg),qos=0, retain=True)
|
||||||
|
#client2.publish(topic, msg)
|
||||||
|
topic = "sectorq/amd/backups"
|
||||||
|
msg = {"mode":_MODE, "status":"started","bak_name":"complete","host":"","cur_job":"","start_time":STARTTIME,"end_time":"in progress","progress":0,"finished":",".join(finished)}
|
||||||
|
client2.publish(topic, json.dumps(msg),qos=0, retain=True)
|
||||||
|
|
||||||
|
# iterate over files in
|
||||||
|
# that directory
|
||||||
|
|
||||||
|
|
||||||
|
host = server
|
||||||
|
logging.info("Backup")
|
||||||
|
for b in backups[host]["jobs"]:
|
||||||
|
|
||||||
|
if not backups[host]["jobs"][b]["active"]:
|
||||||
|
logging.info("Backup {} is not active!".format(b))
|
||||||
|
msg = {"status":"inactive","bak_name":b,"start_time":"inactive","end_time":"inactive","progress":0}
|
||||||
|
client2.publish(topic, json.dumps(msg),qos=0, retain=True)
|
||||||
|
continue
|
||||||
|
|
||||||
|
SOURCE_DIR = backups[host]["jobs"][b]["source"]
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
BACKUP_HOST = backups[host]["login"]
|
||||||
|
BACKUP_DEVICE = "/mnt/raid"
|
||||||
|
BACKUP_DIR = f"{BACKUP_HOST}:{SOURCE_DIR}"
|
||||||
|
BACKUP_ROOT = f"{BACKUP_DEVICE}/backup/{host}/{b}"
|
||||||
|
DATETIME = now.strftime("%Y-%m-%d_%H-%M-%S")
|
||||||
|
|
||||||
|
if _FIRST:
|
||||||
|
NEW_BACKUP_DIR = f"{BACKUP_ROOT}/initial"
|
||||||
|
else:
|
||||||
|
NEW_BACKUP_DIR = f"{BACKUP_ROOT}/{DATETIME}_running"
|
||||||
|
|
||||||
|
FULL_BACKUP_LATEST = f"{BACKUP_ROOT}/latest"
|
||||||
|
|
||||||
|
# msg = {"status":"started","bak_name":b,"start_time":DATETIME,"end_time":"in progress", "progress":0}
|
||||||
|
msg = {"mode":_MODE, "status":"started","bak_name":"complete","host":host,"cur_job":b,"start_time":STARTTIME,"end_time":"in progress","progress":0,"finished":",".join(finished)}
|
||||||
|
|
||||||
|
client2.publish(topic, json.dumps(msg),qos=0, retain=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cmnd = "mkdir -p " + NEW_BACKUP_DIR
|
||||||
|
logging.info(cmnd)
|
||||||
|
|
||||||
|
if _EXECUTE:
|
||||||
|
status, output = subprocess.getstatusoutput(cmnd)
|
||||||
|
logging.info(output)
|
||||||
|
logging.info(status)
|
||||||
|
logging.info("Create backup dir")
|
||||||
|
|
||||||
|
cmnd = f"ssh {BACKUP_HOST} 'ls {SOURCE_DIR}'"
|
||||||
|
logger.debug(cmnd)
|
||||||
|
status, output = subprocess.getstatusoutput(cmnd)
|
||||||
|
logger.debug(output)
|
||||||
|
apps = output.splitlines()
|
||||||
|
c = len(apps)
|
||||||
|
print(apps)
|
||||||
|
print(len(apps))
|
||||||
|
|
||||||
|
step = round(100 / c,1)
|
||||||
|
progress = 0
|
||||||
|
cmd = ['rsync', '-avz', '--delete', BACKUP_DIR, '--link-dest', FULL_BACKUP_LATEST, '--exclude-from=/myapps/exclude.txt', NEW_BACKUP_DIR]
|
||||||
|
logging.info(" ".join(cmd))
|
||||||
|
topic = "sectorq/amd/backups"
|
||||||
|
|
||||||
|
if not _DRYRUN:
|
||||||
|
process = subprocess.Popen(cmd,
|
||||||
|
stdout=subprocess.PIPE)
|
||||||
|
while process.poll() is None:
|
||||||
|
line = process.stdout.readline().decode("utf-8").split("/")
|
||||||
|
#print(line[0])
|
||||||
|
if line[0] in apps:
|
||||||
|
logging.info(f"Working on app {line[0]}")
|
||||||
|
while True:
|
||||||
|
if line[0] != apps[0]:
|
||||||
|
del apps[0]
|
||||||
|
progress = progress + step
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
apps.remove(line[0])
|
||||||
|
sub_finished.append(line[0])
|
||||||
|
msg = {"mode":_MODE, "status":"started","bak_name":"complete","host":host,"cur_job":b,"sub":line[0],"start_time":STARTTIME,"end_time":"in progress","progress":str(round(progress)) + "%","finished":",".join(finished),"sub_finished":",".join(sub_finished)}
|
||||||
|
logging.info(f"Sending message with topic {topic} {json.dumps(msg)}")
|
||||||
|
if not "gitea-runner" == line[0]:
|
||||||
|
client2.publish(topic, json.dumps(msg),qos=0, retain=False)
|
||||||
|
progress = progress + step
|
||||||
|
|
||||||
topic = "sectorq/amd/restore"
|
cmnd = f"rm -rf {FULL_BACKUP_LATEST}"
|
||||||
for s in servers:
|
|
||||||
#if s != "rack.home.lan":
|
#logging.info(cmnd)
|
||||||
if s == "m-server.home.lan":
|
logging.info("Removing latest link")
|
||||||
continue
|
# input("????")
|
||||||
elif s == "nas.home.lan":
|
if not _DRYRUN:
|
||||||
user = "admin"
|
status, output = subprocess.getstatusoutput(cmnd)
|
||||||
cmnd = "/share/Data/python/bin/python3 /share/Data/__GITLAB/omv_backup/omv_backup.py -r all"
|
if _FIRST:
|
||||||
|
cmnd = f"cd {BACKUP_ROOT}; ln -s initial latest"
|
||||||
|
else:
|
||||||
|
cmnd = f"cd {BACKUP_ROOT}; mv {DATETIME}_running {DATETIME};ln -s {DATETIME} latest"
|
||||||
|
logging.info("Creating new latest link")
|
||||||
|
#print(cmnd)
|
||||||
|
# input("????")
|
||||||
|
if not _DRYRUN:
|
||||||
|
status, output = subprocess.getstatusoutput(cmnd)
|
||||||
|
|
||||||
|
#Remove old
|
||||||
|
logging.info("Removing old dirs")
|
||||||
|
|
||||||
|
cmnd = f"ls {BACKUP_ROOT}"
|
||||||
|
|
||||||
|
if not _DRYRUN:
|
||||||
|
status, output = subprocess.getstatusoutput(cmnd)
|
||||||
|
for f in output.splitlines():
|
||||||
|
pattern = r"^[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}$" # regex pattern: string starts with 'abc'
|
||||||
|
# logging.info(f"Checking {f}")
|
||||||
|
if re.match(pattern, f):
|
||||||
|
# logging.info("Match!")
|
||||||
|
dt = datetime.datetime.strptime(f, "%Y-%m-%d_%H-%M-%S")
|
||||||
|
epoch_time = int(dt.timestamp())
|
||||||
|
|
||||||
|
now_epoch = int(datetime.datetime.now().timestamp())
|
||||||
|
x = now_epoch - epoch_time
|
||||||
|
# logging.info(epoch_time) # Output: 45
|
||||||
|
if x > 2592000:
|
||||||
|
dir_path = f"{BACKUP_ROOT}/{f}"
|
||||||
|
logging.info(f"removing {dir_path}")
|
||||||
|
shutil.rmtree(dir_path)
|
||||||
else:
|
else:
|
||||||
user = "jd"
|
print("No match.")
|
||||||
cmnd = "sudo /myapps/omv_backup.py -r all"
|
if not _DRYRUN:
|
||||||
msg = {"mode":_MODE, "status":"restore","bak_name":"s","host":s,"cur_job":"aaa","start_time":1,"end_time":1,"progress":0,"finished":1,"used_space":1}
|
logging.info(f"Clearing multiple days")
|
||||||
logging.info(msg)
|
multiple_per_day = {}
|
||||||
|
to_remove = []
|
||||||
|
for f in output.splitlines():
|
||||||
|
pattern = r"^[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}-[0-9]{2}$" # regex pattern: string starts with 'abc'
|
||||||
|
|
||||||
send_mqtt_message(msg)
|
if re.match(pattern, f):
|
||||||
if is_port_open(s,22):
|
cday = f.split("_")[0]
|
||||||
ssh = paramiko.SSHClient()
|
if cday in multiple_per_day:
|
||||||
ssh.load_system_host_keys()
|
multiple_per_day[cday].append(f)
|
||||||
# Add SSH host key automatically if needed.
|
else:
|
||||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
multiple_per_day[cday] = [f]
|
||||||
# Connect to router using username/password authentication.
|
|
||||||
logger.info(f"Sync {s}")
|
|
||||||
print(f"Sync {s}")
|
|
||||||
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
||||||
pkey = paramiko.RSAKey.from_private_key_file("/home/jd/.ssh/id_rsa")
|
|
||||||
ssh.connect(s,
|
|
||||||
username=user,
|
|
||||||
look_for_keys=False,
|
|
||||||
allow_agent=False,
|
|
||||||
pkey=pkey)
|
|
||||||
print(cmnd)
|
|
||||||
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(cmnd)
|
|
||||||
for line in iter(ssh_stdout.readline, ""):
|
|
||||||
logger.info(line)
|
|
||||||
print(line, end="")
|
|
||||||
for line in iter(ssh_stderr.readline, ""):
|
|
||||||
logger.info(line)
|
|
||||||
ssh.close()
|
|
||||||
try:
|
|
||||||
os.remove("/backups/restore")
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
# if _MODE == "auto":
|
|
||||||
# hostup = True
|
|
||||||
# cmnd = "ssh root@omv.home.lan 'systemctl suspend &'"
|
|
||||||
# status, output = subprocess.getstatusoutput(cmnd)
|
|
||||||
# while hostup:
|
|
||||||
# #HOST_UP = os.system(f"ping -c 1 -w 2 omv.home.lan") == 0
|
|
||||||
# cmnd = f"ping -c 1 -w 2 {BACKUP_HOST}"
|
|
||||||
# status, output = subprocess.getstatusoutput(cmnd)
|
|
||||||
# # print(status)
|
|
||||||
# # print(output)
|
|
||||||
|
|
||||||
|
|
||||||
# if status == 0:
|
|
||||||
# print(f"Backup host up, waiting - {n}\r", end="")
|
|
||||||
# time.sleep(5)
|
|
||||||
# n += 1
|
|
||||||
# else:
|
|
||||||
# print("Backup host down " )
|
|
||||||
# hostup = False
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# try:
|
|
||||||
# url = "http://m-server.home.lan:8123/api/webhook/-0eWYFhSTzdusAO8jwQS9t1AT?mode=off"
|
|
||||||
|
|
||||||
# x = requests.post(url)
|
|
||||||
|
|
||||||
# print(x.text)
|
|
||||||
# except:
|
# # logging.info("Match!")
|
||||||
# pass
|
# dt = datetime.datetime.strptime(f, "%Y-%m-%d_%H-%M-%S")
|
||||||
|
# epoch_time = int(dt.timestamp())
|
||||||
|
# now_epoch = int(datetime.datetime.now().timestamp())
|
||||||
|
|
||||||
|
|
||||||
|
# x = now_epoch - epoch_time
|
||||||
|
# # logging.info(epoch_time) # Output: 45
|
||||||
|
# if x > 2592000:
|
||||||
|
# dir_path = f"{BACKUP_ROOT}/{f}"
|
||||||
|
# logging.info(f"removing {dir_path}")
|
||||||
|
# shutil.rmtree(dir_path)
|
||||||
|
else:
|
||||||
|
print("No match.")
|
||||||
|
logging.info(f"Clearing multiple days: {multiple_per_day}")
|
||||||
|
for f in multiple_per_day:
|
||||||
|
logging.info(f"Looping multiple_per_day : {f}")
|
||||||
|
if len(multiple_per_day[f]) > 1:
|
||||||
|
last = multiple_per_day[f][-1]
|
||||||
|
multiple_per_day[f].pop()
|
||||||
|
logging.info(f"Last from day: {last}")
|
||||||
|
for d in multiple_per_day[f]:
|
||||||
|
logging.info(f"Looping multiple_per_day : {f} : {d}")
|
||||||
|
dir_path = f"{BACKUP_ROOT}/{d}"
|
||||||
|
logging.info(f"removing {dir_path}")
|
||||||
|
shutil.rmtree(dir_path)
|
||||||
|
|
||||||
|
|
||||||
|
cmnd = f"ls {BACKUP_ROOT}|grep _running"
|
||||||
|
logging.info(f"removing obsolete dirs")
|
||||||
|
if not _DRYRUN:
|
||||||
|
status, output = subprocess.getstatusoutput(cmnd)
|
||||||
|
for f in output.splitlines():
|
||||||
|
dir_path = f"{BACKUP_ROOT}/{f}"
|
||||||
|
logging.info(f"removing {dir_path}")
|
||||||
|
shutil.rmtree(dir_path)
|
||||||
|
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
ENDTIME = now.strftime("%Y-%m-%d_%H:%M:%S")
|
||||||
|
#msg = {"status":"finished","bak_name":b,"start_time":DATETIME,"end_time":ENDTIME,"progress":0}
|
||||||
|
finished.append(b)
|
||||||
|
msg = {"mode":_MODE, "status":"finished","bak_name":"complete","host":host,"cur_job":b,"start_time":ENDTIME,"end_time":"in progress","progress":0,"finished":",".join(finished)}
|
||||||
|
client2.publish(topic, json.dumps(msg),qos=0, retain=True)
|
||||||
|
|
||||||
|
logging.info("Getting size of FS")
|
||||||
|
cmnd = "df -h /mnt/raid|awk '{ print $3 }'|tail -1"
|
||||||
|
logging.info(cmnd)
|
||||||
|
status, output = subprocess.getstatusoutput(cmnd)
|
||||||
|
used_space = (output.split())[0]
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
ENDJOB = now.strftime("%Y-%m-%d_%H:%M:%S")
|
||||||
|
logging.info("Size : {}".format(used_space))
|
||||||
|
logging.info("Sending finished status")
|
||||||
|
#msg = {"mode":_MODE,"status":"finished","bak_name":"complete","start_time":STARTTIME,"end_time":ENDJOB,"progress":0,"used_space":used_space}
|
||||||
|
msg = {"mode":_MODE, "status":"finished","bak_name":"complete","host":host,"cur_job":b,"start_time":STARTTIME,"end_time":ENDTIME,"progress":0,"finished":",".join(finished),"used_space":used_space}
|
||||||
|
logging.info(msg)
|
||||||
|
|
||||||
|
client2.publish(topic, json.dumps(msg),qos=0, retain=True)
|
||||||
|
topic = "sectorq/backups/start"
|
||||||
|
logging.info(f"LALA : {topic}")
|
||||||
|
client2.publish(topic, "finished",qos=0, retain=True)
|
||||||
|
time.sleep(1)
|
||||||
|
client2.publish(topic, "finished2",qos=0, retain=True)
|
||||||
|
client2.disconnect()
|
||||||
|
#return "finished"
|
||||||
|
|
||||||
|
if _DRYRUN:
|
||||||
|
return
|
||||||
|
topic = "sectorq/amd/restore"
|
||||||
|
for s in servers:
|
||||||
|
logging.info(f"Restoring {s}")
|
||||||
|
#if s != "rack.home.lan":
|
||||||
|
if s == "m-server.home.lan":
|
||||||
|
continue
|
||||||
|
elif s == "nas.home.lan":
|
||||||
|
user = "admin"
|
||||||
|
cmnd = "/share/Data/python/bin/python3 /share/Data/__GITLAB/omv_backup/omv_backup.py -r all"
|
||||||
|
else:
|
||||||
|
user = "jd"
|
||||||
|
cmnd = "sudo /myapps/omv_backup.py -r all"
|
||||||
|
msg = {"mode":_MODE, "status":"restore","bak_name":"s","host":s,"cur_job":"aaa","start_time":1,"end_time":1,"progress":0,"finished":1,"used_space":1}
|
||||||
|
#logging.info(msg)
|
||||||
|
|
||||||
|
send_mqtt_message(topic,msg)
|
||||||
|
#continue
|
||||||
|
if is_port_open(s,22):
|
||||||
|
ssh = paramiko.SSHClient()
|
||||||
|
ssh.load_system_host_keys()
|
||||||
|
# Add SSH host key automatically if needed.
|
||||||
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||||
|
# Connect to router using username/password authentication.
|
||||||
|
logger.info(f"Sync {s}")
|
||||||
|
print(f"Sync {s}")
|
||||||
|
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||||
|
pkey = paramiko.RSAKey.from_private_key_file("/home/jd/.ssh/id_rsa")
|
||||||
|
ssh.connect(s,
|
||||||
|
username=user,
|
||||||
|
look_for_keys=False,
|
||||||
|
allow_agent=False,
|
||||||
|
pkey=pkey)
|
||||||
|
print(cmnd)
|
||||||
|
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command(cmnd)
|
||||||
|
for line in iter(ssh_stdout.readline, ""):
|
||||||
|
logger.info(line)
|
||||||
|
print(line, end="")
|
||||||
|
for line in iter(ssh_stderr.readline, ""):
|
||||||
|
logger.info(line)
|
||||||
|
ssh.close()
|
||||||
|
try:
|
||||||
|
os.remove("/backups/restore")
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return "finished1"
|
||||||
|
|
||||||
|
|
||||||
|
if _RESTORE:
|
||||||
|
restore_job(_APP)
|
||||||
|
sys.exit()
|
||||||
if _SSH_TEST:
|
if _SSH_TEST:
|
||||||
user = "root"
|
user = "root"
|
||||||
cmnd = "ls -la"
|
cmnd = "ls -la"
|
||||||
@@ -750,9 +786,9 @@ if _SSH_TEST:
|
|||||||
# user = "admin"
|
# user = "admin"
|
||||||
# cmnd = "/share/Data/__GITLAB/omv_backup/venv/bin/python3 /share/Data/__GITLAB/omv_backup/omv_backup.py -r all"
|
# cmnd = "/share/Data/__GITLAB/omv_backup/venv/bin/python3 /share/Data/__GITLAB/omv_backup/omv_backup.py -r all"
|
||||||
msg = {"mode":_MODE, "status":"restore","bak_name":"s","host":s,"cur_job":"aaa","start_time":1,"end_time":1,"progress":0,"finished":1,"used_space":1}
|
msg = {"mode":_MODE, "status":"restore","bak_name":"s","host":s,"cur_job":"aaa","start_time":1,"end_time":1,"progress":0,"finished":1,"used_space":1}
|
||||||
logging.info(msg)
|
#logging.info(msg)
|
||||||
|
|
||||||
send_mqtt_message(msg)
|
send_mqtt_message(topic,msg)
|
||||||
if s != "rack.home.lan":
|
if s != "rack.home.lan":
|
||||||
continue
|
continue
|
||||||
if is_port_open(s,22):
|
if is_port_open(s,22):
|
||||||
@@ -777,4 +813,57 @@ if _SSH_TEST:
|
|||||||
print(line, end="")
|
print(line, end="")
|
||||||
for line in iter(ssh_stderr.readline, ""):
|
for line in iter(ssh_stderr.readline, ""):
|
||||||
logger.info(line)
|
logger.info(line)
|
||||||
ssh.close()
|
ssh.close()
|
||||||
|
|
||||||
|
# Define actions based on payload
|
||||||
|
def handle_payload(payload):
|
||||||
|
try:
|
||||||
|
pl = json.loads(payload)
|
||||||
|
except:
|
||||||
|
pl = payload
|
||||||
|
logging.debug(pl)
|
||||||
|
|
||||||
|
if "host" in pl:
|
||||||
|
if pl["host"] == 'm-server':
|
||||||
|
logging.info("💡 Starting backup job")
|
||||||
|
backup_job(pl)
|
||||||
|
logging.info(f"💡 Finished backup job")
|
||||||
|
elif pl["host"] == 'nas':
|
||||||
|
logging.info("💡 Starting backup job")
|
||||||
|
backup_job(pl)
|
||||||
|
logging.info(f"💡 Finished backup job")
|
||||||
|
else:
|
||||||
|
logging.error(f"⚠️ Unknown command: {pl}")
|
||||||
|
else:
|
||||||
|
logging.error(f"⚠️ Wrong payload: {pl}")
|
||||||
|
# Callback when connected
|
||||||
|
def on_connect(client, userdata, flags, rc):
|
||||||
|
if rc == 0:
|
||||||
|
logging.info("✅ Connected securely to broker")
|
||||||
|
client.subscribe(TOPIC)
|
||||||
|
logging.info(f"📡 Subscribed to topic: {TOPIC}")
|
||||||
|
else:
|
||||||
|
logging.error(f"❌ Connection failed with code {rc}")
|
||||||
|
|
||||||
|
# Callback when a message is received
|
||||||
|
def on_message(client, userdata, msg):
|
||||||
|
payload = msg.payload.decode()
|
||||||
|
logging.info(f"📨 Received message: {payload} on topic: {msg.topic}")
|
||||||
|
handle_payload(payload)
|
||||||
|
|
||||||
|
# MQTT client setup
|
||||||
|
client = mqtt.Client()
|
||||||
|
client.username_pw_set(USERNAME, PASSWORD)
|
||||||
|
client.on_connect = on_connect
|
||||||
|
client.on_message = on_message
|
||||||
|
|
||||||
|
# Use TLS for encrypted connection
|
||||||
|
if USE_TLS:
|
||||||
|
client.tls_set() # You can customize this with certs if needed
|
||||||
|
|
||||||
|
# Connect and loop forever
|
||||||
|
client.connect(BROKER, PORT, keepalive=60)
|
||||||
|
|
||||||
|
|
||||||
|
client.publish("sectorq/backups/start", "finished", qos=0, retain=True)
|
||||||
|
client.loop_forever()
|
Reference in New Issue
Block a user