5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
22 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 # Use is subject to license terms.
26 """Implements the Dataset class, providing methods for manipulating ZFS
27 datasets. Also implements the Property class, which describes ZFS
36 class Property(object):
37 """This class represents a ZFS property. It contains
38 information about the property -- if it's readonly, a number vs
39 string vs index, etc. Only native properties are represented by
40 this class -- not user properties (eg "user:prop") or userspace
41 properties (eg "userquota@joe")."""
43 __slots__ = "name", "number", "type", "default", "attr", "validtypes", \
44 "values", "colname", "rightalign", "visible", "indextable"
45 __repr__ = zfs.util.default_repr
47 def __init__(self, t):
48 """t is the tuple of information about this property
49 from zfs.ioctl.get_proptable, which should match the
50 members of zprop_desc_t (see zfs_prop.h)."""
55 if self.type == "string":
60 self.validtypes = t[6]
63 self.rightalign = t[9]
65 self.indextable = t[11]
67 def delegatable(self):
68 """Return True if this property can be delegated with
70 return self.attr != "readonly"
73 for name, t in zfs.ioctl.get_proptable().iteritems():
74 proptable[name] = Property(t)
78 """Return the Property object that is identified by the given
79 name string. It can be the full name, or the column name."""
81 return proptable[name]
83 for p in proptable.itervalues():
84 if p.colname and p.colname.lower() == name:
88 class Dataset(object):
89 """Represents a ZFS dataset (filesystem, snapshot, zvol, clone, etc).
91 Generally, this class provides interfaces to the C functions in
92 zfs.ioctl which actually interface with the kernel to manipulate
95 Unless otherwise noted, any method can raise a ZFSError to
98 __slots__ = "name", "__props"
99 __repr__ = zfs.util.default_repr
101 def __init__(self, name, props=None,
102 types=("filesystem", "volume"), snaps=True):
103 """Open the named dataset, checking that it exists and
104 is of the specified type.
106 name is the string name of this dataset.
108 props is the property settings dict from zfs.ioctl.next_dataset.
110 types is an iterable of strings specifying which types
111 of datasets are permitted. Accepted strings are
112 "filesystem" and "volume". Defaults to acceptying all
115 snaps is a boolean specifying if snapshots are acceptable.
117 Raises a ZFSError if the dataset can't be accessed (eg
118 doesn't exist) or is not of the specified type.
123 e = zfs.util.ZFSError(errno.EINVAL,
124 _("cannot open %s") % name,
125 _("operation not applicable to datasets of this type"))
126 if "@" in name and not snaps:
129 props = zfs.ioctl.dataset_props(name)
131 if "volume" not in types and self.getprop("type") == 3:
133 if "filesystem" not in types and self.getprop("type") == 2:
136 def getprop(self, propname):
137 """Return the value of the given property for this dataset.
139 Currently only works for native properties (those with a
142 Raises KeyError if propname does not specify a native property.
143 Does not raise ZFSError.
146 p = getpropobj(propname)
148 return self.__props[p.name]["value"]
153 """Return a Dataset representing the parent of this one."""
154 return Dataset(self.name[:self.name.rindex("/")])
156 def descendents(self):
157 """A generator function which iterates over all
158 descendent Datasets (not including snapshots."""
162 # next_dataset raises StopIteration when done
163 (name, cookie, props) = \
164 zfs.ioctl.next_dataset(self.name, False, cookie)
165 ds = Dataset(name, props)
167 for child in ds.descendents():
170 def userspace(self, prop):
171 """A generator function which iterates over a
172 userspace-type property.
174 prop specifies which property ("userused@",
175 "userquota@", "groupused@", or "groupquota@").
177 returns 3-tuple of domain (string), rid (int), and space (int).
180 d = zfs.ioctl.userspace_many(self.name, prop)
181 for ((domain, rid), space) in d.iteritems():
182 yield (domain, rid, space)
184 def userspace_upgrade(self):
185 """Initialize the accounting information for
186 userused@... and groupused@... properties."""
187 return zfs.ioctl.userspace_upgrade(self.name)
189 def set_fsacl(self, un, d):
190 """Add to the "zfs allow"-ed permissions on this Dataset.
192 un is True if the specified permissions should be removed.
194 d is a dict specifying which permissions to add/remove:
195 { "whostr" -> None # remove all perms for this entity
196 "whostr" -> { "perm" -> None} # add/remove these perms
198 return zfs.ioctl.set_fsacl(self.name, un, d)
201 """Get the "zfs allow"-ed permissions on the Dataset.
203 Return a dict("whostr": { "perm" -> None })."""
205 return zfs.ioctl.get_fsacl(self.name)