Move “rapi_users” file into separate directory
authorMichael Hanselmann <hansmi@google.com>
Wed, 24 Nov 2010 17:37:07 +0000 (18:37 +0100)
committerMichael Hanselmann <hansmi@google.com>
Mon, 29 Nov 2010 15:14:30 +0000 (16:14 +0100)
This reduces the number of notifications in “ganeti-rapi”. Until now it
was notified for every change in …/lib/ganeti and had to check whether
the users file was affected. A symlink is always created in cfgupgrade
to not break tools referring to the old name.

Signed-off-by: Michael Hanselmann <hansmi@google.com>
Reviewed-by: Iustin Pop <iustin@google.com>

NEWS
daemons/ensure-dirs.in
doc/rapi.rst
lib/constants.py
man/ganeti-rapi.rst
test/cfgupgrade_unittest.py
tools/cfgupgrade

diff --git a/NEWS b/NEWS
index 12e26c3..23e86ee 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,15 @@
 News
 ====
 
+Version 2.4.0 rc1
+-----------------
+
+*(unreleased)*
+
+- Moved ``rapi_users`` file into separate directory, now named
+  ``…/ganeti/rapi/users``
+
+
 Version 2.3.0 rc1
 -----------------
 
index 252f24a..272d407 100644 (file)
@@ -80,6 +80,7 @@ _ensure_datadir() {
   _ensure_dir ${DATADIR}/queue 0700 "$(_fileset_owner masterd)"
   _ensure_dir ${DATADIR}/queue/archive 0700 "$(_fileset_owner masterd)"
   _ensure_dir ${DATADIR}/uidpool 0750 "$(_fileset_owner noded)"
+  _ensure_dir ${DATADIR}/rapi 0750 "$(_fileset_owner rapi)"
 
   # We ignore these files if they don't exists (incomplete setup)
   _ensure_file ${DATADIR}/cluster-domain-secret 0640 \
@@ -88,7 +89,7 @@ _ensure_datadir() {
   _ensure_file ${DATADIR}/hmac.key 0440 "$(_fileset_owner confd)" || :
   _ensure_file ${DATADIR}/known_hosts 0644 "$(_fileset_owner masterd)" || :
   _ensure_file ${DATADIR}/rapi.pem 0440 "$(_fileset_owner rapi)" || :
-  _ensure_file ${DATADIR}/rapi_users 0640 "$(_fileset_owner rapi)" || :
+  _ensure_file ${DATADIR}/rapi/users 0640 "$(_fileset_owner rapi)" || :
   _ensure_file ${DATADIR}/server.pem 0440 "$(_fileset_owner masterd)" || :
   _ensure_file ${DATADIR}/queue/serial 0600 "$(_fileset_owner masterd)" || :
 
index 9b53a88..f340c12 100644 (file)
@@ -21,7 +21,7 @@ Users and passwords
 -------------------
 
 ``ganeti-rapi`` reads users and passwords from a file (usually
-``/var/lib/ganeti/rapi_users``) on startup. Changes to the file will be
+``/var/lib/ganeti/rapi/users``) on startup. Changes to the file will be
 read automatically.
 
 Each line consists of two or three fields separated by whitespace. The
index 1222bf9..cf04996 100644 (file)
@@ -135,7 +135,7 @@ WATCHER_STATEFILE = DATA_DIR + "/watcher.data"
 WATCHER_PAUSEFILE = DATA_DIR + "/watcher.pause"
 INSTANCE_UPFILE = RUN_GANETI_DIR + "/instance-status"
 SSH_KNOWN_HOSTS_FILE = DATA_DIR + "/known_hosts"
-RAPI_USERS_FILE = DATA_DIR + "/rapi_users"
+RAPI_USERS_FILE = DATA_DIR + "/rapi/users"
 QUEUE_DIR = DATA_DIR + "/queue"
 DAEMON_UTIL = _autoconf.PKGLIBDIR + "/daemon-util"
 SETUP_SSH = _autoconf.TOOLSDIR + "/setup-ssh"
index d6e83ab..2e5e3b4 100644 (file)
@@ -38,8 +38,8 @@ All query operations are allowed without authentication. Only the
 modification operations require authentication, in the form of basic
 authentication.
 
-The users and their rights are defined in a file named rapi_users,
-located in the ``@LOCALSTATEDIR@/lib/ganeti`` directory. The users
+The users and their rights are defined in the
+``@LOCALSTATEDIR@/lib/ganeti/rapi/users`` file. The users
 should be listed one per line, in the following format::
 
     username password options
index 129be6f..06a6f2c 100755 (executable)
@@ -57,6 +57,8 @@ class TestCfgupgrade(unittest.TestCase):
     self.config_path = utils.PathJoin(self.tmpdir, "config.data")
     self.noded_cert_path = utils.PathJoin(self.tmpdir, "server.pem")
     self.rapi_cert_path = utils.PathJoin(self.tmpdir, "rapi.pem")
+    self.rapi_users_path = utils.PathJoin(self.tmpdir, "rapi", "users")
+    self.rapi_users_path_pre24 = utils.PathJoin(self.tmpdir, "rapi_users")
     self.known_hosts_path = utils.PathJoin(self.tmpdir, "known_hosts")
     self.confd_hmac_path = utils.PathJoin(self.tmpdir, "hmac.key")
     self.cds_path = utils.PathJoin(self.tmpdir, "cluster-domain-secret")
@@ -122,12 +124,57 @@ class TestCfgupgrade(unittest.TestCase):
     newcfg = self._LoadConfig()
     self.assertEqual(newcfg["version"], expversion)
 
+  def testRapiUsers(self):
+    self.assertFalse(os.path.exists(self.rapi_users_path))
+    self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
+
+    utils.WriteFile(self.rapi_users_path_pre24, data="some user\n")
+    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
+
+    self.assert_(os.path.islink(self.rapi_users_path_pre24))
+    self.assert_(os.path.isfile(self.rapi_users_path))
+    for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
+      self.assertEqual(utils.ReadFile(path), "some user\n")
+
+  def testRapiUsers24AndAbove(self):
+    self.assertFalse(os.path.exists(self.rapi_users_path))
+    self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
+
+    os.mkdir(os.path.dirname(self.rapi_users_path))
+    utils.WriteFile(self.rapi_users_path, data="other user\n")
+    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
+
+    self.assert_(os.path.islink(self.rapi_users_path_pre24))
+    self.assert_(os.path.isfile(self.rapi_users_path))
+    for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
+      self.assertEqual(utils.ReadFile(path), "other user\n")
+
+  def testRapiUsersExistingSymlink(self):
+    self.assertFalse(os.path.exists(self.rapi_users_path))
+    self.assertFalse(os.path.exists(self.rapi_users_path_pre24))
+
+    os.symlink(self.rapi_users_path, self.rapi_users_path_pre24)
+    utils.WriteFile(self.rapi_users_path_pre24, data="hello world\n")
+
+    self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), False)
+
+    self.assert_(os.path.isfile(self.rapi_users_path))
+    self.assert_(os.path.islink(self.rapi_users_path_pre24))
+    for path in [self.rapi_users_path, self.rapi_users_path_pre24]:
+      self.assertEqual(utils.ReadFile(path), "hello world\n")
+
   def testUpgradeFrom_2_0(self):
     self._TestSimpleUpgrade(constants.BuildVersion(2, 0, 0), False)
 
   def testUpgradeFrom_2_1(self):
     self._TestSimpleUpgrade(constants.BuildVersion(2, 1, 0), False)
 
+  def testUpgradeFrom_2_2(self):
+    self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), False)
+
+  def testUpgradeFrom_2_3(self):
+    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), False)
+
   def testUpgradeCurrent(self):
     self._TestSimpleUpgrade(constants.CONFIG_VERSION, False)
 
@@ -137,6 +184,12 @@ class TestCfgupgrade(unittest.TestCase):
   def testUpgradeDryRunFrom_2_1(self):
     self._TestSimpleUpgrade(constants.BuildVersion(2, 1, 0), True)
 
+  def testUpgradeDryRunFrom_2_2(self):
+    self._TestSimpleUpgrade(constants.BuildVersion(2, 2, 0), True)
+
+  def testUpgradeDryRunFrom_2_3(self):
+    self._TestSimpleUpgrade(constants.BuildVersion(2, 3, 0), True)
+
   def testUpgradeCurrentDryRun(self):
     self._TestSimpleUpgrade(constants.CONFIG_VERSION, True)
 
index 0b135ce..4c10413 100755 (executable)
@@ -102,6 +102,8 @@ def main():
   options.SERVER_PEM_PATH = options.data_dir + "/server.pem"
   options.KNOWN_HOSTS_PATH = options.data_dir + "/known_hosts"
   options.RAPI_CERT_FILE = options.data_dir + "/rapi.pem"
+  options.RAPI_USERS_FILE = options.data_dir + "/rapi/users"
+  options.RAPI_USERS_FILE_PRE24 = options.data_dir + "/rapi_users"
   options.CONFD_HMAC_KEY = options.data_dir + "/hmac.key"
   options.CDS_FILE = options.data_dir + "/cluster-domain-secret"
 
@@ -155,6 +157,18 @@ def main():
     raise Error("Configuration version %d.%d.%d not supported by this tool" %
                 (config_major, config_minor, config_revision))
 
+  if os.path.isfile(options.RAPI_USERS_FILE_PRE24):
+    logging.info("Found pre-2.4 RAPI users file at %s, renaming to %s",
+                 options.RAPI_USERS_FILE_PRE24, options.RAPI_USERS_FILE)
+    utils.RenameFile(options.RAPI_USERS_FILE_PRE24, options.RAPI_USERS_FILE,
+                     mkdir=True, mkdir_mode=0750)
+
+  # Create a symlink for RAPI users file
+  if not os.path.islink(options.RAPI_USERS_FILE_PRE24):
+    logging.info("Creating symlink from %s to %s",
+                 options.RAPI_USERS_FILE_PRE24, options.RAPI_USERS_FILE)
+    os.symlink(options.RAPI_USERS_FILE, options.RAPI_USERS_FILE_PRE24)
+
   try:
     logging.info("Writing configuration file to %s", options.CONFIG_DATA_PATH)
     utils.WriteFile(file_name=options.CONFIG_DATA_PATH,