commit c270ee079abdb966c8b50b8090cc70a36db035b7
Author: Helga Velroyen <helgav@google.com>
Date:   Wed Mar 13 16:28:45 2013 +0100

    gnt-cluster modify: dis/enabling storage types
    
    This patch extends the 'gnt-cluster modify' command to manipulate the list
    of enabled storage types. Note that this currenlty does no validation
    with respect to whether or not there are instances currently using a storage
    type that is being removed from the list.
    
    Signed-off-by: Helga Velroyen <helgav@google.com>
    Reviewed-by: Guido Trotter <ultrotter@google.com>

diff --git a/lib/cli.py b/lib/cli.py
index 34657a0..03ea3b4 100644
--- a/lib/cli.py
+++ b/lib/cli.py
@@ -81,6 +81,7 @@ __all__ = [
   "DST_NODE_OPT",
   "EARLY_RELEASE_OPT",
   "ENABLED_HV_OPT",
+  "ENABLED_STORAGE_TYPES_OPT",
   "ERROR_CODES_OPT",
   "FAILURE_ONLY_OPT",
   "FIELDS_OPT",
@@ -1156,6 +1157,12 @@ ENABLED_HV_OPT = cli_option("--enabled-hypervisors",
                             help="Comma-separated list of hypervisors",
                             type="string", default=None)
 
+ENABLED_STORAGE_TYPES_OPT = cli_option("--enabled-storage-types",
+                                       dest="enabled_storage_types",
+                                       help="Comma-separated list of "
+                                            "storage methods",
+                                       type="string", default=None)
+
 NIC_PARAMS_OPT = cli_option("-N", "--nic-parameters", dest="nicparams",
                             type="keyval", default={},
                             help="NIC parameters")
diff --git a/lib/client/gnt_cluster.py b/lib/client/gnt_cluster.py
index f87a274..61b3f60 100644
--- a/lib/client/gnt_cluster.py
+++ b/lib/client/gnt_cluster.py
@@ -962,6 +962,7 @@ def SetClusterParams(opts, args):
           opts.use_external_mip_script is not None or
           opts.prealloc_wipe_disks is not None or
           opts.hv_state or
+          opts.enabled_storage_types or
           opts.disk_state or
           opts.ispecs_mem_size or
           opts.ispecs_cpu_count or
@@ -994,6 +995,10 @@ def SetClusterParams(opts, args):
   if hvlist is not None:
     hvlist = hvlist.split(",")
 
+  enabled_storage_types = opts.enabled_storage_types
+  if enabled_storage_types is not None:
+    enabled_storage_types = enabled_storage_types.split(",")
+
   # a list of (name, dict) we can pass directly to dict() (or [])
   hvparams = dict(opts.hvparams)
   for hv_params in hvparams.values():
@@ -1061,30 +1066,32 @@ def SetClusterParams(opts, args):
 
   hv_state = dict(opts.hv_state)
 
-  op = opcodes.OpClusterSetParams(vg_name=vg_name,
-                                  drbd_helper=drbd_helper,
-                                  enabled_hypervisors=hvlist,
-                                  hvparams=hvparams,
-                                  os_hvp=None,
-                                  beparams=beparams,
-                                  nicparams=nicparams,
-                                  ndparams=ndparams,
-                                  diskparams=diskparams,
-                                  ipolicy=ipolicy,
-                                  candidate_pool_size=opts.candidate_pool_size,
-                                  maintain_node_health=mnh,
-                                  uid_pool=uid_pool,
-                                  add_uids=add_uids,
-                                  remove_uids=remove_uids,
-                                  default_iallocator=opts.default_iallocator,
-                                  prealloc_wipe_disks=opts.prealloc_wipe_disks,
-                                  master_netdev=opts.master_netdev,
-                                  master_netmask=opts.master_netmask,
-                                  reserved_lvs=opts.reserved_lvs,
-                                  use_external_mip_script=ext_ip_script,
-                                  hv_state=hv_state,
-                                  disk_state=disk_state,
-                                  )
+  op = opcodes.OpClusterSetParams(
+    vg_name=vg_name,
+    drbd_helper=drbd_helper,
+    enabled_hypervisors=hvlist,
+    hvparams=hvparams,
+    os_hvp=None,
+    beparams=beparams,
+    nicparams=nicparams,
+    ndparams=ndparams,
+    diskparams=diskparams,
+    ipolicy=ipolicy,
+    candidate_pool_size=opts.candidate_pool_size,
+    maintain_node_health=mnh,
+    uid_pool=uid_pool,
+    add_uids=add_uids,
+    remove_uids=remove_uids,
+    default_iallocator=opts.default_iallocator,
+    prealloc_wipe_disks=opts.prealloc_wipe_disks,
+    master_netdev=opts.master_netdev,
+    master_netmask=opts.master_netmask,
+    reserved_lvs=opts.reserved_lvs,
+    use_external_mip_script=ext_ip_script,
+    hv_state=hv_state,
+    disk_state=disk_state,
+    enabled_storage_types=enabled_storage_types,
+    )
   SubmitOrSend(op, opts)
   return 0
 
@@ -1566,7 +1573,7 @@ commands = {
      DRBD_HELPER_OPT, NODRBD_STORAGE_OPT, DEFAULT_IALLOCATOR_OPT,
      RESERVED_LVS_OPT, DRY_RUN_OPT, PRIORITY_OPT, PREALLOC_WIPE_DISKS_OPT,
      NODE_PARAMS_OPT, USE_EXTERNAL_MIP_SCRIPT, DISK_PARAMS_OPT, HV_STATE_OPT,
-     DISK_STATE_OPT, SUBMIT_OPT] +
+     DISK_STATE_OPT, SUBMIT_OPT, ENABLED_STORAGE_TYPES_OPT] +
     INSTANCE_POLICY_OPTS,
     "[opts...]",
     "Alters the parameters of the cluster"),
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index c56d7ba..0bc1ace 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -4408,6 +4408,10 @@ class LUClusterSetParams(LogicalUnit):
           hv_class.CheckParameterSyntax(hv_params)
           _CheckHVParams(self, node_list, hv_name, hv_params)
 
