X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/f96e3c4f756dfbe4cd63f77d5a5d06a7ae09be2b..a162cf5b6e67d48b048df0cd03bdaeb8e5bbdb70:/lib/bdev.py diff --git a/lib/bdev.py b/lib/bdev.py index 14f1e5c..834d7b3 100644 --- a/lib/bdev.py +++ b/lib/bdev.py @@ -275,7 +275,8 @@ class LogicalVolume(BlockDev): """ if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2: - raise ValueError("Invalid configuration data %s" % str(unique_id)) + raise errors.ProgrammerError("Invalid configuration data %s" % + str(unique_id)) vg_name, lv_name = unique_id pvs_info = cls.GetPVInfo(vg_name) if not pvs_info: @@ -295,8 +296,8 @@ class LogicalVolume(BlockDev): result = utils.RunCmd(["lvcreate", "-L%dm" % size, "-n%s" % lv_name, vg_name] + pvlist) if result.failed: - raise errors.BlockDeviceError("%s - %s" % (result.fail_reason, - result.output)) + raise errors.BlockDeviceError("LV create failed (%s): %s" % + (result.fail_reason, result.output)) return LogicalVolume(unique_id, children) @staticmethod @@ -539,20 +540,28 @@ class DRBD8Status(object): Note that this doesn't support unconfigured devices (cs:Unconfigured). """ + UNCONF_RE = re.compile(r"\s*[0-9]+:\s*cs:Unconfigured$") LINE_RE = re.compile(r"\s*[0-9]+:\s*cs:(\S+)\s+st:([^/]+)/(\S+)" "\s+ds:([^/]+)/(\S+)\s+.*$") SYNC_RE = re.compile(r"^.*\ssync'ed:\s*([0-9.]+)%.*" "\sfinish: ([0-9]+):([0-9]+):([0-9]+)\s.*$") def __init__(self, procline): - m = self.LINE_RE.match(procline) - if not m: - raise errors.BlockDeviceError("Can't parse input data '%s'" % procline) - self.cstatus = m.group(1) - self.lrole = m.group(2) - self.rrole = m.group(3) - self.ldisk = m.group(4) - self.rdisk = m.group(5) + u = self.UNCONF_RE.match(procline) + if u: + self.cstatus = "Unconfigured" + self.lrole = self.rrole = self.ldisk = self.rdisk = None + else: + m = self.LINE_RE.match(procline) + if not m: + raise errors.BlockDeviceError("Can't parse input data '%s'" % procline) + self.cstatus = m.group(1) + self.lrole = m.group(2) + self.rrole = m.group(3) + self.ldisk = m.group(4) + self.rdisk = m.group(5) + + # end reading of data from the LINE_RE or UNCONF_RE self.is_standalone = self.cstatus == "StandAlone" self.is_wfconn = self.cstatus == "WFConnection" @@ -567,6 +576,9 @@ class DRBD8Status(object): self.is_diskless = self.ldisk == "Diskless" self.is_disk_uptodate = self.ldisk == "UpToDate" + self.is_in_resync = self.cstatus in ("SyncSource", "SyncTarget") + self.is_in_use = self.cstatus != "Unconfigured" + m = self.SYNC_RE.match(procline) if m: self.sync_percent = float(m.group(1)) @@ -680,7 +692,7 @@ class BaseDRBD(BlockDev): return "/dev/drbd%d" % minor @classmethod - def _GetUsedDevs(cls): + def GetUsedDevs(cls): """Compute the list of used DRBD devices. """ @@ -836,21 +848,6 @@ class DRBD8(BaseDRBD): return highest + 1 @classmethod - def _IsValidMeta(cls, meta_device): - """Check if the given meta device looks like a valid one. - - """ - minor = cls._FindUnusedMinor() - minor_path = cls._DevPath(minor) - result = utils.RunCmd(["drbdmeta", minor_path, - "v08", meta_device, "0", - "dstate"]) - if result.failed: - logging.error("Invalid meta device %s: %s", meta_device, result.output) - return False - return True - - @classmethod def _GetShowParser(cls): """Return a parser for `drbd show` output. @@ -1011,12 +1008,7 @@ class DRBD8(BaseDRBD): def _AssembleLocal(cls, minor, backend, meta): """Configure the local part of a DRBD device. - This is the first thing that must be done on an unconfigured DRBD - device. And it must be done only once. - """ - if not cls._IsValidMeta(meta): - return False args = ["drbdsetup", cls._DevPath(minor), "disk", backend, meta, "0", "-e", "detach", "--create-device"] result = utils.RunCmd(args) @@ -1097,8 +1089,6 @@ class DRBD8(BaseDRBD): if not self._CheckMetaSize(meta.dev_path): raise errors.BlockDeviceError("Invalid meta device size") self._InitMeta(self._FindUnusedMinor(), meta.dev_path) - if not self._IsValidMeta(meta.dev_path): - raise errors.BlockDeviceError("Cannot initalize meta device") if not self._AssembleLocal(self.minor, backend.dev_path, meta.dev_path): raise errors.BlockDeviceError("Can't attach to local storage") @@ -1331,7 +1321,7 @@ class DRBD8(BaseDRBD): /proc). """ - used_devs = self._GetUsedDevs() + used_devs = self.GetUsedDevs() if self._aminor in used_devs: minor = self._aminor else: @@ -1522,15 +1512,24 @@ class DRBD8(BaseDRBD): """ if len(children) != 2: raise errors.ProgrammerError("Invalid setup for the drbd device") + # check that the minor is unused + aminor = unique_id[4] + proc_info = cls._MassageProcData(cls._GetProcData()) + if aminor in proc_info: + status = DRBD8Status(proc_info[aminor]) + in_use = status.is_in_use + else: + in_use = False + if in_use: + raise errors.BlockDeviceError("DRBD minor %d already in use at" + " Create() time" % aminor) meta = children[1] meta.Assemble() if not meta.Attach(): raise errors.BlockDeviceError("Can't attach to meta device") if not cls._CheckMetaSize(meta.dev_path): raise errors.BlockDeviceError("Invalid meta device size") - cls._InitMeta(cls._FindUnusedMinor(), meta.dev_path) - if not cls._IsValidMeta(meta.dev_path): - raise errors.BlockDeviceError("Cannot initalize meta device") + cls._InitMeta(aminor, meta.dev_path) return cls(unique_id, children) def Grow(self, amount): @@ -1644,16 +1643,17 @@ class FileStorage(BlockDev): @return: an instance of FileStorage """ + # TODO: decide whether we should check for existing files and + # abort or not if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2: raise ValueError("Invalid configuration data %s" % str(unique_id)) dev_path = unique_id[1] try: f = open(dev_path, 'w') - except IOError, err: - raise errors.BlockDeviceError("Could not create '%'" % err) - else: f.truncate(size * 1024 * 1024) f.close() + except IOError, err: + raise errors.BlockDeviceError("Error in file creation: %" % str(err)) return FileStorage(unique_id, children)