Move bootstrap-related RPC to generated wrappers
[ganeti-local] / test / ganeti.rapi.client_unittest.py
index 9c41b08..e98198d 100755 (executable)
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 #
 
-# Copyright (C) 2010 Google Inc.
+# Copyright (C) 2010, 2011 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
@@ -45,8 +45,8 @@ _URI_RE = re.compile(r"https://(?P<host>.*):(?P<port>\d+)(?P<path>/.*)")
 
 # List of resource handlers which aren't used by the RAPI client
 _KNOWN_UNUSED = set([
-  connector.R_root,
-  connector.R_2,
+  rlib2.R_root,
+  rlib2.R_2,
   ])
 
 # Global variable for collecting used handlers
@@ -151,9 +151,11 @@ class TestConstants(unittest.TestCase):
     self.assertEqual(client._REQ_DATA_VERSION_FIELD, rlib2._REQ_DATA_VERSION)
     self.assertEqual(client._INST_CREATE_REQV1, rlib2._INST_CREATE_REQV1)
     self.assertEqual(client._INST_REINSTALL_REQV1, rlib2._INST_REINSTALL_REQV1)
+    self.assertEqual(client._NODE_MIGRATE_REQV1, rlib2._NODE_MIGRATE_REQV1)
+    self.assertEqual(client._NODE_EVAC_RES1, rlib2._NODE_EVAC_RES1)
     self.assertEqual(client._INST_NIC_PARAMS, constants.INIC_PARAMS)
     self.assertEqual(client.JOB_STATUS_QUEUED, constants.JOB_STATUS_QUEUED)
-    self.assertEqual(client.JOB_STATUS_WAITLOCK, constants.JOB_STATUS_WAITLOCK)
+    self.assertEqual(client.JOB_STATUS_WAITING, constants.JOB_STATUS_WAITING)
     self.assertEqual(client.JOB_STATUS_CANCELING,
                      constants.JOB_STATUS_CANCELING)
     self.assertEqual(client.JOB_STATUS_RUNNING, constants.JOB_STATUS_RUNNING)
@@ -163,6 +165,9 @@ class TestConstants(unittest.TestCase):
     self.assertEqual(client.JOB_STATUS_FINALIZED, constants.JOBS_FINALIZED)
     self.assertEqual(client.JOB_STATUS_ALL, constants.JOB_STATUS_ALL)
 
+    # Legacy name
+    self.assertEqual(client.JOB_STATUS_WAITLOCK, constants.JOB_STATUS_WAITING)
+
 
 class RapiMockTest(unittest.TestCase):
   def test(self):
@@ -510,92 +515,12 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
     self.assertQuery("static", ["1"])
 
   def testCreateInstanceOldVersion(self):
-    # No NICs
+    # The old request format, version 0, is no longer supported
     self.rapi.AddResponse(None, code=404)
     self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
                       "create", "inst1.example.com", "plain", [], [])
     self.assertEqual(self.rapi.CountPending(), 0)
 
-    # More than one NIC
-    self.rapi.AddResponse(None, code=404)
-    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
-                      "create", "inst1.example.com", "plain", [],
-                      [{}, {}, {}])
-    self.assertEqual(self.rapi.CountPending(), 0)
-
-    # Unsupported NIC fields
-    self.rapi.AddResponse(None, code=404)
-    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
-                      "create", "inst1.example.com", "plain", [],
-                      [{"x": True, "y": False}])
-    self.assertEqual(self.rapi.CountPending(), 0)
-
-    # Unsupported disk fields
-    self.rapi.AddResponse(None, code=404)
-    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
-                      "create", "inst1.example.com", "plain",
-                      [{}, {"moo": "foo",}], [{}])
-    self.assertEqual(self.rapi.CountPending(), 0)
-
-    # Unsupported fields
-    self.rapi.AddResponse(None, code=404)
-    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
-                      "create", "inst1.example.com", "plain", [], [{}],
-                      hello_world=123)
-    self.assertEqual(self.rapi.CountPending(), 0)
-
-    self.rapi.AddResponse(None, code=404)
-    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
-                      "create", "inst1.example.com", "plain", [], [{}],
-                      memory=128)
-    self.assertEqual(self.rapi.CountPending(), 0)
-
-    # Normal creation
-    testnics = [
-      [{}],
-      [{ "mac": constants.VALUE_AUTO, }],
-      [{ "ip": "192.0.2.99", "mode": constants.NIC_MODE_ROUTED, }],
-      ]
-
-    testdisks = [
-      [],
-      [{ "size": 128, }],
-      [{ "size": 321, }, { "size": 4096, }],
-      ]
-
-    for idx, nics in enumerate(testnics):
-      for disks in testdisks:
-        beparams = {
-          constants.BE_MEMORY: 512,
-          constants.BE_AUTO_BALANCE: False,
-          }
-        hvparams = {
-          constants.HV_MIGRATION_PORT: 9876,
-          constants.HV_VNC_TLS: True,
-          }
-
-        self.rapi.AddResponse(None, code=404)
-        self.rapi.AddResponse(serializer.DumpJson(3122617 + idx))
-        job_id = self.client.CreateInstance("create", "inst1.example.com",
-                                            "plain", disks, nics,
-                                            pnode="node99", dry_run=True,
-                                            hvparams=hvparams,
-                                            beparams=beparams)
-        self.assertEqual(job_id, 3122617 + idx)
-        self.assertHandler(rlib2.R_2_instances)
-        self.assertDryRun()
-        self.assertEqual(self.rapi.CountPending(), 0)
-
-        data = serializer.LoadJson(self.rapi.GetLastRequestData())
-        self.assertEqual(data["name"], "inst1.example.com")
-        self.assertEqual(data["disk_template"], "plain")
-        self.assertEqual(data["pnode"], "node99")
-        self.assertEqual(data[constants.BE_MEMORY], 512)
-        self.assertEqual(data[constants.BE_AUTO_BALANCE], False)
-        self.assertEqual(data[constants.HV_MIGRATION_PORT], 9876)
-        self.assertEqual(data[constants.HV_VNC_TLS], True)
-        self.assertEqual(data["disks"], [disk["size"] for disk in disks])
-
   def testCreateInstance(self):
     self.rapi.AddResponse(serializer.DumpJson([rlib2._INST_CREATE_REQV1]))
     self.rapi.AddResponse("23030")
