Step 1.Connect to SynetoOS appliance via SSH as admin
ssh admin@<your_ip_address_or_hostname>
Step 2. Become Super User
sudo su
Step 3.Edit /tmp/zfs-list.py file
vi /tmp/zfs-list.py
IMPORTANT Make sure to copy and paste the exact lines below
#!/usr/bin/env python3
import subprocess
import os
import sys
RED = "\033[91m"
RESET = "\033[0m"
def run(cmd):
try:
out = subprocess.check_output(cmd, shell=True, text=True)
return [l for l in out.strip().splitlines() if l]
except subprocess.CalledProcessError:
return []
def get_pool_names():
return [line.split()[0] for line in run("zpool list -H -o name")]
def get_volumes():
lines = run("zfs list -H -o name,mountpoint,used")
excluded = get_pool_names()
volumes = []
for l in lines:
parts = l.split("\t")
if len(parts) < 3:
continue
name, mp, used = parts
if (
any(name == pool or name == f"{pool}/syn-volumes" for pool in excluded)
or "_metadata" in name
):
continue
volumes.append((name, used))
return volumes
def is_replica(vol):
ro = run(f"zfs get -H -o value readonly {vol}")
if ro and ro[0] == "on":
return True
props = run(f"zfs get -H -o property,value all {vol}")
for p in props:
if p.startswith("syncoid:remote") and p.endswith("yes"):
return True
return False
def get_vm_dirs_and_lock(path):
full_path = f"/{path}".rstrip("/")
vm_dirs = []
locked = False
if os.path.isdir(full_path):
try:
for entry in os.listdir(full_path):
if entry.startswith(".") or entry == ".syneto-metadata":
continue
full_entry = os.path.join(full_path, entry)
if os.path.isdir(full_entry):
vm_dirs.append(entry)
for root, dirs, files in os.walk(full_entry):
if any(".lck" in f for f in files):
locked = True
return (", ".join(vm_dirs) if vm_dirs else "<empty>", locked)
except Exception:
return ("<read error>", False)
return ("<not mounted>", False)
def print_table(volumes):
headers = ["VOLUME ID", "VM NAME", "USED SPACE", "IS A REPLICA", "IS IN PRODUCTION"]
rows = []
for name, used in volumes:
replica = "YES" if is_replica(name) else "NO"
vm, locked = get_vm_dirs_and_lock(name)
production = "YES" if locked else "NO"
rows.append((name, vm, used, replica, production, locked))
# Calculate max widths
col_widths = [max(len(row[i]) for row in rows + [headers]) for i in range(5)]
def border():
return "+" + "+".join("-" * (w + 2) for w in col_widths) + "+"
def format_row(values, highlight=False):
line = "|"
for i, val in enumerate(values):
padded = f" {val}".ljust(col_widths[i] + 2)
if highlight:
padded = RED + padded + RESET
line += padded + "|"
return line
print(border())
print(format_row(headers))
print(border())
for row in rows:
print(format_row(row[:5], highlight=row[5]))
print(border())
def main():
volumes = get_volumes()
if not volumes:
print("No ZFS volumes found.")
sys.exit(0)
print_table(volumes)
if __name__ == "__main__":
main()