Add QA tests for RAPI multi-instance allocation
authorHrvoje Ribicic <riba@google.com>
Tue, 28 Jan 2014 18:04:44 +0000 (18:04 +0000)
committerHrvoje Ribicic <riba@google.com>
Wed, 29 Jan 2014 15:26:46 +0000 (16:26 +0100)
The instance multi-allocation had no tests to detect its breakage, and
this patch fixes that.

Signed-off-by: Hrvoje Ribicic <riba@google.com>
Reviewed-by: Klaus Aehlig <aehlig@google.com>

lib/rapi/rlib2.py
qa/ganeti-qa.py
qa/qa_rapi.py

index ac230e0..a3a7f19 100644 (file)
@@ -989,7 +989,8 @@ class R_2_instances_multi_alloc(baserlib.OpcodeResource):
 
     body = objects.FillDict(self.request_body, {
       "instances": [
-        baserlib.FillOpcode(opcodes.OpInstanceCreate, inst, {}, OPCODE_RENAME)
+        baserlib.FillOpcode(opcodes.OpInstanceCreate, inst, {},
+                            rename=OPCODE_RENAME)
         for inst in self.request_body["instances"]
         ],
       })
index c2f1eef..11d129a 100755 (executable)
@@ -809,6 +809,7 @@ def RunQa():
 
       if (qa_config.TestEnabled("instance-add-plain-disk")
           and qa_config.IsTemplateSupported(constants.DT_PLAIN)):
+        # Normal instance allocation via RAPI
         for use_client in [True, False]:
           rapi_instance = RunTest(qa_rapi.TestRapiInstanceAdd, pnode,
                                   use_client)
@@ -820,6 +821,16 @@ def RunQa():
             rapi_instance.Release()
           del rapi_instance
 
+        # Multi-instance allocation
+        rapi_instance_one, rapi_instance_two = \
+          RunTest(qa_rapi.TestRapiInstanceMultiAlloc, pnode)
+
+        try:
+          RunTest(qa_rapi.TestRapiInstanceRemove, rapi_instance_one, True)
+          RunTest(qa_rapi.TestRapiInstanceRemove, rapi_instance_two, True)
+        finally:
+          rapi_instance_one.Release()
+          rapi_instance_two.Release()
   finally:
     pnode.Release()
 
index 010e5e2..80939c7 100644 (file)
@@ -27,6 +27,7 @@ import tempfile
 import random
 import re
 import itertools
+import functools
 
 from ganeti import utils
 from ganeti import constants
@@ -622,6 +623,76 @@ def TestRapiInstanceAdd(node, use_client):
     raise
 
 
+def _GenInstanceAllocationDict(node, instance):
+  """Creates an instance allocation dict to be used with the RAPI"""
+  instance.SetDiskTemplate(constants.DT_PLAIN)
+
+  disks = [{"size": utils.ParseUnit(d.get("size")),
+              "name": str(d.get("name"))}
+             for d in qa_config.GetDiskOptions()]
+
+  nic0_mac = instance.GetNicMacAddr(0, constants.VALUE_GENERATE)
+  nics = [{
+    constants.INIC_MAC: nic0_mac,
+    }]
+
+  beparams = {
+    constants.BE_MAXMEM: utils.ParseUnit(qa_config.get(constants.BE_MAXMEM)),
+    constants.BE_MINMEM: utils.ParseUnit(qa_config.get(constants.BE_MINMEM)),
+    }
+
+  return _rapi_client.InstanceAllocation(constants.INSTANCE_CREATE,
+                                         instance.name,
+                                         constants.DT_PLAIN,
+                                         disks, nics,
+                                         os=qa_config.get("os"),
+                                         pnode=node.primary,
+                                         beparams=beparams)
+
+
+def TestRapiInstanceMultiAlloc(node):
+  """Test adding two new instances via the RAPI instance-multi-alloc method"""
+  if not qa_config.IsTemplateSupported(constants.DT_PLAIN):
+    return
+
+  JOBS_KEY = "jobs"
+
+  instance_one = qa_config.AcquireInstance()
+  instance_two = qa_config.AcquireInstance()
+  instance_list = [instance_one, instance_two]
+  try:
+    rapi_dicts = map(functools.partial(_GenInstanceAllocationDict, node),
+                     instance_list)
+
+    job_id = _rapi_client.InstancesMultiAlloc(rapi_dicts)
+
+    results, = _WaitForRapiJob(job_id)
+
+    if JOBS_KEY not in results:
+      raise qa_error.Error("RAPI instance-multi-alloc did not deliver "
+                           "information about created jobs")
+
+    if len(results[JOBS_KEY]) != len(instance_list):
+      raise qa_error.Error("RAPI instance-multi-alloc failed to return the "
+                           "desired number of jobs!")
+
+    for success, job in results[JOBS_KEY]:
+      if success:
+        _WaitForRapiJob(job)
+      else:
+        raise qa_error.Error("Failed to create instance in "
+                             "instance-multi-alloc call")
+  except:
+    # Note that although released, it may be that some of the instance creations
+    # have in fact succeeded. Handling this in a better way may be possible, but
+    # is not necessary as the QA has already failed at this point.
+    for instance in instance_list:
+      instance.Release()
+    raise
+
+  return (instance_one, instance_two)
+
+
 @InstanceCheck(None, INST_DOWN, FIRST_ARG)
 def TestRapiInstanceRemove(instance, use_client):
   """Test removing instance via RAPI"""