+    # FIXME: Regarding enabled_storage_types: If a method is removed
+    # which is actually currently used by an instance, should removing
+    # it be prevented?
+
     if self.op.os_hvp:
       # no need to check any newly-enabled hypervisors, since the
       # defaults have already been checked in the above code-block
@@ -4459,6 +4463,9 @@ class LUClusterSetParams(LogicalUnit):
     if self.op.enabled_hypervisors is not None:
       self.cluster.hvparams = self.new_hvparams
       self.cluster.enabled_hypervisors = self.op.enabled_hypervisors
+    if self.op.enabled_storage_types is not None:
+      self.cluster.enabled_storage_types = \
+        list(set(self.op.enabled_storage_types))
     if self.op.beparams:
       self.cluster.beparams[constants.PP_DEFAULT] = self.new_beparams
     if self.op.nicparams:
diff --git a/lib/opcodes.py b/lib/opcodes.py
index e6db3c3..969fe71 100644
--- a/lib/opcodes.py
+++ b/lib/opcodes.py
@@ -954,6 +954,10 @@ class OpClusterSetParams(OpCode):
      " ``%s`` or ``%s``" % (constants.DDM_ADD, constants.DDM_REMOVE)),
     ("use_external_mip_script", None, ht.TMaybeBool,
      "Whether to use an external master IP address setup script"),
+    ("enabled_storage_types", None,
+     ht.TMaybe(ht.TAnd(ht.TListOf(ht.TElemOf(constants.VALID_STORAGE_TYPES)),
+                       ht.TTrue)),
+     "List of enabled storage types"),
     ]
   OP_RESULT = ht.TNone
 
diff --git a/src/Ganeti/OpCodes.hs b/src/Ganeti/OpCodes.hs
index f720577..7eba050 100644
--- a/src/Ganeti/OpCodes.hs
+++ b/src/Ganeti/OpCodes.hs
@@ -175,6 +175,7 @@ $(genOpCode "OpCode"
      , pHiddenOs
      , pBlacklistedOs
      , pUseExternalMipScript
+     , pEnabledStorageTypes
      ])
   , ("OpClusterRedistConf", [])
   , ("OpClusterActivateMasterIp", [])
diff --git a/src/Ganeti/OpParams.hs b/src/Ganeti/OpParams.hs
index cccdb7c..7e91ae4 100644
--- a/src/Ganeti/OpParams.hs
+++ b/src/Ganeti/OpParams.hs
@@ -237,6 +237,7 @@ module Ganeti.OpParams
   , pDependencies
   , pComment
   , pReason
+  , pEnabledStorageTypes
   , dOldQuery
   , dOldQueryNoLocking
   ) where
@@ -758,6 +759,12 @@ pEnabledHypervisors =
   optionalField $
   simpleField "enabled_hypervisors" [t| NonEmpty Hypervisor |]
 
+-- | List of enabled storage methods.
+pEnabledStorageTypes :: Field
+pEnabledStorageTypes =
+  optionalField $
+  simpleField "enabled_storage_types" [t| NonEmpty StorageType |]
+
 -- | Selected hypervisor for an instance.
 pHypervisor :: Field
 pHypervisor =
diff --git a/test/hs/Test/Ganeti/OpCodes.hs b/test/hs/Test/Ganeti/OpCodes.hs
index 4c06ee2..c303fd8 100644
--- a/test/hs/Test/Ganeti/OpCodes.hs
+++ b/test/hs/Test/Ganeti/OpCodes.hs
@@ -163,7 +163,7 @@ instance Arbitrary OpCodes.OpCode where
           arbitrary <*> arbitrary <*> arbitrary <*>
           emptyMUD <*> emptyMUD <*> arbitrary <*>
           arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*>
-          arbitrary <*> arbitrary <*> arbitrary
+          arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
       "OP_CLUSTER_REDIST_CONF" -> pure OpCodes.OpClusterRedistConf
       "OP_CLUSTER_ACTIVATE_MASTER_IP" ->
         pure OpCodes.OpClusterActivateMasterIp
