util.py revision 209962
1209962Smm#! /usr/bin/python2.4 2209962Smm# 3209962Smm# CDDL HEADER START 4209962Smm# 5209962Smm# The contents of this file are subject to the terms of the 6209962Smm# Common Development and Distribution License (the "License"). 7209962Smm# You may not use this file except in compliance with the License. 8209962Smm# 9209962Smm# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10209962Smm# or http://www.opensolaris.org/os/licensing. 11209962Smm# See the License for the specific language governing permissions 12209962Smm# and limitations under the License. 13209962Smm# 14209962Smm# When distributing Covered Code, include this CDDL HEADER in each 15209962Smm# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16209962Smm# If applicable, add the following below this CDDL HEADER, with the 17209962Smm# fields enclosed by brackets "[]" replaced with your own identifying 18209962Smm# information: Portions Copyright [yyyy] [name of copyright owner] 19209962Smm# 20209962Smm# CDDL HEADER END 21209962Smm# 22209962Smm# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23209962Smm# Use is subject to license terms. 24209962Smm# 25209962Smm 26209962Smm"""This module provides utility functions for ZFS. 27209962Smmzfs.util.dev -- a file object of /dev/zfs """ 28209962Smm 29209962Smmimport gettext 30209962Smmimport errno 31209962Smmimport os 32209962Smm# Note: this module (zfs.util) should not import zfs.ioctl, because that 33209962Smm# would introduce a circular dependency 34209962Smm 35209962Smmerrno.ECANCELED = 47 36209962Smmerrno.ENOTSUP = 48 37209962Smm 38209962Smmdev = open("/dev/zfs", "w") 39209962Smm 40209962Smm_ = gettext.translation("SUNW_OST_OSLIB", "/usr/lib/locale", 41209962Smm fallback=True).gettext 42209962Smm 43209962Smmdef default_repr(self): 44209962Smm """A simple __repr__ function.""" 45209962Smm if self.__slots__: 46209962Smm str = "<" + self.__class__.__name__ 47209962Smm for v in self.__slots__: 48209962Smm str += " %s: %r" % (v, getattr(self, v)) 49209962Smm return str + ">" 50209962Smm else: 51209962Smm return "<%s %s>" % \ 52209962Smm (self.__class__.__name__, repr(self.__dict__)) 53209962Smm 54209962Smmclass ZFSError(StandardError): 55209962Smm """This exception class represents a potentially user-visible 56209962Smm ZFS error. If uncaught, it will be printed and the process will 57209962Smm exit with exit code 1. 58209962Smm 59209962Smm errno -- the error number (eg, from ioctl(2)).""" 60209962Smm 61209962Smm __slots__ = "why", "task", "errno" 62209962Smm __repr__ = default_repr 63209962Smm 64209962Smm def __init__(self, eno, task=None, why=None): 65209962Smm """Create a ZFS exception. 66209962Smm eno -- the error number (errno) 67209962Smm task -- a string describing the task that failed 68209962Smm why -- a string describing why it failed (defaults to 69209962Smm strerror(eno))""" 70209962Smm 71209962Smm self.errno = eno 72209962Smm self.task = task 73209962Smm self.why = why 74209962Smm 75209962Smm def __str__(self): 76209962Smm s = "" 77209962Smm if self.task: 78209962Smm s += self.task + ": " 79209962Smm if self.why: 80209962Smm s += self.why 81209962Smm else: 82209962Smm s += self.strerror 83209962Smm return s 84209962Smm 85209962Smm __strs = { 86209962Smm errno.EPERM: _("permission denied"), 87209962Smm errno.ECANCELED: 88209962Smm _("delegated administration is disabled on pool"), 89209962Smm errno.EINTR: _("signal received"), 90209962Smm errno.EIO: _("I/O error"), 91209962Smm errno.ENOENT: _("dataset does not exist"), 92209962Smm errno.ENOSPC: _("out of space"), 93209962Smm errno.EEXIST: _("dataset already exists"), 94209962Smm errno.EBUSY: _("dataset is busy"), 95209962Smm errno.EROFS: 96209962Smm _("snapshot permissions cannot be modified"), 97209962Smm errno.ENAMETOOLONG: _("dataset name is too long"), 98209962Smm errno.ENOTSUP: _("unsupported version"), 99209962Smm errno.EAGAIN: _("pool I/O is currently suspended"), 100209962Smm } 101209962Smm 102209962Smm __strs[errno.EACCES] = __strs[errno.EPERM] 103209962Smm __strs[errno.ENXIO] = __strs[errno.EIO] 104209962Smm __strs[errno.ENODEV] = __strs[errno.EIO] 105209962Smm __strs[errno.EDQUOT] = __strs[errno.ENOSPC] 106209962Smm 107209962Smm @property 108209962Smm def strerror(self): 109209962Smm return ZFSError.__strs.get(self.errno, os.strerror(self.errno)) 110209962Smm 111209962Smmdef nicenum(num): 112209962Smm """Return a nice string (eg "1.23M") for this integer.""" 113209962Smm index = 0; 114209962Smm n = num; 115209962Smm 116209962Smm while n >= 1024: 117209962Smm n /= 1024 118209962Smm index += 1 119209962Smm 120209962Smm u = " KMGTPE"[index] 121209962Smm if index == 0: 122209962Smm return "%u" % n; 123209962Smm elif n >= 100 or num & ((1024*index)-1) == 0: 124209962Smm # it's an exact multiple of its index, or it wouldn't 125209962Smm # fit as floating point, so print as an integer 126209962Smm return "%u%c" % (n, u) 127209962Smm else: 128209962Smm # due to rounding, it's tricky to tell what precision to 129209962Smm # use; try each precision and see which one fits 130209962Smm for i in (2, 1, 0): 131209962Smm s = "%.*f%c" % (i, float(num) / (1<<(10*index)), u) 132209962Smm if len(s) <= 5: 133209962Smm return s 134209962Smm 135209962Smmdef append_with_opt(option, opt, value, parser): 136209962Smm """A function for OptionParser which appends a tuple (opt, value).""" 137209962Smm getattr(parser.values, option.dest).append((opt, value)) 138209962Smm 139