Beispiel #1
0
  def Grow(self, amount, dryrun, backingstore, excl_stor):
    """Grow the Volume.

    @type amount: integer
    @param amount: the amount (in mebibytes) to grow with
    @type dryrun: boolean
    @param dryrun: whether to execute the operation in simulation mode
        only, without actually increasing the size

    """
    if not backingstore:
      return
    if not self.Attach():
      base.ThrowError("Can't attach to rbd device during Grow()")

    if dryrun:
      # the rbd tool does not support dry runs of resize operations.
      # Since rbd volumes are thinly provisioned, we assume
      # there is always enough free space for the operation.
      return

    rbd_pool = self.params[constants.LDP_POOL]
    rbd_name = self.unique_id[1]
    new_size = self.size + amount

    # Resize the rbd volume (Image) inside the RADOS cluster.
    cmd = self.__class__.MakeRbdCmd(self.params, ["resize", "-p", rbd_pool,
                                                  rbd_name, "--size",
                                                  "%s" % new_size])
    result = utils.RunCmd(cmd)
    if result.failed:
      base.ThrowError("rbd resize failed (%s): %s",
                      result.fail_reason, result.output)
Beispiel #2
0
  def _AssembleLocal(self, minor, backend, meta, size):
    """Configure the local part of a DRBD device.

    @type minor: int
    @param minor: the minor to assemble locally
    @type backend: string
    @param backend: path to the data device to use
    @type meta: string
    @param meta: path to the meta device to use
    @type size: int
    @param size: size in MiB

    """
    cmds = self._cmd_gen.GenLocalInitCmds(minor, backend, meta,
                                          size, self.params)

    for cmd in cmds:
      result = utils.RunCmd(cmd)
      if result.failed:
        base.ThrowError("drbd%d: can't attach local disk: %s",
                        minor, result.output)
   
    # syncer init only for drbd => 8.4 - in 8.4 it must be set after local, not in net
    info = DRBD8.GetProcInfo()
    version = info.GetVersion()
    if version["k_minor"] >= 4:
      sync_errors = self._SetMinorSyncParams(minor, self.params)
      # try second time because disk config for drbd resource may be still uninitialized
      if sync_errors:
        time.sleep(1)
        sync_errors = self._SetMinorSyncParams(minor, self.params)
        if sync_errors:
          base.ThrowError("drbd%d: can't set the synchronization parameters: %s" %
                          (minor, utils.CommaJoin(sync_errors)))
