Revision 6b90c22e lib/bdev.py

b/lib/bdev.py
545 545
                                  (self.dev_path, result.output))
546 546

  
547 547

  
548
class DRBD8Status(object):
549
  """A DRBD status representation class.
550

  
551
  Note that this doesn't support unconfigured devices (cs:Unconfigured).
552

  
553
  """
554
  LINE_RE = re.compile(r"\s*[0-9]+:\s*cs:(\S+)\s+st:([^/]+)/(\S+)"
555
                       "\s+ds:([^/]+)/(\S+)\s+.*$")
556
  SYNC_RE = re.compile(r"^.*\ssync'ed:\s*([0-9.]+)%.*"
557
                       "\sfinish: ([0-9]+):([0-9]+):([0-9]+)\s.*$")
558

  
559
  def __init__(self, procline):
560
    m = self.LINE_RE.match(procline)
561
    if not m:
562
      raise errors.BlockDeviceError("Can't parse input data '%s'" % procline)
563
    self.cstatus = m.group(1)
564
    self.lrole = m.group(2)
565
    self.rrole = m.group(3)
566
    self.ldisk = m.group(4)
567
    self.rdisk = m.group(5)
568

  
569
    self.is_standalone = self.cstatus == "StandAlone"
570
    self.is_wfconn = self.cstatus == "WFConnection"
571
    self.is_connected = self.cstatus == "Connected"
572
    self.is_primary = self.lrole == "Primary"
573
    self.is_secondary = self.lrole == "Secondary"
574
    self.peer_primary = self.rrole == "Primary"
575
    self.peer_secondary = self.rrole == "Secondary"
576
    self.both_primary = self.is_primary and self.peer_primary
577
    self.both_secondary = self.is_secondary and self.peer_secondary
578

  
579
    self.is_diskless = self.ldisk == "Diskless"
580
    self.is_disk_uptodate = self.ldisk == "UpToDate"
581

  
582
    m = self.SYNC_RE.match(procline)
583
    if m:
584
      self.sync_percent = float(m.group(1))
585
      hours = int(m.group(2))
586
      minutes = int(m.group(3))
587
      seconds = int(m.group(4))
588
      self.est_time = hours * 3600 + minutes * 60 + seconds
589
    else:
590
      self.sync_percent = None
591
      self.est_time = None
592

  
593
    self.is_sync_target = self.peer_sync_source = self.cstatus == "SyncTarget"
594
    self.peer_sync_target = self.is_sync_source = self.cstatus == "SyncSource"
595
    self.is_resync = self.is_sync_target or self.is_sync_source
596

  
597

  
548 598
class BaseDRBD(BlockDev):
549 599
  """Base DRBD class.
550 600

  
......
560 610
  _ST_WFCONNECTION = "WFConnection"
561 611
  _ST_CONNECTED = "Connected"
562 612

  
613
  _STATUS_FILE = "/proc/drbd"
614

  
563 615
  @staticmethod
564
  def _GetProcData():
616
  def _GetProcData(filename=_STATUS_FILE):
565 617
    """Return data from /proc/drbd.
566 618

  
567 619
    """
568
    stat = open("/proc/drbd", "r")
620
    stat = open(filename, "r")
569 621
    try:
570 622
      data = stat.read().splitlines()
571 623
    finally:
572 624
      stat.close()
573 625
    if not data:
574
      raise errors.BlockDeviceError("Can't read any data from /proc/drbd")
626
      raise errors.BlockDeviceError("Can't read any data from %s" % filename)
575 627
    return data
576 628

  
577 629
  @staticmethod
......
1089 1141
                   (result.fail_reason, result.output))
1090 1142
    return not result.failed and children_result
1091 1143

  
1144
  def GetProcStatus(self):
1145
    """Return device data from /proc.
1146

  
1147
    """
1148
    if self.minor is None:
1149
      raise errors.BlockDeviceError("GetStats() called while not attached")
1150
    proc_info = self._MassageProcData(self._GetProcData())
1151
    if self.minor not in proc_info:
1152
      raise errors.BlockDeviceError("Can't find myself in /proc (minor %d)" %
1153
                                    self.minor)
1154
    return DRBD8Status(proc_info[self.minor])
1155

  
1092 1156
  def GetSyncStatus(self):
1093 1157
    """Returns the sync status of the device.
1094 1158

  
......
1109 1173
    """
1110 1174
    if self.minor is None and not self.Attach():
1111 1175
      raise errors.BlockDeviceError("Can't attach to device in GetSyncStatus")
1112
    proc_info = self._MassageProcData(self._GetProcData())
1113
    if self.minor not in proc_info:
1114
      raise errors.BlockDeviceError("Can't find myself in /proc (minor %d)" %
1115
                                    self.minor)
1116
    line = proc_info[self.minor]
1117
    match = re.match("^.*sync'ed: *([0-9.]+)%.*"
1118
                     " finish: ([0-9]+):([0-9]+):([0-9]+) .*$", line)
1119
    if match:
1120
      sync_percent = float(match.group(1))
1121
      hours = int(match.group(2))
1122
      minutes = int(match.group(3))
1123
      seconds = int(match.group(4))
1124
      est_time = hours * 3600 + minutes * 60 + seconds
1125
    else:
1126
      sync_percent = None
1127
      est_time = None
1128
    match = re.match("^ *\d+: cs:(\w+).*ds:(\w+)/(\w+).*$", line)
1129
    if not match:
1130
      raise errors.BlockDeviceError("Can't find my data in /proc (minor %d)" %
1131
                                    self.minor)
1132
    client_state = match.group(1)
1133
    local_disk_state = match.group(2)
1134
    ldisk = local_disk_state != "UpToDate"
1135
    is_degraded = client_state != "Connected"
1136
    return sync_percent, est_time, is_degraded or ldisk, ldisk
1176
    stats = self.GetProcStatus()
1177
    ldisk = not stats.is_disk_uptodate
1178
    is_degraded = not stats.is_connected
1179
    return stats.sync_percent, stats.est_time, is_degraded or ldisk, ldisk
1137 1180

  
1138 1181
  def Open(self, force=False):
1139 1182
    """Make the local state primary.

Also available in: Unified diff