Statistics
| Branch: | Tag: | Revision:

root / lib / storage / base.py @ ac156ecd

History | View | Annotate | Download (13 kB)

1 89ff748d Thomas Thrainer
#
2 89ff748d Thomas Thrainer
#
3 89ff748d Thomas Thrainer
4 89ff748d Thomas Thrainer
# Copyright (C) 2006, 2007, 2010, 2011, 2012, 2013 Google Inc.
5 89ff748d Thomas Thrainer
#
6 89ff748d Thomas Thrainer
# This program is free software; you can redistribute it and/or modify
7 89ff748d Thomas Thrainer
# it under the terms of the GNU General Public License as published by
8 89ff748d Thomas Thrainer
# the Free Software Foundation; either version 2 of the License, or
9 89ff748d Thomas Thrainer
# (at your option) any later version.
10 89ff748d Thomas Thrainer
#
11 89ff748d Thomas Thrainer
# This program is distributed in the hope that it will be useful, but
12 89ff748d Thomas Thrainer
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 89ff748d Thomas Thrainer
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 89ff748d Thomas Thrainer
# General Public License for more details.
15 89ff748d Thomas Thrainer
#
16 89ff748d Thomas Thrainer
# You should have received a copy of the GNU General Public License
17 89ff748d Thomas Thrainer
# along with this program; if not, write to the Free Software
18 89ff748d Thomas Thrainer
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 89ff748d Thomas Thrainer
# 02110-1301, USA.
20 89ff748d Thomas Thrainer
21 89ff748d Thomas Thrainer
22 89ff748d Thomas Thrainer
"""Block device abstraction - base class and utility functions"""
23 89ff748d Thomas Thrainer
24 89ff748d Thomas Thrainer
import logging
25 89ff748d Thomas Thrainer
26 89ff748d Thomas Thrainer
from ganeti import objects
27 89ff748d Thomas Thrainer
from ganeti import constants
28 89ff748d Thomas Thrainer
from ganeti import utils
29 89ff748d Thomas Thrainer
from ganeti import errors
30 89ff748d Thomas Thrainer
31 89ff748d Thomas Thrainer
32 89ff748d Thomas Thrainer
class BlockDev(object):
33 89ff748d Thomas Thrainer
  """Block device abstract class.
34 89ff748d Thomas Thrainer

35 89ff748d Thomas Thrainer
  A block device can be in the following states:
36 89ff748d Thomas Thrainer
    - not existing on the system, and by `Create()` it goes into:
37 89ff748d Thomas Thrainer
    - existing but not setup/not active, and by `Assemble()` goes into:
38 89ff748d Thomas Thrainer
    - active read-write and by `Open()` it goes into
39 89ff748d Thomas Thrainer
    - online (=used, or ready for use)
40 89ff748d Thomas Thrainer

41 89ff748d Thomas Thrainer
  A device can also be online but read-only, however we are not using
42 89ff748d Thomas Thrainer
  the readonly state (LV has it, if needed in the future) and we are
43 89ff748d Thomas Thrainer
  usually looking at this like at a stack, so it's easier to
44 89ff748d Thomas Thrainer
  conceptualise the transition from not-existing to online and back
45 89ff748d Thomas Thrainer
  like a linear one.
46 89ff748d Thomas Thrainer

47 89ff748d Thomas Thrainer
  The many different states of the device are due to the fact that we
48 89ff748d Thomas Thrainer
  need to cover many device types:
49 89ff748d Thomas Thrainer
    - logical volumes are created, lvchange -a y $lv, and used
50 89ff748d Thomas Thrainer
    - drbd devices are attached to a local disk/remote peer and made primary
51 89ff748d Thomas Thrainer

52 89ff748d Thomas Thrainer
  A block device is identified by three items:
53 89ff748d Thomas Thrainer
    - the /dev path of the device (dynamic)
54 89ff748d Thomas Thrainer
    - a unique ID of the device (static)
55 89ff748d Thomas Thrainer
    - it's major/minor pair (dynamic)
56 89ff748d Thomas Thrainer

57 89ff748d Thomas Thrainer
  Not all devices implement both the first two as distinct items. LVM
58 89ff748d Thomas Thrainer
  logical volumes have their unique ID (the pair volume group, logical
59 89ff748d Thomas Thrainer
  volume name) in a 1-to-1 relation to the dev path. For DRBD devices,
60 89ff748d Thomas Thrainer
  the /dev path is again dynamic and the unique id is the pair (host1,
61 89ff748d Thomas Thrainer
  dev1), (host2, dev2).
62 89ff748d Thomas Thrainer

63 89ff748d Thomas Thrainer
  You can get to a device in two ways:
64 89ff748d Thomas Thrainer
    - creating the (real) device, which returns you
65 89ff748d Thomas Thrainer
      an attached instance (lvcreate)
66 89ff748d Thomas Thrainer
    - attaching of a python instance to an existing (real) device
67 89ff748d Thomas Thrainer

68 89ff748d Thomas Thrainer
  The second point, the attachment to a device, is different
69 89ff748d Thomas Thrainer
  depending on whether the device is assembled or not. At init() time,
70 89ff748d Thomas Thrainer
  we search for a device with the same unique_id as us. If found,
71 89ff748d Thomas Thrainer
  good. It also means that the device is already assembled. If not,
72 89ff748d Thomas Thrainer
  after assembly we'll have our correct major/minor.
73 89ff748d Thomas Thrainer

74 89ff748d Thomas Thrainer
  """
