Revision a60e3cb0 lib/rapi/client.py
b/lib/rapi/client.py | ||
---|---|---|
333 | 333 |
self._port = port |
334 | 334 |
self._logger = logger |
335 | 335 |
|
336 |
self._version = None |
|
337 |
|
|
338 | 336 |
self._base_url = "https://%s:%s" % (host, port) |
339 | 337 |
|
340 | 338 |
handlers = [_HTTPSHandler(self._logger, config_ssl_verification)] |
... | ... | |
357 | 355 |
"User-Agent": self.USER_AGENT, |
358 | 356 |
} |
359 | 357 |
|
360 |
def _MakeUrl(self, path, query=None, prepend_version=True):
|
|
358 |
def _MakeUrl(self, path, query=None): |
|
361 | 359 |
"""Constructs the URL to pass to the HTTP client. |
362 | 360 |
|
363 | 361 |
@type path: str |
364 | 362 |
@param path: HTTP URL path |
365 | 363 |
@type query: list of two-tuples |
366 | 364 |
@param query: query arguments to pass to urllib.urlencode |
367 |
@type prepend_version: bool |
|
368 |
@param prepend_version: whether to automatically fetch and prepend the |
|
369 |
Ganeti RAPI version to the URL path |
|
370 | 365 |
|
371 | 366 |
@rtype: str |
372 | 367 |
@return: URL path |
373 | 368 |
|
374 | 369 |
""" |
375 |
if prepend_version: |
|
376 |
path = "/%d%s" % (self.GetVersion(), path) |
|
377 |
|
|
378 | 370 |
return "https://%(host)s:%(port)d%(path)s?%(query)s" % { |
379 | 371 |
"host": self._host, |
380 | 372 |
"port": self._port, |
381 | 373 |
"path": path, |
382 | 374 |
"query": urllib.urlencode(query or [])} |
383 | 375 |
|
384 |
def _SendRequest(self, method, path, query=None, content=None, |
|
385 |
prepend_version=True): |
|
376 |
def _SendRequest(self, method, path, query=None, content=None): |
|
386 | 377 |
"""Sends an HTTP request. |
387 | 378 |
|
388 | 379 |
This constructs a full URL, encodes and decodes HTTP bodies, and |
... | ... | |
396 | 387 |
@param query: query arguments to pass to urllib.urlencode |
397 | 388 |
@type content: str or None |
398 | 389 |
@param content: HTTP body content |
399 |
@type prepend_version: bool |
|
400 |
@param prepend_version: whether to automatically fetch and prepend the |
|
401 |
Ganeti RAPI version to the URL path |
|
402 | 390 |
|
403 | 391 |
@rtype: str |
404 | 392 |
@return: JSON-Decoded response |
... | ... | |
410 | 398 |
if content: |
411 | 399 |
content = simplejson.JSONEncoder(sort_keys=True).encode(content) |
412 | 400 |
|
413 |
url = self._MakeUrl(path, query, prepend_version)
|
|
401 |
url = self._MakeUrl(path, query) |
|
414 | 402 |
|
415 | 403 |
req = _RapiRequest(method, url, self._headers, content) |
416 | 404 |
|
... | ... | |
442 | 430 |
@return: Ganeti Remote API version |
443 | 431 |
|
444 | 432 |
""" |
445 |
if self._version is None: |
|
446 |
self._version = self._SendRequest(HTTP_GET, "/version", |
|
447 |
prepend_version=False) |
|
448 |
return self._version |
|
433 |
return self._SendRequest(HTTP_GET, "/version") |
|
449 | 434 |
|
450 | 435 |
def GetOperatingSystems(self): |
451 | 436 |
"""Gets the Operating Systems running in the Ganeti cluster. |
... | ... | |
454 | 439 |
@return: operating systems |
455 | 440 |
|
456 | 441 |
""" |
457 |
return self._SendRequest(HTTP_GET, "/os") |
|
442 |
return self._SendRequest(HTTP_GET, "/2/os")
|
|
458 | 443 |
|
459 | 444 |
def GetInfo(self): |
460 | 445 |
"""Gets info about the cluster. |
... | ... | |
463 | 448 |
@return: information about the cluster |
464 | 449 |
|
465 | 450 |
""" |
466 |
return self._SendRequest(HTTP_GET, "/info") |
|
451 |
return self._SendRequest(HTTP_GET, "/2/info")
|
|
467 | 452 |
|
468 | 453 |
def GetClusterTags(self): |
469 | 454 |
"""Gets the cluster tags. |
... | ... | |
472 | 457 |
@return: cluster tags |
473 | 458 |
|
474 | 459 |
""" |
475 |
return self._SendRequest(HTTP_GET, "/tags") |
|
460 |
return self._SendRequest(HTTP_GET, "/2/tags")
|
|
476 | 461 |
|
477 | 462 |
def AddClusterTags(self, tags, dry_run=False): |
478 | 463 |
"""Adds tags to the cluster. |
... | ... | |
490 | 475 |
if dry_run: |
491 | 476 |
query.append(("dry-run", 1)) |
492 | 477 |
|
493 |
return self._SendRequest(HTTP_PUT, "/tags", query) |
|
478 |
return self._SendRequest(HTTP_PUT, "/2/tags", query)
|
|
494 | 479 |
|
495 | 480 |
def DeleteClusterTags(self, tags, dry_run=False): |
496 | 481 |
"""Deletes tags from the cluster. |
... | ... | |
505 | 490 |
if dry_run: |
506 | 491 |
query.append(("dry-run", 1)) |
507 | 492 |
|
508 |
self._SendRequest(HTTP_DELETE, "/tags", query) |
|
493 |
self._SendRequest(HTTP_DELETE, "/2/tags", query)
|
|
509 | 494 |
|
510 | 495 |
def GetInstances(self, bulk=False): |
511 | 496 |
"""Gets information about instances on the cluster. |
... | ... | |
521 | 506 |
if bulk: |
522 | 507 |
query.append(("bulk", 1)) |
523 | 508 |
|
524 |
instances = self._SendRequest(HTTP_GET, "/instances", query) |
|
509 |
instances = self._SendRequest(HTTP_GET, "/2/instances", query)
|
|
525 | 510 |
if bulk: |
526 | 511 |
return instances |
527 | 512 |
else: |
... | ... | |
538 | 523 |
@return: info about the instance |
539 | 524 |
|
540 | 525 |
""" |
541 |
return self._SendRequest(HTTP_GET, "/instances/%s" % instance) |
|
526 |
return self._SendRequest(HTTP_GET, "/2/instances/%s" % instance)
|
|
542 | 527 |
|
543 | 528 |
def CreateInstance(self, dry_run=False): |
544 | 529 |
"""Creates a new instance. |
... | ... | |
555 | 540 |
if dry_run: |
556 | 541 |
query.append(("dry-run", 1)) |
557 | 542 |
|
558 |
return self._SendRequest(HTTP_POST, "/instances", query) |
|
543 |
return self._SendRequest(HTTP_POST, "/2/instances", query)
|
|
559 | 544 |
|
560 | 545 |
def DeleteInstance(self, instance, dry_run=False): |
561 | 546 |
"""Deletes an instance. |
... | ... | |
571 | 556 |
if dry_run: |
572 | 557 |
query.append(("dry-run", 1)) |
573 | 558 |
|
574 |
return self._SendRequest(HTTP_DELETE, "/instances/%s" % instance, query) |
|
559 |
return self._SendRequest(HTTP_DELETE, "/2/instances/%s" % instance, query)
|
|
575 | 560 |
|
576 | 561 |
def GetInstanceTags(self, instance): |
577 | 562 |
"""Gets tags for an instance. |
... | ... | |
583 | 568 |
@return: tags for the instance |
584 | 569 |
|
585 | 570 |
""" |
586 |
return self._SendRequest(HTTP_GET, "/instances/%s/tags" % instance) |
|
571 |
return self._SendRequest(HTTP_GET, "/2/instances/%s/tags" % instance)
|
|
587 | 572 |
|
588 | 573 |
def AddInstanceTags(self, instance, tags, dry_run=False): |
589 | 574 |
"""Adds tags to an instance. |
... | ... | |
603 | 588 |
if dry_run: |
604 | 589 |
query.append(("dry-run", 1)) |
605 | 590 |
|
606 |
return self._SendRequest(HTTP_PUT, "/instances/%s/tags" % instance, query) |
|
591 |
return self._SendRequest(HTTP_PUT, "/2/instances/%s/tags" % instance, query)
|
|
607 | 592 |
|
608 | 593 |
def DeleteInstanceTags(self, instance, tags, dry_run=False): |
609 | 594 |
"""Deletes tags from an instance. |
... | ... | |
620 | 605 |
if dry_run: |
621 | 606 |
query.append(("dry-run", 1)) |
622 | 607 |
|
623 |
self._SendRequest(HTTP_DELETE, "/instances/%s/tags" % instance, query) |
|
608 |
self._SendRequest(HTTP_DELETE, "/2/instances/%s/tags" % instance, query)
|
|
624 | 609 |
|
625 | 610 |
def RebootInstance(self, instance, reboot_type=None, ignore_secondaries=None, |
626 | 611 |
dry_run=False): |
... | ... | |
645 | 630 |
if dry_run: |
646 | 631 |
query.append(("dry-run", 1)) |
647 | 632 |
|
648 |
self._SendRequest(HTTP_POST, "/instances/%s/reboot" % instance, query) |
|
633 |
self._SendRequest(HTTP_POST, "/2/instances/%s/reboot" % instance, query)
|
|
649 | 634 |
|
650 | 635 |
def ShutdownInstance(self, instance, dry_run=False): |
651 | 636 |
"""Shuts down an instance. |
... | ... | |
660 | 645 |
if dry_run: |
661 | 646 |
query.append(("dry-run", 1)) |
662 | 647 |
|
663 |
self._SendRequest(HTTP_PUT, "/instances/%s/shutdown" % instance, query) |
|
648 |
self._SendRequest(HTTP_PUT, "/2/instances/%s/shutdown" % instance, query)
|
|
664 | 649 |
|
665 | 650 |
def StartupInstance(self, instance, dry_run=False): |
666 | 651 |
"""Starts up an instance. |
... | ... | |
675 | 660 |
if dry_run: |
676 | 661 |
query.append(("dry-run", 1)) |
677 | 662 |
|
678 |
self._SendRequest(HTTP_PUT, "/instances/%s/startup" % instance, query) |
|
663 |
self._SendRequest(HTTP_PUT, "/2/instances/%s/startup" % instance, query)
|
|
679 | 664 |
|
680 | 665 |
def ReinstallInstance(self, instance, os, no_startup=False): |
681 | 666 |
"""Reinstalls an instance. |
... | ... | |
691 | 676 |
query = [("os", os)] |
692 | 677 |
if no_startup: |
693 | 678 |
query.append(("nostartup", 1)) |
694 |
self._SendRequest(HTTP_POST, "/instances/%s/reinstall" % instance, query) |
|
679 |
self._SendRequest(HTTP_POST, "/2/instances/%s/reinstall" % instance, query)
|
|
695 | 680 |
|
696 | 681 |
def ReplaceInstanceDisks(self, instance, disks, mode="replace_auto", |
697 | 682 |
remote_node=None, iallocator="hail", dry_run=False): |
... | ... | |
737 | 722 |
query.append(("dry-run", 1)) |
738 | 723 |
|
739 | 724 |
return self._SendRequest(HTTP_POST, |
740 |
"/instances/%s/replace-disks" % instance, query) |
|
725 |
"/2/instances/%s/replace-disks" % instance, query)
|
|
741 | 726 |
|
742 | 727 |
def GetJobs(self): |
743 | 728 |
"""Gets all jobs for the cluster. |
... | ... | |
746 | 731 |
@return: job ids for the cluster |
747 | 732 |
|
748 | 733 |
""" |
749 |
return [int(j["id"]) for j in self._SendRequest(HTTP_GET, "/jobs")] |
|
734 |
return [int(j["id"]) for j in self._SendRequest(HTTP_GET, "/2/jobs")]
|
|
750 | 735 |
|
751 | 736 |
def GetJobStatus(self, job_id): |
752 | 737 |
"""Gets the status of a job. |
... | ... | |
758 | 743 |
@return: job status |
759 | 744 |
|
760 | 745 |
""" |
761 |
return self._SendRequest(HTTP_GET, "/jobs/%d" % job_id) |
|
746 |
return self._SendRequest(HTTP_GET, "/2/jobs/%d" % job_id)
|
|
762 | 747 |
|
763 | 748 |
def DeleteJob(self, job_id, dry_run=False): |
764 | 749 |
"""Deletes a job. |
... | ... | |
773 | 758 |
if dry_run: |
774 | 759 |
query.append(("dry-run", 1)) |
775 | 760 |
|
776 |
self._SendRequest(HTTP_DELETE, "/jobs/%d" % job_id, query) |
|
761 |
self._SendRequest(HTTP_DELETE, "/2/jobs/%d" % job_id, query)
|
|
777 | 762 |
|
778 | 763 |
def GetNodes(self, bulk=False): |
779 | 764 |
"""Gets all nodes in the cluster. |
... | ... | |
790 | 775 |
if bulk: |
791 | 776 |
query.append(("bulk", 1)) |
792 | 777 |
|
793 |
nodes = self._SendRequest(HTTP_GET, "/nodes", query) |
|
778 |
nodes = self._SendRequest(HTTP_GET, "/2/nodes", query)
|
|
794 | 779 |
if bulk: |
795 | 780 |
return nodes |
796 | 781 |
else: |
... | ... | |
806 | 791 |
@return: info about the node |
807 | 792 |
|
808 | 793 |
""" |
809 |
return self._SendRequest(HTTP_GET, "/nodes/%s" % node) |
|
794 |
return self._SendRequest(HTTP_GET, "/2/nodes/%s" % node)
|
|
810 | 795 |
|
811 | 796 |
def EvacuateNode(self, node, iallocator=None, remote_node=None, |
812 | 797 |
dry_run=False): |
... | ... | |
838 | 823 |
if dry_run: |
839 | 824 |
query.append(("dry-run", 1)) |
840 | 825 |
|
841 |
return self._SendRequest(HTTP_POST, "/nodes/%s/evacuate" % node, query) |
|
826 |
return self._SendRequest(HTTP_POST, "/2/nodes/%s/evacuate" % node, query)
|
|
842 | 827 |
|
843 | 828 |
def MigrateNode(self, node, live=True, dry_run=False): |
844 | 829 |
"""Migrates all primary instances from a node. |
... | ... | |
860 | 845 |
if dry_run: |
861 | 846 |
query.append(("dry-run", 1)) |
862 | 847 |
|
863 |
return self._SendRequest(HTTP_POST, "/nodes/%s/migrate" % node, query) |
|
848 |
return self._SendRequest(HTTP_POST, "/2/nodes/%s/migrate" % node, query)
|
|
864 | 849 |
|
865 | 850 |
def GetNodeRole(self, node): |
866 | 851 |
"""Gets the current role for a node. |
... | ... | |
872 | 857 |
@return: the current role for a node |
873 | 858 |
|
874 | 859 |
""" |
875 |
return self._SendRequest(HTTP_GET, "/nodes/%s/role" % node) |
|
860 |
return self._SendRequest(HTTP_GET, "/2/nodes/%s/role" % node)
|
|
876 | 861 |
|
877 | 862 |
def SetNodeRole(self, node, role, force=False): |
878 | 863 |
"""Sets the role for a node. |
... | ... | |
894 | 879 |
raise InvalidNodeRole("%s is not a valid node role.", role) |
895 | 880 |
|
896 | 881 |
query = [("force", force)] |
897 |
return self._SendRequest(HTTP_PUT, "/nodes/%s/role" % node, query, |
|
882 |
return self._SendRequest(HTTP_PUT, "/2/nodes/%s/role" % node, query,
|
|
898 | 883 |
content=role) |
899 | 884 |
|
900 | 885 |
def GetNodeStorageUnits(self, node, storage_type, output_fields): |
... | ... | |
918 | 903 |
raise InvalidStorageType("%s is an invalid storage type.", storage_type) |
919 | 904 |
|
920 | 905 |
query = [("storage_type", storage_type), ("output_fields", output_fields)] |
921 |
return self._SendRequest(HTTP_GET, "/nodes/%s/storage" % node, query) |
|
906 |
return self._SendRequest(HTTP_GET, "/2/nodes/%s/storage" % node, query)
|
|
922 | 907 |
|
923 | 908 |
def ModifyNodeStorageUnits(self, node, storage_type, name, allocatable=True): |
924 | 909 |
"""Modifies parameters of storage units on the node. |
... | ... | |
945 | 930 |
("storage_type", storage_type), ("name", name), |
946 | 931 |
("allocatable", allocatable) |
947 | 932 |
] |
948 |
return self._SendRequest(HTTP_PUT, "/nodes/%s/storage/modify" % node, query) |
|
933 |
return self._SendRequest(HTTP_PUT, "/2/nodes/%s/storage/modify" % node, |
|
934 |
query) |
|
949 | 935 |
|
950 | 936 |
def RepairNodeStorageUnits(self, node, storage_type, name): |
951 | 937 |
"""Repairs a storage unit on the node. |
... | ... | |
967 | 953 |
raise InvalidStorageType("%s is an invalid storage type.", storage_type) |
968 | 954 |
|
969 | 955 |
query = [("storage_type", storage_type), ("name", name)] |
970 |
return self._SendRequest(HTTP_PUT, "/nodes/%s/storage/repair" % node, query) |
|
956 |
return self._SendRequest(HTTP_PUT, "/2/nodes/%s/storage/repair" % node, |
|
957 |
query) |
|
971 | 958 |
|
972 | 959 |
def GetNodeTags(self, node): |
973 | 960 |
"""Gets the tags for a node. |
... | ... | |
979 | 966 |
@return: tags for the node |
980 | 967 |
|
981 | 968 |
""" |
982 |
return self._SendRequest(HTTP_GET, "/nodes/%s/tags" % node) |
|
969 |
return self._SendRequest(HTTP_GET, "/2/nodes/%s/tags" % node)
|
|
983 | 970 |
|
984 | 971 |
def AddNodeTags(self, node, tags, dry_run=False): |
985 | 972 |
"""Adds tags to a node. |
... | ... | |
999 | 986 |
if dry_run: |
1000 | 987 |
query.append(("dry-run", 1)) |
1001 | 988 |
|
1002 |
return self._SendRequest(HTTP_PUT, "/nodes/%s/tags" % node, query, |
|
989 |
return self._SendRequest(HTTP_PUT, "/2/nodes/%s/tags" % node, query,
|
|
1003 | 990 |
content=tags) |
1004 | 991 |
|
1005 | 992 |
def DeleteNodeTags(self, node, tags, dry_run=False): |
... | ... | |
1020 | 1007 |
if dry_run: |
1021 | 1008 |
query.append(("dry-run", 1)) |
1022 | 1009 |
|
1023 |
return self._SendRequest(HTTP_DELETE, "/nodes/%s/tags" % node, query) |
|
1010 |
return self._SendRequest(HTTP_DELETE, "/2/nodes/%s/tags" % node, query) |
Also available in: Unified diff