Revision 82463074 lib/bdev.py

b/lib/bdev.py
33 33
from ganeti import constants
34 34

  
35 35

  
36
def _IgnoreError(fn, *args, **kwargs):
37
  """Executes the given function, ignoring BlockDeviceErrors.
38

  
39
  This is used in order to simplify the execution of cleanup or
40
  rollback functions.
41

  
42
  @rtype: boolean
43
  @return: True when fn didn't raise an exception, False otherwise
44

  
45
  """
46
  try:
47
    fn(*args, **kwargs)
48
    return True
49
  except errors.BlockDeviceError, err:
50
    logging.warning("Caught BlockDeviceError but ignoring: %s" % str(err))
51
    return False
52

  
53

  
54
def _ThrowError(msg, *args):
55
  """Log an error to the node daemon and the raise an exception.
56

  
57
  @type msg: string
58
  @param msg: the text of the exception
59
  @raise errors.BlockDeviceError
60

  
61
  """
62
  if args:
63
    msg = msg % args
64
  logging.error(msg)
65
  raise errors.BlockDeviceError(msg)
66

  
67

  
36 68
class BlockDev(object):
37 69
  """Block device abstract class.
38 70

  
......
280 312
    vg_name, lv_name = unique_id
281 313
    pvs_info = cls.GetPVInfo(vg_name)
282 314
    if not pvs_info:
283
      raise errors.BlockDeviceError("Can't compute PV info for vg %s" %
284
                                    vg_name)
315
      _ThrowError("Can't compute PV info for vg %s", vg_name)
285 316
    pvs_info.sort()
286 317
    pvs_info.reverse()
287 318

  
......
291 322
    # The size constraint should have been checked from the master before
292 323
    # calling the create function.
293 324
    if free_size < size:
294
      raise errors.BlockDeviceError("Not enough free space: required %s,"
295
                                    " available %s" % (size, free_size))
325
      _ThrowError("Not enough free space: required %s,"
326
                  " available %s", size, free_size)
296 327
    result = utils.RunCmd(["lvcreate", "-L%dm" % size, "-n%s" % lv_name,
297 328
                           vg_name] + pvlist)
298 329
    if result.failed:
299
      raise errors.BlockDeviceError("LV create failed (%s): %s" %
300
                                    (result.fail_reason, result.output))
330
      _ThrowError("LV create failed (%s): %s",
331
                  result.fail_reason, result.output)
301 332
    return LogicalVolume(unique_id, children)
302 333

  
303 334
  @staticmethod
......
359 390
                                   (self._vg_name, new_vg))
360 391
    result = utils.RunCmd(["lvrename", new_vg, self._lv_name, new_name])
361 392
    if result.failed:
362
      raise errors.BlockDeviceError("Failed to rename the logical volume: %s" %
363
                                    result.output)
393
      _ThrowError("Failed to rename the logical volume: %s", result.output)
364 394
    self._lv_name = new_name
365 395
    self.dev_path = "/dev/%s/%s" % (self._vg_name, self._lv_name)
366 396

  
......
480 510

  
481 511
    pvs_info = self.GetPVInfo(self._vg_name)
482 512
    if not pvs_info:
483
      raise errors.BlockDeviceError("Can't compute PV info for vg %s" %
484
                                    self._vg_name)
513
      _ThrowError("Can't compute PV info for vg %s", self._vg_name)
485 514
    pvs_info.sort()
486 515
    pvs_info.reverse()
487 516
    free_size, pv_name = pvs_info[0]
488 517
    if free_size < size:
489
      raise errors.BlockDeviceError("Not enough free space: required %s,"
490
                                    " available %s" % (size, free_size))
518
      _ThrowError("Not enough free space: required %s,"
519
                  " available %s", size, free_size)
491 520

  
492 521
    result = utils.RunCmd(["lvcreate", "-L%dm" % size, "-s",
493 522
                           "-n%s" % snap_name, self.dev_path])
494 523
    if result.failed:
495
      raise errors.BlockDeviceError("command: %s error: %s - %s" %
496
                                    (result.cmd, result.fail_reason,
497
                                     result.output))
524
      _ThrowError("command: %s error: %s - %s",
525
                  result.cmd, result.fail_reason, result.output)
498 526

  
499 527
    return snap_name
500 528

  
......
514 542
    result = utils.RunCmd(["lvchange", "--addtag", text,
515 543
                           self.dev_path])
516 544
    if result.failed:
517
      raise errors.BlockDeviceError("Command: %s error: %s - %s" %
518
                                    (result.cmd, result.fail_reason,
519
                                     result.output))
545
      _ThrowError("Command: %s error: %s - %s", result.cmd, result.fail_reason,
546
                  result.output)
547

  
520 548
  def Grow(self, amount):
521 549
    """Grow the logical volume.
522 550

  
......
530 558
                             "-L", "+%dm" % amount, self.dev_path])
531 559
      if not result.failed:
532 560
        return
533
    raise errors.BlockDeviceError("Can't grow LV %s: %s" %
534
                                  (self.dev_path, result.output))
561
    _ThrowError("Can't grow LV %s: %s", self.dev_path, result.output)
535 562

  
536 563

  
537 564
class DRBD8Status(object):
......
623 650
    finally:
624 651
      stat.close()
625 652
    if not data:
626
      raise errors.BlockDeviceError("Can't read any data from %s" % filename)
653
      _ThrowError("Can't read any data from %s", filename)
627 654
    return data
628 655

  
629 656
  @staticmethod
......
788 815
    self.major = self._DRBD_MAJOR
789 816
    version = self._GetVersion()
790 817
    if version['k_major'] != 8 :
791
      raise errors.BlockDeviceError("Mismatch in DRBD kernel version and"
792
                                    " requested ganeti usage: kernel is"
793
                                    " %s.%s, ganeti wants 8.x" %
794
                                    (version['k_major'], version['k_minor']))
818
      _ThrowError("Mismatch in DRBD kernel version and requested ganeti"
819
                  " usage: kernel is %s.%s, ganeti wants 8.x",
820
                  version['k_major'], version['k_minor'])
795 821

  
796 822
    if len(children) not in (0, 2):
797 823
      raise ValueError("Invalid configuration data %s" % str(children))
......
816 842
    result = utils.RunCmd(["drbdmeta", "--force", cls._DevPath(minor),
817 843
                           "v08", dev_path, "0", "create-md"])
818 844
    if result.failed:
819
      raise errors.BlockDeviceError("Can't initialize meta device: %s" %
820
                                    result.output)
845
      _ThrowError("Can't initialize meta device: %s", result.output)
821 846

  
822 847
  @classmethod
823 848
  def _FindUnusedMinor(cls):
......
929 954
    try:
930 955
      results = bnf.parseString(out)
931 956
    except pyp.ParseException, err:
932
      raise errors.BlockDeviceError("Can't parse drbdsetup show output: %s" %
933
                                    str(err))
957
      _ThrowError("Can't parse drbdsetup show output: %s", str(err))
934 958

  
935 959
    # and massage the results into our desired format
936 960
    for section in results:
......
1075 1099

  
1076 1100
    """
1077 1101
    if self.minor is None:
1078
      raise errors.BlockDeviceError("Can't attach to dbrd8 during AddChildren")
1102
      _ThrowError("drbd%d: can't attach to dbrd8 during AddChildren",
1103
                  self._aminor)
1079 1104
    if len(devices) != 2:
1080
      raise errors.BlockDeviceError("Need two devices for AddChildren")
1105
      _ThrowError("drbd%d: need two devices for AddChildren", self.minor)
1081 1106
    info = self._GetDevInfo(self._GetShowData(self.minor))
1082 1107
    if "local_dev" in info:
1083
      raise errors.BlockDeviceError("DRBD8 already attached to a local disk")
1108
      _ThrowError("drbd%d: already attached to a local disk", self.minor)
1084 1109
    backend, meta = devices
1085 1110
    if backend.dev_path is None or meta.dev_path is None:
1086
      raise errors.BlockDeviceError("Children not ready during AddChildren")
1111
      _ThrowError("drbd%d: children not ready during AddChildren", self.minor)
1087 1112
    backend.Open()
1088 1113
    meta.Open()
1089 1114
    if not self._CheckMetaSize(meta.dev_path):
......
1099 1124

  
1100 1125
    """
1101 1126
    if self.minor is None:
1102
      raise errors.BlockDeviceError("Can't attach to drbd8 during"
1103
                                    " RemoveChildren")
1127
      _ThrowError("drbd%d: can't attach to drbd8 during RemoveChildren",
1128
                  self._aminor)
1104 1129
    # early return if we don't actually have backing storage
1105 1130
    info = self._GetDevInfo(self._GetShowData(self.minor))