Beispiel #3
0
    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.

    @type multimaster: boolean
    @param multimaster: init the network in dual-primary mode

    """
        if self.minor is None:
            base.ThrowError("drbd%d: device not attached in AttachNet",
                            self._aminor)

        if None in (self._lhost, self._lport, self._rhost, self._rport):
            base.ThrowError("drbd%d: missing network info in AttachNet()",
                            self.minor)

        status = self.GetProcStatus()

        if not status.is_standalone:
            base.ThrowError("drbd%d: device is not standalone in AttachNet",
                            self.minor)

        self._AssembleNet(self.minor,
                          (self._lhost, self._lport, self._rhost, self._rport),
                          dual_pri=multimaster,
                          hmac=constants.DRBD_HMAC_ALG,
                          secret=self._secret)
Beispiel #4
0
  def _ParseLvInfoLine(cls, line, sep):
    """Parse one line of the lvs output used in L{_GetLvInfo}.

    """
    elems = line.strip().split(sep)

    # The previous iteration of code here assumed that LVM might put another
    # separator to the right of the output. The PV info might be empty for
    # thin volumes, so stripping off the separators might cut off the last
    # empty element - do this instead.
    if len(elems) == 7 and elems[-1] == "":
      elems.pop()

    if len(elems) != 6:
      base.ThrowError("Can't parse LVS output, len(%s) != 6", str(elems))

    (status, major, minor, pe_size, stripes, pvs) = elems
    if len(status) < 6:
      base.ThrowError("lvs lv_attr is not at least 6 characters (%s)", status)

    try:
      major = int(major)
      minor = int(minor)
    except (TypeError, ValueError), err:
      base.ThrowError("lvs major/minor cannot be parsed: %s", str(err))
Beispiel #5
0
  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)
Beispiel #6
0
  def _AssembleLocal(self, minor, backend, meta, size):
    """Configure the local part of a DRBD device.

    @type minor: int
    @param minor: the minor to assemble locally
    @type backend: string
    @param backend: path to the data device to use
    @type meta: string
    @param meta: path to the meta device to use
    @type size: int
    @param size: size in MiB

    """
    cmds = self._cmd_gen.GenLocalInitCmds(minor, backend, meta,
                                          size, self.params)

    for cmd in cmds:
      result = utils.RunCmd(cmd)
      if result.failed:
        base.ThrowError("drbd%d: can't attach local disk: %s",
                        minor, result.output)

    def _WaitForMinorSyncParams():
      """Call _SetMinorSyncParams and raise RetryAgain on errors.
      """
      if self._SetMinorSyncParams(minor, self.params):
        raise utils.RetryAgain()

    if self._NeedsLocalSyncerParams():
      # Retry because disk config for DRBD resource may be still uninitialized.
      try:
        utils.Retry(_WaitForMinorSyncParams, 1.0, 5.0)
      except utils.RetryTimeout as e:
        base.ThrowError("drbd%d: can't set the synchronization parameters: %s" %
                        (minor, utils.CommaJoin(e.args[0])))
Beispiel #7
0
  def _MapVolumeToBlockdev(self, unique_id):
    """Maps existing rbd volumes to block devices.

    This method should be idempotent if the mapping already exists.

    @rtype: string
    @return: the block device path that corresponds to the volume

    """
    pool = self.params[constants.LDP_POOL]
    name = unique_id[1]

    # Check if the mapping already exists.
    rbd_dev = self._VolumeToBlockdev(pool, name)
    if rbd_dev:
      # The mapping exists. Return it.
      return rbd_dev

    # The mapping doesn't exist. Create it.
    map_cmd = self.__class__.MakeRbdCmd(self.params, ["map", "-p", pool, name])
    result = utils.RunCmd(map_cmd)
    if result.failed:
      base.ThrowError("rbd map failed (%s): %s",
                      result.fail_reason, result.output)

    # Find the corresponding rbd device.
    rbd_dev = self._VolumeToBlockdev(pool, name)
    if not rbd_dev:
      base.ThrowError("rbd map succeeded, but could not find the rbd block"
                      " device in output of showmapped, for volume: %s", name)

    # The device was successfully mapped. Return it.
    return rbd_dev
Beispiel #8
0
    def RemoveChildren(self, devices):
        """Detach the drbd device from local storage.

    @type devices: list of L{BlockDev}
    @param devices: a list of exactly two L{BlockDev} objects; the first
      denotes the data device, the second the meta device for this DRBD device

    """
        if self.minor is None:
            base.ThrowError(
                "drbd%d: can't attach to drbd8 during RemoveChildren",
                self._aminor)
        # early return if we don't actually have backing storage
        info = self._GetShowInfo(self.minor)
        if "local_dev" not in info:
            return
        if len(self._children) != 2:
            base.ThrowError("drbd%d: we don't have two children: %s",
                            self.minor, self._children)
        if self._children.count(
                None) == 2:  # we don't actually have children :)
            logging.warning("drbd%d: requested detach while detached",
                            self.minor)
            return
        if len(devices) != 2:
            base.ThrowError("drbd%d: we need two children in RemoveChildren",
                            self.minor)
        for child, dev in zip(self._children, devices):
            if dev != child.dev_path:
                base.ThrowError(
                    "drbd%d: mismatch in local storage (%s != %s) in"
                    " RemoveChildren", self.minor, dev, child.dev_path)

        self._ShutdownLocal(self.minor)
        self._children = []
  def Grow(self, amount, dryrun, backingstore, _excl_stor):
    """Grow the file

    @param amount: the amount (in mebibytes) to grow by.

    """
    # Check that the file exists
    self.Exists(assert_exists=True)

    if amount < 0:
      base.ThrowError("%s: can't grow by negative amount", self.path)

    if dryrun:
      return
    if not backingstore:
      return

    current_size = self.Size()
    new_size = current_size + amount * 1024 * 1024
    try:
      f = open(self.path, "a+")
      f.truncate(new_size)
      f.close()
    except EnvironmentError, err:
      base.ThrowError("%s: can't grow: ", self.path, str(err))
Beispiel #10
0
    def _InitMeta(cls, minor, dev_path):
        """Initialize a meta device.

    This will not work if the given minor is in use.

    @type minor: int
    @param minor: the DRBD minor whose (future) meta device should be
      initialized
    @type dev_path: string
    @param dev_path: path to the meta device to initialize

    """
        # Zero the metadata first, in order to make sure drbdmeta doesn't
        # try to auto-detect existing filesystems or similar (see
        # http://code.google.com/p/ganeti/issues/detail?id=182); we only
        # care about the first 128MB of data in the device, even though it
        # can be bigger
        result = utils.RunCmd([
            constants.DD_CMD, "if=/dev/zero",
            "of=%s" % dev_path,
            "bs=%s" % constants.DD_BLOCK_SIZE, "count=128", "oflag=direct"
        ])
        if result.failed:
            base.ThrowError("Can't wipe the meta device: %s", result.output)

        info = DRBD8.GetProcInfo()
        cmd_gen = DRBD8.GetCmdGenerator(info)
        cmd = cmd_gen.GenInitMetaCmd(minor, dev_path)

        result = utils.RunCmd(cmd)
        if result.failed:
            base.ThrowError("Can't initialize meta device: %s", result.output)
Beispiel #11
0
    def _CheckMetaSize(meta_device):
        """Check if the given meta device looks like a valid one.

    This currently only checks the size, which must be around
    128MiB.

    @type meta_device: string
    @param meta_device: the path to the device to check

    """
        result = utils.RunCmd(["blockdev", "--getsize", meta_device])
        if result.failed:
            base.ThrowError("Failed to get device size: %s - %s",
                            result.fail_reason, result.output)
        try:
            sectors = int(result.stdout)
        except (TypeError, ValueError):
            base.ThrowError("Invalid output from blockdev: '%s'",
                            result.stdout)
        num_bytes = sectors * 512
        if num_bytes < 128 * 1024 * 1024:  # less than 128MiB
            base.ThrowError("Meta device too small (%.2fMib)",
                            (num_bytes / 1024 / 1024))
        # the maximum *valid* size of the meta device when living on top
        # of LVM is hard to compute: it depends on the number of stripes
        # and the PE size; e.g. a 2-stripe, 64MB PE will result in a 128MB
        # (normal size), but an eight-stripe 128MB PE will result in a 1GB
        # size meta device; as such, we restrict it to 1GB (a little bit
        # too generous, but making assumptions about PE size is hard)
        if num_bytes > 1024 * 1024 * 1024:
            base.ThrowError("Meta device too big (%.2fMiB)",
                            (num_bytes / 1024 / 1024))
Beispiel #12
0
    def AddChildren(self, devices):
        """Add a disk to the DRBD device.

    @type devices: list of L{BlockDev}
    @param devices: a list of exactly two L{BlockDev} objects; the first
      denotes the data device, the second the meta device for this DRBD device

    """
        if self.minor is None:
            base.ThrowError("drbd%d: can't attach to dbrd8 during AddChildren",
                            self._aminor)
        if len(devices) != 2:
            base.ThrowError("drbd%d: need two devices for AddChildren",
                            self.minor)
        info = self._GetShowInfo(self.minor)
        if "local_dev" in info:
            base.ThrowError("drbd%d: already attached to a local disk",
                            self.minor)
        backend, meta = devices
        if backend.dev_path is None or meta.dev_path is None:
            base.ThrowError("drbd%d: children not ready during AddChildren",
                            self.minor)
        backend.Open()
        meta.Open()
        self._CheckMetaSize(meta.dev_path)
        self._InitMeta(DRBD8.FindUnusedMinor(), meta.dev_path)

        self._AssembleLocal(self.minor, backend.dev_path, meta.dev_path,
                            self.size)
        self._children = devices
Beispiel #13
0
  def _GetLvInfo(cls, dev_path, _run_cmd=utils.RunCmd):
    """Get info about the given existing LV to be used.

    """
    sep = "|"
    result = _run_cmd(["lvs", "--noheadings", "--separator=%s" % sep,
                       "--units=k", "--nosuffix",
                       "-olv_attr,lv_kernel_major,lv_kernel_minor,"
                       "vg_extent_size,stripes,devices", dev_path])
    if result.failed:
      base.ThrowError("Can't find LV %s: %s, %s",
                      dev_path, result.fail_reason, result.output)
    # the output can (and will) have multiple lines for multi-segment
    # LVs, as the 'stripes' parameter is a segment one, so we take
    # only the last entry, which is the one we're interested in; note
    # that with LVM2 anyway the 'stripes' value must be constant
    # across segments, so this is a no-op actually
    out = result.stdout.splitlines()
    if not out: # totally empty result? splitlines() returns at least
                # one line for any non-empty string
      base.ThrowError("Can't parse LVS output, no lines? Got '%s'", str(out))
    pv_names = set()
    for line in out:
      (status, major, minor, pe_size, stripes, more_pvs) = \
        cls._ParseLvInfoLine(line, sep)
      pv_names.update(more_pvs)
    return (status, major, minor, pe_size, stripes, pv_names)
Beispiel #14
0
 def CreateFromFile(filename=constants.DRBD_STATUS_FILE):
   try:
     lines = utils.ReadFile(filename).splitlines()
   except EnvironmentError, err:
     if err.errno == errno.ENOENT:
       base.ThrowError("The file %s cannot be opened, check if the module"
                       " is loaded (%s)", filename, str(err))
     else:
       base.ThrowError("Can't read the DRBD proc file %s: %s",
                       filename, str(err))
Beispiel #15
0
    def _ParseRbdShowmappedPlain(output, volume_name):
        """Parse the (plain / text) output of `rbd showmapped'.

    This method parses the output of `rbd showmapped' and returns
    the rbd block device path (e.g. /dev/rbd0) that matches the
    given rbd volume.

    @type output: string
    @param output: the plain text output of `rbd showmapped'
    @type volume_name: string
    @param volume_name: the name of the volume whose device we search for
    @rtype: string or None
    @return: block device path if the volume is mapped, else None

    """
        allfields = 5
        volumefield = 2
        devicefield = 4

        lines = output.splitlines()

        # Try parsing the new output format (ceph >= 0.55).
        splitted_lines = map(lambda l: l.split(), lines)

        # Check for empty output.
        if not splitted_lines:
            return None

        # Check showmapped output, to determine number of fields.
        field_cnt = len(splitted_lines[0])
        if field_cnt != allfields:
            # Parsing the new format failed. Fallback to parsing the old output
            # format (< 0.55).
            splitted_lines = map(lambda l: l.split("\t"), lines)
            if field_cnt != allfields:
                base.ThrowError(
                    "Cannot parse rbd showmapped output expected %s fields,"
                    " found %s", allfields, field_cnt)

        matched_lines = \
          filter(lambda l: len(l) == allfields and l[volumefield] == volume_name,
                 splitted_lines)

        if len(matched_lines) > 1:
            base.ThrowError("rbd volume %s mapped more than once", volume_name)

        if matched_lines:
            # rbd block device found. Return it.
            rbd_dev = matched_lines[0][devicefield]
            return rbd_dev

        # The given volume is not mapped.
        return None
Beispiel #16
0
 def _GetNetFamily(minor, lhost, rhost):
     if netutils.IP6Address.IsValid(lhost):
         if not netutils.IP6Address.IsValid(rhost):
             base.ThrowError("drbd%d: can't connect ip %s to ip %s" %
                             (minor, lhost, rhost))
         return "ipv6"
     elif netutils.IP4Address.IsValid(lhost):
         if not netutils.IP4Address.IsValid(rhost):
             base.ThrowError("drbd%d: can't connect ip %s to ip %s" %
                             (minor, lhost, rhost))
         return "ipv4"
     else:
         base.ThrowError("drbd%d: Invalid ip %s" % (minor, lhost))
Beispiel #17
0
  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():
      base.ThrowError("drbd%d: can't Attach() in Close()", self._aminor)
    cmd = self._cmd_gen.GenSecondaryCmd(self.minor)
    result = utils.RunCmd(cmd)
    if result.failed:
      base.ThrowError("drbd%d: can't switch drbd device to secondary: %s",
                      self.minor, result.output)
Beispiel #18
0
    def GetProcStatus(self):
        """Return the current status data from /proc/drbd for this device.

    @rtype: DRBD8Status

    """
        if self.minor is None:
            base.ThrowError("drbd%d: GetStats() called while not attached",
                            self._aminor)
        info = DRBD8.GetProcInfo()
        if not info.HasMinorStatus(self.minor):
            base.ThrowError("drbd%d: can't find myself in /proc", self.minor)
        return info.GetMinorStatus(self.minor)
Beispiel #19
0
class DRBD8(object):
    """Various methods to deals with the DRBD system as a whole.

  This class provides a set of methods to deal with the DRBD installation on
  the node or with uninitialized devices as opposed to a DRBD device.

  """
    _USERMODE_HELPER_FILE = "/sys/module/drbd/parameters/usermode_helper"

    _MAX_MINORS = 255

    @staticmethod
    def GetUsermodeHelper(filename=_USERMODE_HELPER_FILE):
        """Returns DRBD usermode_helper currently set.

    @type filename: string
    @param filename: the filename to read the usermode helper from
    @rtype: string
    @return: the currently configured DRBD usermode helper

    """
        try:
            helper = utils.ReadFile(filename).splitlines()[0]
        except EnvironmentError, err:
            if err.errno == errno.ENOENT:
                base.ThrowError(
                    "The file %s cannot be opened, check if the module"
                    " is loaded (%s)", filename, str(err))
            else:
                base.ThrowError("Can't read DRBD helper file %s: %s", filename,
                                str(err))
        if not helper:
            base.ThrowError("Can't read any data from %s", filename)
        return helper
Beispiel #20
0
    def __init__(self, unique_id, children, size, params, dyn_params, *args):
        """Initalizes a file device backend.

    """
        if children:
            base.ThrowError("Invalid setup for file device")

        try:
            driver, path = unique_id
        except ValueError:  # wrong number of arguments
            raise ValueError("Invalid configuration data %s" % repr(unique_id))

        server_addr = params[constants.GLUSTER_HOST]
        port = params[constants.GLUSTER_PORT]
        volume = params[constants.GLUSTER_VOLUME]

        self.volume = GlusterVolume(server_addr, port, volume)
        self.path = path
        self.driver = driver
        self.full_path = io.PathJoin(self.volume.mount_point, self.path)
        self.file = None

        super(GlusterStorage, self).__init__(unique_id, children, size, params,
                                             dyn_params, *args)

        self.Attach()
  def CreateFile(cls, path, size, create_folders=False,
                 _file_path_acceptance_fn=None):
    """Create a new file and its file device helper.

    @param size: the size in MiBs the file should be truncated to.
    @param create_folders: create the directories for the path if necessary
                           (using L{ganeti.utils.io.Makedirs})

    @rtype: FileDeviceHelper
    @return: The FileDeviceHelper object representing the object.
    @raise errors.FileStoragePathError: if the file path is disallowed by policy

    """

    if not _file_path_acceptance_fn:
      _file_path_acceptance_fn = CheckFileStoragePathAcceptance
    _file_path_acceptance_fn(path)

    if create_folders:
      folder = os.path.dirname(path)
      io.Makedirs(folder)

    try:
      fd = os.open(path, os.O_RDWR | os.O_CREAT | os.O_EXCL)
      f = os.fdopen(fd, "w")
      f.truncate(size * 1024 * 1024)
      f.close()
    except EnvironmentError as err:
      base.ThrowError("%s: can't create: %s", path, str(err))

    return FileDeviceHelper(path,
                            _file_path_acceptance_fn=_file_path_acceptance_fn)
Beispiel #22
0
  def Create(cls, unique_id, children, size, spindles, params, excl_stor,
             dyn_params, **kwargs):
    """Create a new rbd device.

    Provision a new rbd volume inside a RADOS pool.

    """
    if not isinstance(unique_id, (tuple, list)) or len(unique_id) != 2:
      raise errors.ProgrammerError("Invalid configuration data %s" %
                                   str(unique_id))
    if excl_stor:
      raise errors.ProgrammerError("RBD device requested with"
                                   " exclusive_storage")
    rbd_pool = params[constants.LDP_POOL]
    rbd_name = unique_id[1]

    # Provision a new rbd volume (Image) inside the RADOS cluster.
    cmd = cls.MakeRbdCmd(params, ["create", "-p", rbd_pool, rbd_name,
                                  "--size", str(size)])
    result = utils.RunCmd(cmd)
    if result.failed:
      base.ThrowError("rbd creation failed (%s): %s",
                      result.fail_reason, result.output)

    return RADOSBlockDevice(unique_id, children, size, params, dyn_params,
                            **kwargs)
Beispiel #23
0
    def Grow(self, amount, dryrun, backingstore, excl_stor):
        """Grow the Volume.

    @type amount: integer
    @param amount: the amount (in mebibytes) to grow with
    @type dryrun: boolean
    @param dryrun: whether to execute the operation in simulation mode
        only, without actually increasing the size

    """
        if not backingstore:
            return
        if not self.Attach():
            base.ThrowError("Can't attach to extstorage device during Grow()")

        if dryrun:
            # we do not support dry runs of resize operations for now.
            return

        new_size = self.size + amount

        # Call the External Storage's grow script,
        # to grow an existing Volume inside the External Storage
        _ExtStorageAction(constants.ES_ACTION_GROW,
                          self.unique_id,
                          self.ext_params,
                          size=self.size,
                          grow=new_size,
                          name=self.name,
                          uuid=self.uuid)
Beispiel #24
0
def _CheckExtStorageFile(base_dir, filename, required):
    """Check prereqs for an ExtStorage file.

  Check if file exists, if it is a regular file and in case it is
  one of extstorage scripts if it is executable.

  @type base_dir: string
  @param base_dir: Base directory containing ExtStorage installations.
  @type filename: string
  @param filename: The basename of the ExtStorage file.
  @type required: bool
  @param required: Whether the file is required or not.

  @rtype: String
  @return: The file path if the file is found and is valid,
           None if the file is not found and not required.

  @raises BlockDeviceError: In case prereqs are not met
    (found and not valid/executable, not found and required)

  """

    file_path = utils.PathJoin(base_dir, filename)
    try:
        st = os.stat(file_path)
    except EnvironmentError, err:
        if not required:
            logging.info("Optional file '%s' under path '%s' is missing",
                         filename, base_dir)
            return None

        base.ThrowError("File '%s' under path '%s' is missing (%s)" %
                        (filename, base_dir, utils.ErrnoOrStr(err)))
Beispiel #25
0
  def _VolumeToBlockdev(cls, pool, volume_name):
    """Do the 'volume name'-to-'rbd block device' resolving.

    @type pool: string
    @param pool: RADOS pool to use
    @type volume_name: string
    @param volume_name: the name of the volume whose device we search for
    @rtype: string or None
    @return: block device path if the volume is mapped, else None

    """
    try:
      # Newer versions of the rbd tool support json output formatting. Use it
      # if available.
      showmap_cmd = cls.MakeRbdCmd({}, ["showmapped", "--format", "json"])
      result = utils.RunCmd(showmap_cmd)
      if result.failed:
        logging.error("rbd JSON output formatting returned error (%s): %s,"
                      "falling back to plain output parsing",
                      result.fail_reason, result.output)
        raise RbdShowmappedJsonError

      return cls._ParseRbdShowmappedJson(result.output, pool, volume_name)
    except RbdShowmappedJsonError:
      # For older versions of rbd, we have to parse the plain / text output
      # manually.
      showmap_cmd = cls.MakeRbdCmd({}, ["showmapped", "-p", pool])
      result = utils.RunCmd(showmap_cmd)
      if result.failed:
        base.ThrowError("rbd showmapped failed (%s): %s",
                        result.fail_reason, result.output)

      return cls._ParseRbdShowmappedPlain(result.output, volume_name)
Beispiel #26
0
  def GetDevInfo(cls, show_data):
    """Parse details about a given DRBD minor.

    This returns, if available, the local backing device (as a path)
    and the local and remote (ip, port) information from a string
    containing the output of the `drbdsetup show` command as returned
    by DRBD8Dev._GetShowData.

    This will return a dict with keys:
      - local_dev
      - meta_dev
      - meta_index
      - local_addr
      - remote_addr

    """
    if not show_data:
      return {}

    try:
      # run pyparse
      results = (cls._GetShowParser()).parseString(show_data)
    except pyp.ParseException as err:
      base.ThrowError("Can't parse drbdsetup show output: %s", str(err))

    return cls._TransformParseResult(results)
Beispiel #27
0
  def Import(self):
    """Builds the shell command for importing data to device.

    @see: L{BlockDev.Import} for details

    """
    base.ThrowError("Importing data is not supported for the"
                    " PersistentBlockDevice template")
Beispiel #28
0
def _CheckResult(result):
  """Throws an error if the given result is a failed one.

  @param result: result from RunCmd

  """
  if result.failed:
    base.ThrowError("Command: %s error: %s - %s",
                    result.cmd, result.fail_reason, result.output)
Beispiel #29
0
    def _ParseLvInfoLine(cls, line, sep):
        """Parse one line of the lvs output used in L{_GetLvInfo}.

    """
        elems = line.strip().rstrip(sep).split(sep)
        if len(elems) != 6:
            base.ThrowError("Can't parse LVS output, len(%s) != 6", str(elems))

        (status, major, minor, pe_size, stripes, pvs) = elems
        if len(status) < 6:
            base.ThrowError("lvs lv_attr is not at least 6 characters (%s)",
                            status)

        try:
            major = int(major)
            minor = int(minor)
        except (TypeError, ValueError), err:
            base.ThrowError("lvs major/minor cannot be parsed: %s", str(err))
Beispiel #30
0
  def GetUsermodeHelper(filename=_USERMODE_HELPER_FILE):
    """Returns DRBD usermode_helper currently set.

    @type filename: string
    @param filename: the filename to read the usermode helper from
    @rtype: string
    @return: the currently configured DRBD usermode helper

    """
    try:
      helper = utils.ReadFile(filename).splitlines()[0]
    except EnvironmentError, err:
      if err.errno == errno.ENOENT:
        base.ThrowError("The file %s cannot be opened, check if the module"
                        " is loaded (%s)", filename, str(err))
      else:
        base.ThrowError("Can't read DRBD helper file %s: %s",
                        filename, str(err))