gnt-network(8): Re-add editor settings and re-wrap
[ganeti-local] / test / ganeti.config_unittest.py
index a21bfa6..b06f774 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 #
 
-# Copyright (C) 2006, 2007, 2010 Google Inc.
+# Copyright (C) 2006, 2007, 2010, 2011, 2012 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -28,6 +28,8 @@ import time
 import tempfile
 import os.path
 import socket
+import operator
+import itertools
 
 from ganeti import bootstrap
 from ganeti import config
@@ -36,6 +38,8 @@ from ganeti import errors
 from ganeti import objects
 from ganeti import utils
 from ganeti import netutils
+from ganeti import compat
+from ganeti import cmdlib
 
 from ganeti.config import TemporaryReservationManager
 
@@ -179,14 +183,14 @@ class TestConfigRunner(unittest.TestCase):
     CheckSyntax = objects.NIC.CheckParameterSyntax
 
     CheckSyntax(constants.NICC_DEFAULTS)
-    CheckSyntax({mode: m_bridged, link: 'br1'})
-    CheckSyntax({mode: m_routed, link: 'default'})
+    CheckSyntax({mode: m_bridged, link: "br1"})
+    CheckSyntax({mode: m_routed, link: "default"})
     self.assertRaises(errors.ConfigurationError,
-                      CheckSyntax, {mode: '000invalid', link: 'any'})
+                      CheckSyntax, {mode: "000invalid", link: "any"})
     self.assertRaises(errors.ConfigurationError,
                       CheckSyntax, {mode: m_bridged, link: None})
     self.assertRaises(errors.ConfigurationError,
-                      CheckSyntax, {mode: m_bridged, link: ''})
+                      CheckSyntax, {mode: m_bridged, link: ""})
 
   def testGetNdParamsDefault(self):
     cfg = self._get_object()
@@ -196,6 +200,8 @@ class TestConfigRunner(unittest.TestCase):
   def testGetNdParamsModifiedNode(self):
     my_ndparams = {
         constants.ND_OOB_PROGRAM: "/bin/node-oob",
+        constants.ND_SPINDLE_COUNT: 1,
+        constants.ND_EXCLUSIVE_STORAGE: False,
         }
 
     cfg = self._get_object()
@@ -204,6 +210,28 @@ class TestConfigRunner(unittest.TestCase):
     cfg.Update(node, None)
     self.assertEqual(cfg.GetNdParams(node), my_ndparams)
 
+  def testGetNdParamsInheritance(self):
+    node_ndparams = {
+      constants.ND_OOB_PROGRAM: "/bin/node-oob",
+      }
+    group_ndparams = {
+      constants.ND_SPINDLE_COUNT: 10,
+      }
+    expected_ndparams = {
+      constants.ND_OOB_PROGRAM: "/bin/node-oob",
+      constants.ND_SPINDLE_COUNT: 10,
+      constants.ND_EXCLUSIVE_STORAGE:
+        constants.NDC_DEFAULTS[constants.ND_EXCLUSIVE_STORAGE],
+      }
+    cfg = self._get_object()
+    node = cfg.GetNodeInfo(cfg.GetNodeList()[0])
+    node.ndparams = node_ndparams
+    cfg.Update(node, None)
+    group = cfg.GetNodeGroup(node.group)
+    group.ndparams = group_ndparams
+    cfg.Update(group, None)
+    self.assertEqual(cfg.GetNdParams(node), expected_ndparams)
+
   def testAddGroupFillsFieldsIfMissing(self):
     cfg = self._get_object()
     group = objects.NodeGroup(name="test", members=[])
@@ -239,6 +267,127 @@ class TestConfigRunner(unittest.TestCase):
     cfg.AddNodeGroup(group, "my-job", check_uuid=False) # Does not raise.
     self.assertEqual(uuid, group.uuid)
 
+  def testAssignGroupNodes(self):
+    me = netutils.Hostname()
+    cfg = self._get_object()
+
+    # Create two groups
+    grp1 = objects.NodeGroup(name="grp1", members=[],
+                             uuid="2f2fadf7-2a70-4a23-9ab5-2568c252032c")
+    grp1_serial = 1
+    cfg.AddNodeGroup(grp1, "job")
+
+    grp2 = objects.NodeGroup(name="grp2", members=[],
+                             uuid="798d0de3-680f-4a0e-b29a-0f54f693b3f1")
+    grp2_serial = 1
+    cfg.AddNodeGroup(grp2, "job")
+    self.assertEqual(set(map(operator.attrgetter("name"),
+                             cfg.GetAllNodeGroupsInfo().values())),
+                     set(["grp1", "grp2", constants.INITIAL_NODE_GROUP_NAME]))
+
+    # No-op
+    cluster_serial = cfg.GetClusterInfo().serial_no
+    cfg.AssignGroupNodes([])
+    cluster_serial += 1
+
+    # Create two nodes
+    node1 = objects.Node(name="node1", group=grp1.uuid, ndparams={})
+    node1_serial = 1
+    node2 = objects.Node(name="node2", group=grp2.uuid, ndparams={})
+    node2_serial = 1
+    cfg.AddNode(node1, "job")
+    cfg.AddNode(node2, "job")
+    cluster_serial += 2
+    self.assertEqual(set(cfg.GetNodeList()), set(["node1", "node2", me.name]))
+
+    def _VerifySerials():
+      self.assertEqual(cfg.GetClusterInfo().serial_no, cluster_serial)
+      self.assertEqual(node1.serial_no, node1_serial)
+      self.assertEqual(node2.serial_no, node2_serial)
+      self.assertEqual(grp1.serial_no, grp1_serial)
+      self.assertEqual(grp2.serial_no, grp2_serial)
+
+    _VerifySerials()
+
+    self.assertEqual(set(grp1.members), set(["node1"]))
+    self.assertEqual(set(grp2.members), set(["node2"]))
+
+    # Check invalid nodes and groups
+    self.assertRaises(errors.ConfigurationError, cfg.AssignGroupNodes, [
+      ("unknown.node.example.com", grp2.uuid),
+      ])
+    self.assertRaises(errors.ConfigurationError, cfg.AssignGroupNodes, [
+      (node1.name, "unknown-uuid"),
+      ])
+
+    self.assertEqual(node1.group, grp1.uuid)
+    self.assertEqual(node2.group, grp2.uuid)
+    self.assertEqual(set(grp1.members), set(["node1"]))
+    self.assertEqual(set(grp2.members), set(["node2"]))
+
+    # Another no-op
+    cfg.AssignGroupNodes([])
+    cluster_serial += 1
+    _VerifySerials()
+
+    # Assign to the same group (should be a no-op)
+    self.assertEqual(node2.group, grp2.uuid)
+    cfg.AssignGroupNodes([
+      (node2.name, grp2.uuid),
+      ])
+    cluster_serial += 1
+    self.assertEqual(node2.group, grp2.uuid)
+    _VerifySerials()
+    self.assertEqual(set(grp1.members), set(["node1"]))
+    self.assertEqual(set(grp2.members), set(["node2"]))
+
+    # Assign node 2 to group 1
+    self.assertEqual(node2.group, grp2.uuid)
+    cfg.AssignGroupNodes([
+      (node2.name, grp1.uuid),
+      ])
+    cluster_serial += 1
+    node2_serial += 1
+    grp1_serial += 1
+    grp2_serial += 1
+    self.assertEqual(node2.group, grp1.uuid)
+    _VerifySerials()
+    self.assertEqual(set(grp1.members), set(["node1", "node2"]))
+    self.assertFalse(grp2.members)
+
+    # And assign both nodes to group 2
+    self.assertEqual(node1.group, grp1.uuid)
+    self.assertEqual(node2.group, grp1.uuid)
+    self.assertNotEqual(grp1.uuid, grp2.uuid)
+    cfg.AssignGroupNodes([
+      (node1.name, grp2.uuid),
+      (node2.name, grp2.uuid),
+      ])
+    cluster_serial += 1
+    node1_serial += 1
+    node2_serial += 1
+    grp1_serial += 1
+    grp2_serial += 1
+    self.assertEqual(node1.group, grp2.uuid)
+    self.assertEqual(node2.group, grp2.uuid)
+    _VerifySerials()
+    self.assertFalse(grp1.members)
+    self.assertEqual(set(grp2.members), set(["node1", "node2"]))
+
+    # Destructive tests
+    orig_group = node2.group
+    try:
+      other_uuid = "68b3d087-6ea5-491c-b81f-0a47d90228c5"
+      assert compat.all(node.group != other_uuid
+                        for node in cfg.GetAllNodesInfo().values())
+      node2.group = "68b3d087-6ea5-491c-b81f-0a47d90228c5"
+      self.assertRaises(errors.ConfigurationError, cfg.AssignGroupNodes, [
+        ("node2", grp2.uuid),
+        ])
+      _VerifySerials()
+    finally:
+      node2.group = orig_group
+
 
 class TestTRM(unittest.TestCase):
   EC_ID = 1
@@ -258,5 +407,28 @@ class TestTRM(unittest.TestCase):
     self.assertFalse(t.Reserved("a"))
 
 
-if __name__ == '__main__':
+class TestCheckInstanceDiskIvNames(unittest.TestCase):
+  @staticmethod
+  def _MakeDisks(names):
+    return [objects.Disk(iv_name=name) for name in names]
+
+  def testNoError(self):
+    disks = self._MakeDisks(["disk/0", "disk/1"])
+    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
+    cmdlib._UpdateIvNames(0, disks)
+    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
+
+  def testWrongNames(self):
+    disks = self._MakeDisks(["disk/1", "disk/3", "disk/2"])
+    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [
+      (0, "disk/0", "disk/1"),
+      (1, "disk/1", "disk/3"),
+      ])
+
+    # Fix names
+    cmdlib._UpdateIvNames(0, disks)
+    self.assertEqual(config._CheckInstanceDiskIvNames(disks), [])
+
+
+if __name__ == "__main__":
   testutils.GanetiTestProgram()