75 0c3d9c7c Thomas Thrainer
  def __init__(self, unique_id, children, size, params, dyn_params):
76 89ff748d Thomas Thrainer
    self._children = children
77 89ff748d Thomas Thrainer
    self.dev_path = None
78 89ff748d Thomas Thrainer
    self.unique_id = unique_id
79 89ff748d Thomas Thrainer
    self.major = None
80 89ff748d Thomas Thrainer
    self.minor = None
81 89ff748d Thomas Thrainer
    self.attached = False
82 89ff748d Thomas Thrainer
    self.size = size
83 89ff748d Thomas Thrainer
    self.params = params
84 0c3d9c7c Thomas Thrainer
    self.dyn_params = dyn_params
85 89ff748d Thomas Thrainer
86 89ff748d Thomas Thrainer
  def Assemble(self):
87 89ff748d Thomas Thrainer
    """Assemble the device from its components.
88 89ff748d Thomas Thrainer

89 89ff748d Thomas Thrainer
    Implementations of this method by child classes must ensure that:
90 89ff748d Thomas Thrainer
      - after the device has been assembled, it knows its major/minor
91 89ff748d Thomas Thrainer
        numbers; this allows other devices (usually parents) to probe
92 89ff748d Thomas Thrainer
        correctly for their children
93 89ff748d Thomas Thrainer
      - calling this method on an existing, in-use device is safe
94 89ff748d Thomas Thrainer
      - if the device is already configured (and in an OK state),
95 89ff748d Thomas Thrainer
        this method is idempotent
96 89ff748d Thomas Thrainer

97 89ff748d Thomas Thrainer
    """
98 89ff748d Thomas Thrainer
    pass
99 89ff748d Thomas Thrainer
100 89ff748d Thomas Thrainer
  def Attach(self):
101 89ff748d Thomas Thrainer
    """Find a device which matches our config and attach to it.
102 89ff748d Thomas Thrainer

103 89ff748d Thomas Thrainer
    """
104 89ff748d Thomas Thrainer
    raise NotImplementedError
105 89ff748d Thomas Thrainer
106 89ff748d Thomas Thrainer
  def Close(self):
107 89ff748d Thomas Thrainer
    """Notifies that the device will no longer be used for I/O.
108 89ff748d Thomas Thrainer

109 89ff748d Thomas Thrainer
    """
110 89ff748d Thomas Thrainer
    raise NotImplementedError
111 89ff748d Thomas Thrainer
112 89ff748d Thomas Thrainer
  @classmethod
113 0c3d9c7c Thomas Thrainer
  def Create(cls, unique_id, children, size, spindles, params, excl_stor,
114 0c3d9c7c Thomas Thrainer
             dyn_params):
