From 4fae38c585c6ba83fb4649d324e04c8e5b217899 Mon Sep 17 00:00:00 2001 From: Guido Trotter <ultrotter@google.com> Date: Tue, 27 Oct 2009 15:27:44 -0400 Subject: [PATCH] ConfigWriter: move _temporary_ids to reservation In order to do this we need to pass a job id when reserving a resource. We have one during _EnsureUUIDs because we passed it in from AddNode and AddInstance. During config upgrade we use a fake job ID which we then cleanup. We can delete the _CleanupTemporaryIDs code, since the cleanup is going to be done at job finish time by mcpu. Signed-off-by: Guido Trotter <ultrotter@google.com> Reviewed-by: Iustin Pop <iustin@google.com> --- lib/cmdlib.py | 2 +- lib/config.py | 49 +++++++++++++++++++------------------------------ 2 files changed, 20 insertions(+), 31 deletions(-) diff --git a/lib/cmdlib.py b/lib/cmdlib.py index abf9e70aa..31d0b6173 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -5311,7 +5311,7 @@ def _GenerateUniqueNames(lu, exts): """ results = [] for val in exts: - new_id = lu.cfg.GenerateUniqueID() + new_id = lu.cfg.GenerateUniqueID(lu.proc.GetECId()) results.append("%s%s" % (new_id, val)) return results diff --git a/lib/config.py b/lib/config.py index 3f5119f3e..58b412ce2 100644 --- a/lib/config.py +++ b/lib/config.py @@ -47,6 +47,9 @@ from ganeti import serializer _config_lock = locking.SharedLock() +# job id used for resource management at config upgrade time +_UPGRADE_CONFIG_JID="jid-cfg-upgrade" + def _ValidateConfig(data): """Verifies that a configuration objects looks valid. @@ -132,7 +135,7 @@ class ConfigWriter: self._cfg_file = constants.CLUSTER_CONF_FILE else: self._cfg_file = cfg_file - self._temporary_ids = set() + self._temporary_ids = TemporaryReservationManager() self._temporary_drbds = {} self._temporary_macs = set() # Note: in order to prevent errors when resolving our name in @@ -225,14 +228,14 @@ class ConfigWriter: """ existing = set() if include_temporary: - existing.update(self._temporary_ids) + existing.update(self._temporary_ids.GetReserved()) existing.update(self._AllLVs()) existing.update(self._config_data.instances.keys()) existing.update(self._config_data.nodes.keys()) existing.update([i.uuid for i in self._AllUUIDObjects() if i.uuid]) return existing - def _GenerateUniqueID(self): + def _GenerateUniqueID(self, ec_id): """Generate an unique UUID. This checks the current node, instances and disk names for @@ -242,33 +245,20 @@ class ConfigWriter: @return: the unique id """ - existing = self._AllIDs(include_temporary=True) - retries = 64 - while retries > 0: - unique_id = utils.NewUUID() - if unique_id not in existing and unique_id is not None: - break - else: - raise errors.ConfigurationError("Not able generate an unique ID" - " (last tried ID: %s" % unique_id) - self._temporary_ids.add(unique_id) - return unique_id + existing = self._AllIDs(include_temporary=False) + return self._temporary_ids.Generate(existing, utils.NewUUID, ec_id) @locking.ssynchronized(_config_lock, shared=1) - def GenerateUniqueID(self): + def GenerateUniqueID(self, ec_id): """Generate an unique ID. This is just a wrapper over the unlocked version. - """ - return self._GenerateUniqueID() - - def _CleanupTemporaryIDs(self): - """Cleanups the _temporary_ids structure. + @type ec_id: string + @param ec_id: unique id for the job to reserve the id to """ - existing = self._AllIDs(include_temporary=False) - self._temporary_ids = self._temporary_ids - existing + return self._GenerateUniqueID(ec_id) def _AllMACs(self): """Return all MACs present in the config. @@ -821,7 +811,7 @@ class ConfigWriter: """ if not item.uuid: - item.uuid = self._GenerateUniqueID() + item.uuid = self._GenerateUniqueID(ec_id) elif item.uuid in self._AllIDs(temporary=True): raise errors.ConfigurationError("Cannot add '%s': UUID already in use" % (item.name, item.uuid)) @@ -1205,10 +1195,14 @@ class ConfigWriter: modified = False for item in self._AllUUIDObjects(): if item.uuid is None: - item.uuid = self._GenerateUniqueID() + item.uuid = self._GenerateUniqueID(_UPGRADE_CONFIG_JID) modified = True if modified: self._WriteConfig() + # This is ok even if it acquires the internal lock, as _UpgradeConfig is + # only called at config init time, without the lock held + self.DropECReservations(_UPGRADE_CONFIG_JID) + def _DistributeConfig(self, feedback_fn): """Distribute the configuration to the other nodes. @@ -1260,11 +1254,6 @@ class ConfigWriter: """ assert feedback_fn is None or callable(feedback_fn) - # First, cleanup the _temporary_ids set, if an ID is now in the - # other objects it should be discarded to prevent unbounded growth - # of that structure - self._CleanupTemporaryIDs() - # Warn on config errors, but don't abort the save - the # configuration has already been modified, and we can't revert; # the best we can do is to warn the user and save as is, leaving @@ -1441,5 +1430,5 @@ class ConfigWriter: """Drop per-execution-context reservations """ - pass + self._temporary_ids.DropECReservations(ec_id) -- GitLab