mon: AuthMonitor: always encode full regardless of keyserver having keys

On clusters without cephx, assuming an admin never added a key to the
cluster, the monitors have empty key servers.  A previous patch had the
AuthMonitor not encoding an empty keyserver as a full version.

As such, whenever the monitor restarts we will have to read the whole
state from disk in the form of incrementals.  This poses a problem upon
trimming, as we do every now and then: whenever we start the monitor, it
will start with an empty keyserver, waiting to be populated from whatever
we have on disk.  This is performed in update_from_paxos(), and the
AuthMonitor's will rely on the keyserver version to decide which
incrementals we care about -- basically, all versions > keyserver version.

Although we started with an empty keyserver (version 0) and are expecting
to read state from disk, in this case it means we will attempt to read
version 1 first.  If the cluster has been running for a while now, and
even if no keys have been added, it's fair to assume that version is
greater than 0 (or even 1), as the AuthMonitor also deals and keeps track
of auth global ids.  As such, we expect to read version 1, then version 2,
and so on.  If we trim at some point however this will not be possible,
as version 1 will not exist -- and we will assert because of that.

This is fixed by ensuring the AuthMonitor keeps track of full versions
of the key server, even if it's of an empty key server -- it will still
keep track of the key server's version, which is incremented each time
we update from paxos even if it is empty.

Fixes: #8851
Backport: dumpling, firefly

Signed-off-by: Joao Eduardo Luis <joao.luis@inktank.com>
This commit is contained in:
Joao Eduardo Luis 2014-07-22 00:25:37 +01:00
parent 27f6dbb64a
commit b551ae2bce

View File

@ -247,24 +247,25 @@ void AuthMonitor::encode_pending(MonitorDBStore::Transaction *t)
void AuthMonitor::encode_full(MonitorDBStore::Transaction *t)
{
version_t version = mon->key_server.get_ver();
// do not stash full version 0 as it will never be removed nor read
if (version == 0)
return;
dout(10) << __func__ << " auth v " << version << dendl;
assert(get_last_committed() == version);
bufferlist full_bl;
Mutex::Locker l(mon->key_server.get_lock());
if (mon->key_server.has_secrets()) {
dout(20) << __func__ << " key server has secrets!" << dendl;
__u8 v = 1;
::encode(v, full_bl);
::encode(max_global_id, full_bl);
::encode(mon->key_server, full_bl);
dout(20) << __func__ << " key server has "
<< (mon->key_server.has_secrets() ? "" : "no ")
<< "secrets!" << dendl;
__u8 v = 1;
::encode(v, full_bl);
::encode(max_global_id, full_bl);
::encode(mon->key_server, full_bl);
put_version_full(t, version, full_bl);
put_version_latest_full(t, version);
} else {
dout(20) << __func__
<< " key server has no secrets; do not put them in tx" << dendl;
}
put_version_full(t, version, full_bl);
put_version_latest_full(t, version);
}
version_t AuthMonitor::get_trim_to()