HTools/Types.hs: more auto-repair types
[ganeti-local] / lib / objects.py
index 4be25ab..2a0b8bd 100644 (file)
@@ -51,7 +51,7 @@ from socket import AF_INET
 
 
 __all__ = ["ConfigObject", "ConfigData", "NIC", "Disk", "Instance",
-           "OS", "Node", "NodeGroup", "Cluster", "FillDict"]
+           "OS", "Node", "NodeGroup", "Cluster", "FillDict", "Network"]
 
 _TIMESTAMPS = ["ctime", "mtime"]
 _UUID = ["uuid"]
@@ -420,7 +420,7 @@ class MasterNetworkParameters(ConfigObject):
     "ip",
     "netmask",
     "netdev",
-    "ip_family"
+    "ip_family",
     ]
 
 
@@ -432,6 +432,7 @@ class ConfigData(ConfigObject):
     "nodes",
     "nodegroups",
     "instances",
+    "networks",
     "serial_no",
     ] + _TIMESTAMPS
 
@@ -444,7 +445,7 @@ class ConfigData(ConfigObject):
     """
     mydict = super(ConfigData, self).ToDict()
     mydict["cluster"] = mydict["cluster"].ToDict()
-    for key in "nodes", "instances", "nodegroups":
+    for key in "nodes", "instances", "nodegroups", "networks":
       mydict[key] = self._ContainerToDicts(mydict[key])
 
     return mydict
@@ -459,6 +460,7 @@ class ConfigData(ConfigObject):
     obj.nodes = cls._ContainerFromDicts(obj.nodes, dict, Node)
     obj.instances = cls._ContainerFromDicts(obj.instances, dict, Instance)
     obj.nodegroups = cls._ContainerFromDicts(obj.nodegroups, dict, NodeGroup)
+    obj.networks = cls._ContainerFromDicts(obj.networks, dict, Network)
     return obj
 
   def HasAnyDiskOfType(self, dev_type):
@@ -495,11 +497,13 @@ class ConfigData(ConfigObject):
       # gives a good approximation.
       if self.HasAnyDiskOfType(constants.LD_DRBD8):
         self.cluster.drbd_usermode_helper = constants.DEFAULT_DRBD_HELPER
+    if self.networks is None:
+      self.networks = {}
 
 
 class NIC(ConfigObject):
   """Config object representing a network card."""
-  __slots__ = ["mac", "ip", "nicparams"]
+  __slots__ = ["mac", "ip", "network", "nicparams", "netinfo"]
 
   @classmethod
   def CheckParameterSyntax(cls, nicparams):
@@ -510,15 +514,14 @@ class NIC(ConfigObject):
     @raise errors.ConfigurationError: when a parameter is not valid
 
     """
-    if (nicparams[constants.NIC_MODE] not in constants.NIC_VALID_MODES and
-        nicparams[constants.NIC_MODE] != constants.VALUE_AUTO):
-      err = "Invalid nic mode: %s" % nicparams[constants.NIC_MODE]
-      raise errors.ConfigurationError(err)
+    mode = nicparams[constants.NIC_MODE]
+    if (mode not in constants.NIC_VALID_MODES and
+        mode != constants.VALUE_AUTO):
+      raise errors.ConfigurationError("Invalid NIC mode '%s'" % mode)
 
-    if (nicparams[constants.NIC_MODE] == constants.NIC_MODE_BRIDGED and
+    if (mode == constants.NIC_MODE_BRIDGED and
         not nicparams[constants.NIC_LINK]):
-      err = "Missing bridged nic link"
-      raise errors.ConfigurationError(err)
+      raise errors.ConfigurationError("Missing bridged NIC link")
 
 
 class Disk(ConfigObject):
@@ -598,7 +601,8 @@ class Disk(ConfigObject):
 
     """
     if self.dev_type in [constants.LD_LV, constants.LD_FILE,
-                         constants.LD_BLOCKDEV, constants.LD_RBD]:
+                         constants.LD_BLOCKDEV, constants.LD_RBD,
+                         constants.LD_EXT]:
       result = [node]
     elif self.dev_type in constants.LDS_DRBD:
       result = [self.logical_id[0], self.logical_id[1]]
@@ -674,7 +678,7 @@ class Disk(ConfigObject):
 
     """
     if self.dev_type in (constants.LD_LV, constants.LD_FILE,
-                         constants.LD_RBD):
+                         constants.LD_RBD, constants.LD_EXT):
       self.size += amount
     elif self.dev_type == constants.LD_DRBD8:
       if self.children:
@@ -901,9 +905,12 @@ class Disk(ConfigObject):
 
     elif disk_template == constants.DT_RBD:
       result.append(FillDict(constants.DISK_LD_DEFAULTS[constants.LD_RBD], {
-        constants.LDP_POOL: dt_params[constants.RBD_POOL]
+        constants.LDP_POOL: dt_params[constants.RBD_POOL],
         }))
 
+    elif disk_template == constants.DT_EXT:
+      result.append(constants.DISK_LD_DEFAULTS[constants.LD_EXT])
+
     return result
 
 
@@ -1019,7 +1026,7 @@ class Instance(TaggableObject):
     return tuple(all_nodes)
 
   secondary_nodes = property(_ComputeSecondaryNodes, None, None,
-                             "List of secondary nodes")
+                             "List of names of secondary nodes")
 
   def _ComputeAllNodes(self):
     """Compute the list of all nodes.
@@ -1047,7 +1054,7 @@ class Instance(TaggableObject):
     return tuple(all_nodes)
 
   all_nodes = property(_ComputeAllNodes, None, None,
-                       "List of all nodes of the instance")
+                       "List of names of all the nodes of the instance")
 
   def MapLVsByNode(self, lvmap=None, devs=None, node=None):
     """Provide a mapping of nodes to LVs this instance owns.
@@ -1231,6 +1238,24 @@ class OS(ConfigObject):
     return cls.SplitNameVariant(name)[1]
 
 
+class ExtStorage(ConfigObject):
+  """Config object representing an External Storage Provider.
+
+  """
+  __slots__ = [
+    "name",
+    "path",
+    "create_script",
+    "remove_script",
+    "grow_script",
+    "attach_script",
+    "detach_script",
+    "setinfo_script",
+    "verify_script",
+    "supported_parameters",
+    ]
+
+
 class NodeHvState(ConfigObject):
   """Hypvervisor state on a node.
 
@@ -1359,6 +1384,7 @@ class NodeGroup(TaggableObject):
     "hv_state_static",
     "disk_state_static",
     "alloc_policy",
+    "networks",
     ] + _TIMESTAMPS + _UUID
 
   def ToDict(self):
@@ -1406,6 +1432,9 @@ class NodeGroup(TaggableObject):
     if self.ipolicy is None:
       self.ipolicy = MakeEmptyIPolicy()
 
+    if self.networks is None:
+      self.networks = {}
+
   def FillND(self, node):
     """Return filled out ndparams for L{objects.Node}
 
@@ -1989,6 +2018,26 @@ class InstanceConsole(ConfigObject):
     return True
 
 
+class Network(TaggableObject):
+  """Object representing a network definition for ganeti.
+
+  """
+  __slots__ = [
+    "name",
+    "serial_no",
+    "network_type",
+    "mac_prefix",
+    "family",
+    "network",
+    "network6",
+    "gateway",
+    "gateway6",
+    "size",
+    "reservations",
+    "ext_reservations",
+    ] + _TIMESTAMPS + _UUID
+
+
 class SerializableConfigParser(ConfigParser.SafeConfigParser):
   """Simple wrapper over ConfigParse that allows serialization.
 
@@ -2010,3 +2059,38 @@ class SerializableConfigParser(ConfigParser.SafeConfigParser):
     cfp = cls()
     cfp.readfp(buf)
     return cfp
+
+
+class LvmPvInfo(ConfigObject):
+  """Information about an LVM physical volume (PV).
+
+  @type name: string
+  @ivar name: name of the PV
+  @type vg_name: string
+  @ivar vg_name: name of the volume group containing the PV
+  @type size: float
+  @ivar size: size of the PV in MiB
+  @type free: float
+  @ivar free: free space in the PV, in MiB
+  @type attributes: string
+  @ivar attributes: PV attributes
+  """
+  __slots__ = [
+    "name",
+    "vg_name",
+    "size",
+    "free",
+    "attributes",
+    ]
+
+  def IsEmpty(self):
+    """Is this PV empty?
+
+    """
+    return self.size <= (self.free + 1)
+
+  def IsAllocatable(self):
+    """Is this PV allocatable?
+
+    """
+    return ("a" in self.attributes)