xref: /titanic_44/usr/src/lib/pyzfs/common/util.py (revision 6a634c9dca3093f3922e4b7ab826d7bdf17bf78e)
1*6d52f363SLori Alt#! /usr/bin/python2.6
214843421SMatthew Ahrens#
314843421SMatthew Ahrens# CDDL HEADER START
414843421SMatthew Ahrens#
514843421SMatthew Ahrens# The contents of this file are subject to the terms of the
614843421SMatthew Ahrens# Common Development and Distribution License (the "License").
714843421SMatthew Ahrens# You may not use this file except in compliance with the License.
814843421SMatthew Ahrens#
914843421SMatthew Ahrens# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1014843421SMatthew Ahrens# or http://www.opensolaris.org/os/licensing.
1114843421SMatthew Ahrens# See the License for the specific language governing permissions
1214843421SMatthew Ahrens# and limitations under the License.
1314843421SMatthew Ahrens#
1414843421SMatthew Ahrens# When distributing Covered Code, include this CDDL HEADER in each
1514843421SMatthew Ahrens# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1614843421SMatthew Ahrens# If applicable, add the following below this CDDL HEADER, with the
1714843421SMatthew Ahrens# fields enclosed by brackets "[]" replaced with your own identifying
1814843421SMatthew Ahrens# information: Portions Copyright [yyyy] [name of copyright owner]
1914843421SMatthew Ahrens#
2014843421SMatthew Ahrens# CDDL HEADER END
2114843421SMatthew Ahrens#
22*6d52f363SLori Alt# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2314843421SMatthew Ahrens#
2414843421SMatthew Ahrens
2514843421SMatthew Ahrens"""This module provides utility functions for ZFS.
2614843421SMatthew Ahrenszfs.util.dev -- a file object of /dev/zfs """
2714843421SMatthew Ahrens
2814843421SMatthew Ahrensimport gettext
2914843421SMatthew Ahrensimport errno
3014843421SMatthew Ahrensimport os
31e4d060fbSSam Falknerimport solaris.misc
3214843421SMatthew Ahrens# Note: this module (zfs.util) should not import zfs.ioctl, because that
3314843421SMatthew Ahrens# would introduce a circular dependency
3414843421SMatthew Ahrens
3514843421SMatthew Ahrenserrno.ECANCELED = 47
3614843421SMatthew Ahrenserrno.ENOTSUP = 48
3714843421SMatthew Ahrens
3814843421SMatthew Ahrensdev = open("/dev/zfs", "w")
3914843421SMatthew Ahrens
40e4d060fbSSam Falknertry:
4114843421SMatthew Ahrens	_ = gettext.translation("SUNW_OST_OSLIB", "/usr/lib/locale",
4214843421SMatthew Ahrens	    fallback=True).gettext
43e4d060fbSSam Falknerexcept:
44e4d060fbSSam Falkner	_ = solaris.misc.gettext
4514843421SMatthew Ahrens
4614843421SMatthew Ahrensdef default_repr(self):
4714843421SMatthew Ahrens	"""A simple __repr__ function."""
4814843421SMatthew Ahrens	if self.__slots__:
4914843421SMatthew Ahrens		str = "<" + self.__class__.__name__
5014843421SMatthew Ahrens		for v in self.__slots__:
5114843421SMatthew Ahrens			str += " %s: %r" % (v, getattr(self, v))
5214843421SMatthew Ahrens		return str + ">"
5314843421SMatthew Ahrens	else:
5414843421SMatthew Ahrens		return "<%s %s>" % \
5514843421SMatthew Ahrens		    (self.__class__.__name__, repr(self.__dict__))
5614843421SMatthew Ahrens
5714843421SMatthew Ahrensclass ZFSError(StandardError):
5814843421SMatthew Ahrens	"""This exception class represents a potentially user-visible
5914843421SMatthew Ahrens	ZFS error.  If uncaught, it will be printed and the process will
6014843421SMatthew Ahrens	exit with exit code 1.
6114843421SMatthew Ahrens
6214843421SMatthew Ahrens	errno -- the error number (eg, from ioctl(2))."""
6314843421SMatthew Ahrens
6414843421SMatthew Ahrens	__slots__ = "why", "task", "errno"
6514843421SMatthew Ahrens	__repr__ = default_repr
6614843421SMatthew Ahrens
6714843421SMatthew Ahrens	def __init__(self, eno, task=None, why=None):
6814843421SMatthew Ahrens		"""Create a ZFS exception.
6914843421SMatthew Ahrens		eno -- the error number (errno)
7014843421SMatthew Ahrens		task -- a string describing the task that failed
7114843421SMatthew Ahrens		why -- a string describing why it failed (defaults to
7214843421SMatthew Ahrens		    strerror(eno))"""
7314843421SMatthew Ahrens
7414843421SMatthew Ahrens		self.errno = eno
7514843421SMatthew Ahrens		self.task = task
7614843421SMatthew Ahrens		self.why = why
7714843421SMatthew Ahrens
7814843421SMatthew Ahrens	def __str__(self):
7914843421SMatthew Ahrens		s = ""
8014843421SMatthew Ahrens		if self.task:
8114843421SMatthew Ahrens			s += self.task + ": "
8214843421SMatthew Ahrens		if self.why:
8314843421SMatthew Ahrens			s += self.why
8414843421SMatthew Ahrens		else:
8514843421SMatthew Ahrens			s += self.strerror
8614843421SMatthew Ahrens		return s
8714843421SMatthew Ahrens
8814843421SMatthew Ahrens	__strs = {
8914843421SMatthew Ahrens		errno.EPERM: _("permission denied"),
9014843421SMatthew Ahrens		errno.ECANCELED:
9114843421SMatthew Ahrens		    _("delegated administration is disabled on pool"),
9214843421SMatthew Ahrens		errno.EINTR: _("signal received"),
9314843421SMatthew Ahrens		errno.EIO: _("I/O error"),
9414843421SMatthew Ahrens		errno.ENOENT: _("dataset does not exist"),
9514843421SMatthew Ahrens		errno.ENOSPC: _("out of space"),
9614843421SMatthew Ahrens		errno.EEXIST: _("dataset already exists"),
9714843421SMatthew Ahrens		errno.EBUSY: _("dataset is busy"),
9814843421SMatthew Ahrens		errno.EROFS:
9914843421SMatthew Ahrens		    _("snapshot permissions cannot be modified"),
10014843421SMatthew Ahrens		errno.ENAMETOOLONG: _("dataset name is too long"),
10114843421SMatthew Ahrens		errno.ENOTSUP: _("unsupported version"),
10214843421SMatthew Ahrens		errno.EAGAIN: _("pool I/O is currently suspended"),
10314843421SMatthew Ahrens	}
10414843421SMatthew Ahrens
10514843421SMatthew Ahrens	__strs[errno.EACCES] = __strs[errno.EPERM]
10614843421SMatthew Ahrens	__strs[errno.ENXIO] = __strs[errno.EIO]
10714843421SMatthew Ahrens	__strs[errno.ENODEV] = __strs[errno.EIO]
10814843421SMatthew Ahrens	__strs[errno.EDQUOT] = __strs[errno.ENOSPC]
10914843421SMatthew Ahrens
11014843421SMatthew Ahrens	@property
11114843421SMatthew Ahrens	def strerror(self):
11214843421SMatthew Ahrens		return ZFSError.__strs.get(self.errno, os.strerror(self.errno))
11314843421SMatthew Ahrens
11414843421SMatthew Ahrensdef nicenum(num):
11514843421SMatthew Ahrens	"""Return a nice string (eg "1.23M") for this integer."""
11614843421SMatthew Ahrens	index = 0;
11714843421SMatthew Ahrens	n = num;
11814843421SMatthew Ahrens
11914843421SMatthew Ahrens	while n >= 1024:
12014843421SMatthew Ahrens		n /= 1024
12114843421SMatthew Ahrens		index += 1
12214843421SMatthew Ahrens
12314843421SMatthew Ahrens	u = " KMGTPE"[index]
12414843421SMatthew Ahrens	if index == 0:
12514843421SMatthew Ahrens		return "%u" % n;
12614843421SMatthew Ahrens	elif n >= 100 or num & ((1024*index)-1) == 0:
12714843421SMatthew Ahrens		# it's an exact multiple of its index, or it wouldn't
12814843421SMatthew Ahrens		# fit as floating point, so print as an integer
12914843421SMatthew Ahrens		return "%u%c" % (n, u)
13014843421SMatthew Ahrens	else:
13114843421SMatthew Ahrens		# due to rounding, it's tricky to tell what precision to
13214843421SMatthew Ahrens		# use; try each precision and see which one fits
13314843421SMatthew Ahrens		for i in (2, 1, 0):
13414843421SMatthew Ahrens			s = "%.*f%c" % (i, float(num) / (1<<(10*index)), u)
13514843421SMatthew Ahrens			if len(s) <= 5:
13614843421SMatthew Ahrens				return s
13714843421SMatthew Ahrens
13814843421SMatthew Ahrensdef append_with_opt(option, opt, value, parser):
13914843421SMatthew Ahrens	"""A function for OptionParser which appends a tuple (opt, value)."""
14014843421SMatthew Ahrens	getattr(parser.values, option.dest).append((opt, value))
14114843421SMatthew Ahrens
142