Commit 0b58db81 authored by Michael Hanselmann's avatar Michael Hanselmann
Browse files

RAPI: Make node evacuation actually work

Commit e1f23243 changed te LU and opcode for node evacuation to receive
a “mode” parameter (among other things). Commit de40437a

 changed the
RAPI code accordingly, but did so for an earlier version of the first
patch. Obviously this couldn't work, so here's the fix.
Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarGuido Trotter <ultrotter@google.com>
parent a867283d
......@@ -63,6 +63,10 @@ REPLACE_DISK_SECONDARY = "replace_on_secondary"
REPLACE_DISK_CHG = "replace_new_secondary"
REPLACE_DISK_AUTO = "replace_auto"
NODE_EVAC_PRI = "primary-only"
NODE_EVAC_SEC = "secondary-only"
NODE_EVAC_ALL = "all"
NODE_ROLE_DRAINED = "drained"
NODE_ROLE_MASTER_CANDIATE = "master-candidate"
NODE_ROLE_MASTER = "master"
......@@ -1284,7 +1288,7 @@ class GanetiRapiClient(object): # pylint: disable=R0904
def EvacuateNode(self, node, iallocator=None, remote_node=None,
dry_run=False, early_release=None,
primary=None, secondary=None, accept_old=False):
mode=None, accept_old=False):
"""Evacuates instances from a Ganeti node.
@type node: str
......@@ -1297,10 +1301,8 @@ class GanetiRapiClient(object): # pylint: disable=R0904
@param dry_run: whether to perform a dry run
@type early_release: bool
@param early_release: whether to enable parallelization
@type primary: bool
@param primary: Whether to evacuate primary instances
@type secondary: bool
@param secondary: Whether to evacuate secondary instances
@type mode: string
@param mode: Node evacuation mode
@type accept_old: bool
@param accept_old: Whether caller is ready to accept old-style (pre-2.5)
results
......@@ -1323,6 +1325,7 @@ class GanetiRapiClient(object): # pylint: disable=R0904
query.append(("dry-run", 1))
if _NODE_EVAC_RES1 in self.GetFeatures():
# Server supports body parameters
body = {}
if iallocator is not None:
......@@ -1331,10 +1334,8 @@ class GanetiRapiClient(object): # pylint: disable=R0904
body["remote_node"] = remote_node
if early_release is not None:
body["early_release"] = early_release
if primary is not None:
body["primary"] = primary
if secondary is not None:
body["secondary"] = secondary
if mode is not None:
body["mode"] = mode
else:
# Pre-2.5 request format
body = None
......@@ -1344,7 +1345,8 @@ class GanetiRapiClient(object): # pylint: disable=R0904
" not accept old-style results (parameter"
" accept_old)")
if primary or primary is None or not (secondary is None or secondary):
# Pre-2.5 servers can only evacuate secondaries
if mode is not None and mode != NODE_EVAC_SEC:
raise GanetiApiError("Server can only evacuate secondary instances")
if iallocator:
......
......@@ -165,6 +165,11 @@ class TestConstants(unittest.TestCase):
self.assertEqual(client.JOB_STATUS_FINALIZED, constants.JOBS_FINALIZED)
self.assertEqual(client.JOB_STATUS_ALL, constants.JOB_STATUS_ALL)
# Node evacuation
self.assertEqual(client.NODE_EVAC_PRI, constants.IALLOCATOR_NEVAC_PRI)
self.assertEqual(client.NODE_EVAC_SEC, constants.IALLOCATOR_NEVAC_SEC)
self.assertEqual(client.NODE_EVAC_ALL, constants.IALLOCATOR_NEVAC_ALL)
# Legacy name
self.assertEqual(client.JOB_STATUS_WAITLOCK, constants.JOB_STATUS_WAITING)
......@@ -860,11 +865,16 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
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)
job_id = self.client.EvacuateNode("node-3", iallocator="hail", dry_run=True,
mode=constants.IALLOCATOR_NEVAC_ALL,
early_release=True)
self.assertEqual(8888, job_id)
self.assertItems(["node-3"])
self.assertEqual(serializer.LoadJson(self.rapi.GetLastRequestData()),
{ "iallocator": "hail", })
self.assertEqual(serializer.LoadJson(self.rapi.GetLastRequestData()), {
"iallocator": "hail",
"mode": "all",
"early_release": True,
})
self.assertDryRun()
self.assertRaises(client.GanetiApiError,
......@@ -878,34 +888,26 @@ class GanetiRapiClientTests(testutils.GanetiTestCase):
"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)
for mode in [client.NODE_EVAC_PRI, client.NODE_EVAC_ALL]:
self.rapi.AddResponse(serializer.DumpJson([]))
self.assertRaises(client.GanetiApiError, self.client.EvacuateNode,
"node-4", accept_old=True, mode=mode)
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.rapi.AddResponse(serializer.DumpJson("21533"))
result = self.client.EvacuateNode("node-3", iallocator="hail",
dry_run=True, accept_old=True,
mode=client.NODE_EVAC_SEC,
early_release=True)
self.assertEqual(result, "21533")
self.assertItems(["node-3"])
self.assertQuery("iallocator", ["hail"])
self.assertQuery("early_release", ["1"])
self.assertFalse(self.rapi.GetLastRequestData())
self.assertDryRun()
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")
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment