1219089Spjd#! /usr/bin/python2.6 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# 22219089Spjd# Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 23209962Smm# 24209962Smm 25209962Smm"""This module provides utility functions for ZFS. 26209962Smmzfs.util.dev -- a file object of /dev/zfs """ 27209962Smm 28209962Smmimport gettext 29209962Smmimport errno 30209962Smmimport os 31219089Spjdimport solaris.misc 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 40219089Spjdtry: 41219089Spjd _ = gettext.translation("SUNW_OST_OSLIB", "/usr/lib/locale", 42219089Spjd fallback=True).gettext 43219089Spjdexcept: 44219089Spjd _ = solaris.misc.gettext 45209962Smm 46209962Smmdef default_repr(self): 47209962Smm """A simple __repr__ function.""" 48209962Smm if self.__slots__: 49209962Smm str = "<" + self.__class__.__name__ 50209962Smm for v in self.__slots__: 51209962Smm str += " %s: %r" % (v, getattr(self, v)) 52209962Smm return str + ">" 53209962Smm else: 54209962Smm return "<%s %s>" % \ 55209962Smm (self.__class__.__name__, repr(self.__dict__)) 56209962Smm 57209962Smmclass ZFSError(StandardError): 58209962Smm """This exception class represents a potentially user-visible 59209962Smm ZFS error. If uncaught, it will be printed and the process will 60209962Smm exit with exit code 1. 61209962Smm 62209962Smm errno -- the error number (eg, from ioctl(2)).""" 63209962Smm 64209962Smm __slots__ = "why", "task", "errno" 65209962Smm __repr__ = default_repr 66209962Smm 67209962Smm def __init__(self, eno, task=None, why=None): 68209962Smm """Create a ZFS exception. 69209962Smm eno -- the error number (errno) 70209962Smm task -- a string describing the task that failed 71209962Smm why -- a string describing why it failed (defaults to 72209962Smm strerror(eno))""" 73209962Smm 74209962Smm self.errno = eno 75209962Smm self.task = task 76209962Smm self.why = why 77209962Smm 78209962Smm def __str__(self): 79209962Smm s = "" 80209962Smm if self.task: 81209962Smm s += self.task + ": " 82209962Smm if self.why: 83209962Smm s += self.why 84209962Smm else: 85209962Smm s += self.strerror 86209962Smm return s 87209962Smm 88209962Smm __strs = { 89209962Smm errno.EPERM: _("permission denied"), 90209962Smm errno.ECANCELED: 91209962Smm _("delegated administration is disabled on pool"), 92209962Smm errno.EINTR: _("signal received"), 93209962Smm errno.EIO: _("I/O error"), 94209962Smm errno.ENOENT: _("dataset does not exist"), 95209962Smm errno.ENOSPC: _("out of space"), 96209962Smm errno.EEXIST: _("dataset already exists"), 97209962Smm errno.EBUSY: _("dataset is busy"), 98209962Smm errno.EROFS: 99209962Smm _("snapshot permissions cannot be modified"), 100209962Smm errno.ENAMETOOLONG: _("dataset name is too long"), 101209962Smm errno.ENOTSUP: _("unsupported version"), 102209962Smm errno.EAGAIN: _("pool I/O is currently suspended"), 103209962Smm } 104209962Smm 105209962Smm __strs[errno.EACCES] = __strs[errno.EPERM] 106209962Smm __strs[errno.ENXIO] = __strs[errno.EIO] 107209962Smm __strs[errno.ENODEV] = __strs[errno.EIO] 108209962Smm __strs[errno.EDQUOT] = __strs[errno.ENOSPC] 109209962Smm 110209962Smm @property 111209962Smm def strerror(self): 112209962Smm return ZFSError.__strs.get(self.errno, os.strerror(self.errno)) 113209962Smm 114209962Smmdef nicenum(num): 115209962Smm """Return a nice string (eg "1.23M") for this integer.""" 116209962Smm index = 0; 117209962Smm n = num; 118209962Smm 119209962Smm while n >= 1024: 120209962Smm n /= 1024 121209962Smm index += 1 122209962Smm 123209962Smm u = " KMGTPE"[index] 124209962Smm if index == 0: 125209962Smm return "%u" % n; 126209962Smm elif n >= 100 or num & ((1024*index)-1) == 0: 127209962Smm # it's an exact multiple of its index, or it wouldn't 128209962Smm # fit as floating point, so print as an integer 129209962Smm return "%u%c" % (n, u) 130209962Smm else: 131209962Smm # due to rounding, it's tricky to tell what precision to 132209962Smm # use; try each precision and see which one fits 133209962Smm for i in (2, 1, 0): 134209962Smm s = "%.*f%c" % (i, float(num) / (1<<(10*index)), u) 135209962Smm if len(s) <= 5: 136209962Smm return s 137209962Smm 138209962Smmdef append_with_opt(option, opt, value, parser): 139209962Smm """A function for OptionParser which appends a tuple (opt, value).""" 140209962Smm getattr(parser.values, option.dest).append((opt, value)) 141209962Smm 142