Add ParseCpuMask() utility function
[ganeti-local] / lib / objects.py
index b1793e6..be6f2d7 100644 (file)
@@ -340,6 +340,21 @@ class ConfigData(ConfigObject):
     obj.instances = cls._ContainerFromDicts(obj.instances, dict, Instance)
     return obj
 
+  def HasAnyDiskOfType(self, dev_type):
+    """Check if in there is at disk of the given type in the configuration.
+
+    @type dev_type: L{constants.LDS_BLOCK}
+    @param dev_type: the type to look for
+    @rtype: boolean
+    @return: boolean indicating if a disk of the given type was found or not
+
+    """
+    for instance in self.instances.values():
+      for disk in instance.disks:
+        if disk.IsBasedOnDiskType(dev_type):
+          return True
+    return False
+
   def UpgradeConfig(self):
     """Fill defaults for missing configuration values.
 
@@ -349,6 +364,12 @@ class ConfigData(ConfigObject):
       node.UpgradeConfig()
     for instance in self.instances.values():
       instance.UpgradeConfig()
+    if self.cluster.drbd_usermode_helper is None:
+      # To decide if we set an helper let's check if at least one instance has
+      # a DRBD disk. This does not cover all the possible scenarios but it
+      # gives a good approximation.
+      if self.HasAnyDiskOfType(constants.LD_DRBD8):
+        self.cluster.drbd_usermode_helper = constants.DEFAULT_DRBD_HELPER
 
 
 class NIC(ConfigObject):
@@ -383,7 +404,8 @@ class NIC(ConfigObject):
         self.nicparams[constants.NIC_MODE] = constants.NIC_MODE_BRIDGED
         self.nicparams[constants.NIC_LINK] = self.bridge
     # bridge is no longer used it 2.1. The slot is left there to support
-    # upgrading, but will be removed in 2.2
+    # upgrading, but can be removed once upgrades to the current version
+    # straight from 2.0 are deprecated.
     if self.bridge is not None:
       self.bridge = None
 
@@ -436,6 +458,21 @@ class Disk(ConfigObject):
       return 0
     return -1
 
+  def IsBasedOnDiskType(self, dev_type):
+    """Check if the disk or its children are based on the given type.
+
+    @type dev_type: L{constants.LDS_BLOCK}
+    @param dev_type: the type to look for
+    @rtype: boolean
+    @return: boolean indicating if a device of the given type was found or not
+
+    """
+    if self.children:
+      for child in self.children:
+        if child.IsBasedOnDiskType(dev_type):
+          return True
+    return self.dev_type == dev_type
+
   def GetNodes(self, node):
     """This function returns the nodes this device lives on.
 
@@ -657,6 +694,7 @@ class Instance(TaggableObject):
     "hypervisor",
     "hvparams",
     "beparams",
+    "osparams",
     "admin_up",
     "nics",
     "disks",
@@ -812,10 +850,18 @@ class Instance(TaggableObject):
           del self.hvparams[key]
         except KeyError:
           pass
+    if self.osparams is None:
+      self.osparams = {}
 
 
 class OS(ConfigObject):
-  """Config object representing an operating system."""
+  """Config object representing an operating system.
+
+  @type supported_parameters: list
+  @ivar supported_parameters: a list of tuples, name and description,
+      containing the supported parameters by this OS
+
+  """
   __slots__ = [
     "name",
     "path",
@@ -824,7 +870,9 @@ class OS(ConfigObject):
     "export_script",
     "import_script",
     "rename_script",
+    "verify_script",
     "supported_variants",
+    "supported_parameters",
     ]
 
 
@@ -850,6 +898,7 @@ class Cluster(TaggableObject):
     "tcpudp_port_pool",
     "mac_prefix",
     "volume_group_name",
+    "drbd_usermode_helper",
     "default_bridge",
     "default_hypervisor",
     "master_node",
@@ -861,12 +910,14 @@ class Cluster(TaggableObject):
     "hvparams",
     "os_hvp",
     "beparams",
+    "osparams",
     "nicparams",
     "candidate_pool_size",
     "modify_etc_hosts",
     "modify_ssh_setup",
     "maintain_node_health",
     "uid_pool",
+    "default_iallocator",
     ] + _TIMESTAMPS + _UUID
 
   def UpgradeConfig(self):
@@ -885,6 +936,10 @@ class Cluster(TaggableObject):
     if self.os_hvp is None:
       self.os_hvp = {}
 
+    # osparams added before 2.2
+    if self.osparams is None:
+      self.osparams = {}
+
     self.beparams = UpgradeGroupedParams(self.beparams,
                                          constants.BEC_DEFAULTS)
     migrate_default_bridge = not self.nicparams
@@ -901,11 +956,13 @@ class Cluster(TaggableObject):
       self.modify_ssh_setup = True
 
     # default_bridge is no longer used it 2.1. The slot is left there to
-    # support auto-upgrading, but will be removed in 2.2
+    # support auto-upgrading. It can be removed once we decide to deprecate
+    # upgrading straight from 2.0.
     if self.default_bridge is not None:
       self.default_bridge = None
 
-    # default_hypervisor is just the first enabled one in 2.1
+    # default_hypervisor is just the first enabled one in 2.1. This slot and
+    # code can be removed once upgrading straight from 2.0 is deprecated.
     if self.default_hypervisor is not None:
       self.enabled_hypervisors = ([self.default_hypervisor] +
         [hvname for hvname in self.enabled_hypervisors
@@ -919,6 +976,9 @@ class Cluster(TaggableObject):
     if self.uid_pool is None:
       self.uid_pool = []
 
+    if self.default_iallocator is None:
+      self.default_iallocator = ""
+
   def ToDict(self):
     """Custom function for cluster.
 
@@ -1002,8 +1062,8 @@ class Cluster(TaggableObject):
   def SimpleFillBE(self, beparams):
     """Fill a given beparams dict with cluster defaults.
 
-    @type beparam: dict
-    @param beparam: the dict to fill
+    @type beparams: dict
+    @param beparams: the dict to fill
     @rtype: dict
     @return: a copy of the passed in beparams with missing keys filled
         from the cluster defaults
@@ -1026,8 +1086,8 @@ class Cluster(TaggableObject):
   def SimpleFillNIC(self, nicparams):
     """Fill a given nicparams dict with cluster defaults.
 
-    @type nicparam: dict
-    @param nicparam: the dict to fill
+    @type nicparams: dict
+    @param nicparams: the dict to fill
     @rtype: dict
     @return: a copy of the passed in nicparams with missing keys filled
         from the cluster defaults
@@ -1035,6 +1095,26 @@ class Cluster(TaggableObject):
     """
     return FillDict(self.nicparams.get(constants.PP_DEFAULT, {}), nicparams)
 
+  def SimpleFillOS(self, os_name, os_params):
+    """Fill an instance's osparams dict with cluster defaults.
+
+    @type os_name: string
+    @param os_name: the OS name to use
+    @type os_params: dict
+    @param os_params: the dict to fill with default values
+    @rtype: dict
+    @return: a copy of the instance's osparams with missing keys filled from
+        the cluster defaults
+
+    """
+    name_only = os_name.split("+", 1)[0]
+    # base OS
+    result = self.osparams.get(name_only, {})
+    # OS with variant
+    result = FillDict(result, self.osparams.get(os_name, {}))
+    # specified params
+    return FillDict(result, os_params)
+
 
 class BlockDevStatus(ConfigObject):
   """Config object representing the status of a block device."""