Revision 915faf72

b/lib/rapi/client.py
674 674
                             ("/%s/instances/%s/info" %
675 675
                              (GANETI_RAPI_VERSION, instance)), query, None)
676 676

  
677
  @staticmethod
678
  def _UpdateWithKwargs(base, **kwargs):
679
    """Updates the base with params from kwargs.
680

  
681
    @param base: The base dict, filled with required fields
682

  
683
    @note: This is an inplace update of base
684

  
685
    """
686
    conflicts = set(kwargs.iterkeys()) & set(base.iterkeys())
687
    if conflicts:
688
      raise GanetiApiError("Required fields can not be specified as"
689
                           " keywords: %s" % ", ".join(conflicts))
690

  
691
    base.update((key, value) for key, value in kwargs.iteritems()
692
                if key != "dry_run")
693

  
694
  def InstanceAllocation(self, mode, name, disk_template, disks, nics,
695
                         **kwargs):
696
    """Generates an instance allocation as used by multiallocate.
697

  
698
    More details for parameters can be found in the RAPI documentation.
699
    It is the same as used by CreateInstance.
700

  
701
    @type mode: string
702
    @param mode: Instance creation mode
703
    @type name: string
704
    @param name: Hostname of the instance to create
705
    @type disk_template: string
706
    @param disk_template: Disk template for instance (e.g. plain, diskless,
707
                          file, or drbd)
708
    @type disks: list of dicts
709
    @param disks: List of disk definitions
710
    @type nics: list of dicts
711
    @param nics: List of NIC definitions
712

  
713
    @return: A dict with the generated entry
714

  
715
    """
716
    # All required fields for request data version 1
717
    alloc = {
718
      "mode": mode,
719
      "name": name,
720
      "disk_template": disk_template,
721
      "disks": disks,
722
      "nics": nics,
723
      }
724

  
725
    self._UpdateWithKwargs(alloc, **kwargs)
726

  
727
    return alloc
728

  
729
  def InstancesMultiAlloc(self, instances, **kwargs):
730
    """Tries to allocate multiple instances.
731

  
732
    More details for parameters can be found in the RAPI documentation.
733

  
734
    @param instances: A list of L{InstanceAllocation} results
735

  
736
    """
737
    query = []
738
    body = {
739
      "instances": instances,
740
      }
741
    self._UpdateWithKwargs(body, **kwargs)
742

  
743
    _AppendDryRunIf(query, kwargs.get("dry_run"))
744

  
745
    return self._SendRequest(HTTP_POST,
746
                             "/%s/instances-multi-alloc" % GANETI_RAPI_VERSION,
747
                             query, body)
748

  
677 749
  def CreateInstance(self, mode, name, disk_template, disks, nics,
678 750
                     **kwargs):
679 751
    """Creates a new instance.
......
703 775
    _AppendDryRunIf(query, kwargs.get("dry_run"))
704 776

  
705 777
    if _INST_CREATE_REQV1 in self.GetFeatures():
706
      # All required fields for request data version 1
707
      body = {
708
        _REQ_DATA_VERSION_FIELD: 1,
709
        "mode": mode,
710
        "name": name,
711
        "disk_template": disk_template,
712
        "disks": disks,
713
        "nics": nics,
714
        }
715

  
716
      conflicts = set(kwargs.iterkeys()) & set(body.iterkeys())
717
      if conflicts:
718
        raise GanetiApiError("Required fields can not be specified as"
719
                             " keywords: %s" % ", ".join(conflicts))
720

  
721
      body.update((key, value) for key, value in kwargs.iteritems()
722
                  if key != "dry_run")
778
      body = self.InstanceAllocation(mode, name, disk_template, disks, nics,
779
                                     **kwargs)
780
      body[_REQ_DATA_VERSION_FIELD] = 1
723 781
    else:
724 782
      raise GanetiApiError("Server does not support new-style (version 1)"
725 783
                           " instance creation requests")
b/test/ganeti.rapi.client_unittest.py
26 26
import warnings
27 27
import pycurl
28 28

  
29
from ganeti import opcodes
29 30
from ganeti import constants
30 31
from ganeti import http
31 32
from ganeti import serializer
......
46 47
_KNOWN_UNUSED = set([
47 48
  rlib2.R_root,
48 49
  rlib2.R_2,
49
  rlib2.R_2_instances_multi_alloc,
50 50
  ])
51 51

  
52 52
# Global variable for collecting used handlers
......
481 481
    self.assertItems(["inst32"])
482 482
    self.assertQuery("static", ["1"])
483 483

  
484
  def testInstancesMultiAlloc(self):
485
    response = {
486
      constants.JOB_IDS_KEY: ["23423"],
487
      opcodes.OpInstanceMultiAlloc.ALLOCATABLE_KEY: ["foobar"],
488
      opcodes.OpInstanceMultiAlloc.FAILED_KEY: ["foobar2"],
489
      }
490
    self.rapi.AddResponse(serializer.DumpJson(response))
491
    insts = [self.client.InstanceAllocation("create", "foobar",
492
                                            "plain", [], []),
493
             self.client.InstanceAllocation("create", "foobar2",
494
                                            "drbd8", [{"size": 100}], [])]
495
    resp = self.client.InstancesMultiAlloc(insts)
496
    self.assertEqual(resp, response)
497
    self.assertHandler(rlib2.R_2_instances_multi_alloc)
498

  
484 499
  def testCreateInstanceOldVersion(self):
485 500
    # The old request format, version 0, is no longer supported
486 501
    self.rapi.AddResponse(None, code=404)

Also available in: Unified diff