Revision 74409b12

b/lib/cmdlib.py
31 31
import re
32 32
import platform
33 33
import logging
34
import copy
34 35

  
35 36
from ganeti import ssh
36 37
from ganeti import logger
......
3139 3140
  return req_size_dict[disk_template]
3140 3141

  
3141 3142

  
3143
def _CheckHVParams(lu, nodenames, hvname, hvparams):
3144
  """Hypervisor parameter validation.
3145

  
3146
  This function abstract the hypervisor parameter validation to be
3147
  used in both instance create and instance modify.
3148

  
3149
  @type lu: L{LogicalUnit}
3150
  @param lu: the logical unit for which we check
3151
  @type nodenames: list
3152
  @param nodenames: the list of nodes on which we should check
3153
  @type hvname: string
3154
  @param hvname: the name of the hypervisor we should use
3155
  @type hvparams: dict
3156
  @param hvparams: the parameters which we need to check
3157
  @raise errors.OpPrereqError: if the parameters are not valid
3158

  
3159
  """
3160
  hvinfo = lu.rpc.call_hypervisor_validate_params(nodenames,
3161
                                                  hvname,
3162
                                                  hvparams)
3163
  for node in nodenames:
3164
    info = hvinfo.get(node, None)
3165
    if not info or not isinstance(info, (tuple, list)):
3166
      raise errors.OpPrereqError("Cannot get current information"
3167
                                 " from node '%s' (%s)" % (node, info))
3168
    if not info[0]:
3169
      raise errors.OpPrereqError("Hypervisor parameter validation failed:"
3170
                                 " %s" % info[1])
3171

  
3172

  
3142 3173
class LUCreateInstance(LogicalUnit):
3143 3174
  """Create an instance.
3144 3175

  
......
3449 3480
                                     " %d MB available, %d MB required" %
3450 3481
                                     (node, info['vg_free'], req_size))
3451 3482

  
3452
    # hypervisor parameter validation
3453
    hvinfo = self.rpc.call_hypervisor_validate_params(nodenames,
3454
                                                      self.op.hypervisor,
3455
                                                      self.op.hvparams)
3456
    for node in nodenames:
3457
      info = hvinfo.get(node, None)
3458
      if not info or not isinstance(info, (tuple, list)):
3459
        raise errors.OpPrereqError("Cannot get current information"
3460
                                   " from node '%s' (%s)" % (node, info))
3461
      if not info[0]:
3462
        raise errors.OpPrereqError("Hypervisor parameter validation failed:"
3463
                                   " %s" % info[1])
3483
    _CheckHVParams(self, nodenames, self.op.hypervisor, self.op.hvparams)
3464 3484

  
3465 3485
    # os verification
3466 3486
    os_obj = self.rpc.call_os_get(pnode.name, self.op.os_type)
......
4450 4470
  """
4451 4471
  HPATH = "instance-modify"
4452 4472
  HTYPE = constants.HTYPE_INSTANCE
4453
  _OP_REQP = ["instance_name"]
4473
  _OP_REQP = ["instance_name", "hvparams"]
4454 4474
  REQ_BGL = False
4455 4475

  
4456 4476
  def ExpandNames(self):
4457 4477
    self._ExpandAndLockInstance()
4478
    self.needed_locks[locking.LEVEL_NODE] = []
4479
    self.recalculate_locks[locking.LEVEL_NODE] = constants.LOCKS_REPLACE
4480

  
4481

  
4482
  def DeclareLocks(self, level):
4483
    if level == locking.LEVEL_NODE:
4484
      self._LockInstancesNodes()
4458 4485

  
4459 4486
  def BuildHooksEnv(self):
4460 4487
    """Build hooks env.
......
4502 4529
    self.bridge = getattr(self.op, "bridge", None)
4503 4530
    self.kernel_path = getattr(self.op, "kernel_path", None)
4504 4531
    self.initrd_path = getattr(self.op, "initrd_path", None)
4505
    self.hvm_boot_order = getattr(self.op, "hvm_boot_order", None)
4506
    self.hvm_acpi = getattr(self.op, "hvm_acpi", None)
4507
    self.hvm_pae = getattr(self.op, "hvm_pae", None)
4508
    self.hvm_nic_type = getattr(self.op, "hvm_nic_type", None)
4509
    self.hvm_disk_type = getattr(self.op, "hvm_disk_type", None)
4510
    self.hvm_cdrom_image_path = getattr(self.op, "hvm_cdrom_image_path", None)
4511
    self.vnc_bind_address = getattr(self.op, "vnc_bind_address", None)
4512 4532
    self.force = getattr(self.op, "force", None)
4513
    all_parms = [self.mem, self.vcpus, self.ip, self.bridge, self.mac,
4514
                 self.kernel_path, self.initrd_path, self.hvm_boot_order,
4515
                 self.hvm_acpi, self.hvm_pae, self.hvm_cdrom_image_path,
4516
                 self.vnc_bind_address, self.hvm_nic_type, self.hvm_disk_type]
4517
    if all_parms.count(None) == len(all_parms):
4533
    all_parms = [self.mem, self.vcpus, self.ip, self.bridge, self.mac]
4534
    if all_parms.count(None) == len(all_parms) and not self.op.hvparams:
4518 4535
      raise errors.OpPrereqError("No changes submitted")
4519 4536
    if self.mem is not None:
4520 4537
      try:
......
4543 4560
      if not utils.IsValidMac(self.mac):
4544 4561
        raise errors.OpPrereqError('Invalid MAC address %s' % self.mac)
4545 4562

  
4546
    if self.kernel_path is not None:
4547
      self.do_kernel_path = True
4548
      if self.kernel_path == constants.VALUE_NONE:
4549
        raise errors.OpPrereqError("Can't set instance to no kernel")
4550

  
4551
      if self.kernel_path != constants.VALUE_DEFAULT:
4552
        if not os.path.isabs(self.kernel_path):
4553
          raise errors.OpPrereqError("The kernel path must be an absolute"
4554
                                    " filename")
4555
    else:
4556
      self.do_kernel_path = False
4557

  
4558
    if self.initrd_path is not None:
4559
      self.do_initrd_path = True
4560
      if self.initrd_path not in (constants.VALUE_NONE,
4561
                                  constants.VALUE_DEFAULT):
4562
        if not os.path.isabs(self.initrd_path):
4563
          raise errors.OpPrereqError("The initrd path must be an absolute"
4564
                                    " filename")
4565
    else:
4566
      self.do_initrd_path = False
4567

  
4568
    # boot order verification
4569
    if self.hvm_boot_order is not None:
4570
      if self.hvm_boot_order != constants.VALUE_DEFAULT:
4571
        if len(self.hvm_boot_order.strip("acdn")) != 0:
4572
          raise errors.OpPrereqError("invalid boot order specified,"
4573
                                     " must be one or more of [acdn]"
4574
                                     " or 'default'")
4575

  
4576
    # hvm_cdrom_image_path verification
4577
    if self.op.hvm_cdrom_image_path is not None:
4578
      if not (os.path.isabs(self.op.hvm_cdrom_image_path) or
4579
              self.op.hvm_cdrom_image_path.lower() == "none"):
4580
        raise errors.OpPrereqError("The path to the HVM CDROM image must"
4581
                                   " be an absolute path or None, not %s" %
4582
                                   self.op.hvm_cdrom_image_path)
4583
      if not (os.path.isfile(self.op.hvm_cdrom_image_path) or
4584
              self.op.hvm_cdrom_image_path.lower() == "none"):
4585
        raise errors.OpPrereqError("The HVM CDROM image must either be a"
4586
                                   " regular file or a symlink pointing to"
4587
                                   " an existing regular file, not %s" %
4588
                                   self.op.hvm_cdrom_image_path)
4589

  
4590
    # vnc_bind_address verification
4591
    if self.op.vnc_bind_address is not None:
4592
      if not utils.IsValidIP(self.op.vnc_bind_address):
4593
        raise errors.OpPrereqError("given VNC bind address '%s' doesn't look"
4594
                                   " like a valid IP address" %
4595
                                   self.op.vnc_bind_address)
4563
    # checking the new params on the primary/secondary nodes
4596 4564

  
4597 4565
    instance = self.instance = self.cfg.GetInstanceInfo(self.op.instance_name)
4598 4566
    assert self.instance is not None, \
4599 4567
      "Cannot retrieve locked instance %s" % self.op.instance_name
4568
    pnode = self.instance.primary_node
4569
    nodelist = [pnode]
4570
    nodelist.extend(instance.secondary_nodes)
4571

  
4572
    if self.op.hvparams:
4573
      i_hvdict = copy.deepcopy(instance.hvparams)
4574
      for key, val in self.op.hvparams.iteritems():
4575
        if val is None:
4576
          try:
4577
            del i_hvdict[key]
4578
          except KeyError:
4579
            pass
4580
        else:
4581
          i_hvdict[key] = val
4582
      cluster = self.cfg.GetClusterInfo()
4583
      hv_new = cluster.FillDict(cluster.hvparams[instance.hypervisor],
4584
                                i_hvdict)
4585
      # local check
4586
      hypervisor.GetHypervisor(
4587
        instance.hypervisor).CheckParameterSyntax(hv_new)
4588
      _CheckHVParams(self, nodelist, instance.hypervisor, hv_new)
4589
      self.hv_new = hv_new
4590

  
4600 4591
    self.warn = []
4601 4592
    if self.mem is not None and not self.force:
4602
      pnode = self.instance.primary_node
4603
      nodelist = [pnode]
4604
      nodelist.extend(instance.secondary_nodes)
4605 4593
      instance_info = self.rpc.call_instance_info(pnode, instance.name,
4606 4594
                                                  instance.hypervisor)
4607 4595
      nodeinfo = self.rpc.call_node_info(nodelist, self.cfg.GetVGName(),
......
4628 4616
        if node not in nodeinfo or not isinstance(nodeinfo[node], dict):
4629 4617
          self.warn.append("Can't get info from secondary node %s" % node)
4630 4618
        elif self.mem > nodeinfo[node]['memory_free']:
4631
          self.warn.append("Not enough memory to failover instance to secondary"
4632
                           " node %s" % node)
4633

  
4634
    # Xen HVM device type checks
4635
    if instance.hypervisor == constants.HT_XEN_HVM:
4636
      if self.op.hvm_nic_type is not None:
4637
        if self.op.hvm_nic_type not in constants.HT_HVM_VALID_NIC_TYPES:
4638
          raise errors.OpPrereqError("Invalid NIC type %s specified for Xen"
4639
                                     " HVM  hypervisor" % self.op.hvm_nic_type)
4640
      if self.op.hvm_disk_type is not None:
4641
        if self.op.hvm_disk_type not in constants.HT_HVM_VALID_DISK_TYPES:
4642
          raise errors.OpPrereqError("Invalid disk type %s specified for Xen"
4643
                                     " HVM hypervisor" % self.op.hvm_disk_type)
4619
          self.warn.append("Not enough memory to failover instance to"
4620
                           " secondary node %s" % node)
4644 4621

  
4645 4622
    return
4646 4623

  
......
4671 4648
    if self.mac:
4672 4649
      instance.nics[0].mac = self.mac
4673 4650
      result.append(("mac", self.mac))
4674
    if self.do_kernel_path:
4675
      instance.kernel_path = self.kernel_path
4676
      result.append(("kernel_path", self.kernel_path))
4677
    if self.do_initrd_path:
4678
      instance.initrd_path = self.initrd_path
4679
      result.append(("initrd_path", self.initrd_path))
4680
    if self.hvm_boot_order:
4681
      if self.hvm_boot_order == constants.VALUE_DEFAULT:
4682
        instance.hvm_boot_order = None
4683
      else:
4684
        instance.hvm_boot_order = self.hvm_boot_order
4685
      result.append(("hvm_boot_order", self.hvm_boot_order))
4686
    if self.hvm_acpi is not None:
4687
      instance.hvm_acpi = self.hvm_acpi
4688
      result.append(("hvm_acpi", self.hvm_acpi))
4689
    if self.hvm_pae is not None:
4690
      instance.hvm_pae = self.hvm_pae
4691
      result.append(("hvm_pae", self.hvm_pae))
4692
    if self.hvm_nic_type is not None:
4693
      instance.hvm_nic_type = self.hvm_nic_type
4694
      result.append(("hvm_nic_type", self.hvm_nic_type))
4695
    if self.hvm_disk_type is not None:
4696
      instance.hvm_disk_type = self.hvm_disk_type
4697
      result.append(("hvm_disk_type", self.hvm_disk_type))
4698
    if self.hvm_cdrom_image_path:
4699
      if self.hvm_cdrom_image_path == constants.VALUE_NONE:
4700
        instance.hvm_cdrom_image_path = None
4701
      else:
4702
        instance.hvm_cdrom_image_path = self.hvm_cdrom_image_path
4703
      result.append(("hvm_cdrom_image_path", self.hvm_cdrom_image_path))
4704
    if self.vnc_bind_address:
4705
      instance.vnc_bind_address = self.vnc_bind_address
4706
      result.append(("vnc_bind_address", self.vnc_bind_address))
4651
    if self.op.hvparams:
4652
      instance.hvparams = self.hv_new
4653
      for key, val in self.op.hvparams.iteritems():
4654
        result.append(("hv/%s" % key, val))
4707 4655

  
4708 4656
    self.cfg.Update(instance)
4709 4657

  
b/lib/opcodes.py
424 424
  OP_DSC_FIELD = "instance_name"
425 425
  __slots__ = [
426 426
    "instance_name", "mem", "vcpus", "ip", "bridge", "mac",
427
    "kernel_path", "initrd_path", "hvm_boot_order", "hvm_acpi",
428
    "hvm_pae", "hvm_cdrom_image_path", "vnc_bind_address",
429
    "hvm_nic_type", "hvm_disk_type", "force"
427
    "hvparams", "force",
430 428
    ]
431 429

  
432 430

  
b/scripts/gnt-instance
771 771

  
772 772
  """
773 773
  if not (opts.mem or opts.vcpus or opts.ip or opts.bridge or opts.mac or
774
          opts.kernel_path or opts.initrd_path or opts.hvm_boot_order or
775
          opts.hvm_acpi or opts.hvm_pae or opts.hvm_cdrom_image_path or
776
          opts.vnc_bind_address or opts.hvm_nic_type or opts.hvm_disk_type):
774
          opts.hypervisor):
777 775
    logger.ToStdout("Please give at least one of the parameters.")
778 776
    return 1
779 777

  
780
  kernel_path = _TransformPath(opts.kernel_path)
781
  initrd_path = _TransformPath(opts.initrd_path)
782
  if opts.hvm_boot_order == 'default':
783
    hvm_boot_order = constants.VALUE_DEFAULT
784
  else:
785
    hvm_boot_order = opts.hvm_boot_order
786

  
787
  if opts.hvm_acpi is None:
788
    hvm_acpi = opts.hvm_acpi
789
  else:
790
    hvm_acpi = opts.hvm_acpi == _VALUE_TRUE
791

  
792
  if opts.hvm_pae is None:
793
    hvm_pae = opts.hvm_pae
794
  else:
795
    hvm_pae = opts.hvm_pae == _VALUE_TRUE
796

  
797
  if opts.hvm_nic_type == constants.VALUE_NONE:
798
    hvm_nic_type = None
799
  else:
800
    hvm_nic_type = opts.hvm_nic_type
801

  
802
  if opts.hvm_disk_type == constants.VALUE_NONE:
803
    hvm_disk_type = None
804
  else:
805
    hvm_disk_type = opts.hvm_disk_type
806

  
807 778
  op = opcodes.OpSetInstanceParams(instance_name=args[0], mem=opts.mem,
808 779
                                   vcpus=opts.vcpus, ip=opts.ip,
809 780
                                   bridge=opts.bridge, mac=opts.mac,
810
                                   kernel_path=opts.kernel_path,
811
                                   initrd_path=opts.initrd_path,
812
                                   hvm_boot_order=hvm_boot_order,
813
                                   hvm_acpi=hvm_acpi, hvm_pae=hvm_pae,
814
                                   hvm_cdrom_image_path=
815
                                   opts.hvm_cdrom_image_path,
816
                                   vnc_bind_address=opts.vnc_bind_address,
817
                                   hvm_nic_type=hvm_nic_type,
818
                                   hvm_disk_type=hvm_disk_type,
781
                                   hvparams=opts.hypervisor,
819 782
                                   force=opts.force)
820 783

  
821 784
  # even if here we process the result, we allow submit only
......
1037 1000
              make_option("--mac", dest="mac",
1038 1001
                          help="MAC address", default=None,
1039 1002
                          type="string", metavar="<MACADDRESS>"),
