Revision c99200a3

b/qa/ganeti-qa.py
340 340
            qa_group.GetDefaultGroup())
341 341

  
342 342

  
343
def RunExportImportTests(instance, pnode, snode):
343
def RunExportImportTests(instance, inodes):
344 344
  """Tries to export and import the instance.
345 345

  
346
  @param pnode: current primary node of the instance
347
  @param snode: current secondary node of the instance, if any,
348
      otherwise None
346
  @type inodes: list of nodes
347
  @param inodes: current nodes of the instance
349 348

  
350 349
  """
351 350
  if qa_config.TestEnabled("instance-export"):
352 351
    RunTest(qa_instance.TestInstanceExportNoTarget, instance)
353 352

  
353
    pnode = inodes[0]
354 354
    expnode = qa_config.AcquireNode(exclude=pnode)
355 355
    try:
356 356
      name = RunTest(qa_instance.TestInstanceExport, instance, expnode)
......
373 373
  if qa_config.TestEnabled(["rapi", "inter-cluster-instance-move"]):
374 374
    newinst = qa_config.AcquireInstance()
375 375
    try:
376
      if snode is None:
377
        excl = [pnode]
378
      else:
379
        excl = [pnode, snode]
380
      tnode = qa_config.AcquireNode(exclude=excl)
376
      tnode = qa_config.AcquireNode(exclude=inodes)
381 377
      try:
382 378
        RunTest(qa_rapi.TestInterClusterInstanceMove, instance, newinst,
383
                pnode, snode, tnode)
379
                inodes, tnode)
384 380
      finally:
385 381
        qa_config.ReleaseNode(tnode)
386 382
    finally:
......
414 410
      qa_config.ReleaseNode(othernode)
415 411

  
416 412

  
417
def RunHardwareFailureTests(instance, pnode, snode):
413
def RunHardwareFailureTests(instance, inodes):
418 414
  """Test cluster internal hardware failure recovery.
419 415

  
420 416
  """
......
427 423
            qa_rapi.TestRapiInstanceMigrate, instance)
428 424

  
429 425
  if qa_config.TestEnabled("instance-replace-disks"):
430
    othernode = qa_config.AcquireNode(exclude=[pnode, snode])
426
    # We just need alternative secondary nodes, hence "- 1"
427
    othernodes = qa_config.AcquireManyNodes(len(inodes) - 1, exclude=inodes)
431 428
    try:
432 429
      RunTestIf("rapi", qa_rapi.TestRapiInstanceReplaceDisks, instance)
433 430
      RunTest(qa_instance.TestReplaceDisks,
434
              instance, pnode, snode, othernode)
431
              instance, inodes, othernodes)
435 432
    finally:
436
      qa_config.ReleaseNode(othernode)
433
      qa_config.ReleaseManyNodes(othernodes)
434
    del othernodes
437 435

  
438 436
  if qa_config.TestEnabled("instance-recreate-disks"):
439
    othernode1 = qa_config.AcquireNode(exclude=[pnode, snode])
440 437
    try:
441
      othernode2 = qa_config.AcquireNode(exclude=[pnode, snode, othernode1])
438
      acquirednodes = qa_config.AcquireManyNodes(len(inodes), exclude=inodes)
439
      othernodes = acquirednodes
442 440
    except qa_error.OutOfNodesError:
443
      # Let's reuse one of the nodes if the cluster is not big enough
444
      othernode2 = pnode
441
      if len(inodes) > 1:
442
        # If the cluster is not big enough, let's reuse some of the nodes, but
443
        # with different roles. In this way, we can test a DRBD instance even on
444
        # a 3-node cluster.
445
        acquirednodes = [qa_config.AcquireNode(exclude=inodes)]
446
        othernodes = acquirednodes + inodes[:-1]
447
      else:
448
        raise
445 449
    try:
446 450
      RunTest(qa_instance.TestRecreateDisks,
447
              instance, pnode, snode, [othernode1, othernode2])
451
              instance, inodes, othernodes)
448 452
    finally:
449
      qa_config.ReleaseNode(othernode1)
450
      if othernode2 != pnode:
451
        qa_config.ReleaseNode(othernode2)
452

  
453
  RunTestIf("node-evacuate", qa_node.TestNodeEvacuate, pnode, snode)
453
      qa_config.ReleaseManyNodes(acquirednodes)
454 454

  
455
  RunTestIf("node-failover", qa_node.TestNodeFailover, pnode, snode)
455
  if len(inodes) >= 2:
456
    RunTestIf("node-evacuate", qa_node.TestNodeEvacuate, inodes[0], inodes[1])
457
    RunTestIf("node-failover", qa_node.TestNodeFailover, inodes[0], inodes[1])
456 458

  
457 459

  
458 460
def RunExclusiveStorageTests():
......
471 473
    if qa_config.TestEnabled("instance-add-plain-disk"):
472 474
      # Make sure that the cluster doesn't have any pre-existing problem
473 475
      qa_cluster.AssertClusterVerify()