@@ -813,6 +738,36 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
         self.assertEqual(data["mode"], mode)
         self.assertEqual(data["cleanup"], cleanup)
 
+  def testFailoverInstanceDefaults(self):
+    self.rapi.AddResponse("7639")
+    job_id = self.client.FailoverInstance("inst13579")
+    self.assertEqual(job_id, 7639)
+    self.assertHandler(rlib2.R_2_instances_name_failover)
+    self.assertItems(["inst13579"])
+
+    data = serializer.LoadJson(self.rapi.GetLastRequestData())
+    self.assertFalse(data)
+
+  def testFailoverInstance(self):
+    for iallocator in ["dumb", "hail"]:
+      for ignore_consistency in [False, True]:
+        for target_node in ["node-a", "node2"]:
+          self.rapi.AddResponse("19161")
+          job_id = \
+            self.client.FailoverInstance("inst251", iallocator=iallocator,
+                                         ignore_consistency=ignore_consistency,
+                                         target_node=target_node)
+          self.assertEqual(job_id, 19161)
+          self.assertHandler(rlib2.R_2_instances_name_failover)
+          self.assertItems(["inst251"])
+
+          data = serializer.LoadJson(self.rapi.GetLastRequestData())
+          self.assertEqual(len(data), 3)
+          self.assertEqual(data["iallocator"], iallocator)
+          self.assertEqual(data["ignore_consistency"], ignore_consistency)
+          self.assertEqual(data["target_node"], target_node)
+          self.assertEqual(self.rapi.CountPending(), 0)
+
   def testRenameInstanceDefaults(self):
     new_name = "newnametha7euqu"
     self.rapi.AddResponse("8791")
@@ -896,32 +851,75 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
     self.assertItems(["node-foo"])
 
   def testEvacuateNode(self):
+    self.rapi.AddResponse(serializer.DumpJson([rlib2._NODE_EVAC_RES1]))
     self.rapi.AddResponse("9876")
     job_id = self.client.EvacuateNode("node-1", remote_node="node-2")
     self.assertEqual(9876, job_id)
     self.assertHandler(rlib2.R_2_nodes_name_evacuate)
     self.assertItems(["node-1"])
-    self.assertQuery("remote_node", ["node-2"])
+    self.assertEqual(serializer.LoadJson(self.rapi.GetLastRequestData()),
+                     { "remote_node": "node-2", })
+    self.assertEqual(self.rapi.CountPending(), 0)
 
+    self.rapi.AddResponse(serializer.DumpJson([rlib2._NODE_EVAC_RES1]))
     self.rapi.AddResponse("8888")
     job_id = self.client.EvacuateNode("node-3", iallocator="hail", dry_run=True)
     self.assertEqual(8888, job_id)
     self.assertItems(["node-3"])
-    self.assertQuery("iallocator", ["hail"])
+    self.assertEqual(serializer.LoadJson(self.rapi.GetLastRequestData()),
+                     { "iallocator": "hail", })
     self.assertDryRun()
 
     self.assertRaises(client.GanetiApiError,
                       self.client.EvacuateNode,
                       "node-4", iallocator="hail", remote_node="node-5")
