+ This method recurses over the disks's children and updates their
+ size correspondigly. The method needs to be kept in sync with the
+ actual algorithms from bdev.
+
+ """
+ if self.dev_type == constants.LD_LV:
+ self.size += amount
+ elif self.dev_type == constants.LD_DRBD8:
+ if self.children:
+ self.children[0].RecordGrow(amount)
+ self.size += amount
+ else:
+ raise errors.ProgrammerError("Disk.RecordGrow called for unsupported"
+ " disk type %s" % self.dev_type)
+
+ def SetPhysicalID(self, target_node, nodes_ip):
+ """Convert the logical ID to the physical ID.
+
+ This is used only for drbd, which needs ip/port configuration.
+
+ The routine descends down and updates its children also, because
+ this helps when the only the top device is passed to the remote
+ node.
+
+ Arguments:
+ - target_node: the node we wish to configure for
+ - nodes_ip: a mapping of node name to ip
+
+ The target_node must exist in in nodes_ip, and must be one of the
+ nodes in the logical ID for each of the DRBD devices encountered
+ in the disk tree.
+
+ """
+ if self.children:
+ for child in self.children:
+ child.SetPhysicalID(target_node, nodes_ip)
+
+ if self.logical_id is None and self.physical_id is not None:
+ return
+ if self.dev_type in constants.LDS_DRBD:
+ pnode, snode, port, pminor, sminor, secret = self.logical_id
+ if target_node not in (pnode, snode):
+ raise errors.ConfigurationError("DRBD device not knowing node %s" %
+ target_node)
+ pnode_ip = nodes_ip.get(pnode, None)
+ snode_ip = nodes_ip.get(snode, None)
+ if pnode_ip is None or snode_ip is None:
+ raise errors.ConfigurationError("Can't find primary or secondary node"
+ " for %s" % str(self))
+ p_data = (pnode_ip, port)
+ s_data = (snode_ip, port)
+ if pnode == target_node:
+ self.physical_id = p_data + s_data + (pminor, secret)
+ else: # it must be secondary, we tested above
+ self.physical_id = s_data + p_data + (sminor, secret)
+ else:
+ self.physical_id = self.logical_id
+ return
+
+ def ToDict(self):
+ """Disk-specific conversion to standard python types.
+
+ This replaces the children lists of objects with lists of
+ standard python types.
+
+ """
+ bo = super(Disk, self).ToDict()
+
+ for attr in ("children",):
+ alist = bo.get(attr, None)
+ if alist:
+ bo[attr] = self._ContainerToDicts(alist)
+ return bo
+
+ @classmethod
+ def FromDict(cls, val):
+ """Custom function for Disks
+
+ """
+ obj = super(Disk, cls).FromDict(val)
+ if obj.children:
+ obj.children = cls._ContainerFromDicts(obj.children, list, Disk)
+ if obj.logical_id and isinstance(obj.logical_id, list):
+ obj.logical_id = tuple(obj.logical_id)
+ if obj.physical_id and isinstance(obj.physical_id, list):
+ obj.physical_id = tuple(obj.physical_id)
+ if obj.dev_type in constants.LDS_DRBD:
+ # we need a tuple of length six here
+ if len(obj.logical_id) < 6:
+ obj.logical_id += (None,) * (6 - len(obj.logical_id))
+ return obj
+
+ def __str__(self):
+ """Custom str() formatter for disks.
+
+ """
+ if self.dev_type == constants.LD_LV:
+ val = "<LogicalVolume(/dev/%s/%s" % self.logical_id
+ elif self.dev_type in constants.LDS_DRBD:
+ node_a, node_b, port, minor_a, minor_b = self.logical_id[:5]
+ val = "<DRBD8("
+ if self.physical_id is None:
+ phy = "unconfigured"
+ else:
+ phy = ("configured as %s:%s %s:%s" %
+ (self.physical_id[0], self.physical_id[1],
+ self.physical_id[2], self.physical_id[3]))
+
+ val += ("hosts=%s/%d-%s/%d, port=%s, %s, " %
+ (node_a, minor_a, node_b, minor_b, port, phy))
+ if self.children and self.children.count(None) == 0:
+ val += "backend=%s, metadev=%s" % (self.children[0], self.children[1])
+ else:
+ val += "no local storage"
+ else:
+ val = ("<Disk(type=%s, logical_id=%s, physical_id=%s, children=%s" %
+ (self.dev_type, self.logical_id, self.physical_id, self.children))
+ if self.iv_name is None:
+ val += ", not visible"
+ else:
+ val += ", visible as /dev/%s" % self.iv_name
+ if isinstance(self.size, int):
+ val += ", size=%dm)>" % self.size
+ else:
+ val += ", size='%s')>" % (self.size,)
+ return val
+
+ def Verify(self):
+ """Checks that this disk is correctly configured.
+
+ """
+ errors = []
+ if self.mode not in constants.DISK_ACCESS_SET:
+ errors.append("Disk access mode '%s' is invalid" % (self.mode, ))
+ return errors
+
+
+class Instance(TaggableObject):