modified:   virt-back
This commit is contained in:
Russell Ballestrini 2024-07-07 19:24:18 -04:00
parent fd1592c3b1
commit 85e1f3b28b

View file

@ -124,7 +124,9 @@ def backup(doms):
f.write(xml) f.write(xml)
# Updated regular expression to match file= and dev= within <disk> elements # Updated regular expression to match file= and dev= within <disk> elements
disklist = re.findall(r"<disk.*?<source (?:file|dev)='(.*?)'.*?</disk>", xml, re.DOTALL) disklist = re.findall(
r"<disk.*?<source (?:file|dev)='(.*?)'.*?</disk>", xml, re.DOTALL
)
logit("backup", "invoking backup for " + dom.name()) logit("backup", "invoking backup for " + dom.name())
@ -137,13 +139,24 @@ def backup(doms):
if is_zfs_dataset(disk_source): if is_zfs_dataset(disk_source):
# Handle ZFS dataset # Handle ZFS dataset
zfs_dataset = disk_source[len('/dev/zvol/'):] if disk_source.startswith('/dev/zvol/') else disk_source zfs_dataset = (
disk_source[len("/dev/zvol/") :]
if disk_source.startswith("/dev/zvol/")
else disk_source
)
zfs_snapshot_base = f"{zfs_dataset}@backup-{TODAY}" zfs_snapshot_base = f"{zfs_dataset}@backup-{TODAY}"
zfs_snapshot = zfs_snapshot_base zfs_snapshot = zfs_snapshot_base
suffix = 1 suffix = 1
# Increment snapshot name until an available name is found # Increment snapshot name until an available name is found
while subprocess.run(["zfs", "list", zfs_snapshot], stdout=subprocess.PIPE, stderr=subprocess.PIPE).returncode == 0: while (
subprocess.run(
["zfs", "list", zfs_snapshot],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
).returncode
== 0
):
zfs_snapshot = f"{zfs_snapshot_base}-{suffix}" zfs_snapshot = f"{zfs_snapshot_base}-{suffix}"
suffix += 1 suffix += 1
@ -152,7 +165,9 @@ def backup(doms):
zfs_file += ".gz" zfs_file += ".gz"
# Create ZFS snapshot # Create ZFS snapshot
logit("backup", f"creating ZFS snapshot {zfs_snapshot} for {dom.name()}") logit(
"backup", f"creating ZFS snapshot {zfs_snapshot} for {dom.name()}"
)
try: try:
subprocess.run(["zfs", "snapshot", zfs_snapshot], check=True) subprocess.run(["zfs", "snapshot", zfs_snapshot], check=True)
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
@ -160,14 +175,23 @@ def backup(doms):
continue continue
# Send ZFS snapshot to file with optional compression # Send ZFS snapshot to file with optional compression
logit("backup", f"sending ZFS snapshot {zfs_snapshot} to {zfs_file} for {dom.name()}") logit(
"backup",
f"sending ZFS snapshot {zfs_snapshot} to {zfs_file} for {dom.name()}",
)
try: try:
with open(zfs_file, "wb") as f: with open(zfs_file, "wb") as f:
if options.nogzip: if options.nogzip:
subprocess.run(["zfs", "send", zfs_snapshot], stdout=f, check=True) subprocess.run(
["zfs", "send", zfs_snapshot], stdout=f, check=True
)
else: else:
send_proc = subprocess.Popen(["zfs", "send", zfs_snapshot], stdout=subprocess.PIPE) send_proc = subprocess.Popen(
gzip_proc = subprocess.Popen(["gzip"], stdin=send_proc.stdout, stdout=f) ["zfs", "send", zfs_snapshot], stdout=subprocess.PIPE
)
gzip_proc = subprocess.Popen(
["gzip"], stdin=send_proc.stdout, stdout=f
)
send_proc.stdout.close() # Allow send_proc to receive a SIGPIPE if gzip_proc exits send_proc.stdout.close() # Allow send_proc to receive a SIGPIPE if gzip_proc exits
gzip_proc.communicate() gzip_proc.communicate()
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
@ -222,7 +246,10 @@ def backup(doms):
tar.add(zfs_file) # add zfs snapshot to tar tar.add(zfs_file) # add zfs snapshot to tar
remove(zfs_file) # cleanup tmp files remove(zfs_file) # cleanup tmp files
else: else:
logit("error", f"ZFS snapshot file {zfs_file} not found for {dom.name()}") logit(
"error",
f"ZFS snapshot file {zfs_file} not found for {dom.name()}",
)
else: else:
disk_file = disk_source.split("/")[-1] disk_file = disk_source.split("/")[-1]
disk_dest = path.join(options.backpath, disk_file) disk_dest = path.join(options.backpath, disk_file)
@ -240,12 +267,14 @@ def is_zfs_dataset(disk_source):
logit("backup", f"checking if {disk_source} is a ZFS dataset") logit("backup", f"checking if {disk_source} is a ZFS dataset")
try: try:
# Extract the ZFS dataset name from the device path # Extract the ZFS dataset name from the device path
if disk_source.startswith('/dev/zvol/'): if disk_source.startswith("/dev/zvol/"):
zfs_dataset = disk_source[len('/dev/zvol/'):] zfs_dataset = disk_source[len("/dev/zvol/") :]
else: else:
zfs_dataset = disk_source zfs_dataset = disk_source
result = subprocess.run(["zfs", "list", zfs_dataset], stdout=subprocess.PIPE, stderr=subprocess.PIPE) result = subprocess.run(
["zfs", "list", zfs_dataset], stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
is_zfs = result.returncode == 0 is_zfs = result.returncode == 0
logit("backup", f"{zfs_dataset} is {'a' if is_zfs else 'not a'} ZFS dataset") logit("backup", f"{zfs_dataset} is {'a' if is_zfs else 'not a'} ZFS dataset")
return is_zfs return is_zfs