+    self.assertEqual(self.rapi.CountPending(), 0)
+
+  def testEvacuateNodeOldResponse(self):
+    self.rapi.AddResponse(serializer.DumpJson([]))
+    self.assertRaises(client.GanetiApiError, self.client.EvacuateNode,
+                      "node-4", accept_old=False)
+    self.assertEqual(self.rapi.CountPending(), 0)
+
+    self.rapi.AddResponse(serializer.DumpJson([]))
+    self.assertRaises(client.GanetiApiError, self.client.EvacuateNode,
+                      "node-4", accept_old=True)
+    self.assertEqual(self.rapi.CountPending(), 0)
+
+    self.rapi.AddResponse(serializer.DumpJson([]))
+    self.assertRaises(client.GanetiApiError, self.client.EvacuateNode,
+                      "node-4", accept_old=True, primary=True)
+    self.assertEqual(self.rapi.CountPending(), 0)
+
+    self.rapi.AddResponse(serializer.DumpJson([]))
+    self.assertRaises(client.GanetiApiError, self.client.EvacuateNode,
+                      "node-4", accept_old=True, secondary=False)
+    self.assertEqual(self.rapi.CountPending(), 0)
+
+    for sec in [True, None]:
+      self.rapi.AddResponse(serializer.DumpJson([]))
+      self.rapi.AddResponse(serializer.DumpJson([["res", "foo"]]))
+      result = self.client.EvacuateNode("node-3", iallocator="hail",
+                                        dry_run=True, accept_old=True,
+                                        primary=False, secondary=sec)
+      self.assertEqual(result, [["res", "foo"]])
+      self.assertItems(["node-3"])
+      self.assertQuery("iallocator", ["hail"])
+      self.assertFalse(self.rapi.GetLastRequestData())
+      self.assertDryRun()
+      self.assertEqual(self.rapi.CountPending(), 0)
 
   def testMigrateNode(self):
+    self.rapi.AddResponse(serializer.DumpJson([]))
     self.rapi.AddResponse("1111")
     self.assertEqual(1111, self.client.MigrateNode("node-a", dry_run=True))
     self.assertHandler(rlib2.R_2_nodes_name_migrate)
     self.assertItems(["node-a"])
     self.assert_("mode" not in self.rapi.GetLastHandler().queryargs)
     self.assertDryRun()
+    self.assertFalse(self.rapi.GetLastRequestData())
 
+    self.rapi.AddResponse(serializer.DumpJson([]))
     self.rapi.AddResponse("1112")
     self.assertEqual(1112, self.client.MigrateNode("node-a", dry_run=True,
                                                    mode="live"))
@@ -929,6 +927,36 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
     self.assertItems(["node-a"])
     self.assertQuery("mode", ["live"])
     self.assertDryRun()
+    self.assertFalse(self.rapi.GetLastRequestData())
+
+    self.rapi.AddResponse(serializer.DumpJson([]))
+    self.assertRaises(client.GanetiApiError, self.client.MigrateNode,
+                      "node-c", target_node="foonode")
+    self.assertEqual(self.rapi.CountPending(), 0)
+
+  def testMigrateNodeBodyData(self):
+    self.rapi.AddResponse(serializer.DumpJson([rlib2._NODE_MIGRATE_REQV1]))
+    self.rapi.AddResponse("27539")
+    self.assertEqual(27539, self.client.MigrateNode("node-a", dry_run=False,
+                                                    mode="live"))
+    self.assertHandler(rlib2.R_2_nodes_name_migrate)
+    self.assertItems(["node-a"])
+    self.assertFalse(self.rapi.GetLastHandler().queryargs)
+    self.assertEqual(serializer.LoadJson(self.rapi.GetLastRequestData()),
+                     { "mode": "live", })
+
+    self.rapi.AddResponse(serializer.DumpJson([rlib2._NODE_MIGRATE_REQV1]))
+    self.rapi.AddResponse("14219")
+    self.assertEqual(14219, self.client.MigrateNode("node-x", dry_run=True,
+                                                    target_node="node9",
+                                                    iallocator="ial"))
+    self.assertHandler(rlib2.R_2_nodes_name_migrate)
+    self.assertItems(["node-x"])
+    self.assertDryRun()
+    self.assertEqual(serializer.LoadJson(self.rapi.GetLastRequestData()),
+                     { "target_node": "node9", "iallocator": "ial", })
+
+    self.assertEqual(self.rapi.CountPending(), 0)
 
   def testGetNodeRole(self):
     self.rapi.AddResponse("\"master\"")