474
      instance1 = qa_instance.TestInstanceAddWithPlainDisk(node)
475
      instance2 = qa_instance.TestInstanceAddWithPlainDisk(node)
476
      instance1 = qa_instance.TestInstanceAddWithPlainDisk([node])
477
      instance2 = qa_instance.TestInstanceAddWithPlainDisk([node])
476 478
      # cluster-verify checks that disks are allocated correctly
477 479
      qa_cluster.AssertClusterVerify()
478 480
      qa_instance.TestInstanceRemove(instance1)
......
481 483
      snode = qa_config.AcquireNode()
482 484
      try:
483 485
        qa_cluster.TestSetExclStorCluster(False)
484
        instance = qa_instance.TestInstanceAddWithDrbdDisk(node, snode)
486
        instance = qa_instance.TestInstanceAddWithDrbdDisk([node, snode])
485 487
        qa_cluster.TestSetExclStorCluster(True)
486 488
        exp_err = [constants.CV_EINSTANCEUNSUITABLENODE]
487 489
        qa_cluster.AssertClusterVerify(fail=True, errors=exp_err)
......
542 544
          del rapi_instance
543 545

  
544 546
    if qa_config.TestEnabled("instance-add-plain-disk"):
545
      instance = RunTest(qa_instance.TestInstanceAddWithPlainDisk, pnode)
547
      instance = RunTest(qa_instance.TestInstanceAddWithPlainDisk, [pnode])
546 548
      RunCommonInstanceTests(instance)
547 549
      RunGroupListTests()
548 550
      RunTestIf("cluster-epo", qa_cluster.TestClusterEpo)
549
      RunExportImportTests(instance, pnode, None)
551
      RunExportImportTests(instance, [pnode])
550 552
      RunDaemonTests(instance)
551 553
      RunRepairDiskSizes()
552 554
      RunSingleHomedHardwareFailureTests(instance, pnode)
......
562 564
      if qa_config.TestEnabled(name):
563 565
        snode = qa_config.AcquireNode(exclude=pnode)
564 566
        try:
565
          instance = RunTest(func, pnode, snode)
567
          instance = RunTest(func, [pnode, snode])
566 568
          RunTestIf("haskell-confd", qa_node.TestNodeListDrbd, pnode)
567 569
          RunTestIf("haskell-confd", qa_node.TestNodeListDrbd, snode)
568 570
          RunCommonInstanceTests(instance)
......
572 574
                    pnode["primary"], snode["primary"])
573 575
          if qa_config.TestEnabled("instance-convert-disk"):
574 576
            RunTest(qa_instance.TestInstanceShutdown, instance)
575
            RunTest(qa_instance.TestInstanceConvertDisk, instance, snode)
577
            RunTest(qa_instance.TestInstanceConvertDiskToPlain, instance,
578
                    [pnode, snode])
576 579
            RunTest(qa_instance.TestInstanceStartup, instance)
577
          RunExportImportTests(instance, pnode, snode)
578
          RunHardwareFailureTests(instance, pnode, snode)
580
          RunExportImportTests(instance, [pnode, snode])
581
          RunHardwareFailureTests(instance, [pnode, snode])
579 582
          RunRepairDiskSizes()
580 583
          RunTest(qa_instance.TestInstanceRemove, instance)
581 584
          del instance
......
592 595
    try:
593 596
      pnode = qa_config.AcquireNode(exclude=snode)
594 597
      try:
595
        instance = qa_instance.TestInstanceAddWithDrbdDisk(pnode, snode)
598
        instance = qa_instance.TestInstanceAddWithDrbdDisk([pnode, snode])
596 599
        qa_node.MakeNodeOffline(snode, "yes")
597 600
        try:
598 601
          RunTest(qa_instance.TestInstanceRemove, instance)
......
607 610
  try:
608 611
    if qa_config.TestEnabled(["instance-add-plain-disk", "instance-export"]):
609 612
      for shutdown in [False, True]:
610
        instance = RunTest(qa_instance.TestInstanceAddWithPlainDisk, pnode)
613
        instance = RunTest(qa_instance.TestInstanceAddWithPlainDisk, [pnode])
611 614
        expnode = qa_config.AcquireNode(exclude=pnode)
612 615
        try:
613 616
          if shutdown:
