def Snapshot(self, snap_name=None, snap_size=None): """Create a snapshot copy of an lvm block device. @returns: tuple (vg, lv) """ if not snap_name: snap_name = self._lv_name + ".snap" if not snap_size: # FIXME: choose a saner value for the snapshot size # let's stay on the safe side and ask for the full size, for now snap_size = self.size # remove existing snapshot if found snap = LogicalVolume((self._vg_name, snap_name), None, snap_size, self.params, self.dyn_params) base.IgnoreError(snap.Remove) vg_info = self.GetVGInfo([self._vg_name], False) if not vg_info: base.ThrowError("Can't compute VG info for vg %s", self._vg_name) free_size, _, _ = vg_info[0] if free_size < snap_size: base.ThrowError("Not enough free space: required %s," " available %s", snap_size, free_size) _CheckResult(utils.RunCmd(["lvcreate", "-L%dm" % snap_size, "-s", "-n%s" % snap_name, self.dev_path])) return (self._vg_name, snap_name)
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 = \ base.IgnoreError(self._ShutdownNet, self.minor) or \ dstatus.ever_disconnected raise utils.RetryAgain()
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: base.ThrowError("drbd%d: disk not attached in re-attach net", self._aminor) if None in (self._lhost, self._lport, self._rhost, self._rport): base.ThrowError( "drbd%d: DRBD disk missing network info in" " DisconnectNet()", self.minor) class _DisconnectStatus(object): def __init__(self, ever_disconnected): self.ever_disconnected = ever_disconnected dstatus = _DisconnectStatus( base.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 = \ base.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" base.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)