diff --git a/lib/bootstrap.py b/lib/bootstrap.py index 356513139ede714b716e164abcab2e449ac09bda..6cd742455053394a0e71df72cd0acdce1db942f4 100644 --- a/lib/bootstrap.py +++ b/lib/bootstrap.py @@ -75,6 +75,9 @@ def _InitGanetiServerSetup(ss): This creates the nodepass file containing the shared password for the cluster and also generates the SSL certificate. + Args: + ss: A WritableSimpleStore + """ # Create pseudo random password randpass = sha.new(os.urandom(64)).hexdigest() @@ -191,7 +194,7 @@ def InitCluster(cluster_name, hypervisor_type, mac_prefix, def_bridge, " executable." % constants.NODE_INITD_SCRIPT) # set up the simple store - ss = ssconf.SimpleStore() + ss = ssconf.WritableSimpleStore() ss.SetKey(ss.SS_HYPERVISOR, hypervisor_type) ss.SetKey(ss.SS_MASTER_NODE, hostname.name) ss.SetKey(ss.SS_MASTER_IP, clustername.ip) diff --git a/lib/cmdlib.py b/lib/cmdlib.py index 810cf0cbc4a475c3f853e9a2d728fca3330c3279..596b0deef0e6d4f4e45748d2c135247eba28d350 100644 --- a/lib/cmdlib.py +++ b/lib/cmdlib.py @@ -54,14 +54,18 @@ class LogicalUnit(object): - implement Exec - implement BuildHooksEnv - redefine HPATH and HTYPE - - optionally redefine their run requirements (REQ_MASTER); note that all - commands require root permissions + - optionally redefine their run requirements: + REQ_MASTER: the LU needs to run on the master node + REQ_WSSTORE: the LU needs a writable SimpleStore + + Note that all commands require root permissions. """ HPATH = None HTYPE = None _OP_REQP = [] REQ_MASTER = True + REQ_WSSTORE = False def __init__(self, processor, op, cfg, sstore): """Constructor for LogicalUnit. @@ -849,6 +853,7 @@ class LURenameCluster(LogicalUnit): HPATH = "cluster-rename" HTYPE = constants.HTYPE_CLUSTER _OP_REQP = ["name"] + REQ_WSSTORE = True def BuildHooksEnv(self): """Build hooks env. @@ -1661,6 +1666,7 @@ class LUMasterFailover(LogicalUnit): HPATH = "master-failover" HTYPE = constants.HTYPE_CLUSTER REQ_MASTER = False + REQ_WSSTORE = True _OP_REQP = [] def BuildHooksEnv(self): diff --git a/lib/mcpu.py b/lib/mcpu.py index 360eaf2896bd80c2c52ff6094395b103c5c4430d..b9b06f63127f567a9b2ca6e5f9776eb3dee001ce 100644 --- a/lib/mcpu.py +++ b/lib/mcpu.py @@ -118,7 +118,10 @@ class Processor(object): if self.cfg is None: self.cfg = config.ConfigWriter() - self.sstore = ssconf.SimpleStore() + if lu_class.REQ_WSSTORE: + self.sstore = ssconf.WritableSimpleStore() + else: + self.sstore = ssconf.SimpleStore() if self.cfg is not None: write_count = self.cfg.write_count else: diff --git a/lib/ssconf.py b/lib/ssconf.py index 389071314fa081a0954c99150bc08257da9e3387..d73a267ac2b68a8c7f9a8398d8410d4667ef77e7 100644 --- a/lib/ssconf.py +++ b/lib/ssconf.py @@ -47,8 +47,7 @@ class SimpleStore: Other particularities of the datastore: - keys are restricted to predefined values - values are small (<4k) - - some keys are handled specially (read from the system, so - we can't update them) + - some keys are handled specially (read from the system) """ _SS_FILEPREFIX = "ssconf_" @@ -170,6 +169,25 @@ class SimpleStore: raise errors.ConfigurationError("Failed to convert config version %s to" " int: '%s'" % (value, str(err))) + def GetFileList(self): + """Return the list of all config files. + + This is used for computing node replication data. + + """ + return [self.KeyToFilename(key) for key in self._VALID_KEYS] + + +class WritableSimpleStore(SimpleStore): + """This is a read/write interface to SimpleStore, which is used rarely, when + values need to be changed. Since WriteFile handles updates in an atomic way + it should be fine to use two WritableSimpleStore at the same time, but in + the future we might want to put additional protection for this class. + + A WritableSimpleStore cannot be used to update system-dependent values. + + """ + def SetKey(self, key, value): """Set the value of a key. @@ -181,10 +199,3 @@ class SimpleStore: utils.WriteFile(file_name, data="%s\n" % str(value), uid=0, gid=0, mode=0400) - def GetFileList(self): - """Return the list of all config files. - - This is used for computing node replication data. - - """ - return [self.KeyToFilename(key) for key in self._VALID_KEYS]