Revision 5b3aa9a1

b/lib/errors.py
102 102
  """
103 103

  
104 104

  
105
class HotplugError(HypervisorError):
106
  """Hotplug-related exception.
107

  
108
  This is raised in case a hotplug action fails or is not supported.
109
  It is currently used only by KVM hypervisor.
110

  
111
  """
112

  
113

  
105 114
class ProgrammerError(GenericError):
106 115
  """Programming-related error.
107 116

  
b/lib/hypervisor/hv_kvm.py
79 79
  constants.HV_KVM_SPICE_USE_TLS,
80 80
  ])
81 81

  
82
# below constants show the format of runtime file
83
# the nics are in second possition, while the disks in 4th (last)
84
# moreover disk entries are stored in tupples of L{objects.Disk}, dev_path
85
_KVM_NICS_RUNTIME_INDEX = 1
86
_KVM_DISKS_RUNTIME_INDEX = 3
87
_DEVICE_RUNTIME_INDEX = {
88
  constants.HOTPLUG_TARGET_DISK: _KVM_DISKS_RUNTIME_INDEX,
89
  constants.HOTPLUG_TARGET_NIC: _KVM_NICS_RUNTIME_INDEX
90
  }
91
_FIND_RUNTIME_ENTRY = {
92
  constants.HOTPLUG_TARGET_NIC:
93
    lambda nic, kvm_nics: [n for n in kvm_nics if n.uuid == nic.uuid],
94
  constants.HOTPLUG_TARGET_DISK:
95
    lambda disk, kvm_disks: [(d, l) for (d, l) in kvm_disks
96
                             if d.uuid == disk.uuid]
97
  }
98
_RUNTIME_DEVICE = {
99
  constants.HOTPLUG_TARGET_NIC: lambda d: d,
100
  constants.HOTPLUG_TARGET_DISK: lambda (d, e): d
101
  }
102
_RUNTIME_ENTRY = {
103
  constants.HOTPLUG_TARGET_NIC: lambda d, e: d,
104
  constants.HOTPLUG_TARGET_DISK: lambda d, e: (d, e)
105
  }
106

  
107

  
108
def _GetExistingDeviceInfo(dev_type, device, runtime):
109
  """Helper function to get an existing device inside the runtime file
110

  
111
  Used when an instance is running. Load kvm runtime file and search
112
  for a device based on its type and uuid.
113

  
114
  @type dev_type: sting
115
  @param dev_type: device type of param dev
116
  @type device: L{objects.Disk} or L{objects.NIC}
117
  @param device: the device object for which we generate a kvm name
118
  @type runtime: tuple (cmd, nics, hvparams, disks)
119
  @param runtime: the runtime data to search for the device
120
  @raise errors.HotplugError: in case the requested device does not
121
    exist (e.g. device has been added without --hotplug option) or
122
    device info has not pci slot (e.g. old devices in the cluster)
123

  
124
  """
125
  index = _DEVICE_RUNTIME_INDEX[dev_type]
126
  found = _FIND_RUNTIME_ENTRY[dev_type](device, runtime[index])
127
  if not found:
128
    raise errors.HotplugError("Cannot find runtime info for %s with UUID %s" %
129
                              (dev_type, device.uuid))
130

  
131
  return found[0]
132

  
82 133

  
83 134
def _GetTunFeatures(fd, _ioctl=fcntl.ioctl):
84 135
  """Retrieves supported TUN features from file descriptor.
......
1418 1469
    if hvp[constants.HV_KVM_EXTRA]:
1419 1470
      kvm_cmd.extend(hvp[constants.HV_KVM_EXTRA].split(" "))
1420 1471

  
1421
    bdev_opts = self._GenerateKVMBlockDevicesOptions(instance,
1422
                                                     block_devices,
1423
                                                     kvmhelp)
1424
    kvm_cmd.extend(bdev_opts)
1425
    # Save the current instance nics, but defer their expansion as parameters,
1426
    # as we'll need to generate executable temp files for them.
1427
    kvm_nics = instance.nics
1472
    kvm_disks = []
1473
    for disk, dev_path in block_devices:
1474
      kvm_disks.append((disk, dev_path))
1475

  
1476
    kvm_nics = []
1477
    for nic in instance.nics:
1478
      kvm_nics.append(nic)
1479

  
1428 1480
    hvparams = hvp
1429 1481

  
1430
    return (kvm_cmd, kvm_nics, hvparams)
1482
    return (kvm_cmd, kvm_nics, hvparams, kvm_disks)
1431 1483

  
1432 1484
  def _WriteKVMRuntime(self, instance_name, data):
1433 1485
    """Write an instance's KVM runtime
......
1453 1505
    """Save an instance's KVM runtime
1454 1506

  
1455 1507
    """
1456
    kvm_cmd, kvm_nics, hvparams = kvm_runtime
1508
    kvm_cmd, kvm_nics, hvparams, block_devices = kvm_runtime
1509

  
1457 1510
    serialized_nics = [nic.ToDict() for nic in kvm_nics]
1458
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams))
1511
    serialized_blockdevs = [(blk.ToDict(), link) for blk, link in block_devices]
1512
    serialized_form = serializer.Dump((kvm_cmd, serialized_nics, hvparams,
1513
                                      serialized_blockdevs))
1514

  
1459 1515
    self._WriteKVMRuntime(instance.name, serialized_form)
1460 1516

  
1461 1517
  def _LoadKVMRuntime(self, instance, serialized_runtime=None):
......
1464 1520
    """
1465 1521
    if not serialized_runtime:
1466 1522
      serialized_runtime = self._ReadKVMRuntime(instance.name)
1523

  
1467 1524
    loaded_runtime = serializer.Load(serialized_runtime)
1468
    kvm_cmd, serialized_nics, hvparams = loaded_runtime
1525
    if len(loaded_runtime) == 3:
1526
      serialized_blockdevs = []
1527
      kvm_cmd, serialized_nics, hvparams = loaded_runtime
1528
    else:
1529
      kvm_cmd, serialized_nics, hvparams, serialized_blockdevs = loaded_runtime
1530

  
1469 1531
    kvm_nics = [objects.NIC.FromDict(snic) for snic in serialized_nics]
1470
    return (kvm_cmd, kvm_nics, hvparams)
1532
    block_devices = [(objects.Disk.FromDict(sdisk), link)
1533
                     for sdisk, link in serialized_blockdevs]
1534

  
1535
    return (kvm_cmd, kvm_nics, hvparams, block_devices)
1471 1536

  
1472 1537
  def _RunKVMCmd(self, name, kvm_cmd, tap_fds=None):
1473 1538
    """Run the KVM cmd and check for errors
......
1492 1557
    if not self._InstancePidAlive(name)[2]:
1493 1558
      raise errors.HypervisorError("Failed to start instance %s" % name)
1494 1559

  
1560
  # 52/50 local variables
1561
  # pylint: disable=R0914
1495 1562
  def _ExecuteKVMRuntime(self, instance, kvm_runtime, kvmhelp, incoming=None):
1496 1563
    """Execute a KVM cmd, after completing it with some last minute data.
1497 1564

  
......
1515 1582

  
1516 1583
    temp_files = []
1517 1584

  
1518
    kvm_cmd, kvm_nics, up_hvp = kvm_runtime
1585
    kvm_cmd, kvm_nics, up_hvp, block_devices = kvm_runtime
1519 1586
    # the first element of kvm_cmd is always the path to the kvm binary
1520 1587
    kvm_path = kvm_cmd[0]
1521 1588
    up_hvp = objects.FillDict(conf_hvp, up_hvp)
......
1619 1686
        continue
1620 1687
      self._ConfigureNIC(instance, nic_seq, nic, taps[nic_seq])
1621 1688

  
1689
    bdev_opts = self._GenerateKVMBlockDevicesOptions(instance,
1690
                                                     block_devices,
1691
                                                     kvmhelp)
1692
    kvm_cmd.extend(bdev_opts)
1622 1693
    # CPU affinity requires kvm to start paused, so we set this flag if the
1623 1694
    # instance is not already paused and if we are not going to accept a
1624 1695
    # migrating instance. In the latter case, pausing is not needed.

Also available in: Unified diff