#
#
-# Copyright (C) 2006, 2007 Google Inc.
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
"""
+# pylint: disable-msg=R0904
+# R0904: Too many public methods
+
import os
import random
import logging
from ganeti import objects
from ganeti import serializer
from ganeti import uidpool
+from ganeti import netutils
+from ganeti import runtime
-_config_lock = locking.SharedLock()
+_config_lock = locking.SharedLock("ConfigWriter")
# job id used for resource management at config upgrade time
_UPGRADE_CONFIG_JID = "jid-cfg-upgrade"
@ivar _all_rms: a list of all temporary reservation managers
"""
- def __init__(self, cfg_file=None, offline=False):
+ def __init__(self, cfg_file=None, offline=False, _getents=runtime.GetEnts):
self.write_count = 0
self._lock = _config_lock
self._config_data = None
self._cfg_file = constants.CLUSTER_CONF_FILE
else:
self._cfg_file = cfg_file
+ self._getents = _getents
self._temporary_ids = TemporaryReservationManager()
self._temporary_drbds = {}
self._temporary_macs = TemporaryReservationManager()
# _DistributeConfig, we compute it here once and reuse it; it's
# better to raise an error before starting to modify the config
# file than after it was modified
- self._my_hostname = utils.HostInfo().name
+ self._my_hostname = netutils.Hostname.GetSysName()
self._last_cluster_serial = -1
self._OpenConfig()
(node.name, node.master_candidate, node.drain,
node.offline))
+ # nodegroups checks
+ 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))
+
# drbd minors check
_, duplicates = self._UnlockedComputeDRBDMap()
for node, minor, instance_a, instance_b in duplicates:
"""
return self._config_data.cluster.default_iallocator
+ @locking.ssynchronized(_config_lock, shared=1)
+ def GetPrimaryIPFamily(self):
+ """Get cluster primary ip family.
+
+ @return: primary ip family
+
+ """
+ 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.
"""
return (self._config_data.instances.values() +
self._config_data.nodes.values() +
+ self._config_data.nodegroups.values() +
[self._config_data.cluster])
def _OpenConfig(self):
if item.uuid is None:
item.uuid = self._GenerateUniqueID(_UPGRADE_CONFIG_JID)
modified = True
+ if not self._config_data.nodegroups:
+ default_nodegroup_uuid = self._GenerateUniqueID(_UPGRADE_CONFIG_JID)
+ default_nodegroup = objects.NodeGroup(
+ uuid=default_nodegroup_uuid,
+ name="default",
+ members=[],
+ )
+ self._config_data.nodegroups[default_nodegroup_uuid] = default_nodegroup
+ modified = True
if modified:
self._WriteConfig()
# This is ok even if it acquires the internal lock, as _UpgradeConfig is
self._BumpSerialNo()
txt = serializer.Dump(self._config_data.ToDict())
- utils.WriteFile(destination, data=txt)
+ getents = self._getents()
+ utils.WriteFile(destination, data=txt, gid=getents.confd_gid, mode=0640)
self.write_count += 1
constants.SS_NODE_SECONDARY_IPS: node_snd_ips_data,
constants.SS_OFFLINE_NODES: off_data,
constants.SS_ONLINE_NODES: on_data,
+ constants.SS_PRIMARY_IP_FAMILY: str(cluster.primary_ip_family),
constants.SS_INSTANCE_LIST: instance_data,
constants.SS_RELEASE_VERSION: constants.RELEASE_VERSION,
constants.SS_HYPERVISOR_LIST: hypervisor_list,
}
@locking.ssynchronized(_config_lock, shared=1)
+ def GetSsconfValues(self):
+ """Wrapper using lock around _UnlockedGetSsconf().
+
+ """
+ return self._UnlockedGetSsconfValues()
+
+ @locking.ssynchronized(_config_lock, shared=1)
def GetVGName(self):
"""Return the volume group name.