|
1 #! /usr/bin/python2.4 |
|
2 # |
|
3 # CDDL HEADER START |
|
4 # |
|
5 # The contents of this file are subject to the terms of the |
|
6 # Common Development and Distribution License (the "License"). |
|
7 # You may not use this file except in compliance with the License. |
|
8 # |
|
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
10 # or http://www.opensolaris.org/os/licensing. |
|
11 # See the License for the specific language governing permissions |
|
12 # and limitations under the License. |
|
13 # |
|
14 # When distributing Covered Code, include this CDDL HEADER in each |
|
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
16 # If applicable, add the following below this CDDL HEADER, with the |
|
17 # fields enclosed by brackets "[]" replaced with your own identifying |
|
18 # information: Portions Copyright [yyyy] [name of copyright owner] |
|
19 # |
|
20 # CDDL HEADER END |
|
21 # |
|
22 # Copyright 2009 Sun Microsystems, Inc. All rights reserved. |
|
23 # Use is subject to license terms. |
|
24 # |
|
25 |
|
26 """This module provides utility functions for ZFS. |
|
27 zfs.util.dev -- a file object of /dev/zfs """ |
|
28 |
|
29 import gettext |
|
30 import errno |
|
31 import os |
|
32 # Note: this module (zfs.util) should not import zfs.ioctl, because that |
|
33 # would introduce a circular dependency |
|
34 |
|
35 errno.ECANCELED = 47 |
|
36 errno.ENOTSUP = 48 |
|
37 |
|
38 dev = open("/dev/zfs", "w") |
|
39 |
|
40 _ = gettext.translation("SUNW_OST_OSLIB", "/usr/lib/locale", |
|
41 fallback=True).gettext |
|
42 |
|
43 def default_repr(self): |
|
44 """A simple __repr__ function.""" |
|
45 if self.__slots__: |
|
46 str = "<" + self.__class__.__name__ |
|
47 for v in self.__slots__: |
|
48 str += " %s: %r" % (v, getattr(self, v)) |
|
49 return str + ">" |
|
50 else: |
|
51 return "<%s %s>" % \ |
|
52 (self.__class__.__name__, repr(self.__dict__)) |
|
53 |
|
54 class ZFSError(StandardError): |
|
55 """This exception class represents a potentially user-visible |
|
56 ZFS error. If uncaught, it will be printed and the process will |
|
57 exit with exit code 1. |
|
58 |
|
59 errno -- the error number (eg, from ioctl(2)).""" |
|
60 |
|
61 __slots__ = "why", "task", "errno" |
|
62 __repr__ = default_repr |
|
63 |
|
64 def __init__(self, eno, task=None, why=None): |
|
65 """Create a ZFS exception. |
|
66 eno -- the error number (errno) |
|
67 task -- a string describing the task that failed |
|
68 why -- a string describing why it failed (defaults to |
|
69 strerror(eno))""" |
|
70 |
|
71 self.errno = eno |
|
72 self.task = task |
|
73 self.why = why |
|
74 |
|
75 def __str__(self): |
|
76 s = "" |
|
77 if self.task: |
|
78 s += self.task + ": " |
|
79 if self.why: |
|
80 s += self.why |
|
81 else: |
|
82 s += self.strerror |
|
83 return s |
|
84 |
|
85 __strs = { |
|
86 errno.EPERM: _("permission denied"), |
|
87 errno.ECANCELED: |
|
88 _("delegated administration is disabled on pool"), |
|
89 errno.EINTR: _("signal received"), |
|
90 errno.EIO: _("I/O error"), |
|
91 errno.ENOENT: _("dataset does not exist"), |
|
92 errno.ENOSPC: _("out of space"), |
|
93 errno.EEXIST: _("dataset already exists"), |
|
94 errno.EBUSY: _("dataset is busy"), |
|
95 errno.EROFS: |
|
96 _("snapshot permissions cannot be modified"), |
|
97 errno.ENAMETOOLONG: _("dataset name is too long"), |
|
98 errno.ENOTSUP: _("unsupported version"), |
|
99 errno.EAGAIN: _("pool I/O is currently suspended"), |
|
100 } |
|
101 |
|
102 __strs[errno.EACCES] = __strs[errno.EPERM] |
|
103 __strs[errno.ENXIO] = __strs[errno.EIO] |
|
104 __strs[errno.ENODEV] = __strs[errno.EIO] |
|
105 __strs[errno.EDQUOT] = __strs[errno.ENOSPC] |
|
106 |
|
107 @property |
|
108 def strerror(self): |
|
109 return ZFSError.__strs.get(self.errno, os.strerror(self.errno)) |
|
110 |
|
111 def nicenum(num): |
|
112 """Return a nice string (eg "1.23M") for this integer.""" |
|
113 index = 0; |
|
114 n = num; |
|
115 |
|
116 while n >= 1024: |
|
117 n /= 1024 |
|
118 index += 1 |
|
119 |
|
120 u = " KMGTPE"[index] |
|
121 if index == 0: |
|
122 return "%u" % n; |
|
123 elif n >= 100 or num & ((1024*index)-1) == 0: |
|
124 # it's an exact multiple of its index, or it wouldn't |
|
125 # fit as floating point, so print as an integer |
|
126 return "%u%c" % (n, u) |
|
127 else: |
|
128 # due to rounding, it's tricky to tell what precision to |
|
129 # use; try each precision and see which one fits |
|
130 for i in (2, 1, 0): |
|
131 s = "%.*f%c" % (i, float(num) / (1<<(10*index)), u) |
|
132 if len(s) <= 5: |
|
133 return s |
|
134 |
|
135 def append_with_opt(option, opt, value, parser): |
|
136 """A function for OptionParser which appends a tuple (opt, value).""" |
|
137 getattr(parser.values, option.dest).append((opt, value)) |
|
138 |