1106 1131
    if "local_dev" not in info:
1107 1132
      return
1108 1133
    if len(self._children) != 2:
1109
      raise errors.BlockDeviceError("We don't have two children: %s" %
1110
                                    self._children)
1134
      _ThrowError("drbd%d: we don't have two children: %s", self.minor,
1135
                  self._children)
1111 1136
    if self._children.count(None) == 2: # we don't actually have children :)
1112
      logging.error("Requested detach while detached")
1137
      logging.warning("drbd%d: requested detach while detached", self.minor)
1113 1138
      return
1114 1139
    if len(devices) != 2:
1115
      raise errors.BlockDeviceError("We need two children in RemoveChildren")
1140
      _ThrowError("drbd%d: we need two children in RemoveChildren", self.minor)
1116 1141
    for child, dev in zip(self._children, devices):
1117 1142
      if dev != child.dev_path:
1118
        raise errors.BlockDeviceError("Mismatch in local storage"
1119
                                      " (%s != %s) in RemoveChildren" %
1120
                                      (dev, child.dev_path))
1143
        _ThrowError("drbd%d: mismatch in local storage (%s != %s) in"
1144
                    " RemoveChildren", self.minor, dev, child.dev_path)
1121 1145

  
1122 1146
    if not self._ShutdownLocal(self.minor):
1123 1147
      raise errors.BlockDeviceError("Can't detach from local storage")
......
1164 1188

  
1165 1189
    """
1166 1190
    if self.minor is None:
1167
      raise errors.BlockDeviceError("GetStats() called while not attached")
1191
      _ThrowError("drbd%d: GetStats() called while not attached", self._aminor)
1168 1192
    proc_info = self._MassageProcData(self._GetProcData())
1169 1193
    if self.minor not in proc_info:
1170
      raise errors.BlockDeviceError("Can't find myself in /proc (minor %d)" %
1171
                                    self.minor)
1194
      _ThrowError("drbd%d: can't find myself in /proc", self.minor)
1172 1195
    return DRBD8Status(proc_info[self.minor])
1173 1196

  
1174 1197
  def GetSyncStatus(self):
......
1191 1214

  
1192 1215
    """
1193 1216
    if self.minor is None and not self.Attach():
1194
      raise errors.BlockDeviceError("Can't attach to device in GetSyncStatus")
1217
      _ThrowError("drbd%d: can't Attach() in GetSyncStatus", self._aminor)
1195 1218
    stats = self.GetProcStatus()
1196 1219
    ldisk = not stats.is_disk_uptodate
1197 1220
    is_degraded = not stats.is_connected
......
1214 1237
      cmd.append("-o")
1215 1238
    result = utils.RunCmd(cmd)
1216 1239
    if result.failed:
1217
      msg = ("Can't make drbd device primary: %s" % result.output)
1218
      logging.error(msg)
1219
      raise errors.BlockDeviceError(msg)
1240
      _ThrowError("drbd%d: can't make drbd device primary: %s", self.minor,
1241
                  result.output)
1220 1242

  
1221 1243
  def Close(self):
1222 1244
    """Make the local state secondary.
......
1225 1247

  
1226 1248
    """
1227 1249
    if self.minor is None and not self.Attach():
1228
      logging.info("Instance not attached to a device")
1229
      raise errors.BlockDeviceError("Can't find device")
1250
      _ThrowError("drbd%d: can't Attach() in Close()", self._aminor)
1230 1251
    result = utils.RunCmd(["drbdsetup", self.dev_path, "secondary"])
1231 1252
    if result.failed:
1232
      msg = ("Can't switch drbd device to"
1233
             " secondary: %s" % result.output)
1234
      logging.error(msg)
1235
      raise errors.BlockDeviceError(msg)
1253
      _ThrowError("drbd%d: can't switch drbd device to secondary: %s",
1254
                  self.minor, result.output)
1236 1255

  
1237 1256
  def DisconnectNet(self):
1238 1257
    """Removes network configuration.
......
1249 1268

  
1250 1269
    """
1251 1270
    if self.minor is None:
1252
      raise errors.BlockDeviceError("DRBD disk not attached in re-attach net")
1271
      _ThrowError("drbd%d: disk not attached in re-attach net", self._aminor)
1253 1272

  
1254 1273
    if None in (self._lhost, self._lport, self._rhost, self._rport):
