#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys, os
sys.path.append(
    os.path.join(os.path.dirname(os.path.realpath(__file__)), os.path.pardir, "src")
)
import optparse
import time
from zfstools.models import Dataset, Pool, Snapshot, PoolSet
from zfstools.connection import ZFSConnection
from zfstools.util import stderr, verbose_stderr, set_verbose

#===================== configuration =====================

parser = optparse.OptionParser("usage: %prog [-k NUMSNAPS] <datasetname>")
parser.add_option('-k', '--keep', action='store', dest='keep', default=7, help='how many snapshots to keep (default: %default)')
parser.add_option('-p', '--prefix', action='store', dest='prefix', default="autosnapshot-", help='prefix to prepend to snapshot names (default: %default)')
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False, help='be verbose (default: %default)')
parser.add_option('-t', '--timeformat', action='store', dest='timeformat', default="%Y-%m-%d-%H%M%S", help='postfix time format to append to snapshot names (default: %default, MUST be sortable using a general sort)')
parser.add_option('-n', '--dry-run', action='store_true', dest='dryrun', default=False, help='don\'t actually manipulate any file systems')
opts,args = parser.parse_args(sys.argv[1:])

try:
	keep = int(opts.keep)
	assert keep >= 1
except (ValueError,AssertionError),e:
	parser.error("keep must be greater than 1")
	sys.exit(os.EX_USAGE)

if len(args) == 1:
	try: source_host, source_dataset_name = args[0].split(":",1)
	except ValueError: source_host, source_dataset_name = "localhost",args[0]
else:
	parser.error("arguments are wrong")
	sys.exit(os.EX_USAGE)

set_verbose(opts.verbose)

snapshot_prefix = opts.prefix
snapshot_postfix = lambda: time.strftime(opts.timeformat)

#===================== end configuration =================

# ================ start program algorithm ===================

src_conn = ZFSConnection(source_host)
snapshot_unique_name = snapshot_prefix + snapshot_postfix()
flt = lambda x: x.name.startswith(snapshot_prefix)

verbose_stderr("Assessing that the specified dataset exists...")
try:
	source_dataset = src_conn.pools.lookup(source_dataset_name)
	verbose_stderr("%s: OK" % source_dataset)
except KeyError:
	verbose_stderr("No.\nError: the source dataset does not exist.  Snapshot cannot continue.")
	sys.exit(2)

verbose_stderr("Snapshotting dataset %s:%s" % (source_host, source_dataset_name))

if not opts.dryrun:
	src_conn.snapshot_recursively(source_dataset_name, snapshot_unique_name)
	# FIXME: what follows is retarded design
	src_conn.pools  # trigger update

ssn = sorted([ (x.get_creation(), x.name, x) for x in source_dataset.get_snapshots(flt) ])

if opts.dryrun:
	# simulate the addition of a new dataset
	keep = keep - 1

for x in ssn[:-keep]:
	verbose_stderr("Destroying obsolete snapshot: %s" % (x[-1].get_path()))
	if not opts.dryrun: src_conn.destroy_recursively(x[-1].get_path())
