node.offline))
# nodegroups checks
+ nodegroups_names = set()
for nodegroup_uuid in data.nodegroups:
nodegroup = data.nodegroups[nodegroup_uuid]
if nodegroup.uuid != nodegroup_uuid:
result.append("nodegroup '%s' (uuid: '%s') indexed by wrong uuid '%s'"
% (nodegroup.name, nodegroup.uuid, nodegroup_uuid))
+ if nodegroup.name in nodegroups_names:
+ result.append("duplicate nodegroup name '%s'" % nodegroup.name)
+ else:
+ nodegroups_names.add(nodegroup.name)
# drbd minors check
_, duplicates = self._UnlockedComputeDRBDMap()
"""
return self._config_data.cluster.primary_ip_family
+ @locking.ssynchronized(_config_lock, shared=1)
+ def LookupNodeGroup(self, target):
+ """Lookup a node group.
+
+ @type target: string or None
+ @param target: group name or uuid or None to look for the default
+ @rtype: string
+ @return: nodegroup uuid
+ @raises errors.OpPrereqError: when the target group cannot be found
+
+ """
+ if target is None:
+ if len(self._config_data.nodegroups) != 1:
+ raise errors.OpPrereqError("More than one nodegroup exists. Target"
+ " group must be specified explicitely.")
+ else:
+ return self._config_data.nodegroups.keys()[0]
+ if target in self._config_data.nodegroups:
+ return target
+ for nodegroup in self._config_data.nodegroups.values():
+ if nodegroup.name == target:
+ return nodegroup.uuid
+ raise errors.OpPrereqError("Nodegroup '%s' not found", target)
+
@locking.ssynchronized(_config_lock)
def AddInstance(self, instance, ec_id):
"""Add an instance to the config.
node.serial_no = 1
node.ctime = node.mtime = time.time()
+ self._UnlockedAddNodeToGroup(node.name, node.nodegroup)
self._config_data.nodes[node.name] = node
self._config_data.cluster.serial_no += 1
self._WriteConfig()
if node_name not in self._config_data.nodes:
raise errors.ConfigurationError("Unknown node '%s'" % node_name)
+ self._UnlockedRemoveNodeFromGroup(self._config_data.nodes[node_name])
del self._config_data.nodes[node_name]
self._config_data.cluster.serial_no += 1
self._WriteConfig()
return mod_list
+ def _UnlockedAddNodeToGroup(self, node_name, nodegroup_uuid):
+ """Add a given node to the specified group.
+
+ """
+ if nodegroup_uuid not in self._config_data.nodegroups:
+ # This can happen if a node group gets deleted between its lookup and
+ # when we're adding the first node to it, since we don't keep a lock in
+ # the meantime. It's ok though, as we'll fail cleanly if the node group
+ # is not found anymore.
+ raise errors.OpExecError("Unknown nodegroup: %s" % nodegroup_uuid)
+ if node_name not in self._config_data.nodegroups[nodegroup_uuid].members:
+ self._config_data.nodegroups[nodegroup_uuid].members.append(node_name)
+
+ def _UnlockedRemoveNodeFromGroup(self, node):
+ """Remove a given node from its group.
+
+ """
+ nodegroup = node.nodegroup
+ if nodegroup not in self._config_data.nodegroups:
+ logging.warning("Warning: node '%s' has a non-existing nodegroup '%s'"
+ " (while being removed from it)", node.name, nodegroup)
+ nodegroup_obj = self._config_data.nodegroups[nodegroup]
+ if node.name not in nodegroup_obj.members:
+ logging.warning("Warning: node '%s' not a member of its nodegroup '%s'"
+ " (while being removed from it)", node.name, nodegroup)
+ else:
+ nodegroup_obj.members.remove(node.name)
+
def _BumpSerialNo(self):
"""Bump up the serial number of the config.
)
self._config_data.nodegroups[default_nodegroup_uuid] = default_nodegroup
modified = True
+ for node in self._config_data.nodes.values():
+ if not node.nodegroup:
+ node.nodegroup = self.LookupNodeGroup(None)
+ modified = True
+ # This is technically *not* an upgrade, but needs to be done both when
+ # nodegroups are being added, and upon normally loading the config,
+ # because the members list of a node group is discarded upon
+ # serializing/deserializing the object.
+ self._UnlockedAddNodeToGroup(node.name, node.nodegroup)
if modified:
self._WriteConfig()
# This is ok even if it acquires the internal lock, as _UpgradeConfig is
uid_pool = uidpool.FormatUidPool(cluster.uid_pool, separator="\n")
+ nodegroups = ["%s %s" % (nodegroup.uuid, nodegroup.name) for nodegroup in
+ self._config_data.nodegroups.values()]
+ nodegroups_data = fn(utils.NiceSort(nodegroups))
+
return {
constants.SS_CLUSTER_NAME: cluster.cluster_name,
constants.SS_CLUSTER_TAGS: cluster_tags,
constants.SS_HYPERVISOR_LIST: hypervisor_list,
constants.SS_MAINTAIN_NODE_HEALTH: str(cluster.maintain_node_health),
constants.SS_UID_POOL: uid_pool,
+ constants.SS_NODEGROUPS: nodegroups_data,
}
@locking.ssynchronized(_config_lock, shared=1)