#
#
-# Copyright (C) 2006, 2007, 2010, 2011 Google Inc.
+# Copyright (C) 2006, 2007, 2010, 2011, 2012 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
from ganeti import objects
from ganeti import compat
from ganeti import netutils
+from ganeti import pathutils
# Size of reads in _CanReadDevice
return False
+def _CheckFileStoragePath(path, allowed):
+ """Checks if a path is in a list of allowed paths for file storage.
+
+ @type path: string
+ @param path: Path to check
+ @type allowed: list
+ @param allowed: List of allowed paths
+ @raise errors.FileStoragePathError: If the path is not allowed
+
+ """
+ if not os.path.isabs(path):
+ raise errors.FileStoragePathError("File storage path must be absolute,"
+ " got '%s'" % path)
+
+ for i in allowed:
+ if not os.path.isabs(i):
+ logging.info("Ignoring relative path '%s' for file storage", i)
+ continue
+
+ if utils.IsBelowDir(i, path):
+ break
+ else:
+ raise errors.FileStoragePathError("Path '%s' is not acceptable for file"
+ " storage" % path)
+
+
+def LoadAllowedFileStoragePaths(filename):
+ """Loads file containing allowed file storage paths.
+
+ @rtype: list
+ @return: List of allowed paths (can be an empty list)
+
+ """
+ try:
+ contents = utils.ReadFile(filename)
+ except EnvironmentError:
+ return []
+ else:
+ return utils.FilterEmptyLinesAndComments(contents)
+
+
+def CheckFileStoragePath(path, _filename=pathutils.FILE_STORAGE_PATHS_FILE):
+ """Checks if a path is allowed for file storage.
+
+ @type path: string
+ @param path: Path to check
+ @raise errors.FileStoragePathError: If the path is not allowed
+
+ """
+ _CheckFileStoragePath(path, LoadAllowedFileStoragePaths(_filename))
+
+
class BlockDev(object):
"""Block device abstract class.
for child in self._children:
child.SetInfo(text)
- def Grow(self, amount, dryrun):
+ def Grow(self, amount, dryrun, backingstore):
"""Grow the block device.
@type amount: integer
@type dryrun: boolean
@param dryrun: whether to execute the operation in simulation mode
only, without actually increasing the size
+ @param backingstore: whether to execute the operation on backing storage
+ only, or on "logical" storage only; e.g. DRBD is logical storage,
+ whereas LVM, file, RBD are backing storage
"""
raise NotImplementedError
return False
status, major, minor, pe_size, stripes = out
- if len(status) != 6:
- logging.error("lvs lv_attr is not 6 characters (%s)", status)
+ if len(status) < 6:
+ logging.error("lvs lv_attr is not at least 6 characters (%s)", status)
return False
try:
_ThrowError("Command: %s error: %s - %s", result.cmd, result.fail_reason,
result.output)
- def Grow(self, amount, dryrun):
+ def Grow(self, amount, dryrun, backingstore):
"""Grow the logical volume.
"""
+ if not backingstore:
+ return
if self.pe_size is None or self.stripe_count is None:
if not self.Attach():
_ThrowError("Can't attach to LV during Grow()")
first_line)
values = version.groups()
- retval = {"k_major": int(values[0]),
- "k_minor": int(values[1]),
- "k_point": int(values[2]),
- "api": int(values[3]),
- "proto": int(values[4]),
- }
+ retval = {
+ "k_major": int(values[0]),
+ "k_minor": int(values[1]),
+ "k_point": int(values[2]),
+ "api": int(values[3]),
+ "proto": int(values[4]),
+ }
if values[5] is not None:
retval["proto2"] = values[5]
def _CheckMetaSize(meta_device):
"""Check if the given meta device looks like a valid one.
- This currently only check the size, which must be around
+ This currently only checks the size, which must be around
128MiB.
"""
doesn't do anything to the supposed peer. If you need a fully
connected DRBD pair, you need to use this class on both hosts.
- The unique_id for the drbd device is the (local_ip, local_port,
- remote_ip, remote_port) tuple, and it must have two children: the
- data device and the meta_device. The meta device is checked for
- valid size and is zeroed on create.
+ The unique_id for the drbd device is a (local_ip, local_port,
+ remote_ip, remote_port, local_minor, secret) tuple, and it must have
+ two children: the data device and the meta_device. The meta device
+ is checked for valid size and is zeroed on create.
"""
_MAX_MINORS = 255
def _GetShowParser(cls):
"""Return a parser for `drbd show` output.
- This will either create or return an already-create parser for the
+ This will either create or return an already-created parser for the
output of the command `drbd show`.
"""
defa = pyp.Literal("_is_default").suppress()
dbl_quote = pyp.Literal('"').suppress()
- keyword = pyp.Word(pyp.alphanums + '-')
+ keyword = pyp.Word(pyp.alphanums + "-")
# value types
- value = pyp.Word(pyp.alphanums + '_-/.:')
+ value = pyp.Word(pyp.alphanums + "_-/.:")
quoted = dbl_quote + pyp.CharsNotIn('"') + dbl_quote
ipv4_addr = (pyp.Optional(pyp.Literal("ipv4")).suppress() +
pyp.Word(pyp.nums + ".") + colon + number)
@classmethod
def _ComputeDiskBarrierArgs(cls, vmaj, vmin, vrel, disabled_barriers,
- disable_meta_flush):
+ disable_meta_flush):
"""Compute the DRBD command line parameters for disk barriers
Returns a list of the disk barrier parameters as requested via the
"--c-delay-target", params[constants.LDP_DELAY_TARGET],
"--c-max-rate", params[constants.LDP_MAX_RATE],
"--c-min-rate", params[constants.LDP_MIN_RATE],
- ])
+ ])
else:
args.extend(["-r", "%d" % params[constants.LDP_RESYNC_RATE]])
msg = ("Can't change syncer rate: %s - %s" %
(result.fail_reason, result.output))
logging.error(msg)
- return msg
+ return [msg]
return []
cls._InitMeta(aminor, meta.dev_path)
return cls(unique_id, children, size, params)
- def Grow(self, amount, dryrun):
+ def Grow(self, amount, dryrun, backingstore):
"""Resize the DRBD device and its backing storage.
"""
_ThrowError("drbd%d: Grow called while not attached", self._aminor)
if len(self._children) != 2 or None in self._children:
_ThrowError("drbd%d: cannot grow diskless device", self.minor)
- self._children[0].Grow(amount, dryrun)
- if dryrun:
- # DRBD does not support dry-run mode, so we'll return here
+ self._children[0].Grow(amount, dryrun, backingstore)
+ if dryrun or backingstore:
+ # DRBD does not support dry-run mode and is not backing storage,
+ # so we'll return here
return
result = utils.RunCmd(["drbdsetup", self.dev_path, "resize", "-s",
"%dm" % (self.size + amount)])
# TODO: implement rename for file-based storage
_ThrowError("Rename is not supported for file-based storage")
- def Grow(self, amount, dryrun):
+ def Grow(self, amount, dryrun, backingstore):
"""Grow the file
@param amount: the amount (in mebibytes) to grow with
"""
+ if not backingstore:
+ return
# Check that the file exists
self.Assemble()
current_size = self.GetActualSize()
"""
pass
- def Grow(self, amount, dryrun):
+ def Grow(self, amount, dryrun, backingstore):
"""Grow the logical volume.
"""
"""
pass
- def Grow(self, amount, dryrun):
+ def Grow(self, amount, dryrun, backingstore):
"""Grow the Volume.
@type amount: integer
only, without actually increasing the size
"""
+ if not backingstore:
+ return
if not self.Attach():
_ThrowError("Can't attach to rbd device during Grow()")
raise errors.ProgrammerError("Invalid block device type '%s'" % dev_type)
+def _VerifyDiskParams(disk):
+ """Verifies if all disk parameters are set.
+
+ """
+ missing = set(constants.DISK_LD_DEFAULTS[disk.dev_type]) - set(disk.params)
+ if missing:
+ raise errors.ProgrammerError("Block device is missing disk parameters: %s" %
+ missing)
+
+
def FindDevice(disk, children):
"""Search for an existing, assembled device.
"""
_VerifyDiskType(disk.dev_type)
- dev_params = objects.FillDict(constants.DISK_LD_DEFAULTS[disk.dev_type],
- disk.params)
device = DEV_MAP[disk.dev_type](disk.physical_id, children, disk.size,
- dev_params)
+ disk.params)
if not device.attached:
return None
return device
"""
_VerifyDiskType(disk.dev_type)
- dev_params = objects.FillDict(constants.DISK_LD_DEFAULTS[disk.dev_type],
- disk.params)
+ _VerifyDiskParams(disk)
device = DEV_MAP[disk.dev_type](disk.physical_id, children, disk.size,
- dev_params)
+ disk.params)
device.Assemble()
return device
"""
_VerifyDiskType(disk.dev_type)
- dev_params = objects.FillDict(constants.DISK_LD_DEFAULTS[disk.dev_type],
- disk.params)
+ _VerifyDiskParams(disk)
device = DEV_MAP[disk.dev_type].Create(disk.physical_id, children, disk.size,
- dev_params)
+ disk.params)
return device