1143: Add gnt-cluster modify --modify-ssh-setup option
authorBrian Foley <bpfoley@google.com>
Wed, 17 Aug 2016 13:56:17 +0000 (14:56 +0100)
committerBrian Foley <bpfoley@google.com>
Mon, 22 Aug 2016 13:45:25 +0000 (14:45 +0100)
This allows the cluster flag modify_ssh_setup to be changed after
cluster initialisation.

Signed-off-by: Brian Foley <bpfoley@google.com>
Reviewed-by: Viktor Bachraty <vbachraty@google.com>

lib/cli_opts.py
lib/client/gnt_cluster.py
lib/cmdlib/cluster/__init__.py
man/gnt-cluster.rst
src/Ganeti/OpCodes.hs
src/Ganeti/OpParams.hs
test/hs/Test/Ganeti/OpCodes.hs
test/py/cmdlib/cluster_unittest.py

index c81355d..19a497d 100644 (file)
@@ -149,6 +149,7 @@ __all__ = [
   "MC_OPT",
   "MIGRATION_MODE_OPT",
   "MODIFY_ETCHOSTS_OPT",
+  "MODIFY_SSH_SETUP_OPT",
   "NET_OPT",
   "NETWORK6_OPT",
   "NETWORK_OPT",
@@ -1206,6 +1207,12 @@ NOMODIFY_SSH_SETUP_OPT = cli_option("--no-ssh-init", dest="modify_ssh_setup",
                                     help="Don't initialize SSH keys",
                                     action="store_false", default=True)
 
+MODIFY_SSH_SETUP_OPT = \
+ cli_option("--modify-ssh-setup", dest="modify_ssh_setup", metavar=_YORNO,
+            default=None, type="bool",
+            help="Defines whether the cluster should update node SSH keys"
+            " on node add and on renew-crypto")
+
 ERROR_CODES_OPT = cli_option("--error-codes", dest="error_codes",
                              help="Enable parseable error messages",
                              action="store_true", default=False)
index 2cc8328..83dfca2 100644 (file)
@@ -1402,6 +1402,7 @@ def SetClusterParams(opts, args):
           opts.ipolicy_spindle_ratio is not None or
           opts.ipolicy_memory_ratio is not None or
           opts.modify_etc_hosts is not None or
+          opts.modify_ssh_setup is not None or
           opts.file_storage_dir is not None or
           opts.install_image is not None or
           opts.instance_communication_network is not None or
@@ -1538,6 +1539,7 @@ def SetClusterParams(opts, args):
     max_tracked_jobs=opts.max_tracked_jobs,
     maintain_node_health=mnh,
     modify_etc_hosts=opts.modify_etc_hosts,
+    modify_ssh_setup=opts.modify_ssh_setup,
     uid_pool=uid_pool,
     add_uids=add_uids,
     remove_uids=remove_uids,
@@ -2590,7 +2592,7 @@ commands = {
      PREALLOC_WIPE_DISKS_OPT, NODE_PARAMS_OPT, USE_EXTERNAL_MIP_SCRIPT,
      DISK_PARAMS_OPT, HV_STATE_OPT, DISK_STATE_OPT] + SUBMIT_OPTS +
      [ENABLED_DISK_TEMPLATES_OPT, IPOLICY_STD_SPECS_OPT, MODIFY_ETCHOSTS_OPT,
-      ENABLED_USER_SHUTDOWN_OPT] +
+      MODIFY_SSH_SETUP_OPT, ENABLED_USER_SHUTDOWN_OPT] +
      INSTANCE_POLICY_OPTS +
      [GLOBAL_FILEDIR_OPT, GLOBAL_SHARED_FILEDIR_OPT, ZEROING_IMAGE_OPT,
       COMPRESSION_TOOLS_OPT] +
index 8182910..76b50f1 100644 (file)
@@ -1728,6 +1728,15 @@ class LUClusterSetParams(LogicalUnit):
     if self.op.modify_etc_hosts is not None:
       self.cluster.modify_etc_hosts = self.op.modify_etc_hosts
 
+    if self.op.modify_ssh_setup is not None:
+      if (self.op.modify_ssh_setup and
+          not self.cfg.GetClusterInfo().modify_ssh_setup):
+        feedback_fn(
+          "Enabling modify_ssh_setup for cluster. You may need to run"
+          " 'gnt-cluster renew-crypto --new-ssh-keys --no-ssh-key-check'"
+          " to redistribute the ssh public key settings for each node.")
+      self.cluster.modify_ssh_setup = self.op.modify_ssh_setup
+
     if self.op.prealloc_wipe_disks is not None:
       self.cluster.prealloc_wipe_disks = self.op.prealloc_wipe_disks
 
