Revision bfc2002f
b/lib/rapi/client.py | ||
---|---|---|
45 | 45 |
REPLACE_DISK_SECONDARY = "replace_on_secondary" |
46 | 46 |
REPLACE_DISK_CHG = "replace_new_secondary" |
47 | 47 |
REPLACE_DISK_AUTO = "replace_auto" |
48 |
VALID_REPLACEMENT_MODES = frozenset([ |
|
49 |
REPLACE_DISK_PRI, |
|
50 |
REPLACE_DISK_SECONDARY, |
|
51 |
REPLACE_DISK_CHG, |
|
52 |
REPLACE_DISK_AUTO, |
|
53 |
]) |
|
54 | 48 |
VALID_NODE_ROLES = frozenset([ |
55 | 49 |
"drained", "master", "master-candidate", "offline", "regular", |
56 | 50 |
]) |
... | ... | |
79 | 73 |
self.code = code |
80 | 74 |
|
81 | 75 |
|
82 |
class InvalidReplacementMode(Error): |
|
83 |
"""Raised when an invalid disk replacement mode is attempted. |
|
84 |
|
|
85 |
""" |
|
86 |
pass |
|
87 |
|
|
88 |
|
|
89 | 76 |
class InvalidNodeRole(Error): |
90 | 77 |
"""Raised when an invalid node role is used. |
91 | 78 |
|
... | ... | |
721 | 708 |
("/%s/instances/%s/reinstall" % |
722 | 709 |
(GANETI_RAPI_VERSION, instance)), query, None) |
723 | 710 |
|
724 |
def ReplaceInstanceDisks(self, instance, disks, mode=REPLACE_DISK_AUTO, |
|
711 |
def ReplaceInstanceDisks(self, instance, disks=None, mode=REPLACE_DISK_AUTO,
|
|
725 | 712 |
remote_node=None, iallocator=None, dry_run=False): |
726 | 713 |
"""Replaces disks on an instance. |
727 | 714 |
|
728 | 715 |
@type instance: str |
729 | 716 |
@param instance: instance whose disks to replace |
730 |
@type disks: list of str
|
|
731 |
@param disks: disks to replace |
|
717 |
@type disks: list of ints
|
|
718 |
@param disks: Indexes of disks to replace
|
|
732 | 719 |
@type mode: str |
733 | 720 |
@param mode: replacement mode to use (defaults to replace_auto) |
734 | 721 |
@type remote_node: str or None |
... | ... | |
743 | 730 |
@rtype: int |
744 | 731 |
@return: job id |
745 | 732 |
|
746 |
@raises InvalidReplacementMode: If an invalid disk replacement mode is given |
|
747 |
@raises GanetiApiError: If no secondary node is given with a non-auto |
|
748 |
replacement mode is requested. |
|
749 |
|
|
750 | 733 |
""" |
751 |
if mode not in VALID_REPLACEMENT_MODES: |
|
752 |
raise InvalidReplacementMode("%s is not a valid disk replacement mode" % |
|
753 |
mode) |
|
754 |
|
|
755 | 734 |
query = [ |
756 | 735 |
("mode", mode), |
757 |
("disks", ",".join(disks)), |
|
758 | 736 |
] |
759 | 737 |
|
760 |
if mode == REPLACE_DISK_AUTO: |
|
761 |
query.append(("iallocator", iallocator)) |
|
762 |
elif mode == REPLACE_DISK_SECONDARY: |
|
763 |
if remote_node is None: |
|
764 |
raise GanetiApiError("Missing secondary node") |
|
738 |
if disks: |
|
739 |
query.append(("disks", ",".join(str(idx) for idx in disks))) |
|
740 |
|
|
741 |
if remote_node: |
|
765 | 742 |
query.append(("remote_node", remote_node)) |
766 | 743 |
|
744 |
if iallocator: |
|
745 |
query.append(("iallocator", iallocator)) |
|
746 |
|
|
767 | 747 |
if dry_run: |
768 | 748 |
query.append(("dry-run", 1)) |
769 | 749 |
|
b/test/ganeti.rapi.client_unittest.py | ||
---|---|---|
309 | 309 |
def testReplaceInstanceDisks(self): |
310 | 310 |
self.rapi.AddResponse("999") |
311 | 311 |
job_id = self.client.ReplaceInstanceDisks("instance-name", |
312 |
["hda", "hdc"], dry_run=True, iallocator="hail")
|
|
312 |
disks=[0, 1], dry_run=True, iallocator="hail")
|
|
313 | 313 |
self.assertEqual(999, job_id) |
314 | 314 |
self.assertHandler(rlib2.R_2_instances_name_replace_disks) |
315 | 315 |
self.assertItems(["instance-name"]) |
316 |
self.assertQuery("disks", ["hda,hdc"])
|
|
316 |
self.assertQuery("disks", ["0,1"])
|
|
317 | 317 |
self.assertQuery("mode", ["replace_auto"]) |
318 | 318 |
self.assertQuery("iallocator", ["hail"]) |
319 | 319 |
self.assertDryRun() |
320 | 320 |
|
321 |
self.assertRaises(client.InvalidReplacementMode, |
|
322 |
self.client.ReplaceInstanceDisks, |
|
323 |
"instance_a", ["hda"], mode="invalid_mode") |
|
324 |
self.assertRaises(client.GanetiApiError, |
|
325 |
self.client.ReplaceInstanceDisks, |
|
326 |
"instance-foo", ["hda"], mode="replace_on_secondary") |
|
327 |
|
|
328 | 321 |
self.rapi.AddResponse("1000") |
329 | 322 |
job_id = self.client.ReplaceInstanceDisks("instance-bar", |
330 |
["hda"], mode="replace_on_secondary", remote_node="foo-node",
|
|
323 |
disks=[1], mode="replace_on_secondary", remote_node="foo-node",
|
|
331 | 324 |
dry_run=True) |
332 | 325 |
self.assertEqual(1000, job_id) |
333 | 326 |
self.assertItems(["instance-bar"]) |
334 |
self.assertQuery("disks", ["hda"])
|
|
327 |
self.assertQuery("disks", ["1"])
|
|
335 | 328 |
self.assertQuery("remote_node", ["foo-node"]) |
336 | 329 |
self.assertDryRun() |
337 | 330 |
|
331 |
self.rapi.AddResponse("5175") |
|
332 |
self.assertEqual(5175, self.client.ReplaceInstanceDisks("instance-moo")) |
|
333 |
self.assertItems(["instance-moo"]) |
|
334 |
self.assertQuery("disks", None) |
|
335 |
|
|
338 | 336 |
def testGetJobs(self): |
339 | 337 |
self.rapi.AddResponse('[ { "id": "123", "uri": "\\/2\\/jobs\\/123" },' |
340 | 338 |
' { "id": "124", "uri": "\\/2\\/jobs\\/124" } ]') |
Also available in: Unified diff