@@ -945,6 +973,24 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
     self.assertQuery("force", ["1"])
     self.assertEqual("\"master-candidate\"", self.rapi.GetLastRequestData())
 
+  def testPowercycleNode(self):
+    self.rapi.AddResponse("23051")
+    self.assertEqual(23051,
+        self.client.PowercycleNode("node5468", force=True))
+    self.assertHandler(rlib2.R_2_nodes_name_powercycle)
+    self.assertItems(["node5468"])
+    self.assertQuery("force", ["1"])
+    self.assertFalse(self.rapi.GetLastRequestData())
+    self.assertEqual(self.rapi.CountPending(), 0)
+
+  def testModifyNode(self):
+    self.rapi.AddResponse("3783")
+    job_id = self.client.ModifyNode("node16979.example.com", drained=True)
+    self.assertEqual(job_id, 3783)
+    self.assertHandler(rlib2.R_2_nodes_name_modify)
+    self.assertItems(["node16979.example.com"])
+    self.assertEqual(self.rapi.CountPending(), 0)
+
   def testGetNodeStorageUnits(self):
     self.rapi.AddResponse("42")
     self.assertEqual(42,
@@ -1138,6 +1184,14 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
     self.assertHandler(rlib2.R_2_instances_name_deactivate_disks)
     self.assertFalse(self.rapi.GetLastHandler().queryargs)
 
+  def testRecreateInstanceDisks(self):
+    self.rapi.AddResponse("13553")
+    job_id = self.client.RecreateInstanceDisks("inst23153")
+    self.assertEqual(job_id, 13553)
+    self.assertItems(["inst23153"])
+    self.assertHandler(rlib2.R_2_instances_name_recreate_disks)
+    self.assertFalse(self.rapi.GetLastHandler().queryargs)
+
   def testGetInstanceConsole(self):
     self.rapi.AddResponse("26876")
     job_id = self.client.GetInstanceConsole("inst21491")
@@ -1167,24 +1221,48 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
       self.assertEqual(data["amount"], amount)
       self.assertEqual(self.rapi.CountPending(), 0)
 
+  def testGetGroupTags(self):
+    self.rapi.AddResponse("[]")
+    self.assertEqual([], self.client.GetGroupTags("fooGroup"))
+    self.assertHandler(rlib2.R_2_groups_name_tags)
+    self.assertItems(["fooGroup"])
+
+  def testAddGroupTags(self):
+    self.rapi.AddResponse("1234")
+    self.assertEqual(1234,
+        self.client.AddGroupTags("fooGroup", ["awesome"], dry_run=True))
+    self.assertHandler(rlib2.R_2_groups_name_tags)
+    self.assertItems(["fooGroup"])
+    self.assertDryRun()
+    self.assertQuery("tag", ["awesome"])
+
+  def testDeleteGroupTags(self):
+    self.rapi.AddResponse("25826")
+    self.assertEqual(25826, self.client.DeleteGroupTags("foo", ["awesome"],
+                                                        dry_run=True))
+    self.assertHandler(rlib2.R_2_groups_name_tags)
+    self.assertItems(["foo"])
+    self.assertDryRun()
+    self.assertQuery("tag", ["awesome"])
+
   def testQuery(self):
     for idx, what in enumerate(constants.QR_VIA_RAPI):
-      for idx2, filter_ in enumerate([None, ["?", "name"]]):
+      for idx2, qfilter in enumerate([None, ["?", "name"]]):
         job_id = 11010 + (idx << 4) + (idx2 << 16)
         fields = sorted(query.ALL_FIELDS[what].keys())[:10]
 
         self.rapi.AddResponse(str(job_id))
-        self.assertEqual(self.client.Query(what, fields, filter_=filter_),
+        self.assertEqual(self.client.Query(what, fields, qfilter=qfilter),
                          job_id)
         self.assertItems([what])
         self.assertHandler(rlib2.R_2_query)
         self.assertFalse(self.rapi.GetLastHandler().queryargs)
         data = serializer.LoadJson(self.rapi.GetLastRequestData())
         self.assertEqual(data["fields"], fields)
-        if filter_ is None:
-          self.assertTrue("filter" not in data)
+        if qfilter is None:
+          self.assertTrue("qfilter" not in data)
         else:
-          self.assertEqual(data["filter"], filter_)
+          self.assertEqual(data["qfilter"], qfilter)
         self.assertEqual(self.rapi.CountPending(), 0)
 
   def testQueryFields(self):
@@ -1218,7 +1296,7 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
 
   def testWaitForJobCompletionNoChange(self):
     resp = serializer.DumpJson({
-      "status": constants.JOB_STATUS_WAITLOCK,
+      "status": constants.JOB_STATUS_WAITING,
       })
 
     for retries in [1, 5, 25]: