How To List and Identify ZFS Volumes in SynetoOS 5

Written By Sebastian Sime (Draft Writer)

Updated at January 29th, 2026

→ Applies to: SynetoOS 5.x

 

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()

Save and EXIT

:wq

 

Step 4.  Give permissions to /tmp/zfs-list.py file

chmod +x /tmp/zfs-list.py

 

Step 5.  Run the script

sudo python3 /tmp/zfs-list.py

EXAMPLE OUTPUT