+ self.Attach()
+ if self.minor is None:
+ # local device completely unconfigured
+ return self._FastAssemble()
+ else:
+ # we have to recheck the local and network status and try to fix
+ # the device
+ return self._SlowAssemble()
+
+ def _SlowAssemble(self):
+ """Assembles the DRBD device from a (partially) configured device.
+
+ 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._aminor,):
+ 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),
+ constants.DRBD_NET_PROTOCOL,
+ hmac=constants.DRBD_HMAC_ALG,
+ secret=self._secret
+ )
+ 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),
+ constants.DRBD_NET_PROTOCOL,
+ hmac=constants.DRBD_HMAC_ALG,
+ secret=self._secret) and
+ self._MatchesNet(self._GetDevInfo(self._GetShowData(minor)))):
+ break
+
+ else:
+ minor = None
+
+ self._SetFromMinor(minor)
+ return minor is not None
+
+ def _FastAssemble(self):
+ """Assemble the drbd device from zero.
+
+ This is run when in Assemble we detect our minor is unused.
+
+ """
+ # TODO: maybe completely tear-down the minor (drbdsetup ... down)
+ # before attaching our own?
+ minor = self._aminor