dataset.py revision 9f9230833b50b8271840dc2c12bd1e94d9df7d12
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore#!@PYTHON@
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# CDDL HEADER START
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore#
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# The contents of this file are subject to the terms of the
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# Common Development and Distribution License (the "License").
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# You may not use this file except in compliance with the License.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# or http://www.opensolaris.org/os/licensing.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# See the License for the specific language governing permissions
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# and limitations under the License.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# When distributing Covered Code, include this CDDL HEADER in each
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# If applicable, add the following below this CDDL HEADER, with the
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# fields enclosed by brackets "[]" replaced with your own identifying
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# information: Portions Copyright [yyyy] [name of copyright owner]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# CDDL HEADER END
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore#
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore"""Implements the Dataset class, providing methods for manipulating ZFS
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoredatasets. Also implements the Property class, which describes ZFS
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreproperties."""
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreimport zfs.ioctl
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreimport zfs.util
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreimport errno
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore_ = zfs.util._
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreclass Property(object):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """This class represents a ZFS property. It contains
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore information about the property -- if it's readonly, a number vs
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore string vs index, etc. Only native properties are represented by
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore this class -- not user properties (eg "user:prop") or userspace
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore properties (eg "userquota@joe")."""
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore __slots__ = "name", "number", "type", "default", "attr", "validtypes", \
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "values", "colname", "rightalign", "visible", "indextable"
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore __repr__ = zfs.util.default_repr
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore def __init__(self, t):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """t is the tuple of information about this property
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore from zfs.ioctl.get_proptable, which should match the
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore members of zprop_desc_t (see zfs_prop.h)."""
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore self.name = t[0]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore self.number = t[1]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore self.type = t[2]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if self.type == "string":
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore self.default = t[3]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore else:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore self.default = t[4]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore self.attr = t[5]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore self.validtypes = t[6]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore self.values = t[7]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore self.colname = t[8]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore self.rightalign = t[9]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore self.visible = t[10]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore self.indextable = t[11]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore def delegatable(self):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """Return True if this property can be delegated with
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "zfs allow"."""
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore return self.attr != "readonly"
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreproptable = dict()
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorefor name, t in zfs.ioctl.get_proptable().iteritems():
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore proptable[name] = Property(t)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoredel name, t
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoredef getpropobj(name):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """Return the Property object that is identified by the given
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore name string. It can be the full name, or the column name."""
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore try:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore return proptable[name]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore except KeyError:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore for p in proptable.itervalues():
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if p.colname and p.colname.lower() == name:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore return p
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore raise
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoreclass Dataset(object):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """Represents a ZFS dataset (filesystem, snapshot, zvol, clone, etc).
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore Generally, this class provides interfaces to the C functions in
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore zfs.ioctl which actually interface with the kernel to manipulate
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore datasets.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore Unless otherwise noted, any method can raise a ZFSError to
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore indicate failure."""
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore __slots__ = "name", "__props"
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore __repr__ = zfs.util.default_repr
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore def __init__(self, name, props=None,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore types=("filesystem", "volume"), snaps=True):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """Open the named dataset, checking that it exists and
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore is of the specified type.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore name is the string name of this dataset.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore props is the property settings dict from zfs.ioctl.next_dataset.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore types is an iterable of strings specifying which types
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore of datasets are permitted. Accepted strings are
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore "filesystem" and "volume". Defaults to accepting all
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore types.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore snaps is a boolean specifying if snapshots are acceptable.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore Raises a ZFSError if the dataset can't be accessed (eg
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore doesn't exist) or is not of the specified type.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore self.name = name
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore e = zfs.util.ZFSError(errno.EINVAL,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore _("cannot open %s") % name,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore _("operation not applicable to datasets of this type"))
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if "@" in name and not snaps:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore raise e
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if not props:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore props = zfs.ioctl.dataset_props(name)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore self.__props = props
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if "volume" not in types and self.getprop("type") == 3:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore raise e
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if "filesystem" not in types and self.getprop("type") == 2:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore raise e
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore def getprop(self, propname):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """Return the value of the given property for this dataset.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore Currently only works for native properties (those with a
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore Property object.)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore Raises KeyError if propname does not specify a native property.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore Does not raise ZFSError.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore p = getpropobj(propname)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore try:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore return self.__props[p.name]["value"]
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore except KeyError:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore return p.default
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore def parent(self):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """Return a Dataset representing the parent of this one."""
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore return Dataset(self.name[:self.name.rindex("/")])
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore def descendents(self):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """A generator function which iterates over all
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore descendent Datasets (not including snapshots."""
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore cookie = 0
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore while True:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore # next_dataset raises StopIteration when done
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore (name, cookie, props) = \
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore zfs.ioctl.next_dataset(self.name, False, cookie)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ds = Dataset(name, props)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore yield ds
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore for child in ds.descendents():
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore yield child
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore def userspace(self, prop):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """A generator function which iterates over a
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore userspace-type property.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore prop specifies which property ("userused@",
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "userquota@", "groupused@", or "groupquota@").
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore returns 3-tuple of domain (string), rid (int), and space (int).
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore d = zfs.ioctl.userspace_many(self.name, prop)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore for ((domain, rid), space) in d.iteritems():
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore yield (domain, rid, space)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore def userspace_upgrade(self):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """Initialize the accounting information for
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore userused@... and groupused@... properties."""
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore return zfs.ioctl.userspace_upgrade(self.name)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore def set_fsacl(self, un, d):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore """Add to the "zfs allow"-ed permissions on this Dataset.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore un is True if the specified permissions should be removed.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore d is a dict specifying which permissions to add/remove:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore { "whostr" -> None # remove all perms for this entity
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore "whostr" -> { "perm" -> None} # add/remove these perms
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore } """
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore return zfs.ioctl.set_fsacl(self.name, un, d)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore def get_fsacl(self):
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore """Get the "zfs allow"-ed permissions on the Dataset.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore Return a dict("whostr": { "perm" -> None })."""
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore return zfs.ioctl.get_fsacl(self.name)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore def get_holds(self):
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore """Get the user holds on this Dataset.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore Return a dict("tag": timestamp)."""
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore return zfs.ioctl.get_holds(self.name)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amoredef snapshots_fromcmdline(dsnames, recursive):
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore for dsname in dsnames:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if not "@" in dsname:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore raise zfs.util.ZFSError(errno.EINVAL,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore _("cannot open %s") % dsname,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore _("operation only applies to snapshots"))
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore try:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore ds = Dataset(dsname)
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore yield ds
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore except zfs.util.ZFSError, e:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if not recursive or e.errno != errno.ENOENT:
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore raise
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore if recursive:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore (base, snapname) = dsname.split('@')
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore parent = Dataset(base)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore for child in parent.descendents():
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore try:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore yield Dataset(child.name + "@" +
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore snapname)
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore except zfs.util.ZFSError, e:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if e.errno != errno.ENOENT:
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore raise
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore