Commit 90e99856 authored by Adeodato Simo's avatar Adeodato Simo

Add the "alloc_policy" attribute to node groups

This can be set at group creation time and via OpSetGroupParams. The default
is "preferred", and existing node groups from previous Ganeti version will
get the attribute set to this value.
Signed-off-by: default avatarAdeodato Simo <dato@google.com>
Reviewed-by: default avatarGuido Trotter <ultrotter@google.com>
parent 4da7909a
......@@ -181,6 +181,16 @@ Adds a node group to the cluster.
:pre-execution: master node
:post-execution: master node
OP_GROUP_SET_PARAMS
+++++++++++++++++++
Changes a node group's parameters.
:directory: group-modify
:env. vars: GROUP_NAME, NEW_ALLOC_POLICY
:pre-execution: master node
:post-execution: master node
OP_REMOVE_GROUP
+++++++++++++++
......
......@@ -48,6 +48,7 @@ __all__ = [
# Command line options
"ADD_UIDS_OPT",
"ALLOCATABLE_OPT",
"ALLOC_POLICY_OPT",
"ALL_OPT",
"AUTO_PROMOTE_OPT",
"AUTO_REPLACE_OPT",
......@@ -1117,6 +1118,10 @@ NODE_PARAMS_OPT = cli_option("--node-parameters", dest="ndparams",
type="keyval", default=None,
help="Node parameters")
ALLOC_POLICY_OPT = cli_option("--alloc-policy", dest="alloc_policy",
action="store", metavar="POLICY", default=None,
help="Allocation policy for the node group")
#: Options provided by all commands
COMMON_OPTS = [DEBUG_OPT]
......
......@@ -31,12 +31,12 @@ from ganeti import utils
#: default list of fields for L{ListGroups}
_LIST_DEF_FIELDS = ["name", "node_cnt", "pinst_cnt"]
_LIST_DEF_FIELDS = ["name", "node_cnt", "pinst_cnt", "alloc_policy"]
#: headers (and full field list) for L{ListGroups}
_LIST_HEADERS = {
"name": "Group", "uuid": "UUID",
"name": "Group", "uuid": "UUID", "alloc_policy": "AllocPolicy",
"node_cnt": "Nodes", "node_list": "NodeList",
"pinst_cnt": "Instances", "pinst_list": "InstanceList",
"ctime": "CTime", "mtime": "MTime", "serial_no": "SerialNo",
......@@ -54,7 +54,8 @@ def AddGroup(opts, args):
"""
(group_name,) = args
op = opcodes.OpAddGroup(group_name=group_name, ndparams=opts.ndparams)
op = opcodes.OpAddGroup(group_name=group_name, ndparams=opts.ndparams,
alloc_policy=opts.alloc_policy)
SubmitOpCode(op, opts=opts)
......@@ -118,13 +119,15 @@ def SetGroupParams(opts, args):
"""
all_changes = {
"ndparams": opts.ndparams,
"alloc_policy": opts.alloc_policy,
}
if all_changes.values().count(None) == len(all_changes):
ToStderr("Please give at least one of the parameters.")
return 1
op = opcodes.OpSetGroupParams(group_name=args[0], **all_changes)
op = opcodes.OpSetGroupParams(group_name=args[0], # pylint: disable-msg=W0142
**all_changes)
result = SubmitOrSend(op, opts)
if result:
......@@ -167,7 +170,7 @@ def RenameGroup(opts, args):
commands = {
"add": (
AddGroup, ARGS_ONE_GROUP, [DRY_RUN_OPT, NODE_PARAMS_OPT],
AddGroup, ARGS_ONE_GROUP, [DRY_RUN_OPT, ALLOC_POLICY_OPT, NODE_PARAMS_OPT],
"<group_name>", "Add a new node group to the cluster"),
"list": (
ListGroups, ARGS_MANY_GROUPS,
......@@ -178,7 +181,7 @@ commands = {
(utils.CommaJoin(_LIST_HEADERS), utils.CommaJoin(_LIST_DEF_FIELDS))),
"modify": (
SetGroupParams, ARGS_ONE_GROUP,
[DRY_RUN_OPT, SUBMIT_OPT, NODE_PARAMS_OPT],
[DRY_RUN_OPT, SUBMIT_OPT, ALLOC_POLICY_OPT, NODE_PARAMS_OPT],
"<group_name>", "Alters the parameters of a node group"),
"remove": (
RemoveGroup, ARGS_ONE_GROUP, [DRY_RUN_OPT],
......
......@@ -10179,6 +10179,8 @@ class LUAddGroup(LogicalUnit):
_OP_PARAMS = [
_PGroupName,
("ndparams", None, ht.TOr(ht.TDict, ht.TNone)),
("alloc_policy", None, ht.TOr(ht.TNone,
ht.TElemOf(constants.VALID_ALLOC_POLICIES))),
]
REQ_BGL = False
......@@ -10227,6 +10229,7 @@ class LUAddGroup(LogicalUnit):
"""
group_obj = objects.NodeGroup(name=self.op.group_name, members=[],
uuid=self.group_uuid,
alloc_policy=self.op.alloc_policy,
ndparams=self.op.ndparams)
self.cfg.AddNodeGroup(group_obj, self.proc.GetECId(), check_uuid=False)
......@@ -10247,7 +10250,8 @@ class LUQueryGroups(NoHooksLU):
_FIELDS_DYNAMIC = utils.FieldSet()
_SIMPLE_FIELDS = ["name", "uuid", "ctime", "mtime", "serial_no"]
_SIMPLE_FIELDS = ["name", "uuid", "alloc_policy",
"ctime", "mtime", "serial_no"]
_FIELDS_STATIC = utils.FieldSet(
"node_cnt", "node_list", "pinst_cnt", "pinst_list", *_SIMPLE_FIELDS)
......@@ -10345,12 +10349,14 @@ class LUSetGroupParams(LogicalUnit):
"""Modifies the parameters of a node group.
"""
HPATH = None
HTYPE = None
HPATH = "group-modify"
HTYPE = constants.HTYPE_GROUP
_OP_PARAMS = [
_PGroupName,
("ndparams", None, ht.TOr(ht.TDict, ht.TNone)),
("alloc_policy", None, ht.TOr(ht.TNone,
ht.TElemOf(constants.VALID_ALLOC_POLICIES))),
]
REQ_BGL = False
......@@ -10358,6 +10364,7 @@ class LUSetGroupParams(LogicalUnit):
def CheckArguments(self):
all_changes = [
self.op.ndparams,
self.op.alloc_policy,
]
if all_changes.count(None) == len(all_changes):
......@@ -10386,6 +10393,17 @@ class LUSetGroupParams(LogicalUnit):
utils.ForceDictType(self.op.ndparams, constants.NDS_PARAMETER_TYPES)
self.new_ndparams = self.group.SimpleFillND(self.op.ndparams)
def BuildHooksEnv(self):
"""Build hooks env.
"""
env = {
"GROUP_NAME": self.op.group_name,
"NEW_ALLOC_POLICY": self.op.alloc_policy,
}
mn = self.cfg.GetMasterNode()
return env, [mn], [mn]
def Exec(self, feedback_fn):
"""Modifies the node group.
......@@ -10396,6 +10414,9 @@ class LUSetGroupParams(LogicalUnit):
self.group.ndparams = self.new_ndparams
result.append(("ndparams", str(self.group.ndparams)))
if self.op.alloc_policy:
self.group.alloc_policy = self.op.alloc_policy
self.cfg.Update(self.group, feedback_fn)
return result
......
......@@ -868,6 +868,9 @@ class ConfigWriter:
def AddNodeGroup(self, group, ec_id, check_uuid=True):
"""Add a node group to the configuration.
This method calls group.UpgradeConfig() to fill any missing attributes
according to their default values.
@type group: L{objects.NodeGroup}
@param group: the NodeGroup object to add
@type ec_id: string
......@@ -895,6 +898,7 @@ class ConfigWriter:
group.serial_no = 1
group.ctime = group.mtime = time.time()
group.UpgradeConfig()
self._config_data.nodegroups[group.uuid] = group
self._config_data.cluster.serial_no += 1
......
......@@ -1202,3 +1202,13 @@ PGREP = "pgrep"
# Name of the node group that gets created at cluster init or upgrade
INITIAL_NODE_GROUP_NAME = "default"
# Possible values for NodeGroup.alloc_policy
ALLOC_POLICY_PREFERRED = "preferred"
ALLOC_POLICY_LAST_RESORT = "last_resort"
ALLOC_POLICY_UNALLOCABLE = "unallocable"
VALID_ALLOC_POLICIES = [
ALLOC_POLICY_PREFERRED,
ALLOC_POLICY_LAST_RESORT,
ALLOC_POLICY_UNALLOCABLE,
]
......@@ -956,6 +956,7 @@ class NodeGroup(ConfigObject):
"members",
"ndparams",
"serial_no",
"alloc_policy",
] + _TIMESTAMPS + _UUID
def ToDict(self):
......@@ -990,6 +991,9 @@ class NodeGroup(ConfigObject):
if self.serial_no is None:
self.serial_no = 1
if self.alloc_policy is None:
self.alloc_policy = constants.ALLOC_POLICY_PREFERRED
# We only update mtime, and not ctime, since we would not be able to provide
# a correct value for creation time.
if self.mtime is None:
......
......@@ -728,6 +728,7 @@ class OpAddGroup(OpCode):
__slots__ = [
"group_name",
"ndparams",
"alloc_policy",
]
......@@ -744,6 +745,7 @@ class OpSetGroupParams(OpCode):
__slots__ = [
"group_name",
"ndparams",
"alloc_policy",
]
......
......@@ -1408,11 +1408,13 @@ class GanetiRapiClient(object):
"/%s/groups/%s" % (GANETI_RAPI_VERSION, group),
None, None)
def CreateGroup(self, name, dry_run=False):
def CreateGroup(self, name, alloc_policy=None, dry_run=False):
"""Creates a new node group.
@type name: str
@param name: the name of node group to create
@type alloc_policy: str
@param alloc_policy: the desired allocation policy for the group, if any
@type dry_run: bool
@param dry_run: whether to peform a dry run
......@@ -1426,6 +1428,7 @@ class GanetiRapiClient(object):
body = {
"name": name,
"alloc_policy": alloc_policy
}
return self._SendRequest(HTTP_POST, "/%s/groups" % GANETI_RAPI_VERSION,
......
......@@ -74,6 +74,7 @@ N_FIELDS = ["name", "offline", "master_candidate", "drained",
] + _COMMON_FIELDS
G_FIELDS = ["name", "uuid",
"alloc_policy",
"node_cnt", "node_list",
"ctime", "mtime", "serial_no",
] # "tags" is missing to be able to use _COMMON_FIELDS here.
......@@ -531,6 +532,21 @@ class R_2_nodes_name_storage_repair(baserlib.R_Generic):
return baserlib.SubmitJob([op])
def _ParseCreateGroupRequest(data, dry_run):
"""Parses a request for creating a node group.
@rtype: L{opcodes.OpAddGroup}
@return: Group creation opcode
"""
group_name = baserlib.CheckParameter(data, "name")
alloc_policy = baserlib.CheckParameter(data, "alloc_policy", default=None)
return opcodes.OpAddGroup(group_name=group_name,
alloc_policy=alloc_policy,
dry_run=dry_run)
class R_2_groups(baserlib.R_Generic):
"""/2/groups resource.
......@@ -557,8 +573,7 @@ class R_2_groups(baserlib.R_Generic):
"""
baserlib.CheckType(self.request_body, dict, "Body contents")
group_name = baserlib.CheckParameter(self.request_body, "name")
op = opcodes.OpAddGroup(group_name=group_name, dry_run=self.dryRun())
op = _ParseCreateGroupRequest(self.request_body, self.dryRun())
return baserlib.SubmitJob([op])
......
......@@ -25,6 +25,7 @@ ADD
| **add**
| [--node-parameters=*NDPARAMS*]
| [--alloc-policy=*POLICY*]
| {*group*}
Creates a new group with the given name. The node group will be
......@@ -34,17 +35,36 @@ The ``--node-parameters`` option allows you to set default node
parameters for nodes in the group. Please see **ganeti**(7) for more
information about supported key=value pairs.
The ``--alloc-policy`` option allows you to set an allocation policy for
the group at creation time. Possible values are:
unallocable
nodes in the group should not be candidates for instance allocation,
and the operation (e.g., instance creation) should fail if only
groups in this state could be found to satisfy the requirements.
last_resort
nodes in the group should not be used for instance allocations,
unless this would be the only way to have the operation succeed.
preferred
nodes in the group can be used freely for allocation of instances
(this is the default). Note that prioritization among groups in this
state will be deferred to the iallocator plugin that's being used.
MODIFY
~~~~~~
| **modify**
| [--node-parameters=*NDPARAMS*]
| [--alloc-policy=*POLICY*]
| {*group*}
Modifies some parameters from the node group.
The ``--node-parameters`` option is documented in the **add** command
above.
The ``--node-parameters`` and ``--alloc-policy`` optiosn are documented
in the **add** command above.
REMOVE
~~~~~~
......@@ -93,6 +113,9 @@ pinst_cnt
pinst_list
the list of primary instances in the group
alloc_policy
the current allocation policy for the group
ctime
the creation time of the group; note that this field contains spaces
and as such it's harder to parse
......
......@@ -96,6 +96,7 @@ NODE_FIELDS = ("name", "dtotal", "dfree",
GROUP_FIELDS = frozenset([
"name", "uuid",
"alloc_policy",
"node_cnt", "node_list",
])
......
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