1255
      raise errors.BlockDeviceError("DRBD disk missing network info in"
1256
                                    " DisconnectNet()")
1274
      _ThrowError("drbd%d: DRBD disk missing network info in"
1275
                  " DisconnectNet()", self.minor)
1257 1276

  
1258 1277
    ever_disconnected = self._ShutdownNet(self.minor)
1259 1278
    timeout_limit = time.time() + self._NET_RECONFIG_TIMEOUT
......
1271 1290

  
1272 1291
    if not status.is_standalone:
1273 1292
      if ever_disconnected:
1274
        msg = ("Device did not react to the"
1293
        msg = ("drbd%d: device did not react to the"
1275 1294
               " 'disconnect' command in a timely manner")
1276 1295
      else:
1277
        msg = ("Can't shutdown network, even after multiple retries")
1278
      raise errors.BlockDeviceError(msg)
1296
        msg = "drbd%d: can't shutdown network, even after multiple retries"
1297
      _ThrowError(msg, self.minor)
1279 1298

  
1280 1299
    reconfig_time = time.time() - timeout_limit + self._NET_RECONFIG_TIMEOUT
1281 1300
    if reconfig_time > 15: # hardcoded alert limit
1282
      logging.debug("DRBD8.DisconnectNet: detach took %.3f seconds",
1283
                    reconfig_time)
1301
      logging.info("drbd%d: DisconnectNet: detach took %.3f seconds",
1302
                   self.minor, reconfig_time)
1284 1303

  
1285 1304
  def AttachNet(self, multimaster):
1286 1305
    """Reconnects the network.
......
1294 1313

  
1295 1314
    """
1296 1315
    if self.minor is None:
1297
      raise errors.BlockDeviceError("DRBD disk not attached in AttachNet")
1316
      _ThrowError("drbd%d: device not attached in AttachNet", self._aminor)
1298 1317

  
1299 1318
    if None in (self._lhost, self._lport, self._rhost, self._rport):
1300
      raise errors.BlockDeviceError("DRBD disk missing network info in"
1301
                                    " AttachNet()")
1319
      _ThrowError("drbd%d: missing network info in AttachNet()", self.minor)
1302 1320

  
1303 1321
    status = self.GetProcStatus()
1304 1322

  
1305 1323
    if not status.is_standalone:
1306
      raise errors.BlockDeviceError("Device is not standalone in AttachNet")
1324
      _ThrowError("drbd%d: device is not standalone in AttachNet", self.minor)
1307 1325

  
1308 1326
    return self._AssembleNet(self.minor,
1309 1327
                             (self._lhost, self._lport,
......
1521 1539
    else:
1522 1540
      in_use = False
1523 1541
    if in_use:
1524
      raise errors.BlockDeviceError("DRBD minor %d already in use at"
1525
                                    " Create() time" % aminor)
1542
      _ThrowError("DRBD minor %d already in use at Create() time", aminor)
1526 1543
    meta = children[1]
1527 1544
    meta.Assemble()
1528 1545
    if not meta.Attach():
......
1537 1554

  
1538 1555
    """
1539 1556
    if self.minor is None:
1540
      raise errors.ProgrammerError("drbd8: Grow called while not attached")
1557
      _ThrowError("drbd%d: Grow called while not attached", self._aminor)
1541 1558
    if len(self._children) != 2 or None in self._children:
1542
      raise errors.BlockDeviceError("Cannot grow diskless DRBD8 device")
1559
      _ThrowError("drbd%d: cannot grow diskless device", self.minor)
1543 1560
    self._children[0].Grow(amount)
1544 1561
    result = utils.RunCmd(["drbdsetup", self.dev_path, "resize"])
1545 1562
    if result.failed:
1546
      raise errors.BlockDeviceError("resize failed for %s: %s" %
1547
                                    (self.dev_path, result.output))
1548
    return
1563
      _ThrowError("drbd%d: resize failed: %s", self.minor, result.output)
1549 1564

  
1550 1565

  
1551 1566
class FileStorage(BlockDev):
......
1653 1668
      f.truncate(size * 1024 * 1024)
1654 1669
      f.close()
1655 1670
    except IOError, err:
1656
      raise errors.BlockDeviceError("Error in file creation: %" % str(err))
1671
      _ThrowError("Error in file creation: %", str(err))
1657 1672

  
1658 1673
    return FileStorage(unique_id, children)
1659 1674

  

Also available in: Unified diff