b/qa/qa_instance.py
23 23

  
24 24
"""
25 25

  
26
import operator
26 27
import re
27 28

  
28 29
from ganeti import utils
......
177 178

  
178 179

  
179 180
@InstanceCheck(None, INST_UP, RETURN_VALUE)
180
def TestInstanceAddWithPlainDisk(node):
181
def TestInstanceAddWithPlainDisk(nodes):
181 182
  """gnt-instance add -t plain"""
182
  return _DiskTest(node["primary"], "plain")
183
  assert len(nodes) == 1
184
  return _DiskTest(nodes[0]["primary"], "plain")
183 185

  
184 186

  
185 187
@InstanceCheck(None, INST_UP, RETURN_VALUE)
186
def TestInstanceAddWithDrbdDisk(node, node2):
188
def TestInstanceAddWithDrbdDisk(nodes):
187 189
  """gnt-instance add -t drbd"""
188
  return _DiskTest("%s:%s" % (node["primary"], node2["primary"]),
190
  assert len(nodes) == 2
191
  return _DiskTest(":".join(map(operator.itemgetter("primary"), nodes)),
189 192
                   "drbd")
190 193

  
191 194

  
......
481 484

  
482 485

  
483 486
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
484
def TestInstanceConvertDisk(instance, snode):
487
def TestInstanceConvertDiskToPlain(instance, inodes):
485 488
  """gnt-instance modify -t"""
486 489
  name = instance["name"]
487 490
  template = qa_config.GetInstanceTemplate(instance)
......
489 492
    print qa_utils.FormatInfo("Unsupported template %s, skipping conversion"
490 493
                              " test" % template)
491 494
    return
495
  assert len(inodes) == 2
492 496
  AssertCommand(["gnt-instance", "modify", "-t", "plain", name])
493 497
  AssertCommand(["gnt-instance", "modify", "-t", "drbd",
494
                 "-n", snode["primary"], name])
498
                 "-n", inodes[1]["primary"], name])
495 499

  
496 500

  
497 501
@InstanceCheck(INST_DOWN, INST_DOWN, FIRST_ARG)
......
537 541

  
538 542

  
539 543
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
540
def TestReplaceDisks(instance, pnode, snode, othernode):
544
def TestReplaceDisks(instance, curr_nodes, other_nodes):
541 545
  """gnt-instance replace-disks"""
542
  # pylint: disable=W0613
543
  # due to unused pnode arg
544
  # FIXME: should be removed from the function completely
545 546
  def buildcmd(args):
546 547
    cmd = ["gnt-instance", "replace-disks"]
547 548
    cmd.extend(args)
......
553 554
                              " skipping test")
554 555
    return
555 556

  
557
  # Currently all supported templates have one primary and one secondary node
558
  assert len(curr_nodes) == 2
559
  snode = curr_nodes[1]
560
  assert len(other_nodes) == 1
561
  othernode = other_nodes[0]
562

  
556 563
  options = qa_config.get("options", {})
557 564
  use_ialloc = options.get("use-iallocators", True)
558 565
  for data in [
......
604 611

  
605 612

  
606 613
@InstanceCheck(INST_UP, INST_UP, FIRST_ARG)
607
def TestRecreateDisks(instance, pnode, snode, othernodes):
614
def TestRecreateDisks(instance, inodes, othernodes):
608 615
  """gnt-instance recreate-disks
609 616

  
610 617
  @param instance: Instance to work on
611
  @param pnode: Primary node
612
  @param snode: Secondary node, or None for sigle-homed instances
618
  @param inodes: List of the current nodes of the instance
613 619
  @param othernodes: list/tuple of nodes where to temporarily recreate disks
614 620

  
615 621
  """
616 622
  options = qa_config.get("options", {})
617 623
  use_ialloc = options.get("use-iallocators", True)
618 624
  other_seq = ":".join([n["primary"] for n in othernodes])
619
  orig_seq = pnode["primary"]
620
  if snode:
621
    orig_seq = orig_seq + ":" + snode["primary"]
625
  orig_seq = ":".join([n["primary"] for n in inodes])
622 626
  # These fail because the instance is running
623 627
  _AssertRecreateDisks(["-n", other_seq], instance, fail=True, destroy=False)
624 628
  if use_ialloc:
b/qa/qa_rapi.py
759 759

  
760 760

  
761 761
def TestInterClusterInstanceMove(src_instance, dest_instance,
762
                                 pnode, snode, tnode):
762
                                 inodes, tnode):
763 763
  """Test tools/move-instance"""
764 764
  master = qa_config.GetMasterNode()
765 765

  
......
772 772

  
773 773
  # TODO: Run some instance tests before moving back
774 774

  
775
  if snode is None:
775
  if len(inodes) > 1:
776
    # No disk template currently requires more than 1 secondary node. If this
777
    # changes, either this test must be skipped or the script must be updated.
778
    assert len(inodes) == 2
779
    snode = inodes[1]
780
  else:
776 781
    # instance is not redundant, but we still need to pass a node
777 782
    # (which will be ignored)
778
    fsec = tnode
779
  else:
780
    fsec = snode
783
    snode = tnode
784
  pnode = inodes[0]
781 785
  # note: pnode:snode are the *current* nodes, so we move it first to
782 786
  # tnode:pnode, then back to pnode:snode
783 787
  for si, di, pn, sn in [(src_instance["name"], dest_instance["name"],
784 788
                          tnode["primary"], pnode["primary"]),
785 789
                         (dest_instance["name"], src_instance["name"],
786
                          pnode["primary"], fsec["primary"])]:
790
                          pnode["primary"], snode["primary"])]:
787 791
    cmd = [
788 792
      "../tools/move-instance",
789 793
      "--verbose",

Also available in: Unified diff