Commit 7c848a6a authored by Bernardo Dal Seno's avatar Bernardo Dal Seno

Spindles are mandatory with exclusive storage

If they are not specified in the command line an error is reported. Also,
disk creation would fail without them.

QA has been updated.
Signed-off-by: default avatarBernardo Dal Seno <bdalseno@google.com>
Reviewed-by: default avatarHelga Velroyen <helgav@google.com>
parent 40d93e3b
......@@ -1032,7 +1032,7 @@ class LUInstanceCreate(LogicalUnit):
" exclusive storage" % self.op.disk_template,
errors.ECODE_STATE)
for disk in self.disks:
CheckSpindlesExclusiveStorage(disk, excl_stor)
CheckSpindlesExclusiveStorage(disk, excl_stor, True)
nodenames = [pnode.name] + self.secondaries
......@@ -2241,7 +2241,7 @@ class LUInstanceSetParams(LogicalUnit):
if name is not None and name.lower() == constants.VALUE_NONE:
params[constants.IDISK_NAME] = None
CheckSpindlesExclusiveStorage(params, excl_stor)
CheckSpindlesExclusiveStorage(params, excl_stor, True)
elif op == constants.DDM_MODIFY:
if constants.IDISK_SIZE in params:
......
......@@ -519,13 +519,15 @@ def GenerateDiskTemplate(
return disks
def CheckSpindlesExclusiveStorage(diskdict, es_flag):
def CheckSpindlesExclusiveStorage(diskdict, es_flag, required):
"""Check the presence of the spindle options with exclusive_storage.
@type diskdict: dict
@param diskdict: disk parameters
@type es_flag: bool
@param es_flag: the effective value of the exlusive_storage flag
@type required: bool
@param required: whether spindles are required or just optional
@raise errors.OpPrereqError when spindles are given and they should not
"""
......@@ -534,6 +536,11 @@ def CheckSpindlesExclusiveStorage(diskdict, es_flag):
raise errors.OpPrereqError("Spindles in instance disks cannot be specified"
" when exclusive storage is not active",
errors.ECODE_INVAL)
if (es_flag and required and (constants.IDISK_SPINDLES not in diskdict or
diskdict[constants.IDISK_SPINDLES] is None)):
raise errors.OpPrereqError("You must specify spindles in instance disks"
" when exclusive storage is active",
errors.ECODE_INVAL)
class LUInstanceRecreateDisks(LogicalUnit):
......@@ -787,7 +794,7 @@ class LUInstanceRecreateDisks(LogicalUnit):
rpc.GetExclusiveStorageForNodeNames(self.cfg, nodes).values()
)
for new_params in self.disks.values():
CheckSpindlesExclusiveStorage(new_params, excl_stor)
CheckSpindlesExclusiveStorage(new_params, excl_stor, False)
def Exec(self, feedback_fn):
"""Recreate the disks.
......
......@@ -262,18 +262,21 @@ class LogicalVolume(base.BlockDev):
stripes = min(current_pvs, desired_stripes)
if excl_stor:
if spindles is None:
base.ThrowError("Unspecified number of spindles: this is required"
"when exclusive storage is enabled, try running"
" gnt-cluster repair-disk-sizes")
(err_msgs, _) = utils.LvmExclusiveCheckNodePvs(pvs_info)
if err_msgs:
for m in err_msgs:
logging.warning(m)
req_pvs = cls._ComputeNumPvs(size, pvs_info)
if spindles:
if spindles < req_pvs:
base.ThrowError("Requested number of spindles (%s) is not enough for"
" a disk of %d MB (at least %d spindles needed)",
spindles, size, req_pvs)
else:
req_pvs = spindles
if spindles < req_pvs:
base.ThrowError("Requested number of spindles (%s) is not enough for"
" a disk of %d MB (at least %d spindles needed)",
spindles, size, req_pvs)
else:
req_pvs = spindles
pvlist = cls._GetEmptyPvNames(pvs_info, req_pvs)
current_pvs = len(pvlist)
if current_pvs < req_pvs:
......
......@@ -630,10 +630,22 @@ def TestInstanceModifyDisks(instance):
print qa_utils.FormatInfo("Instance doesn't support disks, skipping test")
return
size = qa_config.GetDiskOptions()[-1].get("size")
disk_conf = qa_config.GetDiskOptions()[-1]
size = disk_conf.get("size")
name = instance.name
build_cmd = lambda arg: ["gnt-instance", "modify", "--disk", arg, name]
AssertCommand(build_cmd("add:size=%s" % size))
if qa_config.AreSpindlesSupported():
spindles = disk_conf.get("spindles")
spindles_supported = True
else:
# Any number is good for spindles in this case
spindles = 1
spindles_supported = False
AssertCommand(build_cmd("add:size=%s,spindles=%s" % (size, spindles)),
fail=not spindles_supported)
AssertCommand(build_cmd("add:size=%s" % size),
fail=spindles_supported)
# Exactly one of the above commands has succeded, so we need one remove
AssertCommand(build_cmd("remove"))
......@@ -681,6 +693,8 @@ def TestInstanceDeviceNames(instance):
for dev_type in ["disk", "net"]:
if dev_type == "disk":
options = ",size=512M"
if qa_config.AreSpindlesSupported():
options += ",spindles=1"
else:
options = ""
# succeed in adding a device named 'test_device'
......@@ -806,6 +820,33 @@ def _AssertRecreateDisks(cmdargs, instance, fail=False, check=True,
AssertCommand(["gnt-instance", "deactivate-disks", instance.name])
def _BuildRecreateDisksOpts(en_disks, with_spindles, with_growth,
spindles_supported):
if with_spindles:
if spindles_supported:
if with_growth:
build_spindles_opt = (lambda disk:
",spindles=%s" %
(disk["spindles"] + disk["spindles-growth"]))
else:
build_spindles_opt = (lambda disk:
",spindles=%s" % disk["spindles"])
else:
build_spindles_opt = (lambda _: ",spindles=1")
else:
build_spindles_opt = (lambda _: "")
if with_growth:
build_size_opt = (lambda disk:
"size=%s" % (utils.ParseUnit(disk["size"]) +
utils.ParseUnit(disk["growth"])))
else:
build_size_opt = (lambda disk: "size=%s" % disk["size"])
build_disk_opt = (lambda (idx, disk):
"--disk=%s:%s%s" % (idx, build_size_opt(disk),
build_spindles_opt(disk)))
return map(build_disk_opt, en_disks)
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
def TestRecreateDisks(instance, inodes, othernodes):
"""gnt-instance recreate-disks
......@@ -845,32 +886,31 @@ def TestRecreateDisks(instance, inodes, othernodes):
# Move disks back
_AssertRecreateDisks(["-n", orig_seq], instance)
# Recreate resized disks
# One of the two commands fails because either spindles are given when they
# should not or vice versa
alldisks = qa_config.GetDiskOptions()
if qa_config.AreSpindlesSupported():
build_disks_opt = (lambda idx, disk:
("--disk=%s:size=%s,spindles=%s" %
(idx, (utils.ParseUnit(disk["size"]) +
utils.ParseUnit(disk["growth"])),
disk["spindles"] + disk["spindles-growth"])))
else:
build_disks_opt = (lambda idx, disk:
("--disk=%s:size=%s" %
(idx, (utils.ParseUnit(disk["size"]) +
utils.ParseUnit(disk["growth"])))))
disk_opts = map(build_disks_opt, range(0, len(alldisks)), (alldisks))
_AssertRecreateDisks(disk_opts, instance)
spindles_supported = qa_config.AreSpindlesSupported()
disk_opts = _BuildRecreateDisksOpts(enumerate(alldisks), True, True,
spindles_supported)
_AssertRecreateDisks(disk_opts, instance, destroy=True,
fail=not spindles_supported)
disk_opts = _BuildRecreateDisksOpts(enumerate(alldisks), False, True,
spindles_supported)
_AssertRecreateDisks(disk_opts, instance, destroy=False,
fail=spindles_supported)
# Recreate the disks one by one (with the original size)
if qa_config.AreSpindlesSupported():
build_disks_opt = lambda idx, disk: ("--disk=%s:size=%s,spindles=%s" %
(idx, disk["size"], disk["spindles"]))
else:
build_disks_opt = lambda idx, disk: ("--disk=%s:size=%s" %
(idx, disk["size"]))
for (idx, disk) in enumerate(alldisks):
# Only the first call should destroy all the disk
destroy = (idx == 0)
_AssertRecreateDisks([build_disks_opt(idx, disk)], instance,
destroy=destroy, check=False)
# Again, one of the two commands is expected to fail
disk_opts = _BuildRecreateDisksOpts([(idx, disk)], True, False,
spindles_supported)
_AssertRecreateDisks(disk_opts, instance, destroy=destroy, check=False,
fail=not spindles_supported)
disk_opts = _BuildRecreateDisksOpts([(idx, disk)], False, False,
spindles_supported)
_AssertRecreateDisks(disk_opts, instance, destroy=False, check=False,
fail=spindles_supported)
# This and InstanceCheck decoration check that the disks are working
AssertCommand(["gnt-instance", "reinstall", "-f", instance.name])
AssertCommand(["gnt-instance", "start", instance.name])
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment