This patch will handle the downgrade of the SSL setup
from 2.12 to 2.11. Essentially, all client.pem and
ssconf_master_candidates_certs files will be deleted.
This will kick the cluster in a pre-2.11 mode wrt to
SSL and result in a nagging message to re-run
'gnt-cluster renew-crypto' when as output of 'gnt-cluster
verify'.
Signed-off-by: Helga Velroyen <[email protected]>
---
lib/client/gnt_cluster.py | 33 +++++++++++++++++++++++++++++++++
lib/tools/ssl_update.py | 45 ++++++++++++++++++++++++++++++++++++++++++++-
src/Ganeti/Constants.hs | 14 +++++++++++++-
tools/cfgupgrade | 5 +++++
4 files changed, 95 insertions(+), 2 deletions(-)
diff --git a/lib/client/gnt_cluster.py b/lib/client/gnt_cluster.py
index a25c130..c56e2bb 100644
--- a/lib/client/gnt_cluster.py
+++ b/lib/client/gnt_cluster.py
@@ -1071,6 +1071,7 @@ def _RenewCrypto(new_cluster_cert, new_rapi_cert, #
pylint: disable=R0911
constants.NDS_NODE_DAEMON_CERTIFICATE:
utils.ReadFile(pathutils.NODED_CERT_FILE),
constants.NDS_NODE_NAME: node_name,
+ constants.NDS_ACTION: constants.CRYPTO_ACTION_CREATE,
}
bootstrap.RunNodeSetupCmd(
@@ -2068,6 +2069,38 @@ def _VersionSpecificDowngrade():
@return: True upon success
"""
ToStdout("Performing version-specific downgrade tasks.")
+
+ nodes = ssconf.SimpleStore().GetOnlineNodeList()
+ cluster_name = ssconf.SimpleStore().GetClusterName()
+ ssh_ports = ssconf.SimpleStore().GetSshPortMap()
+
+ for node in nodes:
+ data = {
+ constants.NDS_CLUSTER_NAME: cluster_name,
+ constants.NDS_NODE_DAEMON_CERTIFICATE:
+ utils.ReadFile(pathutils.NODED_CERT_FILE),
+ constants.NDS_NODE_NAME: node,
+ constants.NDS_ACTION: constants.CRYPTO_ACTION_DELETE,
+ }
+
+ try:
+ bootstrap.RunNodeSetupCmd(
+ cluster_name,
+ node,
+ pathutils.SSL_UPDATE,
+ True, # debug
+ True, # verbose,
+ True, # use cluster key
+ False, # ask key
+ True, # strict host check
+ ssh_ports[node],
+ data)
+ except Exception as e: # pylint: disable=W0703
+ # As downgrading can fail if a node is temporarily unreachable
+ # only output the error, but do not abort the entire operation.
+ ToStderr("Downgrading SSL setup of node '%s' failed: %s." %
+ (node, e))
+
return True
diff --git a/lib/tools/ssl_update.py b/lib/tools/ssl_update.py
index 4d17d9d..88a24ee 100644
--- a/lib/tools/ssl_update.py
+++ b/lib/tools/ssl_update.py
@@ -42,6 +42,7 @@ from ganeti import constants
from ganeti import errors
from ganeti import utils
from ganeti import ht
+from ganeti import pathutils
from ganeti.tools import common
@@ -49,6 +50,7 @@ _DATA_CHECK = ht.TStrictDict(False, True, {
constants.NDS_CLUSTER_NAME: ht.TNonEmptyString,
constants.NDS_NODE_DAEMON_CERTIFICATE: ht.TNonEmptyString,
constants.NDS_NODE_NAME: ht.TNonEmptyString,
+ constants.NDS_ACTION: ht.TNonEmptyString,
})
@@ -75,6 +77,37 @@ def ParseOptions():
return common.VerifyOptions(parser, opts, args)
+def DeleteClientCertificate():
+ """Deleting the client certificate. This is necessary for downgrades."""
+ if os.path.exists(pathutils.NODED_CLIENT_CERT_FILE):
+ os.remove(pathutils.NODED_CLIENT_CERT_FILE)
+ else:
+ logging.debug("Trying to delete the client certificate '%s' which did not"
+ " exist.", pathutils.NODED_CLIENT_CERT_FILE)
+
+
+def ClearMasterCandidateSsconfList():
+ """Clear the ssconf list of master candidate certs.
+
+ This is necessary when deleting the client certificates for a downgrade,
+ because otherwise the master cannot distribute the configuration to the
+ nodes via RPC during a downgrade anymore.
+
+ """
+ ssconf_file = os.path.join(
+ pathutils.DATA_DIR,
+ "%s%s" % (constants.SSCONF_FILEPREFIX,
+ constants.SS_MASTER_CANDIDATES_CERTS))
+ if os.path.exists:
+ os.remove(ssconf_file)
+ else:
+ logging.debug("Trying to delete the ssconf file '%s' which does not"
+ " exist.", ssconf_file)
+
+
+# pylint: disable=E1103
+# This pyling message complains about 'data' as 'bool' not having a get
+# member, but obviously the type is wrongly inferred.
def Main():
"""Main routine.
@@ -92,7 +125,17 @@ def Main():
# is the same as on this node.
common.VerifyCertificate(data, SslSetupError)
- common.GenerateClientCertificate(data, SslSetupError)
+ action = data.get(constants.NDS_ACTION)
+ if not action:
+ raise SslSetupError("No Action specified.")
+
+ if action == constants.CRYPTO_ACTION_CREATE:
+ common.GenerateClientCertificate(data, SslSetupError)
+ elif action == constants.CRYPTO_ACTION_DELETE:
+ DeleteClientCertificate()
+ ClearMasterCandidateSsconfList()
+ else:
+ raise SslSetupError("Unsupported action: %s." % action)
except Exception, err: # pylint: disable=W0703
logging.debug("Caught unhandled exception", exc_info=True)
diff --git a/src/Ganeti/Constants.hs b/src/Ganeti/Constants.hs
index 305ffc6..f525d6e 100644
--- a/src/Ganeti/Constants.hs
+++ b/src/Ganeti/Constants.hs
@@ -4388,8 +4388,17 @@ cryptoTypes = ConstantUtils.mkSet [cryptoTypeSslDigest]
cryptoActionGet :: String
cryptoActionGet = "get"
+cryptoActionCreate :: String
+cryptoActionCreate = "create"
+
+cryptoActionDelete :: String
+cryptoActionDelete = "delete"
+
cryptoActions :: FrozenSet String
-cryptoActions = ConstantUtils.mkSet [cryptoActionGet]
+cryptoActions =
+ ConstantUtils.mkSet [ cryptoActionCreate
+ , cryptoActionGet
+ , cryptoActionDelete]
-- Key word for master candidate cert list for bootstrapping.
@@ -4479,6 +4488,9 @@ ndsStartNodeDaemon = "start_node_daemon"
ndsNodeName :: String
ndsNodeName = "node_name"
+ndsAction :: String
+ndsAction = "action"
+
-- * VCluster related constants
vClusterEtcHosts :: String
diff --git a/tools/cfgupgrade b/tools/cfgupgrade
index 9c2775d..9131fde 100755
--- a/tools/cfgupgrade
+++ b/tools/cfgupgrade
@@ -524,6 +524,11 @@ def DowngradeCluster(config_data):
if "max_tracked_jobs" in cluster:
del cluster["max_tracked_jobs"]
+ if "candidate_certs" in cluster:
+ # Clear the candidate certs to make people run 'gnt-cluster renew-crypto'
+ # after a downgrade from 2.12 to 2.11.
+ cluster["candidate_certs"] = {}
+
def DowngradeGroups(config_data):
for group in config_data["nodegroups"].values():
--
2.4.3.573.g4eafbef