From ff6c5e551eeafbe74b6dbaa670ef3e50a3dd5a2d Mon Sep 17 00:00:00 2001
From: Iustin Pop <iustin@google.com>
Date: Mon, 23 Jan 2012 17:12:22 +0100
Subject: [PATCH] Add new ipolicy parameter vcpu_ratio

This adds the new parameter and changes the validation routines to
handle IPOLICY_PARAMETER value as floats. Very very ugly code :(,
should be redone much cleaner.

Signed-off-by: Iustin Pop <iustin@google.com>
Reviewed-by: Michael Hanselmann <hansmi@google.com>
---
 lib/client/gnt_cluster.py |  2 ++
 lib/cmdlib.py             | 15 ++++++++++++---
 lib/config.py             | 10 +++++++---
 lib/constants.py          | 11 ++++++++++-
 lib/objects.py            | 19 +++++++++++++++++++
 5 files changed, 50 insertions(+), 7 deletions(-)

diff --git a/lib/client/gnt_cluster.py b/lib/client/gnt_cluster.py
index 1fc0cf8e8..cbaea0d44 100644
--- a/lib/client/gnt_cluster.py
+++ b/lib/client/gnt_cluster.py
@@ -468,6 +468,8 @@ def ShowClusterConfig(opts, args):
     _PrintGroupedParams(result["ipolicy"][key], roman=opts.roman_integers)
   ToStdout("  - enabled disk templates: %s",
            utils.CommaJoin(result["ipolicy"][constants.IPOLICY_DTS]))
+  for key in constants.IPOLICY_PARAMETERS:
+    ToStdout("  - %s: %s", key, result["ipolicy"][key])
 
   return 0
 
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 46bf7eeca..7e00bf880 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -740,8 +740,6 @@ def _GetUpdatedIPolicy(old_ipolicy, new_ipolicy, group_policy=False):
                                        use_none=use_none,
                                        use_default=use_default)
     else:
-      # FIXME: we assume all others are lists; this should be redone
-      # in a nicer way
       if not value or value == [constants.VALUE_DEFAULT]:
         if group_policy:
           del ipolicy[key]
@@ -750,7 +748,18 @@ def _GetUpdatedIPolicy(old_ipolicy, new_ipolicy, group_policy=False):
                                      " on the cluster'" % key,
                                      errors.ECODE_INVAL)
       else:
-        ipolicy[key] = list(value)
+        if key in constants.IPOLICY_PARAMETERS:
+          # FIXME: we assume all such values are float
+          try:
+            ipolicy[key] = float(value)
+          except (TypeError, ValueError), err:
+            raise errors.OpPrereqError("Invalid value for attribute"
+                                       " '%s': '%s', error: %s" %
+                                       (key, value, err), errors.ECODE_INVAL)
+        else:
+          # FIXME: we assume all others are lists; this should be redone
+          # in a nicer way
+          ipolicy[key] = list(value)
   try:
     objects.InstancePolicy.CheckParameterSyntax(ipolicy)
   except errors.ConfigurationError, err:
diff --git a/lib/config.py b/lib/config.py
index a4f864d82..abf379d4f 100644
--- a/lib/config.py
+++ b/lib/config.py
@@ -439,10 +439,14 @@ class ConfigWriter:
           _helper(owner, fullkey, value, constants.ISPECS_PARAMETER_TYPES)
         else:
           # FIXME: assuming list type
-          if not isinstance(value, list):
+          if key in constants.IPOLICY_PARAMETERS:
+            exp_type = float
+          else:
+            exp_type = list
+          if not isinstance(value, exp_type):
             result.append("%s has invalid instance policy: for %s,"
-                          " expecting list, got %s" %
-                          (owner, key, type(value)))
+                          " expecting %s, got %s" %
+                          (owner, key, exp_type.__name__, type(value)))
 
     # check cluster parameters
     _helper("cluster", "beparams", cluster.SimpleFillBE({}),
diff --git a/lib/constants.py b/lib/constants.py
index b2cdfec35..dcece0b45 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -950,13 +950,21 @@ ISPECS_MIN = "min"
 ISPECS_MAX = "max"
 ISPECS_STD = "std"
 IPOLICY_DTS = "disk_templates"
+IPOLICY_VCPU_RATIO = "vcpu_ratio"
 
 IPOLICY_ISPECS = frozenset([
   ISPECS_MIN,
   ISPECS_MAX,
   ISPECS_STD,
   ])
-IPOLICY_ALL_KEYS = IPOLICY_ISPECS.union([IPOLICY_DTS])
+
+IPOLICY_PARAMETERS = frozenset([
+  IPOLICY_VCPU_RATIO,
+  ])
+
+IPOLICY_ALL_KEYS = (IPOLICY_ISPECS |
+                    IPOLICY_PARAMETERS |
+                    frozenset([IPOLICY_DTS]))
 
 # Node parameter names
 ND_OOB_PROGRAM = "oob_program"
@@ -1907,6 +1915,7 @@ IPOLICY_DEFAULTS = {
     ISPEC_NIC_COUNT: 1,
     },
   IPOLICY_DTS: DISK_TEMPLATES,
+  IPOLICY_VCPU_RATIO: 4.0,
   }
 
 MASTER_POOL_SIZE_DEFAULT = 10
diff --git a/lib/objects.py b/lib/objects.py
index ff921d619..cfd723b81 100644
--- a/lib/objects.py
+++ b/lib/objects.py
@@ -105,6 +105,9 @@ def FillIPolicy(default_ipolicy, custom_ipolicy, skip_keys=None):
   # list items
   for key in [constants.IPOLICY_DTS]:
     ret_dict[key] = list(custom_ipolicy.get(key, default_ipolicy[key]))
+  # other items which we know we can directly copy (immutables)
+  for key in constants.IPOLICY_PARAMETERS:
+    ret_dict[key] = custom_ipolicy.get(key, default_ipolicy[key])
 
   return ret_dict
 
@@ -908,6 +911,9 @@ class InstancePolicy(ConfigObject):
       InstancePolicy.CheckISpecSyntax(ipolicy, param)
     if constants.IPOLICY_DTS in ipolicy:
       InstancePolicy.CheckDiskTemplates(ipolicy[constants.IPOLICY_DTS])
+    for key in constants.IPOLICY_PARAMETERS:
+      if key in ipolicy:
+        InstancePolicy.CheckParameter(key, ipolicy[key])
     wrong_keys = frozenset(ipolicy.keys()) - constants.IPOLICY_ALL_KEYS
     if wrong_keys:
       raise errors.ConfigurationError("Invalid keys in ipolicy: %s" %
@@ -948,6 +954,19 @@ class InstancePolicy(ConfigObject):
       raise errors.ConfigurationError("Invalid disk template(s) %s" %
                                       utils.CommaJoin(wrong))
 
+  @classmethod
+  def CheckParameter(cls, key, value):
+    """Checks a parameter.
+
+    Currently we expect all parameters to be float values.
+
+    """
+    try:
+      float(value)
+    except (TypeError, ValueError), err:
+      raise errors.ConfigurationError("Invalid value for key" " '%s':"
+                                      " '%s', error: %s" % (key, value, err))
+
 
 class Instance(TaggableObject):
   """Config object representing an instance."""
-- 
GitLab