On Wed, Mar 18, 2015 at 03:30:35PM +0000, Helga Velroyen wrote:
commit a530af1d88f608d10f613909d63e6fb342e0df56
Merge: 47f95a9 6e8f7fe
Author: Helga Velroyen <[email protected]>
Date:   Wed Mar 18 16:23:52 2015 +0100

   Merge branch 'stable-2.11' into stable-2.12

   * stable-2.11
     Renew crypto retries for non-master nodes
     Retries for the master's SSL cert renewal
     Unit tests for offline nodes
     De-duplicate testing code regarding pathutils
     Make LURenewCrypto handle unreachable nodes properly
     Error handling on failed SSL cert renewal for master
     Unit test for LURenewCrypto's valid case
     Mock support for pathutils
     Increase timeout of crypto token RPC

    Conflicts:
   lib/cmdlib/cluster.py
   test/py/cmdlib/cluster_unittest.py
   test/py/cmdlib/testsupport/__init__.py

    Resolution:
           for all affected files: update changes to
           configuration handling

    Signed-off-by: Helga Velroyen <[email protected]>

diff --cc Makefile.am
index a61755b,a384351..c9e64cd
--- a/Makefile.am
+++ b/Makefile.am
@@@ -1756,8 -1572,9 +1756,9 @@@ python_test_support =
 test/py/cmdlib/testsupport/cmdlib_testcase.py \
 test/py/cmdlib/testsupport/config_mock.py \
 test/py/cmdlib/testsupport/iallocator_mock.py \
- test/py/cmdlib/testsupport/lock_manager_mock.py \
+ test/py/cmdlib/testsupport/livelock_mock.py \
 test/py/cmdlib/testsupport/netutils_mock.py \
+ test/py/cmdlib/testsupport/pathutils_mock.py \
 test/py/cmdlib/testsupport/processor_mock.py \
 test/py/cmdlib/testsupport/rpc_runner_mock.py \
 test/py/cmdlib/testsupport/ssh_mock.py \