115 89ff748d Thomas Thrainer
    """Create the device.
116 89ff748d Thomas Thrainer

117 89ff748d Thomas Thrainer
    If the device cannot be created, it will return None
118 89ff748d Thomas Thrainer
    instead. Error messages go to the logging system.
119 89ff748d Thomas Thrainer

120 89ff748d Thomas Thrainer
    Note that for some devices, the unique_id is used, and for other,
121 89ff748d Thomas Thrainer
    the children. The idea is that these two, taken together, are
122 89ff748d Thomas Thrainer
    enough for both creation and assembly (later).
123 89ff748d Thomas Thrainer

124 5073fa0c Bernardo Dal Seno
    @type unique_id: 2-element tuple or list
125 5073fa0c Bernardo Dal Seno
    @param unique_id: unique identifier; the details depend on the actual device
126 5073fa0c Bernardo Dal Seno
        type
127 5073fa0c Bernardo Dal Seno
    @type children: list of L{BlockDev}
128 5073fa0c Bernardo Dal Seno
    @param children: for hierarchical devices, the child devices
129 5073fa0c Bernardo Dal Seno
    @type size: float
130 5073fa0c Bernardo Dal Seno
    @param size: size in MiB
131 24c06acb Bernardo Dal Seno
    @type spindles: int
132 24c06acb Bernardo Dal Seno
    @param spindles: number of physical disk to dedicate to the device
133 5073fa0c Bernardo Dal Seno
    @type params: dict
134 5073fa0c Bernardo Dal Seno
    @param params: device-specific options/parameters
135 5073fa0c Bernardo Dal Seno
    @type excl_stor: bool
136 5073fa0c Bernardo Dal Seno
    @param excl_stor: whether exclusive_storage is active
137 0c3d9c7c Thomas Thrainer
    @type dyn_params: dict
138 0c3d9c7c Thomas Thrainer
    @param dyn_params: dynamic parameters of the disk only valid for this node.
139 0c3d9c7c Thomas Thrainer
        As set by L{objects.Disk.UpdateDynamicDiskParams}.
140 5073fa0c Bernardo Dal Seno
    @rtype: L{BlockDev}
141 5073fa0c Bernardo Dal Seno
    @return: the created device, or C{None} in case of an error
142 5073fa0c Bernardo Dal Seno

143 89ff748d Thomas Thrainer
    """
144 89ff748d Thomas Thrainer
    raise NotImplementedError
145 89ff748d Thomas Thrainer
146 89ff748d Thomas Thrainer
  def Remove(self):
147 89ff748d Thomas Thrainer
    """Remove this device.
148 89ff748d Thomas Thrainer

149 89ff748d Thomas Thrainer
    This makes sense only for some of the device types: LV and file
150 89ff748d Thomas Thrainer
    storage. Also note that if the device can't attach, the removal
151 89ff748d Thomas Thrainer
    can't be completed.
152 89ff748d Thomas Thrainer

153 89ff748d Thomas Thrainer
    """
154 89ff748d Thomas Thrainer
    raise NotImplementedError
155 89ff748d Thomas Thrainer
156 89ff748d Thomas Thrainer
  def Rename(self, new_id):
157 89ff748d Thomas Thrainer
    """Rename this device.
158 89ff748d Thomas Thrainer

159 89ff748d Thomas Thrainer
    This may or may not make sense for a given device type.
160 89ff748d Thomas Thrainer

161 89ff748d Thomas Thrainer
    """
162 89ff748d Thomas Thrainer
    raise NotImplementedError
163 89ff748d Thomas Thrainer
164 89ff748d Thomas Thrainer
  def Open(self, force=False):
165 89ff748d Thomas Thrainer
    """Make the device ready for use.
166 89ff748d Thomas Thrainer

167 89ff748d Thomas Thrainer
    This makes the device ready for I/O. For now, just the DRBD
168 89ff748d Thomas Thrainer
    devices need this.
169 89ff748d Thomas Thrainer

170 89ff748d Thomas Thrainer
    The force parameter signifies that if the device has any kind of
171 89ff748d Thomas Thrainer
    --force thing, it should be used, we know what we are doing.
172 89ff748d Thomas Thrainer

173 47e0abee Thomas Thrainer
    @type force: boolean
174 47e0abee Thomas Thrainer

175 89ff748d Thomas Thrainer
    """
176 89ff748d Thomas Thrainer
    raise NotImplementedError
177 89ff748d Thomas Thrainer
178 89ff748d Thomas Thrainer
  def Shutdown(self):
179 89ff748d Thomas Thrainer
    """Shut down the device, freeing its children.
180 89ff748d Thomas Thrainer

181 89ff748d Thomas Thrainer
    This undoes the `Assemble()` work, except for the child
182 89ff748d Thomas Thrainer
    assembling; as such, the children on the device are still
183 89ff748d Thomas Thrainer
    assembled after this call.
184 89ff748d Thomas Thrainer

185 89ff748d Thomas Thrainer
    """
186 89ff748d Thomas Thrainer
    raise NotImplementedError
187 89ff748d Thomas Thrainer
188 89ff748d Thomas Thrainer
  def SetSyncParams(self, params):
189 89ff748d Thomas Thrainer
    """Adjust the synchronization parameters of the mirror.
190 89ff748d Thomas Thrainer

191 89ff748d Thomas Thrainer
    In case this is not a mirroring device, this is no-op.
192 89ff748d Thomas Thrainer

193 89ff748d Thomas Thrainer
    @param params: dictionary of LD level disk parameters related to the
194 89ff748d Thomas Thrainer
    synchronization.
195 89ff748d Thomas Thrainer
    @rtype: list
196 89ff748d Thomas Thrainer
    @return: a list of error messages, emitted both by the current node and by
197 89ff748d Thomas Thrainer
    children. An empty list means no errors.
198 89ff748d Thomas Thrainer

199 89ff748d Thomas Thrainer
    """
200 89ff748d Thomas Thrainer
    result = []
201 89ff748d Thomas Thrainer
    if self._children:
202 89ff748d Thomas Thrainer
      for child in self._children:
203 89ff748d Thomas Thrainer
        result.extend(child.SetSyncParams(params))
204 89ff748d Thomas Thrainer
    return result
205 89ff748d Thomas Thrainer
206 89ff748d Thomas Thrainer
  def PauseResumeSync(self, pause):
207 89ff748d Thomas Thrainer
    """Pause/Resume the sync of the mirror.
208 89ff748d Thomas Thrainer

209 89ff748d Thomas Thrainer
    In case this is not a mirroring device, this is no-op.
210 89ff748d Thomas Thrainer

211 47e0abee Thomas Thrainer
    @type pause: boolean
212 89ff748d Thomas Thrainer
    @param pause: Whether to pause or resume
213 89ff748d Thomas Thrainer

214 89ff748d Thomas Thrainer
    """
215 89ff748d Thomas Thrainer
    result = True
216 89ff748d Thomas Thrainer
    if self._children:
217 89ff748d Thomas Thrainer
      for child in self._children:
218 89ff748d Thomas Thrainer
        result = result and child.PauseResumeSync(pause)
219 89ff748d Thomas Thrainer
    return result
220 89ff748d Thomas Thrainer
221 89ff748d Thomas Thrainer
  def GetSyncStatus(self):
222 89ff748d Thomas Thrainer
    """Returns the sync status of the device.
223 89ff748d Thomas Thrainer

224 89ff748d Thomas Thrainer
    If this device is a mirroring device, this function returns the
225 89ff748d Thomas Thrainer
    status of the mirror.
226 89ff748d Thomas Thrainer

227 89ff748d Thomas Thrainer
    If sync_percent is None, it means the device is not syncing.
228 89ff748d Thomas Thrainer

229 89ff748d Thomas Thrainer
    If estimated_time is None, it means we can't estimate
230 89ff748d Thomas Thrainer
    the time needed, otherwise it's the time left in seconds.
231 89ff748d Thomas Thrainer

232 89ff748d Thomas Thrainer
    If is_degraded is True, it means the device is missing
233 89ff748d Thomas Thrainer
    redundancy. This is usually a sign that something went wrong in
234 89ff748d Thomas Thrainer
    the device setup, if sync_percent is None.
235 89ff748d Thomas Thrainer

236 89ff748d Thomas Thrainer
    The ldisk parameter represents the degradation of the local
237 89ff748d Thomas Thrainer
    data. This is only valid for some devices, the rest will always
238 89ff748d Thomas Thrainer
    return False (not degraded).
239 89ff748d Thomas Thrainer

240 89ff748d Thomas Thrainer
    @rtype: objects.BlockDevStatus
241 89ff748d Thomas Thrainer

242 89ff748d Thomas Thrainer
    """
