From 76fda9007f9450b63f5f815b279a8fa9b8a85304 Mon Sep 17 00:00:00 2001
From: Michael Hanselmann <hansmi@google.com>
Date: Fri, 8 Feb 2013 17:36:57 +0100
Subject: [PATCH] QA: Add config entries for virtual cluster
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

If these new options are set, a virtual cluster is created and used.
Virtual clusters consist of 1..N virtual nodes on a single physical (or
virtual) node. The design of virtual clusters is described in
β€œdoc/design-virtual-clusters.rst”.

Signed-off-by: Michael Hanselmann <hansmi@google.com>
Reviewed-by: Bernardo Dal Seno <bdalseno@google.com>
---
 qa/qa-sample.json                |  4 +++
 qa/qa_config.py                  | 53 ++++++++++++++++++++++++++++++++
 test/py/qa.qa_config_unittest.py | 30 ++++++++++++++++++
 3 files changed, 87 insertions(+)

diff --git a/qa/qa-sample.json b/qa/qa-sample.json
index 10b93a89f..ffe9a3dd1 100644
--- a/qa/qa-sample.json
+++ b/qa/qa-sample.json
@@ -9,6 +9,10 @@
   "# Name used for renaming cluster": null,
   "rename": "xen-test-rename",
 
+  "# Virtual cluster": null,
+  "#vcluster-master": "xen-vcluster",
+  "#vcluster-basedir": "/srv/ganeti/vcluster",
+
   "enabled-hypervisors": "xen-pvm",
   "# Dict of hypervisor name and parameters (like on the cmd line)": null,
   "hypervisor-parameters": {},
diff --git a/qa/qa_config.py b/qa/qa_config.py
index 6b74f82b1..43d3350e3 100644
--- a/qa/qa_config.py
+++ b/qa/qa_config.py
@@ -29,12 +29,15 @@ from ganeti import constants
 from ganeti import utils
 from ganeti import serializer
 from ganeti import compat
+from ganeti import ht
 
 import qa_error
 
 
 _INSTANCE_CHECK_KEY = "instance-check"
 _ENABLED_HV_KEY = "enabled-hypervisors"
+_VCLUSTER_MASTER_KEY = "vcluster-master"
+_VCLUSTER_BASEDIR_KEY = "vcluster-basedir"
 
 #: QA configuration (L{_QaConfig})
 _config = None
@@ -299,6 +302,16 @@ class _QaConfig(object):
       raise qa_error.Error("Unknown hypervisor(s) enabled: %s" %
                            utils.CommaJoin(difference))
 
+    (vc_master, vc_basedir) = self.GetVclusterSettings()
+    if bool(vc_master) != bool(vc_basedir):
+      raise qa_error.Error("All or none of the config options '%s' and '%s'"
+                           " must be set" %
+                           (_VCLUSTER_MASTER_KEY, _VCLUSTER_BASEDIR_KEY))
+
+    if vc_basedir and not utils.IsNormAbsPath(vc_basedir):
+      raise qa_error.Error("Path given in option '%s' must be absolute and"
+                           " normalized" % _VCLUSTER_BASEDIR_KEY)
+
   def __getitem__(self, name):
     """Returns configuration value.
 
@@ -379,6 +392,15 @@ class _QaConfig(object):
     return (not self.GetExclusiveStorage() or
             templ in constants.DTS_EXCL_STORAGE)
 
+  def GetVclusterSettings(self):
+    """Returns settings for virtual cluster.
+
+    """
+    master = self.get(_VCLUSTER_MASTER_KEY)
+    basedir = self.get(_VCLUSTER_BASEDIR_KEY)
+
+    return (master, basedir)
+
 
 def Load(path):
   """Loads the passed configuration file.
@@ -625,3 +647,34 @@ def AcquireManyNodes(num, exclude=None):
 def ReleaseManyNodes(nodes):
   for node in nodes:
     node.Release()
+
+
+def GetVclusterSettings():
+  """Wrapper for L{_QaConfig.GetVclusterSettings}.
+
+  """
+  return GetConfig().GetVclusterSettings()
+
+
+def UseVirtualCluster(_cfg=None):
+  """Returns whether a virtual cluster is used.
+
+  @rtype: bool
+
+  """
+  if _cfg is None:
+    cfg = GetConfig()
+  else:
+    cfg = _cfg
+
+  (master, _) = cfg.GetVclusterSettings()
+
+  return bool(master)
+
+
+@ht.WithDesc("No virtual cluster")
+def NoVirtualCluster():
+  """Used to disable tests for virtual clusters.
+
+  """
+  return not UseVirtualCluster()
diff --git a/test/py/qa.qa_config_unittest.py b/test/py/qa.qa_config_unittest.py
index f2de71427..feff7dfb4 100755
--- a/test/py/qa.qa_config_unittest.py
+++ b/test/py/qa.qa_config_unittest.py
@@ -222,6 +222,30 @@ class TestQaConfigLoad(unittest.TestCase):
     # Unknown hypervisor
     testconfig[qa_config._ENABLED_HV_KEY] = ["#unknownhv#"]
     check_fn("Unknown hypervisor(s) enabled:")
+    del testconfig[qa_config._ENABLED_HV_KEY]
+
+    # Invalid path for virtual cluster base directory
+    testconfig[qa_config._VCLUSTER_MASTER_KEY] = "value"
+    testconfig[qa_config._VCLUSTER_BASEDIR_KEY] = "./not//normalized/"
+    check_fn("Path given in option 'vcluster-basedir' must be")
+
+    # Inconsistent virtual cluster settings
+    testconfig.pop(qa_config._VCLUSTER_MASTER_KEY)
+    testconfig[qa_config._VCLUSTER_BASEDIR_KEY] = "/tmp"
+    check_fn("All or none of the")
+
+    testconfig[qa_config._VCLUSTER_MASTER_KEY] = "master.example.com"
+    testconfig.pop(qa_config._VCLUSTER_BASEDIR_KEY)
+    check_fn("All or none of the")
+
+    # Accepted virtual cluster settings
+    testconfig[qa_config._VCLUSTER_MASTER_KEY] = "master.example.com"
+    testconfig[qa_config._VCLUSTER_BASEDIR_KEY] = "/tmp"
+
+    self._WriteConfig(filename, testconfig)
+    result = qa_config._QaConfig.Load(filename)
+    self.assertEqual(result.GetVclusterSettings(),
+                     ("master.example.com", "/tmp"))
 
 
 class TestQaConfigWithSampleConfig(unittest.TestCase):
@@ -257,6 +281,12 @@ class TestQaConfigWithSampleConfig(unittest.TestCase):
   def testGetMasterNode(self):
     self.assertEqual(self.config.GetMasterNode(), self.config["nodes"][0])
 
+  def testGetVclusterSettings(self):
+    # Shipped default settings should be to not use a virtual cluster
+    self.assertEqual(self.config.GetVclusterSettings(), (None, None))
+
+    self.assertFalse(qa_config.UseVirtualCluster(_cfg=self.config))
+
 
 class TestQaConfig(unittest.TestCase):
   def setUp(self):
-- 
GitLab