index 0c466b9..0469f75 100644 (file)
@@ -727,6 +727,7 @@ MODIFY
 | [\--master-netdev *interface-name*]
 | [\--master-netmask *netmask*]
 | [\--modify-etc-hosts {yes \| no}]
+| [\--modify-ssh-setup {yes \| no}]
 | [\--use-external-mip-script {yes \| no}]
 | [\--hypervisor-state *hvstate*]
 | [\--disk-state *diskstate*]
@@ -768,8 +769,8 @@ The ``--vg-name``, ``--enabled-hypervisors``, ``-H (--hypervisor-parameters)``,
 ``--user-shutdown`` options are
 described in the **init** command.
 
-The ``--modify-etc-hosts`` option is described by ``--no-etc-hosts`` in
-the **init** command.
+The ``--modify-etc-hosts`` and ``--modify-ssh-setup`` options are described
+by ``--no-etc-hosts`` and ``--no-ssh-setup`` in the **init** command.
 
 The ``--hypervisor-state`` and ``--disk-state`` options are described in
 detail in **ganeti**\(7).
index 4a3660e..8c20fac 100644 (file)
@@ -256,6 +256,7 @@ $(genOpCode "OpCode"
      , pUseExternalMipScript
      , pEnabledDiskTemplates
      , pModifyEtcHosts
+     , pModifySshSetup
      , pClusterFileStorageDir
      , pClusterSharedFileStorageDir
      , pClusterGlusterStorageDir
index e507a4a..95f11e2 100644 (file)
@@ -147,6 +147,7 @@ module Ganeti.OpParams
   , pRemoveUids
   , pMaintainNodeHealth
   , pModifyEtcHosts
+  , pModifySshSetup
   , pPreallocWipeDisks
   , pNicParams
   , pInstNics
@@ -770,6 +771,10 @@ pMaintainNodeHealth =
 pModifyEtcHosts :: Field
 pModifyEtcHosts = optionalField $ booleanField "modify_etc_hosts"
 
+-- | Whether to modify SSH setup on node add or when renewing crypto
+pModifySshSetup :: Field
+pModifySshSetup = optionalField $ booleanField "modify_ssh_setup"
+
 -- | Whether to wipe disks before allocating them to instances.
 pPreallocWipeDisks :: Field
 pPreallocWipeDisks =
index bc16c9e..ed7934e 100644 (file)
@@ -244,6 +244,7 @@ instance Arbitrary OpCodes.OpCode where
           <*> arbitrary                    -- use_external_mip_script
           <*> arbitrary                    -- enabled_disk_templates
           <*> arbitrary                    -- modify_etc_hosts
+          <*> arbitrary                    -- modify_ssh_setup
           <*> genMaybe genName             -- file_storage_dir
           <*> genMaybe genName             -- shared_file_storage_dir
           <*> genMaybe genName             -- gluster_file_storage_dir
index 1bdac3f..fe8b9f4 100644 (file)
@@ -998,6 +998,28 @@ class TestLUClusterSetParams(CmdlibTestCase):
     self.assertEqual(["/dev/mock_lv"], self.cluster.reserved_lvs)
     self.assertEqual(True, self.cluster.use_external_mip_script)
 
+  def testEnableSshSetup(self):
+    # Check the flag is disabled by default
+    old = False
+    self.assertEqual(old, self.cluster.modify_ssh_setup)
+
+    # Try all 4 permutations of off->off, off->on, on->on, on->off
+    for new in (False, True, True, False):
+      self.mcpu.ClearLogMessages()
+      self.ExecOpCode(opcodes.OpClusterSetParams(modify_ssh_setup=new))
+
+      # Check the flag is updated to the new value
+      self.assertEqual(new, self.cluster.modify_ssh_setup)
+
+      # Switching off modify_ssh_setup should succeed silently,
+      # Switching it on should warn, and leaving it the same should do nothing
+      if not old and new:
+        self.mcpu.assertLogContainsRegex("gnt-cluster renew-crypto")
+      else:
+        self.mcpu.assertLogIsEmpty()
+
+      old = new
+
   def testAddHiddenOs(self):
     self.cluster.hidden_os = ["hidden1", "hidden2"]
     op = opcodes.OpClusterSetParams(hidden_os=[(constants.DDM_ADD, "hidden2"),