class MMonElection : public Message {
- static const int HEAD_VERSION = 6;
+ static const int HEAD_VERSION = 7;
static const int COMPAT_VERSION = 5;
public:
uint64_t quorum_features;
mon_feature_t mon_features;
bufferlist sharing_bl;
- /* the following were both used in the next branch for a while
- * on user cluster, so we've left them in for compatibility. */
- version_t defunct_one;
- version_t defunct_two;
+ map<string,string> metadata;
MMonElection() : Message(MSG_MON_ELECTION, HEAD_VERSION, COMPAT_VERSION),
op(0), epoch(0),
quorum_features(0),
- mon_features(0),
- defunct_one(0),
- defunct_two(0)
+ mon_features(0)
{ }
MMonElection(int o, epoch_t e, MonMap *m)
: Message(MSG_MON_ELECTION, HEAD_VERSION, COMPAT_VERSION),
fsid(m->fsid), op(o), epoch(e),
quorum_features(0),
- mon_features(0),
- defunct_one(0), defunct_two(0)
+ mon_features(0)
{
// encode using full feature set; we will reencode for dest later,
// if necessary
::encode(monmap_bl, payload);
::encode(quorum, payload);
::encode(quorum_features, payload);
- ::encode(defunct_one, payload);
- ::encode(defunct_two, payload);
+ ::encode((version_t)0, payload); // defunct
+ ::encode((version_t)0, payload); // defunct
::encode(sharing_bl, payload);
::encode(mon_features, payload);
+ ::encode(metadata, payload);
}
void decode_payload() override {
bufferlist::iterator p = payload.begin();
::decode(monmap_bl, p);
::decode(quorum, p);
::decode(quorum_features, p);
- ::decode(defunct_one, p);
- ::decode(defunct_two, p);
+ {
+ version_t v; // defunct fields from old encoding
+ ::decode(v, p);
+ ::decode(v, p);
+ }
::decode(sharing_bl, p);
if (header.version >= 6)
::decode(mon_features, p);
+ if (header.version >= 7)
+ ::decode(metadata, p);
}
};
electing_me = true;
acked_me[mon->rank].cluster_features = CEPH_FEATURES_ALL;
acked_me[mon->rank].mon_features = ceph::features::mon::get_supported();
+ mon->collect_metadata(&acked_me[mon->rank].metadata);
leader_acked = -1;
// bcast to everyone else
MMonElection *m = new MMonElection(MMonElection::OP_ACK, epoch, mon->monmap);
m->mon_features = ceph::features::mon::get_supported();
m->sharing_bl = mon->get_supported_commands_bl();
+ mon->collect_metadata(&m->metadata);
mon->messenger->send_message(m, mon->monmap->get_inst(who));
// set a timer
uint64_t cluster_features = CEPH_FEATURES_ALL;
mon_feature_t mon_features = ceph::features::mon::get_supported();
set<int> quorum;
- for (map<int, elector_features_t>::iterator p = acked_me.begin();
+ map<int,Metadata> metadata;
+ for (map<int, elector_info_t>::iterator p = acked_me.begin();
p != acked_me.end();
++p) {
quorum.insert(p->first);
cluster_features &= p->second.cluster_features;
mon_features &= p->second.mon_features;
+ metadata[p->first] = p->second.metadata;
}
cancel_timer();
m->sharing_bl = *cmds_bl;
mon->messenger->send_message(m, mon->monmap->get_inst(*p));
}
-
+
// tell monitor
mon->win_election(epoch, quorum,
- cluster_features, mon_features,
+ cluster_features, mon_features, metadata,
cmds, cmdsize);
}
// thanks
acked_me[from].cluster_features = m->get_connection()->get_features();
acked_me[from].mon_features = m->mon_features;
+ acked_me[from].metadata = m->metadata;
dout(5) << " so far i have {";
- for (map<int, elector_features_t>::const_iterator p = acked_me.begin();
+ for (map<int, elector_info_t>::const_iterator p = acked_me.begin();
p != acked_me.end();
++p) {
if (p != acked_me.begin())
* mon-specific features. Instead of keeping maps to hold them both, or
* a pair, which would be weird, a struct to keep them seems appropriate.
*/
- struct elector_features_t {
+ struct elector_info_t {
uint64_t cluster_features;
mon_feature_t mon_features;
+ map<string,string> metadata;
};
/**
* If we are acked by everyone in the MonMap, we will declare
* victory. Also note each peer's feature set.
*/
- map<int, elector_features_t> acked_me;
+ map<int, elector_info_t> acked_me;
/**
* @}
*/
set<int> q;
q.insert(rank);
- const MonCommand *my_cmds;
- int cmdsize;
+ map<int,Metadata> metadata;
+ collect_metadata(&metadata[0]);
+
+ const MonCommand *my_cmds = nullptr;
+ int cmdsize = 0;
get_locally_supported_monitor_commands(&my_cmds, &cmdsize);
win_election(elector.get_epoch(), q,
CEPH_FEATURES_ALL,
ceph::features::mon::get_supported(),
+ metadata,
my_cmds, cmdsize);
}
void Monitor::win_election(epoch_t epoch, set<int>& active, uint64_t features,
const mon_feature_t& mon_features,
+ const map<int,Metadata>& metadata,
const MonCommand *cmdset, int cmdsize)
{
dout(10) << __func__ << " epoch " << epoch << " quorum " << active
quorum = active;
quorum_con_features = features;
quorum_mon_features = mon_features;
+ pending_metadata = metadata;
outside_quorum.clear();
clog->info() << "mon." << name << "@" << rank
logger->inc(l_mon_election_win);
+ // inject new metadata in first transaction.
+ {
+ // include previous metadata for missing mons (that aren't part of
+ // the current quorum).
+ map<int,Metadata> m = metadata;
+ for (unsigned rank = 0; rank < monmap->size(); ++rank) {
+ if (m.count(rank) == 0 &&
+ mon_metadata.count(rank)) {
+ m[rank] = mon_metadata[rank];
+ }
+ }
+
+ // FIXME: This is a bit sloppy because we aren't guaranteed to submit
+ // a new transaction immediately after the election finishes. We should
+ // do that anyway for other reasons, though.
+ MonitorDBStore::TransactionRef t = paxos->get_pending_transaction();
+ bufferlist bl;
+ ::encode(m, bl);
+ t->put(MONITOR_STORE_PREFIX, "last_metadata", bl);
+ }
+
finish_election();
if (monmap->size() > 1 &&
monmap->get_epoch() > 0) {
do_health_to_clog_interval();
scrub_event_start();
}
-
- Metadata my_meta;
- collect_metadata(&my_meta);
- update_mon_metadata(rank, std::move(my_meta));
}
void Monitor::lose_election(epoch_t epoch, set<int> &q, int l,
finish_election();
- if (quorum_con_features & CEPH_FEATURE_MON_METADATA) {
+ if ((quorum_con_features & CEPH_FEATURE_MON_METADATA) &&
+ !HAVE_FEATURE(quorum_con_features, SERVER_LUMINOUS)) {
+ // for pre-luminous mons only
Metadata sys_info;
collect_metadata(&sys_info);
messenger->send_message(new MMonMetadata(sys_info),
void Monitor::update_mon_metadata(int from, Metadata&& m)
{
+ // NOTE: this is now for legacy (kraken or jewel) mons only.
pending_metadata[from] = std::move(m);
MonitorDBStore::TransactionRef t = paxos->get_pending_transaction();
void win_election(epoch_t epoch, set<int>& q,
uint64_t features,
const mon_feature_t& mon_features,
+ const map<int,Metadata>& metadata,
const MonCommand *cmdset, int cmdsize);
void lose_election(epoch_t epoch, set<int>& q, int l,
uint64_t features,