Implement functions 'AddDisk' and 'AttachInstDisk'. The first one adds a new disk to the config file and the second one attaches a disk to an instance. A wrapper 'AddInstDisk' is provided in order to add a disk and attach it to an instance at once (because ganeti doesn't support dangling disks right now).
Signed-off-by: Ilias Tsitsimpis <[email protected]> --- lib/config.py | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/lib/config.py b/lib/config.py index febc4ee..4df28c5 100644 --- a/lib/config.py +++ b/lib/config.py @@ -255,6 +255,16 @@ class ConfigManager(object): return False +def _UpdateIvNames(base_index, disks): + """Update the C{iv_name} attribute of disks. + + @type disks: list of L{objects.Disk} + + """ + for (idx, disk) in enumerate(disks): + disk.iv_name = "disk/%s" % (base_index + idx) + + class ConfigWriter(object): """The interface to the cluster configuration. @@ -371,6 +381,89 @@ class ConfigWriter(object): """ return self._UnlockedGetInstanceDisks(instance) + def _UnlockedAddDisk(self, disk): + """Add a disk to the config. + + This function is for internal use, when the config lock is already held. + + @type disk: L{objects.Disk} + @param disk: the disk object + + """ + if not isinstance(disk, objects.Disk): + raise errors.ProgrammerError("Invalid type passed to _UnlockedAddDisk") + + logging.info("Adding disk %s to configuration", disk.uuid) + + self._CheckUniqueUUID(disk, include_temporary=False) + disk.serial_no = 1 + disk.ctime = disk.mtime = time.time() + disk.UpgradeConfig() + self._ConfigData().disks[disk.uuid] = disk + self._ConfigData().cluster.serial_no += 1 + + def _UnlockedAttachInstDisk(self, instance, disk, idx=None): + """Attach a disk to an instance. + + This function is for internal use, when the config lock is already held. + + @type instance: L{objects.Instance} + @param instance: the instance object + @type disk: L{objects.Disk} + @param disk: the disk object + @type idx: int + @param idx: the index of the newly attached disk + + """ + if not isinstance(instance, objects.Instance) or \ + not isinstance(disk, objects.Disk): + raise errors.ProgrammerError( + "Invalid type passed to _UnlockedAttachInstDisk") + if instance.uuid not in self._ConfigData().instances: + raise errors.ConfigurationError("Instance %s doesn't exist" + % instance.uuid) + if disk.uuid not in self._ConfigData().disks: + raise errors.ConfigurationError("Disk %s doesn't exist" % disk.uuid) + + if idx is None: + idx = len(instance.disks) + else: + if idx < 0: + raise IndexError("Not accepting negative indices other than -1") + elif idx > len(instance.disks): + raise IndexError("Got disk index %s, but there are only %s" % + (idx, len(instance.disks))) + + # Disk must not be attached anywhere else + for inst in self._ConfigData().instances.values(): + if disk.uuid in inst.disks: + raise errors.ReservationError("Disk %s already attached to instance %s" + % (disk.uuid, inst.name)) + + instance.disks.insert(idx, disk.uuid) + inst_disks = self._UnlockedGetInstanceDisks(instance) + _UpdateIvNames(idx, inst_disks[idx:]) + instance.serial_no += 1 + instance.mtime = time.time() + + # Update instance object + self._ConfigData().instances[instance.uuid] = instance + + @_ConfigSync() + def AddInstDisk(self, instance, disk, idx=None): + """Add a disk to the config and attach it to instance. + + @type instance: L{objects.Instance} + @param instance: the instance object + @type disk: L{objects.Disk} + @param disk: the disk object + @type idx: int + @param idx: the index of the newly attached disk + + """ + self._UnlockedAddDisk(disk) + self._UnlockedAttachInstDisk(instance, disk, idx) + def _UnlockedGetDiskInfo(self, disk_uuid): """Returns information about an instance. @@ -3084,6 +3177,8 @@ class ConfigWriter(object): replace_in(target, self._ConfigData().nodegroups) elif isinstance(target, objects.Network): replace_in(target, self._ConfigData().networks) + elif isinstance(target, objects.Disk): + replace_in(target, self._ConfigData().disks) else: raise errors.ProgrammerError("Invalid object type (%s) passed to" " ConfigWriter.Update" % type(target)) -- 1.9.1
