114843421SMatthew Ahrens#! /usr/bin/python2.4 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*e4d060fbSSam Falkner# Copyright 2010 Sun Microsystems, Inc. All rights reserved. 2314843421SMatthew Ahrens# Use is subject to license terms. 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 32*e4d060fbSSam 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 41*e4d060fbSSam Falknertry: 4214843421SMatthew Ahrens _ = gettext.translation("SUNW_OST_OSLIB", "/usr/lib/locale", 4314843421SMatthew Ahrens fallback=True).gettext 44*e4d060fbSSam Falknerexcept: 45*e4d060fbSSam 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 5814843421SMatthew Ahrensclass ZFSError(StandardError): 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. 6214843421SMatthew Ahrens 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