|
|
@ -1,3 +1,4 @@ |
|
|
|
|
|
|
|
#!/usr/local/bin/python |
|
|
|
import pathlib |
|
|
|
import pathlib |
|
|
|
import subprocess |
|
|
|
import subprocess |
|
|
|
|
|
|
|
|
|
|
@ -36,7 +37,7 @@ def list_snapshots(): |
|
|
|
return clean_split(call(cmd, as_text=True)) |
|
|
|
return clean_split(call(cmd, as_text=True)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def elab_snapshots(): |
|
|
|
def list_elab_snapshots(): |
|
|
|
result = {} |
|
|
|
result = {} |
|
|
|
for snapshot in list_snapshots(): |
|
|
|
for snapshot in list_snapshots(): |
|
|
|
pool, snap_name = snapshot.split("/", 1) |
|
|
|
pool, snap_name = snapshot.split("/", 1) |
|
|
@ -49,12 +50,13 @@ def elab_snapshots(): |
|
|
|
return result |
|
|
|
return result |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def gzip_filename(name): |
|
|
|
def gzip_filename(snapshot_name): |
|
|
|
|
|
|
|
pool, name = snapshot_name.split("/", 1) |
|
|
|
return f"{name}.gz" |
|
|
|
return f"{name}.gz" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def gzip_filepath(name): |
|
|
|
def gzip_filepath(snapshot_name): |
|
|
|
return pathlib.Path(TMP_BACKUP_FOLDER) / gzip_filename(name) |
|
|
|
return pathlib.Path(TMP_BACKUP_FOLDER) / gzip_filename(snapshot_name) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def list_remote_backups(members): |
|
|
|
def list_remote_backups(members): |
|
|
@ -81,43 +83,43 @@ def backup_latest_snapshot(member, elab_snapshots, existing_backups): |
|
|
|
break |
|
|
|
break |
|
|
|
if current_snapshot == latest_backup: |
|
|
|
if current_snapshot == latest_backup: |
|
|
|
# nothing to back up |
|
|
|
# nothing to back up |
|
|
|
print("- nothing to backup, latest snapshot: {current_snapshot}") |
|
|
|
print(f"- nothing to backup, latest snapshot: {current_snapshot}") |
|
|
|
return |
|
|
|
return |
|
|
|
elif latest_backup is None: |
|
|
|
elif latest_backup is None: |
|
|
|
# no snapshot was found in backups, make a full backup for consistency |
|
|
|
# no snapshot was found in backups, make a full backup for consistency |
|
|
|
send_cmd = ["zfs", "send", current_snapshot] |
|
|
|
send_cmd = ["zfs", "send", current_snapshot] |
|
|
|
print(" - full backup, latest snapshot: {current_snapshot}") |
|
|
|
print(f" - full backup, latest snapshot: {current_snapshot}") |
|
|
|
else: |
|
|
|
else: |
|
|
|
# make an incremental backup |
|
|
|
# make an incremental backup |
|
|
|
print( |
|
|
|
print( |
|
|
|
" - incremental backup, from: {latest_backup} to: {current_snapshot}" |
|
|
|
f" - incremental backup, from: {latest_backup} to: {current_snapshot}" |
|
|
|
) |
|
|
|
) |
|
|
|
send_cmd = ["zfs", "send", "-I", latest_backup, current_snapshot] |
|
|
|
send_cmd = ["zfs", "send", "-I", latest_backup, current_snapshot] |
|
|
|
|
|
|
|
|
|
|
|
# create the backup |
|
|
|
# create the backup |
|
|
|
print(" - generating temporary backup file") |
|
|
|
tmp_gzip_filepath = gzip_filepath(current_snapshot) |
|
|
|
#tmp_gzip_filepath = gzip_filepath(current_snapshot) |
|
|
|
print(f" - generating temporary backup file {tmp_gzip_filepath.name}") |
|
|
|
#with open(tmp_gzip_filepath, "wb") as file_handle: |
|
|
|
with open(tmp_gzip_filepath, "wb") as file_handle: |
|
|
|
# gzip_in = subprocess.Popen( |
|
|
|
gzip_in = subprocess.Popen( |
|
|
|
# "gzip", stdin=subprocess.PIPE, stdout=file_handle, check=True |
|
|
|
"gzip", stdin=subprocess.PIPE, stdout=file_handle |
|
|
|
# ).stdin |
|
|
|
).stdin |
|
|
|
# subprocess.call(send_cmd, stdout=gzip_in, check=True) |
|
|
|
subprocess.run(send_cmd, stdout=gzip_in, check=True) |
|
|
|
|
|
|
|
|
|
|
|
# copy the backup to the remote server |
|
|
|
# copy the backup to the remote server |
|
|
|
print(" - copying temporary backup file") |
|
|
|
print(" - copying temporary backup file") |
|
|
|
#remote_url = ( |
|
|
|
remote_url = ( |
|
|
|
# f"{SSH_REMOTE}:~/{REMOTE_PATH}/{member}/{tmp_gzip_filepath.name}" |
|
|
|
f"{SSH_REMOTE}:~/{REMOTE_PATH}/{member}/{tmp_gzip_filepath.name}" |
|
|
|
#) |
|
|
|
) |
|
|
|
#copy_cmd = ["scp", "-i", SSH_KEY_FILE, str(tmp_gzip_filepath), remote_url] |
|
|
|
copy_cmd = ["scp", "-i", SSH_KEY_FILE, str(tmp_gzip_filepath), remote_url] |
|
|
|
#call(copy_cmd) |
|
|
|
call(copy_cmd) |
|
|
|
|
|
|
|
|
|
|
|
# remove the temporary file |
|
|
|
# remove the temporary file |
|
|
|
print(" - removing temporary backup file") |
|
|
|
print(" - removing temporary backup file") |
|
|
|
#tmp_gzip_filepath.unlink() |
|
|
|
tmp_gzip_filepath.unlink() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_backups(): |
|
|
|
def create_backups(): |
|
|
|
elab_snapshots = list_snapshots() |
|
|
|
elab_snapshots = list_elab_snapshots() |
|
|
|
existing_backups = list_remote_backups(elab_snapshots.keys()) |
|
|
|
existing_backups = list_remote_backups(elab_snapshots.keys()) |
|
|
|
for member, snapshots in elab_snapshots.items(): |
|
|
|
for member, snapshots in elab_snapshots.items(): |
|
|
|
members_backups = existing_backups.get(member, []) |
|
|
|
members_backups = existing_backups.get(member, []) |
|
|
|