243 89ff748d Thomas Thrainer
    return objects.BlockDevStatus(dev_path=self.dev_path,
244 89ff748d Thomas Thrainer
                                  major=self.major,
245 89ff748d Thomas Thrainer
                                  minor=self.minor,
246 89ff748d Thomas Thrainer
                                  sync_percent=None,
247 89ff748d Thomas Thrainer
                                  estimated_time=None,
248 89ff748d Thomas Thrainer
                                  is_degraded=False,
249 89ff748d Thomas Thrainer
                                  ldisk_status=constants.LDS_OKAY)
250 89ff748d Thomas Thrainer
251 89ff748d Thomas Thrainer
  def CombinedSyncStatus(self):
252 89ff748d Thomas Thrainer
    """Calculate the mirror status recursively for our children.
253 89ff748d Thomas Thrainer

254 89ff748d Thomas Thrainer
    The return value is the same as for `GetSyncStatus()` except the
255 89ff748d Thomas Thrainer
    minimum percent and maximum time are calculated across our
256 89ff748d Thomas Thrainer
    children.
257 89ff748d Thomas Thrainer

258 89ff748d Thomas Thrainer
    @rtype: objects.BlockDevStatus
259 89ff748d Thomas Thrainer

260 89ff748d Thomas Thrainer
    """
261 89ff748d Thomas Thrainer
    status = self.GetSyncStatus()
262 89ff748d Thomas Thrainer
263 89ff748d Thomas Thrainer
    min_percent = status.sync_percent
264 89ff748d Thomas Thrainer
    max_time = status.estimated_time
265 89ff748d Thomas Thrainer
    is_degraded = status.is_degraded
266 89ff748d Thomas Thrainer
    ldisk_status = status.ldisk_status
267 89ff748d Thomas Thrainer
268 89ff748d Thomas Thrainer
    if self._children:
269 89ff748d Thomas Thrainer
      for child in self._children:
270 89ff748d Thomas Thrainer
        child_status = child.GetSyncStatus()
271 89ff748d Thomas Thrainer
272 89ff748d Thomas Thrainer
        if min_percent is None:
273 89ff748d Thomas Thrainer
          min_percent = child_status.sync_percent
274 89ff748d Thomas Thrainer
        elif child_status.sync_percent is not None:
275 89ff748d Thomas Thrainer
          min_percent = min(min_percent, child_status.sync_percent)
276 89ff748d Thomas Thrainer
277 89ff748d Thomas Thrainer
        if max_time is None:
278 89ff748d Thomas Thrainer
          max_time = child_status.estimated_time
279 89ff748d Thomas Thrainer
        elif child_status.estimated_time is not None:
280 89ff748d Thomas Thrainer
          max_time = max(max_time, child_status.estimated_time)
281 89ff748d Thomas Thrainer
282 89ff748d Thomas Thrainer
        is_degraded = is_degraded or child_status.is_degraded
283 89ff748d Thomas Thrainer
284 89ff748d Thomas Thrainer
        if ldisk_status is None:
285 89ff748d Thomas Thrainer
          ldisk_status = child_status.ldisk_status
286 89ff748d Thomas Thrainer
        elif child_status.ldisk_status is not None:
287 89ff748d Thomas Thrainer
          ldisk_status = max(ldisk_status, child_status.ldisk_status)
288 89ff748d Thomas Thrainer
289 89ff748d Thomas Thrainer
    return objects.BlockDevStatus(dev_path=self.dev_path,
290 89ff748d Thomas Thrainer
                                  major=self.major,
291 89ff748d Thomas Thrainer
                                  minor=self.minor,
292 89ff748d Thomas Thrainer
                                  sync_percent=min_percent,
293 89ff748d Thomas Thrainer
                                  estimated_time=max_time,
294 89ff748d Thomas Thrainer
                                  is_degraded=is_degraded,
295 89ff748d Thomas Thrainer
                                  ldisk_status=ldisk_status)
