#
#
-# 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
from ganeti import rpc
from ganeti import objects
from ganeti import serializer
+from ganeti import uidpool
+from ganeti import netutils
-_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"
# _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.HostInfo().name
self._last_cluster_serial = -1
self._OpenConfig()
if invalid_hvs:
result.append("enabled hypervisors contains invalid entries: %s" %
invalid_hvs)
+ missing_hvp = (set(data.cluster.enabled_hypervisors) -
+ set(data.cluster.hvparams.keys()))
+ if missing_hvp:
+ result.append("hypervisor parameters missing for the enabled"
+ " hypervisor(s) %s" % utils.CommaJoin(missing_hvp))
if data.cluster.master_node not in data.nodes:
result.append("cluster has invalid primary node '%s'" %
if [node.master_candidate, node.drained, node.offline].count(True) > 1:
result.append("Node %s state is invalid: master_candidate=%s,"
" drain=%s, offline=%s" %
- (node.name, node.master_candidate, node.drain,
+ (node.name, node.master_candidate, node.drained,
node.offline))
# drbd minors check
"""
return self._config_data.cluster.rsahostkeypub
+ @locking.ssynchronized(_config_lock, shared=1)
+ def GetDefaultIAllocator(self):
+ """Get the default instance allocator for this cluster.
+
+ """
+ return self._config_data.cluster.default_iallocator
+
@locking.ssynchronized(_config_lock)
def AddInstance(self, instance, ec_id):
"""Add an instance to the config.
This is because some data elements need uniqueness across the
whole configuration, etc.
- @warning: this function will call L{_WriteConfig()}, so it needs
- to either be called with the lock held or from a safe place
- (the constructor)
+ @warning: this function will call L{_WriteConfig()}, but also
+ L{DropECReservations} so it needs to be called only from a
+ "safe" place (the constructor). If one wanted to call it with
+ the lock held, a DropECReservationUnlocked would need to be
+ created first, to avoid causing deadlock.
"""
modified = False
hypervisor_list = fn(cluster.enabled_hypervisors)
+ uid_pool = uidpool.FormatUidPool(cluster.uid_pool, separator="\n")
+
return {
constants.SS_CLUSTER_NAME: cluster.cluster_name,
constants.SS_CLUSTER_TAGS: cluster_tags,
constants.SS_INSTANCE_LIST: instance_data,
constants.SS_RELEASE_VERSION: constants.RELEASE_VERSION,
constants.SS_HYPERVISOR_LIST: hypervisor_list,
+ constants.SS_MAINTAIN_NODE_HEALTH: str(cluster.maintain_node_health),
+ constants.SS_UID_POOL: uid_pool,
}
@locking.ssynchronized(_config_lock, shared=1)
self._WriteConfig()
@locking.ssynchronized(_config_lock, shared=1)
+ def GetDRBDHelper(self):
+ """Return DRBD usermode helper.
+
+ """
+ return self._config_data.cluster.drbd_usermode_helper
+
+ @locking.ssynchronized(_config_lock)
+ def SetDRBDHelper(self, drbd_helper):
+ """Set DRBD usermode helper.
+
+ """
+ self._config_data.cluster.drbd_usermode_helper = drbd_helper
+ self._config_data.cluster.serial_no += 1
+ self._WriteConfig()
+
+ @locking.ssynchronized(_config_lock, shared=1)
def GetMACPrefix(self):
"""Return the mac prefix.
"""
return self._config_data.cluster
+ @locking.ssynchronized(_config_lock, shared=1)
+ def HasAnyDiskOfType(self, dev_type):
+ """Check if in there is at disk of the given type in the configuration.
+
+ """
+ return self._config_data.HasAnyDiskOfType(dev_type)
+
@locking.ssynchronized(_config_lock)
def Update(self, target, feedback_fn):
"""Notify function to be called after updates.