Revision 7c848a6a

b/lib/cmdlib/instance.py
1032 1032
                                 " exclusive storage" % self.op.disk_template,
1033 1033
                                 errors.ECODE_STATE)
1034 1034
    for disk in self.disks:
1035
      CheckSpindlesExclusiveStorage(disk, excl_stor)
1035
      CheckSpindlesExclusiveStorage(disk, excl_stor, True)
1036 1036

  
1037 1037
    nodenames = [pnode.name] + self.secondaries
1038 1038

  
......
2241 2241
      if name is not None and name.lower() == constants.VALUE_NONE:
2242 2242
        params[constants.IDISK_NAME] = None
2243 2243

  
2244
      CheckSpindlesExclusiveStorage(params, excl_stor)
2244
      CheckSpindlesExclusiveStorage(params, excl_stor, True)
2245 2245

  
2246 2246
    elif op == constants.DDM_MODIFY:
2247 2247
      if constants.IDISK_SIZE in params:
b/lib/cmdlib/instance_storage.py
519 519
  return disks
520 520

  
521 521

  
522
def CheckSpindlesExclusiveStorage(diskdict, es_flag):
522
def CheckSpindlesExclusiveStorage(diskdict, es_flag, required):
523 523
  """Check the presence of the spindle options with exclusive_storage.
524 524

  
525 525
  @type diskdict: dict
526 526
  @param diskdict: disk parameters
527 527
  @type es_flag: bool
528 528
  @param es_flag: the effective value of the exlusive_storage flag
529
  @type required: bool
530
  @param required: whether spindles are required or just optional
529 531
  @raise errors.OpPrereqError when spindles are given and they should not
530 532

  
531 533
  """
......
534 536
    raise errors.OpPrereqError("Spindles in instance disks cannot be specified"
535 537
                               " when exclusive storage is not active",
536 538
                               errors.ECODE_INVAL)
539
  if (es_flag and required and (constants.IDISK_SPINDLES not in diskdict or
540
                                diskdict[constants.IDISK_SPINDLES] is None)):
541
    raise errors.OpPrereqError("You must specify spindles in instance disks"
542
                               " when exclusive storage is active",
543
                               errors.ECODE_INVAL)
537 544

  
538 545

  
539 546
class LUInstanceRecreateDisks(LogicalUnit):
......
787 794
      rpc.GetExclusiveStorageForNodeNames(self.cfg, nodes).values()
788 795
      )
789 796
    for new_params in self.disks.values():
790
      CheckSpindlesExclusiveStorage(new_params, excl_stor)
797
      CheckSpindlesExclusiveStorage(new_params, excl_stor, False)
791 798

  
792 799
  def Exec(self, feedback_fn):
793 800
    """Recreate the disks.
b/lib/storage/bdev.py
262 262
    stripes = min(current_pvs, desired_stripes)
263 263

  
264 264
    if excl_stor:
265
      if spindles is None:
266
        base.ThrowError("Unspecified number of spindles: this is required"
267
                        "when exclusive storage is enabled, try running"
268
                        " gnt-cluster repair-disk-sizes")
265 269
      (err_msgs, _) = utils.LvmExclusiveCheckNodePvs(pvs_info)
266 270
      if err_msgs:
267 271
        for m in err_msgs:
268 272
          logging.warning(m)
269 273
      req_pvs = cls._ComputeNumPvs(size, pvs_info)
270
      if spindles:
271
        if spindles < req_pvs:
272
          base.ThrowError("Requested number of spindles (%s) is not enough for"
273
                          " a disk of %d MB (at least %d spindles needed)",
274
                          spindles, size, req_pvs)
275
        else:
276
          req_pvs = spindles
274
      if spindles < req_pvs:
275
        base.ThrowError("Requested number of spindles (%s) is not enough for"
276
                        " a disk of %d MB (at least %d spindles needed)",
277
                        spindles, size, req_pvs)
278
      else:
279
        req_pvs = spindles
277 280
      pvlist = cls._GetEmptyPvNames(pvs_info, req_pvs)
278 281
      current_pvs = len(pvlist)
279 282
      if current_pvs < req_pvs:
b/qa/qa_instance.py
630 630
    print qa_utils.FormatInfo("Instance doesn't support disks, skipping test")
631 631
    return
632 632

  
633
  size = qa_config.GetDiskOptions()[-1].get("size")
633
  disk_conf = qa_config.GetDiskOptions()[-1]
634
  size = disk_conf.get("size")
634 635
  name = instance.name
635 636
  build_cmd = lambda arg: ["gnt-instance", "modify", "--disk", arg, name]
636
  AssertCommand(build_cmd("add:size=%s" % size))
637
  if qa_config.AreSpindlesSupported():
638
    spindles = disk_conf.get("spindles")
639
    spindles_supported = True
640
  else:
641
    # Any number is good for spindles in this case
642
    spindles = 1
643
    spindles_supported = False
644
  AssertCommand(build_cmd("add:size=%s,spindles=%s" % (size, spindles)),
645
                fail=not spindles_supported)
646
  AssertCommand(build_cmd("add:size=%s" % size),
647
                fail=spindles_supported)
648
  # Exactly one of the above commands has succeded, so we need one remove
637 649
  AssertCommand(build_cmd("remove"))
638 650

  
639 651

  
......
681 693
  for dev_type in ["disk", "net"]:
682 694
    if dev_type == "disk":
683 695
      options = ",size=512M"
696
      if qa_config.AreSpindlesSupported():
697
        options += ",spindles=1"
684 698
    else:
685 699
      options = ""
686 700
    # succeed in adding a device named 'test_device'
......
806 820
    AssertCommand(["gnt-instance", "deactivate-disks", instance.name])
807 821

  
808 822

  
823
def _BuildRecreateDisksOpts(en_disks, with_spindles, with_growth,
824
                            spindles_supported):
825
  if with_spindles:
826
    if spindles_supported:
827
      if with_growth:
828
        build_spindles_opt = (lambda disk:
829
                              ",spindles=%s" %
830
                              (disk["spindles"] + disk["spindles-growth"]))
831
      else:
832
        build_spindles_opt = (lambda disk:
833
                              ",spindles=%s" % disk["spindles"])
834
    else:
835
      build_spindles_opt = (lambda _: ",spindles=1")
836
  else:
837
    build_spindles_opt = (lambda _: "")
838
  if with_growth:
839
    build_size_opt = (lambda disk:
840
                      "size=%s" % (utils.ParseUnit(disk["size"]) +
841
                                   utils.ParseUnit(disk["growth"])))
842
  else:
843
    build_size_opt = (lambda disk: "size=%s" % disk["size"])
844
  build_disk_opt = (lambda (idx, disk):
845
                    "--disk=%s:%s%s" % (idx, build_size_opt(disk),
846
                                        build_spindles_opt(disk)))
847
  return map(build_disk_opt, en_disks)
848

  
849

  
809 850
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
810 851
def TestRecreateDisks(instance, inodes, othernodes):
811 852
  """gnt-instance recreate-disks