296 89ff748d Thomas Thrainer
297 89ff748d Thomas Thrainer
  def SetInfo(self, text):
298 89ff748d Thomas Thrainer
    """Update metadata with info text.
299 89ff748d Thomas Thrainer

300 89ff748d Thomas Thrainer
    Only supported for some device types.
301 89ff748d Thomas Thrainer

302 89ff748d Thomas Thrainer
    """
303 89ff748d Thomas Thrainer
    for child in self._children:
304 89ff748d Thomas Thrainer
      child.SetInfo(text)
305 89ff748d Thomas Thrainer
306 be9150ea Bernardo Dal Seno
  def Grow(self, amount, dryrun, backingstore, excl_stor):
307 89ff748d Thomas Thrainer
    """Grow the block device.
308 89ff748d Thomas Thrainer

309 89ff748d Thomas Thrainer
    @type amount: integer
310 89ff748d Thomas Thrainer
    @param amount: the amount (in mebibytes) to grow with
311 89ff748d Thomas Thrainer
    @type dryrun: boolean
312 89ff748d Thomas Thrainer
    @param dryrun: whether to execute the operation in simulation mode
313 89ff748d Thomas Thrainer
        only, without actually increasing the size
314 89ff748d Thomas Thrainer
    @param backingstore: whether to execute the operation on backing storage
315 89ff748d Thomas Thrainer
        only, or on "logical" storage only; e.g. DRBD is logical storage,
316 89ff748d Thomas Thrainer
        whereas LVM, file, RBD are backing storage
317 be9150ea Bernardo Dal Seno
    @type excl_stor: boolean
318 be9150ea Bernardo Dal Seno
    @param excl_stor: Whether exclusive_storage is active
319 89ff748d Thomas Thrainer

320 89ff748d Thomas Thrainer
    """
321 89ff748d Thomas Thrainer
    raise NotImplementedError
322 89ff748d Thomas Thrainer
323 89ff748d Thomas Thrainer
  def GetActualSize(self):
324 89ff748d Thomas Thrainer
    """Return the actual disk size.
325 89ff748d Thomas Thrainer

326 89ff748d Thomas Thrainer
    @note: the device needs to be active when this is called
327 89ff748d Thomas Thrainer

328 89ff748d Thomas Thrainer
    """
329 89ff748d Thomas Thrainer
    assert self.attached, "BlockDevice not attached in GetActualSize()"
330 89ff748d Thomas Thrainer
    result = utils.RunCmd(["blockdev", "--getsize64", self.dev_path])
331 89ff748d Thomas Thrainer
    if result.failed:
332 89ff748d Thomas Thrainer
      ThrowError("blockdev failed (%s): %s",
333 89ff748d Thomas Thrainer
                  result.fail_reason, result.output)
334 89ff748d Thomas Thrainer
    try:
335 89ff748d Thomas Thrainer
      sz = int(result.output.strip())
336 89ff748d Thomas Thrainer
    except (ValueError, TypeError), err:
337 89ff748d Thomas Thrainer
      ThrowError("Failed to parse blockdev output: %s", str(err))
338 89ff748d Thomas Thrainer
    return sz
339 89ff748d Thomas Thrainer
340 baa7f1d6 Bernardo Dal Seno
  def GetActualSpindles(self):
341 baa7f1d6 Bernardo Dal Seno
    """Return the actual number of spindles used.
342 baa7f1d6 Bernardo Dal Seno

343 baa7f1d6 Bernardo Dal Seno
    This is not supported by all devices; if not supported, C{None} is returned.
344 baa7f1d6 Bernardo Dal Seno

345 baa7f1d6 Bernardo Dal Seno
    @note: the device needs to be active when this is called
346 baa7f1d6 Bernardo Dal Seno

347 baa7f1d6 Bernardo Dal Seno
    """
348 baa7f1d6 Bernardo Dal Seno
    assert self.attached, "BlockDevice not attached in GetActualSpindles()"
349 baa7f1d6 Bernardo Dal Seno
    return None
350 baa7f1d6 Bernardo Dal Seno
351 baa7f1d6 Bernardo Dal Seno
  def GetActualDimensions(self):
