+ _ThrowError("drbd%d: can't switch drbd device to secondary: %s",
+ self.minor, result.output)
+
+ def DisconnectNet(self):
+ """Removes network configuration.
+
+ This method shutdowns the network side of the device.
+
+ The method will wait up to a hardcoded timeout for the device to
+ go into standalone after the 'disconnect' command before
+ re-configuring it, as sometimes it takes a while for the
+ disconnect to actually propagate and thus we might issue a 'net'
+ command while the device is still connected. If the device will
+ still be attached to the network and we time out, we raise an
+ exception.
+
+ """
+ if self.minor is None:
+ _ThrowError("drbd%d: disk not attached in re-attach net", self._aminor)
+
+ if None in (self._lhost, self._lport, self._rhost, self._rport):
+ _ThrowError("drbd%d: DRBD disk missing network info in"
+ " DisconnectNet()", self.minor)
+
+ class _DisconnectStatus:
+ def __init__(self, ever_disconnected):
+ self.ever_disconnected = ever_disconnected
+
+ dstatus = _DisconnectStatus(_IgnoreError(self._ShutdownNet, self.minor))
+
+ def _WaitForDisconnect():
+ if self.GetProcStatus().is_standalone:
+ return
+
+ # retry the disconnect, it seems possible that due to a well-time
+ # disconnect on the peer, my disconnect command might be ignored and
+ # forgotten
+ dstatus.ever_disconnected = \
+ _IgnoreError(self._ShutdownNet, self.minor) or dstatus.ever_disconnected
+
+ raise utils.RetryAgain()
+
+ # Keep start time
+ start_time = time.time()
+
+ try:
+ # Start delay at 100 milliseconds and grow up to 2 seconds
+ utils.Retry(_WaitForDisconnect, (0.1, 1.5, 2.0),
+ self._NET_RECONFIG_TIMEOUT)
+ except utils.RetryTimeout:
+ if dstatus.ever_disconnected:
+ msg = ("drbd%d: device did not react to the"
+ " 'disconnect' command in a timely manner")
+ else:
+ msg = "drbd%d: can't shutdown network, even after multiple retries"
+
+ _ThrowError(msg, self.minor)
+
+ reconfig_time = time.time() - start_time
+ if reconfig_time > (self._NET_RECONFIG_TIMEOUT * 0.25):
+ logging.info("drbd%d: DisconnectNet: detach took %.3f seconds",
+ self.minor, reconfig_time)
+
+ def AttachNet(self, multimaster):
+ """Reconnects the network.
+
+ This method connects the network side of the device with a
+ specified multi-master flag. The device needs to be 'Standalone'
+ but have valid network configuration data.
+
+ Args:
+ - multimaster: init the network in dual-primary mode
+
+ """
+ if self.minor is None:
+ _ThrowError("drbd%d: device not attached in AttachNet", self._aminor)
+
+ if None in (self._lhost, self._lport, self._rhost, self._rport):
+ _ThrowError("drbd%d: missing network info in AttachNet()", self.minor)
+
+ status = self.GetProcStatus()
+
+ if not status.is_standalone:
+ _ThrowError("drbd%d: device is not standalone in AttachNet", self.minor)
+
+ self._AssembleNet(self.minor,
+ (self._lhost, self._lport, self._rhost, self._rport),
+ constants.DRBD_NET_PROTOCOL, dual_pri=multimaster,
+ hmac=constants.DRBD_HMAC_ALG, secret=self._secret)