diff --git a/NEWS b/NEWS index 12e26c35cf2c64a4da058cac387d966d4827bcb5..23e86eeb4b37cc5bbedd9c8c3bda05e772e0ae0c 100644 --- 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 ----------------- diff --git a/daemons/ensure-dirs.in b/daemons/ensure-dirs.in index 252f24af8fc877e3ba466fc8a4720a96a67fa6ca..272d40755fb4191b1bb64aee3bb3744d42e7a680 100644 --- a/daemons/ensure-dirs.in +++ b/daemons/ensure-dirs.in @@ -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)" || : diff --git a/doc/rapi.rst b/doc/rapi.rst index 9b53a8854bd5f90aec8c53856ceb0220b0a44920..f340c12fc3fb7103eea02aa2e98ef2ae04e60d0f 100644 --- a/doc/rapi.rst +++ b/doc/rapi.rst @@ -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 diff --git a/lib/constants.py b/lib/constants.py index 1222bf9faaf1a89940857b0b08c34c8ffdff90a6..cf04996301dd429fec1dd2abe5a3fc9d4b9fcdc9 100644 --- a/lib/constants.py +++ b/lib/constants.py @@ -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" diff --git a/man/ganeti-rapi.rst b/man/ganeti-rapi.rst index d6e83ab1ed7c7242248dc0317043eea51a0ca8b1..2e5e3b4114c3b2531071ca285fbc4a58dab8bfe9 100644 --- a/man/ganeti-rapi.rst +++ b/man/ganeti-rapi.rst @@ -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 diff --git a/test/cfgupgrade_unittest.py b/test/cfgupgrade_unittest.py index 129be6f2c583fbd73ec2cee9d4fbfdb96dbc71d0..06a6f2cd5de977ab7a0c8756ec3b79422870a77a 100755 --- a/test/cfgupgrade_unittest.py +++ b/test/cfgupgrade_unittest.py @@ -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) diff --git a/tools/cfgupgrade b/tools/cfgupgrade index 0b135ce2729618661eb4d8dee9e8bb48b8ef6663..4c10413d16d7350c7457705bce4950d8fa4a49b1 100755 --- a/tools/cfgupgrade +++ b/tools/cfgupgrade @@ -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,