352 baa7f1d6 Bernardo Dal Seno
    """Return the actual disk size and number of spindles used.
353 baa7f1d6 Bernardo Dal Seno

354 baa7f1d6 Bernardo Dal Seno
    @rtype: tuple
355 baa7f1d6 Bernardo Dal Seno
    @return: (size, spindles); spindles is C{None} when they are not supported
356 baa7f1d6 Bernardo Dal Seno

357 baa7f1d6 Bernardo Dal Seno
    @note: the device needs to be active when this is called
358 baa7f1d6 Bernardo Dal Seno

359 baa7f1d6 Bernardo Dal Seno
    """
360 baa7f1d6 Bernardo Dal Seno
    return (self.GetActualSize(), self.GetActualSpindles())
361 baa7f1d6 Bernardo Dal Seno
362 f83057ad Raffa Santi
  def GetUserspaceAccessUri(self, hypervisor):
363 f83057ad Raffa Santi
    """Return URIs hypervisors can use to access disks in userspace mode.
364 f83057ad Raffa Santi

365 f83057ad Raffa Santi
    @rtype: string
366 f83057ad Raffa Santi
    @return: userspace device URI
367 f505e3ee Raffa Santi
    @raise errors.BlockDeviceError: if userspace access is not supported
368 f83057ad Raffa Santi

369 f83057ad Raffa Santi
    """
370 f83057ad Raffa Santi
    ThrowError("Userspace access with %s block device and %s hypervisor is not "
371 f83057ad Raffa Santi
               "supported." % (self.__class__.__name__,
372 f83057ad Raffa Santi
                               hypervisor))
373 f83057ad Raffa Santi
374 89ff748d Thomas Thrainer
  def __repr__(self):
375 89ff748d Thomas Thrainer
    return ("<%s: unique_id: %s, children: %s, %s:%s, %s>" %
376 89ff748d Thomas Thrainer
            (self.__class__, self.unique_id, self._children,
377 89ff748d Thomas Thrainer
             self.major, self.minor, self.dev_path))
378 89ff748d Thomas Thrainer
379 89ff748d Thomas Thrainer
380 89ff748d Thomas Thrainer
def ThrowError(msg, *args):
381 89ff748d Thomas Thrainer
  """Log an error to the node daemon and the raise an exception.
382 89ff748d Thomas Thrainer

383 89ff748d Thomas Thrainer
  @type msg: string
384 89ff748d Thomas Thrainer
  @param msg: the text of the exception
385 89ff748d Thomas Thrainer
  @raise errors.BlockDeviceError
386 89ff748d Thomas Thrainer

387 89ff748d Thomas Thrainer
  """
388 89ff748d Thomas Thrainer
  if args:
389 89ff748d Thomas Thrainer
    msg = msg % args
390 89ff748d Thomas Thrainer
  logging.error(msg)
391 89ff748d Thomas Thrainer
  raise errors.BlockDeviceError(msg)
392 89ff748d Thomas Thrainer
393 89ff748d Thomas Thrainer
394 89ff748d Thomas Thrainer
def IgnoreError(fn, *args, **kwargs):
395 89ff748d Thomas Thrainer
  """Executes the given function, ignoring BlockDeviceErrors.
396 89ff748d Thomas Thrainer

397 89ff748d Thomas Thrainer
  This is used in order to simplify the execution of cleanup or
398 89ff748d Thomas Thrainer
  rollback functions.
399 89ff748d Thomas Thrainer

400 89ff748d Thomas Thrainer
  @rtype: boolean
401 89ff748d Thomas Thrainer
  @return: True when fn didn't raise an exception, False otherwise
402 89ff748d Thomas Thrainer

403 89ff748d Thomas Thrainer
  """
404 89ff748d Thomas Thrainer
  try:
405 89ff748d Thomas Thrainer
    fn(*args, **kwargs)
406 89ff748d Thomas Thrainer
    return True
407 89ff748d Thomas Thrainer
  except errors.BlockDeviceError, err:
408 89ff748d Thomas Thrainer
    logging.warning("Caught BlockDeviceError but ignoring: %s", str(err))
409 89ff748d Thomas Thrainer
    return False