Commit f0c7c333 authored by Petr Pudlak's avatar Petr Pudlak
Browse files

Move utility functions for candidate certs. to ConfigWriter



In particular AddNodeToCandidateCerts and RemoveNodeFromCandidateCerts.

Calling 'cfg.Update(cluster)' causes problems in WConfd, as
it doesn't operate on a shared configuration object any more.

Also these functions modify the cluster configuration, so their calls
should be properly locked.
Signed-off-by: default avatarPetr Pudlak <pudlak@google.com>
Reviewed-by: default avatarHelga Velroyen <helgav@google.com>
parent ae8fdfa6
......@@ -63,19 +63,17 @@ import ganeti.masterd.instance
def _UpdateMasterClientCert(
lu, master_uuid, cluster, feedback_fn,
lu, cfg, master_uuid,
client_cert=pathutils.NODED_CLIENT_CERT_FILE,
client_cert_tmp=pathutils.NODED_CLIENT_CERT_FILE_TMP):
"""Renews the master's client certificate and propagates the config.
@type lu: C{LogicalUnit}
@param lu: the logical unit holding the config
@type cfg: C{config.ConfigWriter}
@param cfg: the cluster's configuration
@type master_uuid: string
@param master_uuid: the master node's UUID
@type cluster: C{objects.Cluster}
@param cluster: the cluster's configuration
@type feedback_fn: function
@param feedback_fn: feedback functions for config updates
@type client_cert: string
@param client_cert: the path of the client certificate
@type client_cert_tmp: string
......@@ -85,11 +83,9 @@ def _UpdateMasterClientCert(
"""
client_digest = CreateNewClientCert(lu, master_uuid, filename=client_cert_tmp)
utils.AddNodeToCandidateCerts(master_uuid, client_digest,
cluster.candidate_certs)
cfg.AddNodeToCandidateCerts(master_uuid, client_digest)
# This triggers an update of the config and distribution of it with the old
# SSL certificate
lu.cfg.Update(cluster, feedback_fn)
utils.RemoveFile(client_cert)
utils.RenameFile(client_cert_tmp, client_cert)
......@@ -105,42 +101,31 @@ class LUClusterRenewCrypto(NoHooksLU):
"""
def Exec(self, feedback_fn):
master_uuid = self.cfg.GetMasterNode()
cluster = self.cfg.GetClusterInfo()
server_digest = utils.GetCertificateDigest(
cert_filename=pathutils.NODED_CERT_FILE)
utils.AddNodeToCandidateCerts("%s-SERVER" % master_uuid,
server_digest,
cluster.candidate_certs)
self.cfg.AddNodeToCandidateCerts("%s-SERVER" % master_uuid,
server_digest)
try:
old_master_digest = utils.GetCertificateDigest(
cert_filename=pathutils.NODED_CLIENT_CERT_FILE)
utils.AddNodeToCandidateCerts("%s-OLDMASTER" % master_uuid,
old_master_digest,
cluster.candidate_certs)
self.cfg.AddNodeToCandidateCerts("%s-OLDMASTER" % master_uuid,
old_master_digest)
except IOError:
logging.info("No old certificate available.")
new_master_digest = _UpdateMasterClientCert(self, master_uuid, cluster,
feedback_fn)
new_master_digest = _UpdateMasterClientCert(self, self.cfg, master_uuid)
utils.AddNodeToCandidateCerts(master_uuid,
new_master_digest,
cluster.candidate_certs)
self.cfg.AddNodeToCandidateCerts(master_uuid, new_master_digest)
nodes = self.cfg.GetAllNodesInfo()
for (node_uuid, node_info) in nodes.items():
if node_uuid != master_uuid:
new_digest = CreateNewClientCert(self, node_uuid)
if node_info.master_candidate:
utils.AddNodeToCandidateCerts(node_uuid,
new_digest,
cluster.candidate_certs)
utils.RemoveNodeFromCandidateCerts("%s-SERVER" % master_uuid,
cluster.candidate_certs)
utils.RemoveNodeFromCandidateCerts("%s-OLDMASTER" % master_uuid,
cluster.candidate_certs)
self.cfg.AddNodeToCandidateCerts(node_uuid, new_digest)
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
self.cfg.Update(cluster, feedback_fn)
class LUClusterActivateMasterIp(NoHooksLU):
......@@ -301,8 +286,7 @@ class LUClusterPostInit(LogicalUnit):
self.master_ndparams.get(constants.ND_OVS_LINK, None))
result.Raise("Could not successully configure Open vSwitch")
cluster = self.cfg.GetClusterInfo()
_UpdateMasterClientCert(self, self.master_uuid, cluster, feedback_fn)
_UpdateMasterClientCert(self, self.cfg, self.master_uuid)
return True
......@@ -1532,7 +1516,7 @@ class LUClusterSetParams(LogicalUnit):
if self.op.candidate_pool_size is not None:
self.cluster.candidate_pool_size = self.op.candidate_pool_size
# we need to update the pool size here, otherwise the save will fail
AdjustCandidatePool(self, [], feedback_fn)
AdjustCandidatePool(self, [])
if self.op.max_running_jobs is not None:
self.cluster.max_running_jobs = self.op.max_running_jobs
......
......@@ -460,7 +460,7 @@ def CheckHVParams(lu, node_uuids, hvname, hvparams):
lu.cfg.GetNodeName(node_uuid))
def AdjustCandidatePool(lu, exceptions, feedback_fn):
def AdjustCandidatePool(lu, exceptions):
"""Adjust the candidate pool after node operations.
"""
......@@ -470,9 +470,7 @@ def AdjustCandidatePool(lu, exceptions, feedback_fn):
utils.CommaJoin(node.name for node in mod_list))
for node in mod_list:
lu.context.ReaddNode(node)
cluster = lu.cfg.GetClusterInfo()
AddNodeCertToCandidateCerts(lu, node.uuid, cluster)
lu.cfg.Update(cluster, feedback_fn)
AddNodeCertToCandidateCerts(lu, lu.cfg, node.uuid)
mc_now, mc_max, _ = lu.cfg.GetMasterCandidateStats(exceptions)
if mc_now > mc_max:
lu.LogInfo("Note: more nodes are candidates (%d) than desired (%d)" %
......@@ -1255,13 +1253,15 @@ def IsValidDiskAccessModeCombination(hv, disk_template, mode):
return False
def AddNodeCertToCandidateCerts(lu, node_uuid, cluster):
def AddNodeCertToCandidateCerts(lu, cfg, node_uuid):
"""Add the node's client SSL certificate digest to the candidate certs.
@type lu: L{LogicalUnit}
@param lu: the logical unit
@type cfg: L{ConfigWriter}
@param cfg: the configuration client to use
@type node_uuid: string
@param node_uuid: the node's UUID
@type cluster: C{object.Cluster}
@param cluster: the cluster's configuration
"""
result = lu.rpc.call_node_crypto_tokens(
......@@ -1273,19 +1273,19 @@ def AddNodeCertToCandidateCerts(lu, node_uuid, cluster):
((crypto_type, digest), ) = result.payload
assert crypto_type == constants.CRYPTO_TYPE_SSL_DIGEST
utils.AddNodeToCandidateCerts(node_uuid, digest, cluster.candidate_certs)
cfg.AddNodeToCandidateCerts(node_uuid, digest)
def RemoveNodeCertFromCandidateCerts(node_uuid, cluster):
def RemoveNodeCertFromCandidateCerts(cfg, node_uuid):
"""Removes the node's certificate from the candidate certificates list.
@type cfg: C{config.ConfigWriter}
@param cfg: the cluster's configuration
@type node_uuid: string
@param node_uuid: the node's UUID
@type cluster: C{objects.Cluster}
@param cluster: the cluster's configuration
"""
utils.RemoveNodeFromCandidateCerts(node_uuid, cluster.candidate_certs)
cfg.RemoveNodeFromCandidateCerts(node_uuid)
def CreateNewClientCert(lu, node_uuid, filename=None):
......
......@@ -418,18 +418,12 @@ class LUNodeAdd(LogicalUnit):
self.context.AddNode(self.new_node, self.proc.GetECId())
RedistributeAncillaryFiles(self)
cluster = self.cfg.GetClusterInfo()
# We create a new certificate even if the node is readded
digest = CreateNewClientCert(self, self.new_node.uuid)
if self.new_node.master_candidate:
utils.AddNodeToCandidateCerts(self.new_node.uuid, digest,
cluster.candidate_certs)
self.cfg.Update(cluster, feedback_fn)
self.cfg.AddNodeToCandidateCerts(self.new_node.uuid, digest)
else:
if self.new_node.uuid in cluster.candidate_certs:
utils.RemoveNodeFromCandidateCerts(self.new_node.uuid,
cluster.candidate_certs)
self.cfg.Update(cluster, feedback_fn)
self.cfg.RemoveNodeFromCandidateCerts(self.new_node.uuid, warn_fn=None)
class LUNodeSetParams(LogicalUnit):
......@@ -785,15 +779,14 @@ class LUNodeSetParams(LogicalUnit):
# we locked all nodes, we adjust the CP before updating this node
if self.lock_all:
AdjustCandidatePool(self, [node.uuid], feedback_fn)
AdjustCandidatePool(self, [node.uuid])
cluster = self.cfg.GetClusterInfo()
# if node gets promoted, grant RPC priviledges
if self.new_role == self._ROLE_CANDIDATE:
AddNodeCertToCandidateCerts(self, node.uuid, cluster)
AddNodeCertToCandidateCerts(self, self.cfg, node.uuid)
# if node is demoted, revoke RPC priviledges
if self.old_role == self._ROLE_CANDIDATE:
RemoveNodeCertFromCandidateCerts(node.uuid, cluster)
RemoveNodeCertFromCandidateCerts(self.cfg, node.uuid)
if self.op.secondary_ip:
node.secondary_ip = self.op.secondary_ip
......@@ -1484,7 +1477,7 @@ class LUNodeRemove(LogicalUnit):
"Not owning BGL"
# Promote nodes to master candidate as needed
AdjustCandidatePool(self, [self.node.uuid], feedback_fn)
AdjustCandidatePool(self, [self.node.uuid])
self.context.RemoveNode(self.node)
# Run post hooks on the node before it's removed
......@@ -1502,9 +1495,7 @@ class LUNodeRemove(LogicalUnit):
# Remove node from candidate certificate list
if self.node.master_candidate:
utils.RemoveNodeFromCandidateCerts(self.node.uuid,
cluster.candidate_certs)
self.cfg.Update(cluster, feedback_fn)
self.cfg.RemoveNodeFromCandidateCerts(self.node.uuid)
# Remove node from our /etc/hosts
if cluster.modify_etc_hosts:
......
......@@ -2938,3 +2938,53 @@ class ConfigWriter(object):
return (net_info.name, nodegroup_info.networks[net_uuid])
return (None, None)
@locking.ssynchronized(_config_lock)
def AddNodeToCandidateCerts(self, node_uuid, cert_digest,
info_fn=logging.info, warn_fn=logging.warn):
"""Adds an entry to the candidate certificate map.
@type node_uuid: string
@param node_uuid: the node's UUID
@type cert_digest: string
@param cert_digest: the digest of the node's client SSL certificate
@type info_fn: function
@param info_fn: logging function for information messages
@type warn_fn: function
@param warn_fn: logging function for warning messages
"""
cluster = self._config_data.cluster
if node_uuid in cluster.candidate_certs:
old_cert_digest = cluster.candidate_certs[node_uuid]
if old_cert_digest == cert_digest:
if info_fn is not None:
info_fn("Certificate digest for node %s already in config."
"Not doing anything." % node_uuid)
return
else:
if warn_fn is not None:
warn_fn("Overriding differing certificate digest for node %s"
% node_uuid)
cluster.candidate_certs[node_uuid] = cert_digest
self._WriteConfig()
@locking.ssynchronized(_config_lock)
def RemoveNodeFromCandidateCerts(self, node_uuid,
warn_fn=logging.warn):
"""Removes the entry of the given node in the certificate map.
@type node_uuid: string
@param node_uuid: the node's UUID
@type warn_fn: function
@param warn_fn: logging function for warning messages
"""
cluster = self._config_data.cluster
if node_uuid not in cluster.candidate_certs:
if warn_fn is not None:
warn_fn("Cannot remove certifcate for node %s, because it's not"
" in the candidate map." % node_uuid)
return
del cluster.candidate_certs[node_uuid]
self._WriteConfig()
......@@ -39,57 +39,6 @@ def UuidToInt(uuid):
return uuid_obj.int # pylint: disable=E1101
def AddNodeToCandidateCerts(node_uuid, cert_digest, candidate_certs,
info_fn=logging.info, warn_fn=logging.warn):
"""Adds an entry to the candidate certificate map.
@type node_uuid: string
@param node_uuid: the node's UUID
@type cert_digest: string
@param cert_digest: the digest of the node's client SSL certificate
@type candidate_certs: dict of strings to strings
@param candidate_certs: map of node UUIDs to the digests of their client
SSL certificates, will be manipulated in this function
@type info_fn: function
@param info_fn: logging function for information messages
@type warn_fn: function
@param warn_fn: logging function for warning messages
"""
assert candidate_certs is not None
if node_uuid in candidate_certs:
old_cert_digest = candidate_certs[node_uuid]
if old_cert_digest == cert_digest:
info_fn("Certificate digest for node %s already in config."
"Not doing anything." % node_uuid)
return
else:
warn_fn("Overriding differing certificate digest for node %s"
% node_uuid)
candidate_certs[node_uuid] = cert_digest
def RemoveNodeFromCandidateCerts(node_uuid, candidate_certs,
warn_fn=logging.warn):
"""Removes the entry of the given node in the certificate map.
@type node_uuid: string
@param node_uuid: the node's UUID
@type candidate_certs: dict of strings to strings
@param candidate_certs: map of node UUIDs to the digests of their client
SSL certificates, will be manipulated in this function
@type warn_fn: function
@param warn_fn: logging function for warning messages
"""
if node_uuid not in candidate_certs:
warn_fn("Cannot remove certifcate for node %s, because it's not in the"
"candidate map." % node_uuid)
return
del candidate_certs[node_uuid]
def GetCertificateDigest(cert_filename=pathutils.NODED_CLIENT_CERT_FILE):
"""Reads the SSL certificate and returns the sha1 digest.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment