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