X-Git-Url: https://code.grnet.gr/git/ganeti-local/blobdiff_plain/02691904fad3df9d657d65b980dfca6893b6e3f4..55224070299fd267979208a247c2f4288bbd3dbb:/lib/objects.py diff --git a/lib/objects.py b/lib/objects.py index 6c74876..1fc2db3 100644 --- a/lib/objects.py +++ b/lib/objects.py @@ -50,7 +50,7 @@ class ConfigObject(object): as None instead of raising an error Classes derived from this must always declare __slots__ (we use many - config objects and the memory reduction is useful. + config objects and the memory reduction is useful) """ __slots__ = [] @@ -274,7 +274,7 @@ class NIC(ConfigObject): class Disk(ConfigObject): """Config object representing a block device.""" __slots__ = ["dev_type", "logical_id", "physical_id", - "children", "iv_name", "size"] + "children", "iv_name", "size", "mode"] def CreateOnSecondary(self): """Test if this device needs to be created on a secondary node.""" @@ -518,46 +518,55 @@ class Instance(TaggableObject): def _ComputeSecondaryNodes(self): """Compute the list of secondary nodes. + This is a simple wrapper over _ComputeAllNodes. + + """ + all_nodes = set(self._ComputeAllNodes()) + all_nodes.discard(self.primary_node) + return tuple(all_nodes) + + secondary_nodes = property(_ComputeSecondaryNodes, None, None, + "List of secondary nodes") + + def _ComputeAllNodes(self): + """Compute the list of all nodes. + Since the data is already there (in the drbd disks), keeping it as a separate normal attribute is redundant and if not properly synchronised can cause problems. Thus it's better to compute it dynamically. """ - def _Helper(primary, sec_nodes, device): - """Recursively computes secondary nodes given a top device.""" + def _Helper(nodes, device): + """Recursively computes nodes given a top device.""" if device.dev_type in constants.LDS_DRBD: - nodea, nodeb, dummy = device.logical_id[:3] - if nodea == primary: - candidate = nodeb - else: - candidate = nodea - if candidate not in sec_nodes: - sec_nodes.append(candidate) + nodea, nodeb = device.logical_id[:2] + nodes.add(nodea) + nodes.add(nodeb) if device.children: for child in device.children: - _Helper(primary, sec_nodes, child) + _Helper(nodes, child) - secondary_nodes = [] + all_nodes = set() + all_nodes.add(self.primary_node) for device in self.disks: - _Helper(self.primary_node, secondary_nodes, device) - return tuple(secondary_nodes) + _Helper(all_nodes, device) + return tuple(all_nodes) - secondary_nodes = property(_ComputeSecondaryNodes, None, None, - "List of secondary nodes") + all_nodes = property(_ComputeAllNodes, None, None, + "List of all nodes of the instance") def MapLVsByNode(self, lvmap=None, devs=None, node=None): """Provide a mapping of nodes to LVs this instance owns. - This function figures out what logical volumes should belong on which - nodes, recursing through a device tree. + This function figures out what logical volumes should belong on + which nodes, recursing through a device tree. - Args: - lvmap: (optional) a dictionary to receive the 'node' : ['lv', ...] data. + @param lvmap: optional dictionary to receive the + 'node' : ['lv', ...] data. - Returns: - None if lvmap arg is given. - Otherwise, { 'nodename' : ['volume1', 'volume2', ...], ... } + @return: None if lvmap arg is given, otherwise, a dictionary + of the form { 'nodename' : ['volume1', 'volume2', ...], ... } """ if node == None: @@ -579,12 +588,6 @@ class Instance(TaggableObject): lvmap[node].append(dev.logical_id[1]) elif dev.dev_type in constants.LDS_DRBD: - if dev.logical_id[0] not in lvmap: - lvmap[dev.logical_id[0]] = [] - - if dev.logical_id[1] not in lvmap: - lvmap[dev.logical_id[1]] = [] - if dev.children: self.MapLVsByNode(lvmap, dev.children, dev.logical_id[0]) self.MapLVsByNode(lvmap, dev.children, dev.logical_id[1]) @@ -594,17 +597,26 @@ class Instance(TaggableObject): return ret - def FindDisk(self, name): - """Find a disk given having a specified name. + def FindDisk(self, idx): + """Find a disk given having a specified index. - This will return the disk which has the given iv_name. + This is just a wrapper that does validation of the index. - """ - for disk in self.disks: - if disk.iv_name == name: - return disk + @type idx: int + @param idx: the disk index + @rtype: L{Disk} + @return: the corresponding disk + @raise errors.OpPrereqError: when the given index is not valid - return None + """ + try: + idx = int(idx) + return self.disks[idx] + except ValueError, err: + raise errors.OpPrereqError("Invalid disk index: '%s'" % str(err)) + except IndexError: + raise errors.OpPrereqError("Invalid disk index: %d (instace has disks" + " 0 to %d" % (idx, len(self.disks))) def ToDict(self): """Instance-specific conversion to standard python types. @@ -675,6 +687,8 @@ class Node(TaggableObject): "primary_ip", "secondary_ip", "serial_no", + "master_candidate", + "offline", ] @@ -697,6 +711,7 @@ class Cluster(TaggableObject): "enabled_hypervisors", "hvparams", "beparams", + "candidate_pool_size", ] def ToDict(self):