xref: /illumos-gate/usr/src/lib/pyzfs/common/util.py (revision e8921a52)
19f923083SAlexander Pyhalov#!@PYTHON@
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#
226d52f363SLori Alt# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23*e8921a52SAndy Fiddaman# Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
2414843421SMatthew Ahrens#
2514843421SMatthew Ahrens
2614843421SMatthew Ahrens"""This module provides utility functions for ZFS.
2714843421SMatthew Ahrenszfs.util.dev -- a file object of /dev/zfs """
2814843421SMatthew Ahrens
2914843421SMatthew Ahrensimport gettext
3014843421SMatthew Ahrensimport errno
3114843421SMatthew Ahrensimport os
32e4d060fbSSam Falknerimport solaris.misc
3314843421SMatthew Ahrens# Note: this module (zfs.util) should not import zfs.ioctl, because that
3414843421SMatthew Ahrens# would introduce a circular dependency
3514843421SMatthew Ahrens
3614843421SMatthew Ahrenserrno.ECANCELED = 47
3714843421SMatthew Ahrenserrno.ENOTSUP = 48
3814843421SMatthew Ahrens
3914843421SMatthew Ahrensdev = open("/dev/zfs", "w")
4014843421SMatthew Ahrens
41e4d060fbSSam Falknertry:
42e4d060fbSSam Falkner	_ = gettext.translation("SUNW_OST_OSLIB", "/usr/lib/locale",
43e4d060fbSSam Falkner	    fallback=True).gettext
44e4d060fbSSam Falknerexcept:
45e4d060fbSSam Falkner	_ = solaris.misc.gettext
4614843421SMatthew Ahrens
4714843421SMatthew Ahrensdef default_repr(self):
4814843421SMatthew Ahrens	"""A simple __repr__ function."""
4914843421SMatthew Ahrens	if self.__slots__:
5014843421SMatthew Ahrens		str = "<" + self.__class__.__name__
5114843421SMatthew Ahrens		for v in self.__slots__:
5214843421SMatthew Ahrens			str += " %s: %r" % (v, getattr(self, v))
5314843421SMatthew Ahrens		return str + ">"
5414843421SMatthew Ahrens	else:
5514843421SMatthew Ahrens		return "<%s %s>" % \
5614843421SMatthew Ahrens		    (self.__class__.__name__, repr(self.__dict__))
5714843421SMatthew Ahrens
58*e8921a52SAndy Fiddamanclass ZFSError(Exception):
5914843421SMatthew Ahrens	"""This exception class represents a potentially user-visible
6014843421SMatthew Ahrens	ZFS error.  If uncaught, it will be printed and the process will
6114843421SMatthew Ahrens	exit with exit code 1.
62*e8921a52SAndy Fiddaman
6314843421SMatthew Ahrens	errno -- the error number (eg, from ioctl(2))."""
6414843421SMatthew Ahrens
6514843421SMatthew Ahrens	__slots__ = "why", "task", "errno"
6614843421SMatthew Ahrens	__repr__ = default_repr
6714843421SMatthew Ahrens
6814843421SMatthew Ahrens	def __init__(self, eno, task=None, why=None):
6914843421SMatthew Ahrens		"""Create a ZFS exception.
7014843421SMatthew Ahrens		eno -- the error number (errno)
7114843421SMatthew Ahrens		task -- a string describing the task that failed
7214843421SMatthew Ahrens		why -- a string describing why it failed (defaults to
7314843421SMatthew Ahrens		    strerror(eno))"""
7414843421SMatthew Ahrens
7514843421SMatthew Ahrens		self.errno = eno
7614843421SMatthew Ahrens		self.task = task
7714843421SMatthew Ahrens		self.why = why
7814843421SMatthew Ahrens
7914843421SMatthew Ahrens	def __str__(self):
8014843421SMatthew Ahrens		s = ""
8114843421SMatthew Ahrens		if self.task:
8214843421SMatthew Ahrens			s += self.task + ": "
8314843421SMatthew Ahrens		if self.why:
8414843421SMatthew Ahrens			s += self.why
8514843421SMatthew Ahrens		else:
8614843421SMatthew Ahrens			s += self.strerror
8714843421SMatthew Ahrens		return s
8814843421SMatthew Ahrens
8914843421SMatthew Ahrens	__strs = {
9014843421SMatthew Ahrens		errno.EPERM: _("permission denied"),
9114843421SMatthew Ahrens		errno.ECANCELED:
9214843421SMatthew Ahrens		    _("delegated administration is disabled on pool"),
9314843421SMatthew Ahrens		errno.EINTR: _("signal received"),
9414843421SMatthew Ahrens		errno.EIO: _("I/O error"),
9514843421SMatthew Ahrens		errno.ENOENT: _("dataset does not exist"),
9614843421SMatthew Ahrens		errno.ENOSPC: _("out of space"),
9714843421SMatthew Ahrens		errno.EEXIST: _("dataset already exists"),
9814843421SMatthew Ahrens		errno.EBUSY: _("dataset is busy"),
9914843421SMatthew Ahrens		errno.EROFS:
10014843421SMatthew Ahrens		    _("snapshot permissions cannot be modified"),
10114843421SMatthew Ahrens		errno.ENAMETOOLONG: _("dataset name is too long"),
10214843421SMatthew Ahrens		errno.ENOTSUP: _("unsupported version"),
10314843421SMatthew Ahrens		errno.EAGAIN: _("pool I/O is currently suspended"),
10414843421SMatthew Ahrens	}
10514843421SMatthew Ahrens
10614843421SMatthew Ahrens	__strs[errno.EACCES] = __strs[errno.EPERM]
10714843421SMatthew Ahrens	__strs[errno.ENXIO] = __strs[errno.EIO]
10814843421SMatthew Ahrens	__strs[errno.ENODEV] = __strs[errno.EIO]
10914843421SMatthew Ahrens	__strs[errno.EDQUOT] = __strs[errno.ENOSPC]
11014843421SMatthew Ahrens
11114843421SMatthew Ahrens	@property
11214843421SMatthew Ahrens	def strerror(self):
11314843421SMatthew Ahrens		return ZFSError.__strs.get(self.errno, os.strerror(self.errno))
11414843421SMatthew Ahrens
11514843421SMatthew Ahrensdef nicenum(num):
11614843421SMatthew Ahrens	"""Return a nice string (eg "1.23M") for this integer."""
11714843421SMatthew Ahrens	index = 0;
11814843421SMatthew Ahrens	n = num;
11914843421SMatthew Ahrens
12014843421SMatthew Ahrens	while n >= 1024:
12114843421SMatthew Ahrens		n /= 1024
12214843421SMatthew Ahrens		index += 1
12314843421SMatthew Ahrens
12414843421SMatthew Ahrens	u = " KMGTPE"[index]
12514843421SMatthew Ahrens	if index == 0:
12614843421SMatthew Ahrens		return "%u" % n;
12714843421SMatthew Ahrens	elif n >= 100 or num & ((1024*index)-1) == 0:
12814843421SMatthew Ahrens		# it's an exact multiple of its index, or it wouldn't
12914843421SMatthew Ahrens		# fit as floating point, so print as an integer
13014843421SMatthew Ahrens		return "%u%c" % (n, u)
13114843421SMatthew Ahrens	else:
13214843421SMatthew Ahrens		# due to rounding, it's tricky to tell what precision to
13314843421SMatthew Ahrens		# use; try each precision and see which one fits
13414843421SMatthew Ahrens		for i in (2, 1, 0):
13514843421SMatthew Ahrens			s = "%.*f%c" % (i, float(num) / (1<<(10*index)), u)
13614843421SMatthew Ahrens			if len(s) <= 5:
13714843421SMatthew Ahrens				return s
13814843421SMatthew Ahrens
13914843421SMatthew Ahrensdef append_with_opt(option, opt, value, parser):
14014843421SMatthew Ahrens	"""A function for OptionParser which appends a tuple (opt, value)."""
14114843421SMatthew Ahrens	getattr(parser.values, option.dest).append((opt, value))
14214843421SMatthew Ahrens
143