From 4b7735f913d2c5ca556098f5a33f849e667f4f16 Mon Sep 17 00:00:00 2001 From: Iustin Pop <iustin@google.com> Date: Tue, 2 Dec 2008 05:06:08 +0000 Subject: [PATCH] Add cluster candidate pool size parameter This patch adds a new cluster paramater "candidate_pool_size" which tracks the desired size of the list of nodes with the master_candidate flag set. Reviewed-by: imsnah --- lib/cmdlib.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ lib/objects.py | 1 + lib/opcodes.py | 8 +++++++- scripts/gnt-cluster | 11 +++++++++-- 4 files changed, 61 insertions(+), 3 deletions(-) diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 491e695f8..c6850ff2f 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -32,6 +32,7 @@ import re import platform import logging import copy +import random from ganeti import ssh from ganeti import utils @@ -1186,6 +1187,21 @@ class LUSetClusterParams(LogicalUnit): _OP_REQP = [] REQ_BGL = False + def CheckParameters(self): + """Check parameters + + """ + if not hasattr(self.op, "candidate_pool_size"): + self.op.candidate_pool_size = None + if self.op.candidate_pool_size is not None: + try: + self.op.candidate_pool_size = int(self.op.candidate_pool_size) + except ValueError, err: + raise errors.OpPrereqError("Invalid candidate_pool_size value: %s" % + str(err)) + if self.op.candidate_pool_size < 1: + raise errors.OpPrereqError("At least one master candidate needed") + def ExpandNames(self): # FIXME: in the future maybe other cluster params won't require checking on # all nodes to be modified. @@ -1284,8 +1300,35 @@ class LUSetClusterParams(LogicalUnit): self.cluster.enabled_hypervisors = self.op.enabled_hypervisors if self.op.beparams: self.cluster.beparams[constants.BEGR_DEFAULT] = self.new_beparams + if self.op.candidate_pool_size is not None: + self.cluster.candidate_pool_size = self.op.candidate_pool_size + self.cfg.Update(self.cluster) + # we want to update nodes after the cluster so that if any errors + # happen, we have recorded and saved the cluster info + if self.op.candidate_pool_size is not None: + node_info = self.cfg.GetAllNodesInfo().values() + num_candidates = len([node for node in node_info + if node.master_candidate]) + num_nodes = len(node_info) + if num_candidates < self.op.candidate_pool_size: + random.shuffle(node_info) + for node in node_info: + if num_candidates >= self.op.candidate_pool_size: + break + if node.master_candidate: + continue + node.master_candidate = True + self.LogInfo("Promoting node %s to master candidate", node.name) + self.cfg.Update(node) + self.context.ReaddNode(node) + num_candidates += 1 + elif num_candidates > self.op.candidate_pool_size: + self.LogInfo("Note: more nodes are candidates (%d) than the new value" + " of candidate_pool_size (%d)" % + (num_candidates, self.op.candidate_pool_size)) + def _WaitForSync(lu, instance, oneshot=False, unlock=False): """Sleep and poll for an instance's disk to sync. @@ -2058,6 +2101,7 @@ class LUQueryClusterInfo(NoHooksLU): "enabled_hypervisors": cluster.enabled_hypervisors, "hvparams": cluster.hvparams, "beparams": cluster.beparams, + "candidate_pool_size": cluster.candidate_pool_size, } return result diff --git a/lib/objects.py b/lib/objects.py index 7e8de2a6d..abfeff125 100644 --- a/lib/objects.py +++ b/lib/objects.py @@ -707,6 +707,7 @@ class Cluster(TaggableObject): "enabled_hypervisors", "hvparams", "beparams", + "candidate_pool_size", ] def ToDict(self): diff --git a/lib/opcodes.py b/lib/opcodes.py index c0b88a91a..958ee4261 100644 --- a/lib/opcodes.py +++ b/lib/opcodes.py @@ -255,7 +255,13 @@ class OpSetClusterParams(OpCode): """ OP_ID = "OP_CLUSTER_SET_PARAMS" - __slots__ = ["vg_name", "enabled_hypervisors", "hvparams", "beparams"] + __slots__ = [ + "vg_name", + "enabled_hypervisors", + "hvparams", + "beparams", + "candidate_pool_size", + ] # node opcodes diff --git a/scripts/gnt-cluster b/scripts/gnt-cluster index fcf0fc91e..53cb6a38c 100755 --- a/scripts/gnt-cluster +++ b/scripts/gnt-cluster @@ -238,6 +238,9 @@ def ShowClusterConfig(opts, args): ToStdout(" %s: %s", item, val) ToStdout("Cluster parameters:") + ToStdout(" - candidate pool size: %s", result["candidate_pool_size"]) + + ToStdout("Default instance parameters:") for gr_name, gr_dict in result["beparams"].items(): ToStdout(" - %s:", gr_name) for item, val in gr_dict.iteritems(): @@ -448,7 +451,7 @@ def SetClusterParams(opts, args): """ if not (not opts.lvm_storage or opts.vg_name or opts.enabled_hypervisors or opts.hvparams or - opts.beparams): + opts.beparams or opts.candidate_pool_size is not None): ToStderr("Please give at least one of the parameters.") return 1 @@ -471,7 +474,8 @@ def SetClusterParams(opts, args): op = opcodes.OpSetClusterParams(vg_name=opts.vg_name, enabled_hypervisors=hvlist, hvparams=hvparams, - beparams=beparams) + beparams=beparams, + candidate_pool_size=opts.candidate_pool_size) SubmitOpCode(op) return 0 @@ -636,6 +640,9 @@ commands = { keyval_option("-B", "--backend-parameters", dest="beparams", type="keyval", default={}, help="Backend parameters"), + make_option("-C", "--candidate-pool-size", default=None, + help="Set the candidate pool size", + dest="candidate_pool_size", type="int"), ], "[opts...]", "Alters the parameters of the cluster"), -- GitLab