Revision 9a8ae794

b/lib/rapi/client.py
675 675
      body.update((key, value) for key, value in kwargs.iteritems()
676 676
                  if key != "dry_run")
677 677
    else:
678
      # Old request format (version 0)
679

  
680
      # The following code must make sure that an exception is raised when an
681
      # unsupported setting is requested by the caller. Otherwise this can lead
682
      # to bugs difficult to find. The interface of this function must stay
683
      # exactly the same for version 0 and 1 (e.g. they aren't allowed to
684
      # require different data types).
685

  
686
      # Validate disks
687
      for idx, disk in enumerate(disks):
688
        unsupported = set(disk.keys()) - _INST_CREATE_V0_DISK_PARAMS
689
        if unsupported:
690
          raise GanetiApiError("Server supports request version 0 only, but"
691
                               " disk %s specifies the unsupported parameters"
692
                               " %s, allowed are %s" %
693
                               (idx, unsupported,
694
                                list(_INST_CREATE_V0_DISK_PARAMS)))
695

  
696
      assert (len(_INST_CREATE_V0_DISK_PARAMS) == 1 and
697
              "size" in _INST_CREATE_V0_DISK_PARAMS)
698
      disk_sizes = [disk["size"] for disk in disks]
699

  
700
      # Validate NICs
701
      if not nics:
702
        raise GanetiApiError("Server supports request version 0 only, but"
703
                             " no NIC specified")
704
      elif len(nics) > 1:
705
        raise GanetiApiError("Server supports request version 0 only, but"
706
                             " more than one NIC specified")
707

  
708
      assert len(nics) == 1
709

  
710
      unsupported = set(nics[0].keys()) - _INST_NIC_PARAMS
711
      if unsupported:
712
        raise GanetiApiError("Server supports request version 0 only, but"
713
                             " NIC 0 specifies the unsupported parameters %s,"
714
                             " allowed are %s" %
715
                             (unsupported, list(_INST_NIC_PARAMS)))
716

  
717
      # Validate other parameters
718
      unsupported = (set(kwargs.keys()) - _INST_CREATE_V0_PARAMS -
719
                     _INST_CREATE_V0_DPARAMS)
720
      if unsupported:
721
        allowed = _INST_CREATE_V0_PARAMS.union(_INST_CREATE_V0_DPARAMS)
722
        raise GanetiApiError("Server supports request version 0 only, but"
723
                             " the following unsupported parameters are"
724
                             " specified: %s, allowed are %s" %
725
                             (unsupported, list(allowed)))
726

  
727
      # All required fields for request data version 0
728
      body = {
729
        _REQ_DATA_VERSION_FIELD: 0,
730
        "name": name,
731
        "disk_template": disk_template,
732
        "disks": disk_sizes,
733
        }
734

  
735
      # NIC fields
736
      assert len(nics) == 1
737
      assert not (set(body.keys()) & set(nics[0].keys()))
738
      body.update(nics[0])
739

  
740
      # Copy supported fields
741
      assert not (set(body.keys()) & set(kwargs.keys()))
742
      body.update(dict((key, value) for key, value in kwargs.items()
743
                       if key in _INST_CREATE_V0_PARAMS))
744

  
745
      # Merge dictionaries
746
      for i in (value for key, value in kwargs.items()
747
                if key in _INST_CREATE_V0_DPARAMS):
748
        assert not (set(body.keys()) & set(i.keys()))
749
        body.update(i)
750

  
751
      assert not (set(kwargs.keys()) -
752
                  (_INST_CREATE_V0_PARAMS | _INST_CREATE_V0_DPARAMS))
753
      assert not (set(body.keys()) & _INST_CREATE_V0_DPARAMS)
678
      raise GanetiApiError("Server does not support new-style (version 1)"
679
                           " instance creation requests")
754 680

  
755 681
    return self._SendRequest(HTTP_POST, "/%s/instances" % GANETI_RAPI_VERSION,
756 682
                             query, body)
b/test/ganeti.rapi.client_unittest.py
510 510
    self.assertQuery("static", ["1"])
511 511

  
512 512
  def testCreateInstanceOldVersion(self):
513
    # No NICs
513
    # The old request format, version 0, is no longer supported
514 514
    self.rapi.AddResponse(None, code=404)
515 515
    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
516 516
                      "create", "inst1.example.com", "plain", [], [])
517 517
    self.assertEqual(self.rapi.CountPending(), 0)
518 518

  
519
    # More than one NIC
520
    self.rapi.AddResponse(None, code=404)
521
    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
522
                      "create", "inst1.example.com", "plain", [],
523
                      [{}, {}, {}])
524
    self.assertEqual(self.rapi.CountPending(), 0)
525

  
526
    # Unsupported NIC fields
527
    self.rapi.AddResponse(None, code=404)
528
    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
529
                      "create", "inst1.example.com", "plain", [],
530
                      [{"x": True, "y": False}])
531
    self.assertEqual(self.rapi.CountPending(), 0)
532

  
533
    # Unsupported disk fields
534
    self.rapi.AddResponse(None, code=404)
535
    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
536
                      "create", "inst1.example.com", "plain",
537
                      [{}, {"moo": "foo",}], [{}])
538
    self.assertEqual(self.rapi.CountPending(), 0)
539

  
540
    # Unsupported fields
541
    self.rapi.AddResponse(None, code=404)
542
    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
543
                      "create", "inst1.example.com", "plain", [], [{}],
544
                      hello_world=123)
545
    self.assertEqual(self.rapi.CountPending(), 0)
546

  
547
    self.rapi.AddResponse(None, code=404)
548
    self.assertRaises(client.GanetiApiError, self.client.CreateInstance,
549
                      "create", "inst1.example.com", "plain", [], [{}],
550
                      memory=128)
551
    self.assertEqual(self.rapi.CountPending(), 0)
552

  
553
    # Normal creation
554
    testnics = [
555
      [{}],
556
      [{ "mac": constants.VALUE_AUTO, }],
557
      [{ "ip": "192.0.2.99", "mode": constants.NIC_MODE_ROUTED, }],
558
      ]
559

  
560
    testdisks = [
561
      [],
562
      [{ "size": 128, }],
563
      [{ "size": 321, }, { "size": 4096, }],
564
      ]
565

  
566
    for idx, nics in enumerate(testnics):
567
      for disks in testdisks:
568
        beparams = {
569
          constants.BE_MEMORY: 512,
570
          constants.BE_AUTO_BALANCE: False,
571
          }
572
        hvparams = {
573
          constants.HV_MIGRATION_PORT: 9876,
574
          constants.HV_VNC_TLS: True,
575
          }
576

  
577
        self.rapi.AddResponse(None, code=404)
578
        self.rapi.AddResponse(serializer.DumpJson(3122617 + idx))
579
        job_id = self.client.CreateInstance("create", "inst1.example.com",
580
                                            "plain", disks, nics,
581
                                            pnode="node99", dry_run=True,
582
                                            hvparams=hvparams,
583
                                            beparams=beparams)
584
        self.assertEqual(job_id, 3122617 + idx)
585
        self.assertHandler(rlib2.R_2_instances)
586
        self.assertDryRun()
587
        self.assertEqual(self.rapi.CountPending(), 0)
588

  
589
        data = serializer.LoadJson(self.rapi.GetLastRequestData())
590
        self.assertEqual(data["name"], "inst1.example.com")
591
        self.assertEqual(data["disk_template"], "plain")
592
        self.assertEqual(data["pnode"], "node99")
593
        self.assertEqual(data[constants.BE_MEMORY], 512)
594
        self.assertEqual(data[constants.BE_AUTO_BALANCE], False)
595
        self.assertEqual(data[constants.HV_MIGRATION_PORT], 9876)
596
        self.assertEqual(data[constants.HV_VNC_TLS], True)
597
        self.assertEqual(data["disks"], [disk["size"] for disk in disks])
598

  
599 519
  def testCreateInstance(self):
600 520
    self.rapi.AddResponse(serializer.DumpJson([rlib2._INST_CREATE_REQV1]))
601 521
    self.rapi.AddResponse("23030")

Also available in: Unified diff