diff --cc lib/cmdlib/cluster.py
index 5f6504a,0f4b2eb..828212f
--- a/lib/cmdlib/cluster.py
+++ b/lib/cmdlib/cluster.py
@@@ -110,8 -111,11 +110,10 @@@ class LUClusterRenewCrypto(NoHooksLU)
   takes care of the renewal of the client SSL certificates.

   """
+   _MAX_NUM_RETRIES = 3
+
   def Exec(self, feedback_fn):
     master_uuid = self.cfg.GetMasterNode()
-    cluster = self.cfg.GetClusterInfo()

     server_digest = utils.GetCertificateDigest(
       cert_filename=pathutils.NODED_CERT_FILE)
@@@ -125,21 -131,67 +127,60 @@@
     except IOError:
       logging.info("No old certificate available.")

-     new_master_digest = _UpdateMasterClientCert(self, self.cfg,
master_uuid)
-
-     self.cfg.AddNodeToCandidateCerts(master_uuid, new_master_digest)
+     for _ in range(self._MAX_NUM_RETRIES):
+       try:
+         # Technically it should not be necessary to set the cert
+         # paths. However, due to a bug in the mock library, we
+         # have to do this to be able to test the function properly.
+         _UpdateMasterClientCert(
-            self, master_uuid, cluster, feedback_fn,
++            self, self.cfg, master_uuid,
+             client_cert=pathutils.NODED_CLIENT_CERT_FILE,
+             client_cert_tmp=pathutils.NODED_CLIENT_CERT_FILE_TMP)
+         break
+       except errors.OpExecError as e:
+         pass
+     else:
+       feedback_fn("Could not renew the master's client SSL certificate."
+                    " Cleaning up. Error: %s." % e)
+       # Cleaning up temporary certificates
-      utils.RemoveNodeFromCandidateCerts("%s-SERVER" % master_uuid,
-                                         cluster.candidate_certs)
-      utils.RemoveNodeFromCandidateCerts("%s-OLDMASTER" % master_uuid,
-                                         cluster.candidate_certs)
++      self.cfg.RemoveNodeFromCandidateCerts("%s-SERVER" % master_uuid)
++      self.cfg.RemoveNodeFromCandidateCerts("%s-OLDMASTER" % master_uuid)
+       try:
+         utils.RemoveFile(pathutils.NODED_CLIENT_CERT_FILE_TMP)
+       except IOError:
+         pass
+       return
+
+     node_errors = {}
     nodes = self.cfg.GetAllNodesInfo()
     for (node_uuid, node_info) in nodes.items():
       if node_info.offline:
         feedback_fn("* Skipping offline node %s" % node_info.name)
         continue
       if node_uuid != master_uuid:
-         new_digest = CreateNewClientCert(self, node_uuid)
-         if node_info.master_candidate:
-           self.cfg.AddNodeToCandidateCerts(node_uuid, new_digest)
+         for _ in range(self._MAX_NUM_RETRIES):
+           try:
+             new_digest = CreateNewClientCert(self, node_uuid)
+             if node_info.master_candidate:
-              utils.AddNodeToCandidateCerts(node_uuid,
-                                            new_digest,
-                                            cluster.candidate_certs)
++              self.cfg.AddNodeToCandidateCerts(node_uuid,
++                                               new_digest)
+             break
+           except errors.OpExecError as last_exception:
+             pass
+         else:
+           if last_exception:
+             node_errors[node_uuid] = last_exception
+
+     if node_errors:
+       msg = ("Some nodes' SSL client certificates could not be renewed."
+              " Please make sure those nodes are reachable and rerun"
+              " the operation. The affected nodes and their errors are:\n")
+       for uuid, e in node_errors.items():
+         msg += "Node %s: %s\n" % (uuid, e)
+       feedback_fn(msg)
+
-    utils.RemoveNodeFromCandidateCerts("%s-SERVER" % master_uuid,
-                                       cluster.candidate_certs)
-    utils.RemoveNodeFromCandidateCerts("%s-OLDMASTER" % master_uuid,
-                                       cluster.candidate_certs)
-    # Trigger another update of the config now with the new master cert
-    self.cfg.Update(cluster, feedback_fn)
+    self.cfg.RemoveNodeFromCandidateCerts("%s-SERVER" % master_uuid)
+    self.cfg.RemoveNodeFromCandidateCerts("%s-OLDMASTER" % master_uuid)
-     # Trigger another update of the config now with the new master cert


 class LUClusterActivateMasterIp(NoHooksLU):
diff --cc test/py/cmdlib/cluster_unittest.py
index 1a90972,073b8de..eaed548
--- a/test/py/cmdlib/cluster_unittest.py
+++ b/test/py/cmdlib/cluster_unittest.py
@@@ -37,7 -37,8 +37,9 @@@ import OpenSS
 import copy
 import unittest
 import operator
+import re
+ import shutil
+ import os

 from ganeti.cmdlib import cluster
 from ganeti import constants
diff --cc test/py/cmdlib/testsupport/__init__.py
index e25fc27,d121c37..a1f0678
--- a/test/py/cmdlib/testsupport/__init__.py
+++ b/test/py/cmdlib/testsupport/__init__.py
@@@ -36,10 -36,11 +36,11 @@@ from cmdlib.testsupport.cmdlib_testcas
   withLockedLU
 from cmdlib.testsupport.config_mock import ConfigMock
 from cmdlib.testsupport.iallocator_mock import patchIAllocator
+from cmdlib.testsupport.livelock_mock import LiveLockMock
 from cmdlib.testsupport.utils_mock import patchUtils
-from cmdlib.testsupport.lock_manager_mock import LockManagerMock
 from cmdlib.testsupport.netutils_mock import patchNetutils, HostnameMock
 from cmdlib.testsupport.processor_mock import ProcessorMock
+ from cmdlib.testsupport.pathutils_mock import patchPathutils
 from cmdlib.testsupport.rpc_runner_mock import CreateRpcRunnerMock, \
   RpcResultsBuilder
 from cmdlib.testsupport.ssh_mock import patchSsh
@@@ -54,8 -54,8 +55,9 @@@ __all__ = ["CmdlibTestCase"
            "patchUtils",
            "patchNetutils",
            "patchSsh",
+            "patchPathutils",
-           "LockManagerMock",
            "ProcessorMock",
            "RpcResultsBuilder",
+           "LiveLockMock",
+           "WConfdMock",
            ]

LGTM

Reply via email to