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