Revision ad00ee21

b/lib/backend.py
1646 1646

  
1647 1647
  """
1648 1648
  hyper = hypervisor.GetHypervisor(instance.hypervisor)
1649
  try:
1650
    hyper.VerifyHotplugSupport(instance, action, dev_type)
1651
  except errors.HotplugError, err:
1652
    _Fail("Hotplug is not supported: %s", err)
1653

  
1649 1654
  if action == constants.HOTPLUG_ACTION_ADD:
1650 1655
    fn = hyper.HotAddDevice
1651 1656
  elif action == constants.HOTPLUG_ACTION_REMOVE:
......
1655 1660
  else:
1656 1661
    assert action in constants.HOTPLUG_ALL_ACTIONS
1657 1662
  # This will raise an exception if hotplug is no supported for this case
1658
  hyper.HotplugSupported(instance, action, dev_type)
1659 1663
  return fn(instance, dev_type, device, extra, seq)
1660 1664

  
1661 1665

  
1666
def HotplugSupported(instance):
1667
  """Checks if hotplug is generally supported.
1668

  
1669
  """
1670
  hyper = hypervisor.GetHypervisor(instance.hypervisor)
1671
  try:
1672
    hyper.HotplugSupported(instance)
1673
  except errors.HotplugError, err:
1674
    _Fail("Hotplug is not supported: %s", err)
1675

  
1676

  
1662 1677
def BlockdevCreate(disk, size, owner, on_primary, info, excl_stor):
1663 1678
  """Creates a block device for an instance.
1664 1679

  
b/lib/cmdlib/instance.py
2663 2663
    # dictionary with instance information after the modification
2664 2664
    ispec = {}
2665 2665

  
2666
    if self.op.hotplug:
2667
      result = self.rpc.call_hotplug_supported(self.instance.primary_node,
2668
                                               self.instance)
2669
      result.Raise("Hotplug is not supported.")
2670

  
2666 2671
    # Check disk modifications. This is done here and not in CheckArguments
2667 2672
    # (as with NICs), because we need to know the instance's disk template
2668 2673
    if instance.disk_template == constants.DT_EXT:
b/lib/hypervisor/hv_base.py
557 557
    """
558 558
    pass
559 559

  
560
  def HotplugSupported(self, instance, action, dev_type):
560
  # pylint: disable=R0201,W0613
561
  def VerifyHotplugSupport(self, instance, action, dev_type):
561 562
    """Whether hotplug is supported.
562 563

  
564
    Given the target device and hotplug action checks if hotplug is
565
    actually supported.
566

  
567
    @type instance: L{objects.Instance}
568
    @param instance: the instance object
569
    @type action: string
570
    @param action: one of the supported hotplug commands
571
    @type dev_type: string
572
    @param dev_type: one of the supported device types to hotplug
573
    @raise errors.HotplugError: if hotplugging is not supported
574

  
563 575
    Depends on instance's hvparam, the action. and the dev_type
564 576
    """
565
    pass
577
    raise errors.HotplugError("Hotplug is not supported.")
578

  
579
  # pylint: disable=R0201,W0613
580
  def HotplugSupported(self, instance):
581
    """Checks if hotplug is supported.
582

  
583
    By default is not. Currently only KVM hypervisor supports it.
584

  
585
    """
586
    raise errors.HotplugError("Hotplug is not supported by this hypervisor")
b/lib/hypervisor/hv_kvm.py
1952 1952

  
1953 1953
    dev.pci = int(free)
1954 1954

  
1955
  def HotplugSupported(self, instance, action, dev_type):
1955
  def VerifyHotplugSupport(self, instance, action, dev_type):
1956 1956
    """Check if hotplug is supported.
1957 1957

  
1958 1958
    Hotplug is *not* supported in case of:
1959
     - qemu versions < 1.0
1960 1959
     - security models and chroot (disk hotplug)
1961 1960
     - fdsend module is missing (nic hot-add)
1962 1961

  
1963 1962
    @raise errors.HypervisorError: in previous cases
1964 1963

  
1965 1964
    """
1966
    output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
1967
    # TODO: search for netdev_add, drive_add, device_add.....
1968
    match = self._INFO_VERSION_RE.search(output.stdout)
1969
    if not match:
1970
      raise errors.HotplugError("Try hotplug only in running instances.")
1971
    v_major, v_min, _, _ = match.groups()
1972
    if (v_major, v_min) <= (1, 0):
1973
      raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
1974

  
1975 1965
    if dev_type == constants.HOTPLUG_TARGET_DISK:
1976 1966
      hvp = instance.hvparams
1977 1967
      security_model = hvp[constants.HV_SECURITY_MODEL]
......
1989 1979
                                " fdsend python module is missing.")
1990 1980
    return True
1991 1981

  
1982
  def HotplugSupported(self, instance):
1983
    """Checks if hotplug is generally supported.
1984

  
1985
    Hotplug is *not* supported in case of:
1986
     - qemu versions < 1.0
1987
     - for stopped instances
1988

  
1989
    @raise errors.HypervisorError: in one of the previous cases
1990

  
1991
    """
1992
    output = self._CallMonitorCommand(instance.name, self._INFO_VERSION_CMD)
1993
    # TODO: search for netdev_add, drive_add, device_add.....
1994
    match = self._INFO_VERSION_RE.search(output.stdout)
1995
    if not match:
1996
      raise errors.HotplugError("Try hotplug only in running instances.")
1997
    v_major, v_min, _, _ = match.groups()
1998
    if (int(v_major), int(v_min)) < (1, 0):
1999
      raise errors.HotplugError("Hotplug not supported for qemu versions < 1.0")
2000

  
1992 2001
  def _CallHotplugCommand(self, name, cmd):
1993 2002
    output = self._CallMonitorCommand(name, cmd)
1994 2003
    # TODO: parse output and check if succeeded
b/lib/rpc_defs.py
295 295
    ("extra", None, "Extra info for device (dev_path for disk)"),
296 296
    ("seq", None, "Device seq"),
297 297
    ], None, None, "Hoplug a device to a running instance"),
298
  ("hotplug_supported", SINGLE, None, constants.RPC_TMO_NORMAL, [
299
    ("instance", ED_INST_DICT, "Instance object"),
300
    ], None, None, "Check if hotplug is supported"),
298 301
  ]
299 302

  
300 303
_IMPEXP_CALLS = [
b/lib/server/noded.py
619 619
    return backend.HotplugDevice(instance, action, dev_type, device, extra, seq)
620 620

  
621 621
  @staticmethod
622
  def perspective_hotplug_supported(params):
623
    """Checks if hotplug is supported.
624

  
625
    """
626
    instance = objects.Instance.FromDict(params[0])
627
    return backend.HotplugSupported(instance)
628

  
629
  @staticmethod
622 630
  def perspective_migration_info(params):
623 631
    """Gather information about an instance to be migrated.
624 632

  

Also available in: Unified diff