Commit 45f62156 authored by Bernardo Dal Seno's avatar Bernardo Dal Seno
Browse files

Upgrades made on loading the configuration are always saved



Before, only some upgrades were written back to the configuration file. A
little refactoring of _UpgradeConfig() has been done to write unit tests.
Signed-off-by: default avatarBernardo Dal Seno <bdalseno@google.com>
Reviewed-by: default avatarGuido Trotter <ultrotter@google.com>
parent 7f5edc60
......@@ -34,6 +34,7 @@ much memory.
# pylint: disable=R0904
# R0904: Too many public methods
import copy
import os
import random
import logging
......@@ -2033,24 +2034,22 @@ class ConfigWriter:
(data.cluster.master_node, self._my_hostname))
raise errors.ConfigurationError(msg)
# Upgrade configuration if needed
data.UpgradeConfig()
self._config_data = data
# reset the last serial as -1 so that the next write will cause
# ssconf update
self._last_cluster_serial = -1
# And finally run our (custom) config upgrade sequence
# Upgrade configuration if needed
self._UpgradeConfig()
self._cfg_id = utils.GetFileID(path=self._cfg_file)
def _UpgradeConfig(self):
"""Run upgrade steps that cannot be done purely in the objects.
"""Run any upgrade steps.
This is because some data elements need uniqueness across the
whole configuration, etc.
This method performs both in-object upgrades and also update some data
elements that need uniqueness across the whole configuration or interact
with other objects.
@warning: this function will call L{_WriteConfig()}, but also
L{DropECReservations} so it needs to be called only from a
......@@ -2059,26 +2058,31 @@ class ConfigWriter:
created first, to avoid causing deadlock.
"""
modified = False
# Keep a copy of the persistent part of _config_data to check for changes
# Serialization doesn't guarantee order in dictionaries
oldconf = copy.deepcopy(self._config_data.ToDict())
# In-object upgrades
self._config_data.UpgradeConfig()
for item in self._AllUUIDObjects():
if item.uuid is None:
item.uuid = self._GenerateUniqueID(_UPGRADE_CONFIG_JID)
modified = True
if not self._config_data.nodegroups:
default_nodegroup_name = constants.INITIAL_NODE_GROUP_NAME
default_nodegroup = objects.NodeGroup(name=default_nodegroup_name,
members=[])
self._UnlockedAddNodeGroup(default_nodegroup, _UPGRADE_CONFIG_JID, True)
modified = True
for node in self._config_data.nodes.values():
if not node.group:
node.group = 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.group)
modified = (oldconf != self._config_data.ToDict())
if modified:
self._WriteConfig()
# This is ok even if it acquires the internal lock, as _UpgradeConfig is
......
......@@ -174,6 +174,44 @@ class TestConfigRunner(unittest.TestCase):
self.failUnlessRaises(errors.ConfigurationError, cfg.Update, fake_instance,
None)
def testUpgradeSave(self):
"""Test that any modification done during upgrading is saved back"""
cfg = self._get_object()
# Remove an element, run upgrade, and check if the element is
# back and the file upgraded
node = cfg.GetNodeInfo(cfg.GetNodeList()[0])
# For a ConfigObject, None is the same as a missing field
node.ndparams = None
oldsaved = utils.ReadFile(self.cfg_file)
cfg._UpgradeConfig()
self.assertTrue(node.ndparams is not None)
newsaved = utils.ReadFile(self.cfg_file)
# We rely on the fact that at least the serial number changes
self.assertNotEqual(oldsaved, newsaved)
# Add something that should not be there this time
key = list(constants.NDC_GLOBALS)[0]
node.ndparams[key] = constants.NDC_DEFAULTS[key]
cfg._WriteConfig(None)
oldsaved = utils.ReadFile(self.cfg_file)
cfg._UpgradeConfig()
self.assertTrue(node.ndparams.get(key) is None)
newsaved = utils.ReadFile(self.cfg_file)
self.assertNotEqual(oldsaved, newsaved)
# Do the upgrade again, this time there should be no update
oldsaved = newsaved
cfg._UpgradeConfig()
newsaved = utils.ReadFile(self.cfg_file)
self.assertEqual(oldsaved, newsaved)
# Reload the configuration again: it shouldn't change the file
oldsaved = newsaved
self._get_object()
newsaved = utils.ReadFile(self.cfg_file)
self.assertEqual(oldsaved, newsaved)
def testNICParameterSyntaxCheck(self):
"""Test the NIC's CheckParameterSyntax function"""
mode = constants.NIC_MODE
......
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