xref: /titanic_51/usr/src/lib/pyzfs/common/dataset.py (revision 148434217c040ea38dc844384f6ba68d9b325906)
1*14843421SMatthew Ahrens#! /usr/bin/python2.4
2*14843421SMatthew Ahrens#
3*14843421SMatthew Ahrens# CDDL HEADER START
4*14843421SMatthew Ahrens#
5*14843421SMatthew Ahrens# The contents of this file are subject to the terms of the
6*14843421SMatthew Ahrens# Common Development and Distribution License (the "License").
7*14843421SMatthew Ahrens# You may not use this file except in compliance with the License.
8*14843421SMatthew Ahrens#
9*14843421SMatthew Ahrens# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*14843421SMatthew Ahrens# or http://www.opensolaris.org/os/licensing.
11*14843421SMatthew Ahrens# See the License for the specific language governing permissions
12*14843421SMatthew Ahrens# and limitations under the License.
13*14843421SMatthew Ahrens#
14*14843421SMatthew Ahrens# When distributing Covered Code, include this CDDL HEADER in each
15*14843421SMatthew Ahrens# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*14843421SMatthew Ahrens# If applicable, add the following below this CDDL HEADER, with the
17*14843421SMatthew Ahrens# fields enclosed by brackets "[]" replaced with your own identifying
18*14843421SMatthew Ahrens# information: Portions Copyright [yyyy] [name of copyright owner]
19*14843421SMatthew Ahrens#
20*14843421SMatthew Ahrens# CDDL HEADER END
21*14843421SMatthew Ahrens#
22*14843421SMatthew Ahrens# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*14843421SMatthew Ahrens# Use is subject to license terms.
24*14843421SMatthew Ahrens#
25*14843421SMatthew Ahrens
26*14843421SMatthew Ahrens"""Implements the Dataset class, providing methods for manipulating ZFS
27*14843421SMatthew Ahrensdatasets.  Also implements the Property class, which describes ZFS
28*14843421SMatthew Ahrensproperties."""
29*14843421SMatthew Ahrens
30*14843421SMatthew Ahrensimport zfs.ioctl
31*14843421SMatthew Ahrensimport zfs.util
32*14843421SMatthew Ahrensimport errno
33*14843421SMatthew Ahrens
34*14843421SMatthew Ahrens_ = zfs.util._
35*14843421SMatthew Ahrens
36*14843421SMatthew Ahrensclass Property(object):
37*14843421SMatthew Ahrens	"""This class represents a ZFS property.  It contains
38*14843421SMatthew Ahrens	information about the property -- if it's readonly, a number vs
39*14843421SMatthew Ahrens	string vs index, etc.  Only native properties are represented by
40*14843421SMatthew Ahrens	this class -- not user properties (eg "user:prop") or userspace
41*14843421SMatthew Ahrens	properties (eg "userquota@joe")."""
42*14843421SMatthew Ahrens
43*14843421SMatthew Ahrens	__slots__ = "name", "number", "type", "default", "attr", "validtypes", \
44*14843421SMatthew Ahrens	    "values", "colname", "rightalign", "visible", "indextable"
45*14843421SMatthew Ahrens	__repr__ = zfs.util.default_repr
46*14843421SMatthew Ahrens
47*14843421SMatthew Ahrens	def __init__(self, t):
48*14843421SMatthew Ahrens		"""t is the tuple of information about this property
49*14843421SMatthew Ahrens		from zfs.ioctl.get_proptable, which should match the
50*14843421SMatthew Ahrens		members of zprop_desc_t (see zfs_prop.h)."""
51*14843421SMatthew Ahrens
52*14843421SMatthew Ahrens		self.name = t[0]
53*14843421SMatthew Ahrens		self.number = t[1]
54*14843421SMatthew Ahrens		self.type = t[2]
55*14843421SMatthew Ahrens		if self.type == "string":
56*14843421SMatthew Ahrens			self.default = t[3]
57*14843421SMatthew Ahrens		else:
58*14843421SMatthew Ahrens			self.default = t[4]
59*14843421SMatthew Ahrens		self.attr = t[5]
60*14843421SMatthew Ahrens		self.validtypes = t[6]
61*14843421SMatthew Ahrens		self.values = t[7]
62*14843421SMatthew Ahrens		self.colname = t[8]
63*14843421SMatthew Ahrens		self.rightalign = t[9]
64*14843421SMatthew Ahrens		self.visible = t[10]
65*14843421SMatthew Ahrens		self.indextable = t[11]
66*14843421SMatthew Ahrens
67*14843421SMatthew Ahrens	def delegatable(self):
68*14843421SMatthew Ahrens		"""Return True if this property can be delegated with
69*14843421SMatthew Ahrens		"zfs allow"."""
70*14843421SMatthew Ahrens		return self.attr != "readonly"
71*14843421SMatthew Ahrens
72*14843421SMatthew Ahrensproptable = dict()
73*14843421SMatthew Ahrensfor name, t in zfs.ioctl.get_proptable().iteritems():
74*14843421SMatthew Ahrens	proptable[name] = Property(t)
75*14843421SMatthew Ahrensdel name, t
76*14843421SMatthew Ahrens
77*14843421SMatthew Ahrensdef getpropobj(name):
78*14843421SMatthew Ahrens	"""Return the Property object that is identified by the given
79*14843421SMatthew Ahrens	name string.  It can be the full name, or the column name."""
80*14843421SMatthew Ahrens	try:
81*14843421SMatthew Ahrens		return proptable[name]
82*14843421SMatthew Ahrens	except KeyError:
83*14843421SMatthew Ahrens		for p in proptable.itervalues():
84*14843421SMatthew Ahrens			if p.colname and p.colname.lower() == name:
85*14843421SMatthew Ahrens				return p
86*14843421SMatthew Ahrens		raise
87*14843421SMatthew Ahrens
88*14843421SMatthew Ahrensclass Dataset(object):
89*14843421SMatthew Ahrens	"""Represents a ZFS dataset (filesystem, snapshot, zvol, clone, etc).
90*14843421SMatthew Ahrens
91*14843421SMatthew Ahrens	Generally, this class provides interfaces to the C functions in
92*14843421SMatthew Ahrens	zfs.ioctl which actually interface with the kernel to manipulate
93*14843421SMatthew Ahrens	datasets.
94*14843421SMatthew Ahrens
95*14843421SMatthew Ahrens	Unless otherwise noted, any method can raise a ZFSError to
96*14843421SMatthew Ahrens	indicate failure."""
97*14843421SMatthew Ahrens
98*14843421SMatthew Ahrens	__slots__ = "name", "__props"
99*14843421SMatthew Ahrens	__repr__ = zfs.util.default_repr
100*14843421SMatthew Ahrens
101*14843421SMatthew Ahrens	def __init__(self, name, props=None,
102*14843421SMatthew Ahrens	    types=("filesystem", "volume"), snaps=True):
103*14843421SMatthew Ahrens		"""Open the named dataset, checking that it exists and
104*14843421SMatthew Ahrens		is of the specified type.
105*14843421SMatthew Ahrens
106*14843421SMatthew Ahrens		name is the string name of this dataset.
107*14843421SMatthew Ahrens
108*14843421SMatthew Ahrens		props is the property settings dict from zfs.ioctl.next_dataset.
109*14843421SMatthew Ahrens
110*14843421SMatthew Ahrens		types is an iterable of strings specifying which types
111*14843421SMatthew Ahrens		of datasets are permitted.  Accepted strings are
112*14843421SMatthew Ahrens		"filesystem" and "volume".  Defaults to acceptying all
113*14843421SMatthew Ahrens		types.
114*14843421SMatthew Ahrens
115*14843421SMatthew Ahrens		snaps is a boolean specifying if snapshots are acceptable.
116*14843421SMatthew Ahrens
117*14843421SMatthew Ahrens		Raises a ZFSError if the dataset can't be accessed (eg
118*14843421SMatthew Ahrens		doesn't exist) or is not of the specified type.
119*14843421SMatthew Ahrens		"""
120*14843421SMatthew Ahrens
121*14843421SMatthew Ahrens		self.name = name
122*14843421SMatthew Ahrens
123*14843421SMatthew Ahrens		e = zfs.util.ZFSError(errno.EINVAL,
124*14843421SMatthew Ahrens		    _("cannot open %s") % name,
125*14843421SMatthew Ahrens		    _("operation not applicable to datasets of this type"))
126*14843421SMatthew Ahrens		if "@" in name and not snaps:
127*14843421SMatthew Ahrens			raise e
128*14843421SMatthew Ahrens		if not props:
129*14843421SMatthew Ahrens			props = zfs.ioctl.dataset_props(name)
130*14843421SMatthew Ahrens		self.__props = props
131*14843421SMatthew Ahrens		if "volume" not in types and self.getprop("type") == 3:
132*14843421SMatthew Ahrens			raise e
133*14843421SMatthew Ahrens		if "filesystem" not in types and self.getprop("type") == 2:
134*14843421SMatthew Ahrens			raise e
135*14843421SMatthew Ahrens
136*14843421SMatthew Ahrens	def getprop(self, propname):
137*14843421SMatthew Ahrens		"""Return the value of the given property for this dataset.
138*14843421SMatthew Ahrens
139*14843421SMatthew Ahrens		Currently only works for native properties (those with a
140*14843421SMatthew Ahrens		Property object.)
141*14843421SMatthew Ahrens
142*14843421SMatthew Ahrens		Raises KeyError if propname does not specify a native property.
143*14843421SMatthew Ahrens		Does not raise ZFSError.
144*14843421SMatthew Ahrens		"""
145*14843421SMatthew Ahrens
146*14843421SMatthew Ahrens		p = getpropobj(propname)
147*14843421SMatthew Ahrens		try:
148*14843421SMatthew Ahrens			return self.__props[p.name]["value"]
149*14843421SMatthew Ahrens		except KeyError:
150*14843421SMatthew Ahrens			return p.default
151*14843421SMatthew Ahrens
152*14843421SMatthew Ahrens	def parent(self):
153*14843421SMatthew Ahrens		"""Return a Dataset representing the parent of this one."""
154*14843421SMatthew Ahrens		return Dataset(self.name[:self.name.rindex("/")])
155*14843421SMatthew Ahrens
156*14843421SMatthew Ahrens	def descendents(self):
157*14843421SMatthew Ahrens		"""A generator function which iterates over all
158*14843421SMatthew Ahrens		descendent Datasets (not including snapshots."""
159*14843421SMatthew Ahrens
160*14843421SMatthew Ahrens		cookie = 0
161*14843421SMatthew Ahrens		while True:
162*14843421SMatthew Ahrens			# next_dataset raises StopIteration when done
163*14843421SMatthew Ahrens			(name, cookie, props) = \
164*14843421SMatthew Ahrens			    zfs.ioctl.next_dataset(self.name, False, cookie)
165*14843421SMatthew Ahrens			ds = Dataset(name, props)
166*14843421SMatthew Ahrens			yield ds
167*14843421SMatthew Ahrens			for child in ds.descendents():
168*14843421SMatthew Ahrens				yield child
169*14843421SMatthew Ahrens
170*14843421SMatthew Ahrens	def userspace(self, prop):
171*14843421SMatthew Ahrens		"""A generator function which iterates over a
172*14843421SMatthew Ahrens		userspace-type property.
173*14843421SMatthew Ahrens
174*14843421SMatthew Ahrens		prop specifies which property ("userused@",
175*14843421SMatthew Ahrens		"userquota@", "groupused@", or "groupquota@").
176*14843421SMatthew Ahrens
177*14843421SMatthew Ahrens		returns 3-tuple of domain (string), rid (int), and space (int).
178*14843421SMatthew Ahrens		"""
179*14843421SMatthew Ahrens
180*14843421SMatthew Ahrens		d = zfs.ioctl.userspace_many(self.name, prop)
181*14843421SMatthew Ahrens		for ((domain, rid), space) in d.iteritems():
182*14843421SMatthew Ahrens			yield (domain, rid, space)
183*14843421SMatthew Ahrens
184*14843421SMatthew Ahrens	def userspace_upgrade(self):
185*14843421SMatthew Ahrens		"""Initialize the accounting information for
186*14843421SMatthew Ahrens		userused@... and groupused@... properties."""
187*14843421SMatthew Ahrens		return zfs.ioctl.userspace_upgrade(self.name)
188*14843421SMatthew Ahrens
189*14843421SMatthew Ahrens	def set_fsacl(self, un, d):
190*14843421SMatthew Ahrens		"""Add to the "zfs allow"-ed permissions on this Dataset.
191*14843421SMatthew Ahrens
192*14843421SMatthew Ahrens		un is True if the specified permissions should be removed.
193*14843421SMatthew Ahrens
194*14843421SMatthew Ahrens		d is a dict specifying which permissions to add/remove:
195*14843421SMatthew Ahrens		{ "whostr" -> None # remove all perms for this entity
196*14843421SMatthew Ahrens		  "whostr" -> { "perm" -> None} # add/remove these perms
197*14843421SMatthew Ahrens		} """
198*14843421SMatthew Ahrens		return zfs.ioctl.set_fsacl(self.name, un, d)
199*14843421SMatthew Ahrens
200*14843421SMatthew Ahrens	def get_fsacl(self):
201*14843421SMatthew Ahrens		"""Get the "zfs allow"-ed permissions on the Dataset.
202*14843421SMatthew Ahrens
203*14843421SMatthew Ahrens		Return a dict("whostr": { "perm" -> None })."""
204*14843421SMatthew Ahrens
205*14843421SMatthew Ahrens		return zfs.ioctl.get_fsacl(self.name)
206