Torxed / python-zfs

Python wrapper for zfs-send

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

python-zfs

Python wrapper for zfs

speed-test

speed

Tooling usage

Starting the reciever

$ python -m zfs --reciever --interface testif-out [--dummy-data ./testdata_recv.bin]

Sending a full dataset

$ python -m zfs --interface testif-in --full-sync [--dummy-data ~/testdata.bin] --pool testing --destination-ip 192.168.1.2 --destination-mac 'e2:ff:48:6e:a9:fe' --source-ip '192.168.1.1' --source-mac '46:dc:e7:58:d0:a2'

:note: This will send from 46:dc:e7:58:d0:a2 (192.168.1.1) to e2:ff:48:6e:a9:fe (192.168.2.2). python-zfs sends in promiscious mode so the IP and MAC source doesn't actually have to existing. In theory, neither does the sender, but if there's any network equipment between the sender and reciever, the destination must be known by the network before hand.

:note: Also note that --dummy-data is used to simluate the pool testing and can contain anything. It can also be used to send a file instead, but functionality cannot be guaranteed and is for testing mainly.

Sending delta between two snapshots

$ python -m zfs --interface testif-in --send-delta --delta-start pool/testync@0 --delta-end pool/testsync@1 [--dummy-data ~/testdata.bin] --pool testing --destination-ip 192.168.1.2 --destination-mac 'e2:ff:48:6e:a9:fe' --source-ip '192.168.1.1' --source-mac '46:dc:e7:58:d0:a2'

Library usage

Listing all snapshots

import zfs.list

for volume in zfs.list.volumes():
	if volume.name == 'pool':
		continue

	print(repr(volume))
	for snapshot in volume.snapshots:
		print(repr(snapshot))

Creating and Destroying snapshots

import zfs.list

pool = zfs.list.get_volume('pool/testpool')

snapshot = pool.take_snapshot()
snapshot.destroy()

Sending delta between two snapshots

On the sender side, take a snapshot and send it with:

import time
import zfs.list
import zfs.snapshots
import zfs.stream

def encrypt(data):
	return data

pool = zfs.list.get_volume('pool/testpool')

snapshot1 = pool.take_snapshot()

zfs.log("Writing data between snapshots..", fg="cyan")
with open('/pool/testpool/test.txt', 'w') as fh:
	fh.write(time.strftime('%Y-%m-%d %H:%M:%S\n'))

snapshot2 = pool.take_snapshot()

with zfs.snapshots.Delta(snapshot1, snapshot2) as stream:
	zfs.stream.deliver(stream, to=('192.168.1.1', 1337), on_send=encrypt)

# Roll back the test snapshots and data
snapshot1.destroy()
snapshot2.destroy()

last_snapshot = list(pool.last_snapshots)[-1]
last_snapshot.restore()

And on the reciever end, to recieve the zfs snapshot:

import zfs.list
import zfs.snapshots
import zfs.stream

snapshot = zfs.snapshots.DeltaReader()

with zfs.stream.Reciever(addr='', port=1337) as stream:
	for zfs_snapshot_chunk in stream:
		snapshot.restore(zfs_snapshot_chunk)

Visualize bottlenecks

$ viztracer python -m zfs --reciever --interface eth0 --framesize 9000

Load result.json into https://ui.perfetto.dev/ and dig in.

Running testscenario without zfs

Creating isolated networking (veth interface pair):

# Create veth pair
ip link add dev testif-in type veth peer name testif-out
# Set IP addresses
ip addr add 192.168.1.1 dev testif-in    # Make sure it doesn't collide
ip addr add 192.168.1.2 dev testif-out   # with existing setups on your network.
# Set MAC addresses
ip link set dev testif-in address '46:dc:e7:58:d0:a2'
ip link set dev testif-out address 'e2:ff:48:6e:a9:fe'
# Bring it all up
ip link set dev testif-in up
ip link set dev testif-out up

Creating payload (a known payload):

dd if=/dev/urandom of=./small.img bs=1M count=1

Start reciever

$ python -m zfs --reciever --interface testif-out --dummy-data ./small_recv.img

Starting sender

$ python -m zfs --interface testif-in --full-sync --dummy-data ./small.img --pool testing --destination-ip 192.168.1.2 --destination-mac 'e2:ff:48:6e:a9:fe' --source-ip '192.168.1.1' --source-mac '46:dc:e7:58:d0:a2'

Debugging

Running wireshark on testif-in (and -out) should show traffic, which should have correct IP/UDP headers, with a payload matching the defined structure found in this readme (TBD).

About

Python wrapper for zfs-send

License:MIT License


Languages

Language:Python 100.0%