......
845 886
  # Move disks back
846 887
  _AssertRecreateDisks(["-n", orig_seq], instance)
847 888
  # Recreate resized disks
889
  # One of the two commands fails because either spindles are given when they
890
  # should not or vice versa
848 891
  alldisks = qa_config.GetDiskOptions()
849
  if qa_config.AreSpindlesSupported():
850
    build_disks_opt = (lambda idx, disk:
851
                       ("--disk=%s:size=%s,spindles=%s" %
852
                        (idx, (utils.ParseUnit(disk["size"]) +
853
                               utils.ParseUnit(disk["growth"])),
854
                         disk["spindles"] + disk["spindles-growth"])))
855
  else:
856
    build_disks_opt = (lambda idx, disk:
857
                       ("--disk=%s:size=%s" %
858
                        (idx, (utils.ParseUnit(disk["size"]) +
859
                               utils.ParseUnit(disk["growth"])))))
860
  disk_opts = map(build_disks_opt, range(0, len(alldisks)), (alldisks))
861
  _AssertRecreateDisks(disk_opts, instance)
892
  spindles_supported = qa_config.AreSpindlesSupported()
893
  disk_opts = _BuildRecreateDisksOpts(enumerate(alldisks), True, True,
894
                                      spindles_supported)
895
  _AssertRecreateDisks(disk_opts, instance, destroy=True,
896
                       fail=not spindles_supported)
897
  disk_opts = _BuildRecreateDisksOpts(enumerate(alldisks), False, True,
898
                                      spindles_supported)
899
  _AssertRecreateDisks(disk_opts, instance, destroy=False,
900
                       fail=spindles_supported)
862 901
  # Recreate the disks one by one (with the original size)
863
  if qa_config.AreSpindlesSupported():
864
    build_disks_opt = lambda idx, disk: ("--disk=%s:size=%s,spindles=%s" %
865
                                         (idx, disk["size"], disk["spindles"]))
866
  else:
867
    build_disks_opt = lambda idx, disk: ("--disk=%s:size=%s" %
868
                                         (idx, disk["size"]))
869 902
  for (idx, disk) in enumerate(alldisks):
870 903
    # Only the first call should destroy all the disk
871 904
    destroy = (idx == 0)
872
    _AssertRecreateDisks([build_disks_opt(idx, disk)], instance,
873
                         destroy=destroy, check=False)
905
    # Again, one of the two commands is expected to fail
906
    disk_opts = _BuildRecreateDisksOpts([(idx, disk)], True, False,
907
                                        spindles_supported)
908
    _AssertRecreateDisks(disk_opts, instance, destroy=destroy, check=False,
909
                         fail=not spindles_supported)
910
    disk_opts = _BuildRecreateDisksOpts([(idx, disk)], False, False,
911
                                        spindles_supported)
912
    _AssertRecreateDisks(disk_opts, instance, destroy=False, check=False,
913
                         fail=spindles_supported)
874 914
  # This and InstanceCheck decoration check that the disks are working
875 915
  AssertCommand(["gnt-instance", "reinstall", "-f", instance.name])
876 916
  AssertCommand(["gnt-instance", "start", instance.name])

Also available in: Unified diff