1040
              make_option("--kernel", dest="kernel_path",
1041
                          help="Path to the instances' kernel (or"
1042
                          " 'default')", default=None,
1043
                          type="string", metavar="<FILENAME>"),
1044
              make_option("--initrd", dest="initrd_path",
1045
                          help="Path to the instances' initrd (or 'none', or"
1046
                          " 'default')", default=None,
1047
                          type="string", metavar="<FILENAME>"),
1048
              make_option("--hvm-boot-order", dest="hvm_boot_order",
1049
                          help="boot device order for HVM"
1050
                          "(either one or more of [acdn] or 'default')",
1051
                          default=None, type="string", metavar="<BOOTORDER>"),
1052
              make_option("--hvm-acpi", dest="hvm_acpi",
1053
                          help="ACPI support for HVM (true|false)",
1054
                          metavar="<BOOL>", choices=["true", "false"]),
1055
              make_option("--hvm-pae", dest="hvm_pae",
1056
                          help="PAE support for HVM (true|false)",
1057
                          metavar="<BOOL>", choices=["true", "false"]),
1058
              make_option("--hvm-cdrom-image-path",
1059
                          dest="hvm_cdrom_image_path",
1060
                          help="CDROM image path for HVM"
1061
                          "(absolute path or None)",
1062
                          default=None, type="string", metavar="<CDROMIMAGE>"),
1063
              make_option("--hvm-nic-type", dest="hvm_nic_type",
1064
                          help="Type of virtual NIC for HVM "
1065
                          "(rtl8139,ne2k_pci,ne2k_isa,paravirtual)",
1066
                          metavar="NICTYPE",
1067
                          choices=[constants.HT_HVM_NIC_RTL8139,
1068
                                   constants.HT_HVM_NIC_NE2K_PCI,
1069
                                   constants.HT_HVM_NIC_NE2K_ISA,
1070
                                   constants.HT_HVM_DEV_PARAVIRTUAL],
1071
                          default=None),
1072
              make_option("--hvm-disk-type", dest="hvm_disk_type",
1073
                          help="Type of virtual disks for HVM "
1074
                          "(ioemu,paravirtual)",
1075
                          metavar="DISKTYPE",
1076
                          choices=[constants.HT_HVM_DEV_IOEMU,
1077
                                   constants.HT_HVM_DEV_PARAVIRTUAL],
1078
                          default=None),
1079
              make_option("--vnc-bind-address", dest="vnc_bind_address",
1080
                          help="bind address for VNC (IP address)",
1081
                          default=None, type="string", metavar="<VNCADDRESS>"),
1003
              keyval_option("-H", "--hypervisor", type="keyval",
1004
                            default={}, dest="hypervisor",
1005
                            help="Change hypervisor parameters"),
1082 1006
              SUBMIT_OPT,
1083 1007
              ],
1084 1008
             "<instance>", "Alters the parameters of an instance"),

Also available in: Unified diff