Revision 0834c866 lib/bdev.py

b/lib/bdev.py
220 220
    status of the mirror.
221 221

  
222 222
    Returns:
223
     (sync_percent, estimated_time, is_degraded)
223
     (sync_percent, estimated_time, is_degraded, ldisk)
224

  
225
    If sync_percent is None, it means the device is not syncing.
224 226

  
225
    If sync_percent is None, it means all is ok
226 227
    If estimated_time is None, it means we can't estimate
227
    the time needed, otherwise it's the time left in seconds
228
    the time needed, otherwise it's the time left in seconds.
229

  
228 230
    If is_degraded is True, it means the device is missing
229 231
    redundancy. This is usually a sign that something went wrong in
230 232
    the device setup, if sync_percent is None.
231 233

  
234
    The ldisk parameter represents the degradation of the local
235
    data. This is only valid for some devices, the rest will always
236
    return False (not degraded).
237

  
232 238
    """
233
    return None, None, False
239
    return None, None, False, False
234 240

  
235 241

  
236 242
  def CombinedSyncStatus(self):
......
241 247
    children.
242 248

  
243 249
    """
244
    min_percent, max_time, is_degraded = self.GetSyncStatus()
250
    min_percent, max_time, is_degraded, ldisk = self.GetSyncStatus()
245 251
    if self._children:
246 252
      for child in self._children:
247
        c_percent, c_time, c_degraded = child.GetSyncStatus()
253
        c_percent, c_time, c_degraded, c_ldisk = child.GetSyncStatus()
248 254
        if min_percent is None:
249 255
          min_percent = c_percent
250 256
        elif c_percent is not None:
......
254 260
        elif c_time is not None:
255 261
          max_time = max(max_time, c_time)
256 262
        is_degraded = is_degraded or c_degraded
257
    return min_percent, max_time, is_degraded
263
        ldisk = ldisk or c_ldisk
264
    return min_percent, max_time, is_degraded, ldisk
258 265

  
259 266

  
260 267
  def SetInfo(self, text):
......
458 465
    status of the mirror.
459 466

  
460 467
    Returns:
461
     (sync_percent, estimated_time, is_degraded)
468
     (sync_percent, estimated_time, is_degraded, ldisk)
462 469

  
463 470
    For logical volumes, sync_percent and estimated_time are always
464 471
    None (no recovery in progress, as we don't handle the mirrored LV
465
    case).
472
    case). The is_degraded parameter is the inverse of the ldisk
473
    parameter.
466 474

  
467
    For the is_degraded parameter, we check if the logical volume has
468
    the 'virtual' type, which means it's not backed by existing
469
    storage anymore (read from it return I/O error). This happens
470
    after a physical disk failure and subsequent 'vgreduce
471
    --removemissing' on the volume group.
475
    For the ldisk parameter, we check if the logical volume has the
476
    'virtual' type, which means it's not backed by existing storage
477
    anymore (read from it return I/O error). This happens after a
478
    physical disk failure and subsequent 'vgreduce --removemissing' on
479
    the volume group.
472 480

  
473 481
    """
474 482
    result = utils.RunCmd(["lvs", "--noheadings", "-olv_attr", self.dev_path])
475 483
    if result.failed:
476 484
      logger.Error("Can't display lv: %s" % result.fail_reason)
477
      return None, None, True
485
      return None, None, True, True
478 486
    out = result.stdout.strip()
479 487
    # format: type/permissions/alloc/fixed_minor/state/open
480 488
    if len(out) != 6:
481
      return None, None, True
482
    is_degraded = out[0] == 'v' # virtual volume, i.e. doesn't have
483
                                # backing storage
484
    return None, None, is_degraded
489
      logger.Debug("Error in lvs output: attrs=%s, len != 6" % out)
490
      return None, None, True, True
491
    ldisk = out[0] == 'v' # virtual volume, i.e. doesn't have
492
                          # backing storage
493
    return None, None, ldisk, ldisk
485 494

  
486 495
  def Open(self, force=False):
487 496
    """Make the device ready for I/O.
......
898 907
    """Returns the sync status of the device.
899 908

  
900 909
    Returns:
901
     (sync_percent, estimated_time, is_degraded)
910
     (sync_percent, estimated_time, is_degraded, ldisk)
902 911

  
903 912
    If sync_percent is None, it means all is ok
904 913
    If estimated_time is None, it means we can't esimate
905
    the time needed, otherwise it's the time left in seconds
914
    the time needed, otherwise it's the time left in seconds.
915

  
916
    The ldisk parameter is always true for MD devices.
906 917

  
907 918
    """
908 919
    if self.minor is None and not self.Attach():
......
916 927
    sync_status = f.readline().strip()
917 928
    f.close()
918 929
    if sync_status == "idle":
919
      return None, None, not is_clean
930
      return None, None, not is_clean, False
920 931
    f = file(sys_path + "sync_completed")
921 932
    sync_completed = f.readline().strip().split(" / ")
922 933
    f.close()
923 934
    if len(sync_completed) != 2:
924
      return 0, None, not is_clean
935
      return 0, None, not is_clean, False
925 936
    sync_done, sync_total = [float(i) for i in sync_completed]
926 937
    sync_percent = 100.0*sync_done/sync_total
927 938
    f = file(sys_path + "sync_speed")
......
930 941
      time_est = None
931 942
    else:
932 943
      time_est = (sync_total - sync_done) / 2 / sync_speed_k
933
    return sync_percent, time_est, not is_clean
944
    return sync_percent, time_est, not is_clean, False
934 945

  
935 946
  def Open(self, force=False):
936 947
    """Make the device ready for I/O.
......
1476 1487
    """Returns the sync status of the device.
1477 1488

  
1478 1489
    Returns:
1479
     (sync_percent, estimated_time, is_degraded)
1490
     (sync_percent, estimated_time, is_degraded, ldisk)
1480 1491

  
1481 1492
    If sync_percent is None, it means all is ok
1482 1493
    If estimated_time is None, it means we can't esimate
1483
    the time needed, otherwise it's the time left in seconds
1494
    the time needed, otherwise it's the time left in seconds.
1495

  
1496
    The ldisk parameter will be returned as True, since the DRBD7
1497
    devices have not been converted.
1484 1498

  
1485 1499
    """
1486 1500
    if self.minor is None and not self.Attach():
......
1507 1521
                                    self.minor)
1508 1522
    client_state = match.group(1)
1509 1523
    is_degraded = client_state != "Connected"
1510
    return sync_percent, est_time, is_degraded
1524
    return sync_percent, est_time, is_degraded, False
1511 1525

  
1512 1526
  def GetStatus(self):
1513 1527
    """Compute the status of the DRBD device
......
1953 1967

  
1954 1968
    If sync_percent is None, it means all is ok
1955 1969
    If estimated_time is None, it means we can't esimate
1956
    the time needed, otherwise it's the time left in seconds
1970
    the time needed, otherwise it's the time left in seconds.
1971

  
1972

  
1973
    We set the is_degraded parameter to True on two conditions:
1974
    network not connected or local disk missing.
1975

  
1976
    We compute the ldisk parameter based on wheter we have a local
1977
    disk or not.
1957 1978

  
1958 1979
    """
1959 1980
    if self.minor is None and not self.Attach():
......
1980 2001
                                    self.minor)
1981 2002
    client_state = match.group(1)
1982 2003
    local_disk_state = match.group(2)
1983
    is_degraded = (client_state != "Connected" or
1984
                   local_disk_state != "UpToDate")
1985
    return sync_percent, est_time, is_degraded
2004
    ldisk = local_disk_state != "UpToDate"
2005
    is_degraded = client_state != "Connected"
2006
    return sync_percent, est_time, is_degraded or ldisk, ldisk
1986 2007

  
1987 2008
  def GetStatus(self):
1988 2009
    """Compute the status of the DRBD device

Also available in: Unified diff