From e60c73a173895fd5e6034bbbe4690c44b5ac5b6d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ren=C3=A9=20Nussbaumer?= <rn@google.com>
Date: Tue, 31 Aug 2010 13:43:16 +0200
Subject: [PATCH] The config now should also belong to confd group and readable
 by it
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: RenΓ© Nussbaumer <rn@google.com>
Reviewed-by: Michael Hanselmann <hansmi@google.com>
---
 lib/config.py                  |  7 +++++--
 test/ganeti.config_unittest.py |  8 +++++++-
 test/mocks.py                  | 24 ++++++++++++++++++++++++
 3 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/lib/config.py b/lib/config.py
index e620c2104..cda944168 100644
--- a/lib/config.py
+++ b/lib/config.py
@@ -48,6 +48,7 @@ from ganeti import objects
 from ganeti import serializer
 from ganeti import uidpool
 from ganeti import netutils
+from ganeti import runtime
 
 
 _config_lock = locking.SharedLock("ConfigWriter")
@@ -134,7 +135,7 @@ class ConfigWriter:
   @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
@@ -143,6 +144,7 @@ class ConfigWriter:
       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()
@@ -1342,7 +1344,8 @@ class ConfigWriter:
     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
 
diff --git a/test/ganeti.config_unittest.py b/test/ganeti.config_unittest.py
index 32a8cb843..984bfff62 100755
--- a/test/ganeti.config_unittest.py
+++ b/test/ganeti.config_unittest.py
@@ -38,6 +38,11 @@ from ganeti import utils
 from ganeti import netutils
 
 import testutils
+import mocks
+
+
+def _StubGetEntResolver():
+  return mocks.FakeGetentResolver()
 
 
 class TestConfigRunner(unittest.TestCase):
@@ -55,7 +60,8 @@ class TestConfigRunner(unittest.TestCase):
 
   def _get_object(self):
     """Returns a instance of ConfigWriter"""
-    cfg = config.ConfigWriter(cfg_file=self.cfg_file, offline=True)
+    cfg = config.ConfigWriter(cfg_file=self.cfg_file, offline=True,
+                              _getents=_StubGetEntResolver)
     return cfg
 
   def _init_cluster(self, cfg):
diff --git a/test/mocks.py b/test/mocks.py
index b2fb1392a..a5140fb57 100644
--- a/test/mocks.py
+++ b/test/mocks.py
@@ -21,6 +21,9 @@
 
 """Module implementing a fake ConfigWriter"""
 
+
+import os
+
 from ganeti import utils
 from ganeti import netutils
 
@@ -79,3 +82,24 @@ class FakeContext:
         self.cfg = FakeConfig()
         # TODO: decide what features a mock Ganeti Lock Manager must have
         self.GLM = None
+
+
+class FakeGetentResolver:
+    """Fake runtime.GetentResolver"""
+
+    def __init__(self):
+        # As we nomally don't run under root we use our own uid/gid for all
+        # fields. This way we don't run into permission denied problems.
+        uid = os.getuid()
+        gid = os.getgid()
+
+        self.masterd_uid = uid
+        self.masterd_gid = gid
+        self.confd_uid = uid
+        self.confd_gid = gid
+        self.rapi_uid = uid
+        self.rapi_gid = gid
+        self.noded_uid = uid
+
+        self.daemons_gid = gid
+        self.admin_gid = gid
-- 
GitLab