+ if self.minor is None and not self.Attach():
+ raise errors.BlockDeviceError("Can't attach to device in GetSyncStatus")
+ stats = self.GetProcStatus()
+ ldisk = not stats.is_disk_uptodate
+ is_degraded = not stats.is_connected
+ return stats.sync_percent, stats.est_time, is_degraded or ldisk, ldisk
+
+ def Open(self, force=False):
+ """Make the local state primary.
+
+ If the 'force' parameter is given, the '-o' option is passed to
+ drbdsetup. Since this is a potentially dangerous operation, the
+ force flag should be only given after creation, when it actually
+ is mandatory.
+
+ """
+ if self.minor is None and not self.Attach():
+ logging.error("DRBD cannot attach to a device during open")
+ return False
+ cmd = ["drbdsetup", self.dev_path, "primary"]
+ if force:
+ cmd.append("-o")
+ result = utils.RunCmd(cmd)
+ if result.failed:
+ msg = ("Can't make drbd device primary: %s" % result.output)
+ logging.error(msg)
+ raise errors.BlockDeviceError(msg)
+
+ def Close(self):
+ """Make the local state secondary.
+
+ This will, of course, fail if the device is in use.
+
+ """
+ if self.minor is None and not self.Attach():
+ logging.info("Instance not attached to a device")
+ raise errors.BlockDeviceError("Can't find device")
+ result = utils.RunCmd(["drbdsetup", self.dev_path, "secondary"])
+ if result.failed:
+ msg = ("Can't switch drbd device to"
+ " secondary: %s" % result.output)
+ logging.error(msg)
+ raise errors.BlockDeviceError(msg)
+
+ def Attach(self):
+ """Find a DRBD device which matches our config and attach to it.
+
+ In case of partially attached (local device matches but no network
+ setup), we perform the network attach. If successful, we re-test
+ the attach if can return success.
+
+ """
+ for minor in self._GetUsedDevs():
+ info = self._GetDevInfo(self._GetShowData(minor))
+ match_l = self._MatchesLocal(info)
+ match_r = self._MatchesNet(info)
+ if match_l and match_r:
+ break
+ if match_l and not match_r and "local_addr" not in info:
+ res_r = self._AssembleNet(minor,
+ (self._lhost, self._lport,
+ self._rhost, self._rport),
+ "C")
+ if res_r:
+ if self._MatchesNet(self._GetDevInfo(self._GetShowData(minor))):
+ break
+ # the weakest case: we find something that is only net attached
+ # even though we were passed some children at init time
+ if match_r and "local_dev" not in info:
+ break
+
+ # this case must be considered only if we actually have local
+ # storage, i.e. not in diskless mode, because all diskless
+ # devices are equal from the point of view of local
+ # configuration
+ if (match_l and "local_dev" in info and
+ not match_r and "local_addr" in info):
+ # strange case - the device network part points to somewhere
+ # else, even though its local storage is ours; as we own the
+ # drbd space, we try to disconnect from the remote peer and
+ # reconnect to our correct one
+ if not self._ShutdownNet(minor):
+ raise errors.BlockDeviceError("Device has correct local storage,"
+ " wrong remote peer and is unable to"
+ " disconnect in order to attach to"
+ " the correct peer")
+ # note: _AssembleNet also handles the case when we don't want
+ # local storage (i.e. one or more of the _[lr](host|port) is
+ # None)
+ if (self._AssembleNet(minor, (self._lhost, self._lport,
+ self._rhost, self._rport), "C") and
+ self._MatchesNet(self._GetDevInfo(self._GetShowData(minor)))):
+ break
+