diff --git a/include/RaftManager.h b/include/RaftManager.h index 594e23257a..71d54c074f 100644 --- a/include/RaftManager.h +++ b/include/RaftManager.h @@ -99,6 +99,12 @@ public: // ------------------------------------------------------------------------- // Raft state query functions // ------------------------------------------------------------------------- + /** + * Return the Raft status in XML format + * @return xml document with the raft state + */ + std::string& to_xml(std::string& state_xml); + /** * Makes this server follower. Stop associated replication facilities */ diff --git a/include/RequestManagerZone.h b/include/RequestManagerZone.h index bbc7933dbe..d2a27bfed4 100644 --- a/include/RequestManagerZone.h +++ b/include/RequestManagerZone.h @@ -112,4 +112,20 @@ public: RequestAttributes& att); }; +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +class ZoneRaftStatus : public RequestManagerZone +{ +public: + ZoneRaftStatus(): + RequestManagerZone("ZoneRaftInformation", "Returns Raft status", + "A:s"){}; + + ~ZoneRaftStatus(){}; + + void request_execute(xmlrpc_c::paramList const& _paramList, + RequestAttributes& att); +}; + #endif diff --git a/src/cli/one_helper/onezone_helper.rb b/src/cli/one_helper/onezone_helper.rb index 23a1996c5b..f0967f9ca1 100644 --- a/src/cli/one_helper/onezone_helper.rb +++ b/src/cli/one_helper/onezone_helper.rb @@ -117,6 +117,42 @@ class OneZoneHelper < OpenNebulaHelper::OneHelper zone_hash=zone.to_hash if zone.has_elements?("/ZONE/SERVER_POOL/SERVER") + servers = zone_hash["ZONE"]["SERVER_POOL"]["SERVER"] + + servers.each { |s| + endpoint = s["ENDPOINT"] + + next if endpoint.nil? + + client = OpenNebula::Client.new(nil, endpoint) + + xml_doc = client.call("zone.raftstatus") + + if OpenNebula::is_error?(xml_doc) + s["STATE"] = "error" + s["TERM"] = "-" + s["VOTEDFOR"] = "-" + s["COMMIT" ] = "-" + s["LOG_INDEX"] = "-" + + next + end + + xml_doc = Nokogiri::XML(xml_doc) + + s["STATE"] = case xml_doc.root.at_xpath("STATE").text + when "0" then "solo" + when "1" then "candidate" + when "2" then "follower" + when "3" then "leader" + else "-" + end + s["TERM"] = xml_doc.root.at_xpath("TERM").text + s["VOTEDFOR"] = xml_doc.root.at_xpath("VOTEDFOR").text + s["COMMIT"] = xml_doc.root.at_xpath("COMMIT").text + s["LOG_INDEX"] = xml_doc.root.at_xpath("LOG_INDEX").text + } + puts CLIHelper.print_header(str_h1 % "SERVERS",false) @@ -130,10 +166,29 @@ class OneZoneHelper < OpenNebulaHelper::OneHelper d["NAME"] if !d.nil? end - column :"ENDPOINT", "", :left, :size=>30 do |d| - d["ENDPOINT"] if !d.nil? + column :"STATE", "", :left, :size=>10 do |d| + d["STATE"] if !d.nil? end + column :"TERM", "", :left, :size=>10 do |d| + d["TERM"] if !d.nil? + end + + column :"INDEX", "", :left, :size=>10 do |d| + d["LOG_INDEX"] if !d.nil? + end + + column :"COMMIT", "", :left, :size=>10 do |d| + d["COMMIT"] if !d.nil? + end + + column :"VOTE", "", :left, :size=>5 do |d| + d["VOTEDFOR"] if !d.nil? + end + + column :"ENDPOINT", "", :left, :size=>18 do |d| + d["ENDPOINT"] if !d.nil? + end end.show([zone_hash['ZONE']['SERVER_POOL']['SERVER']].flatten, {}) end diff --git a/src/raft/RaftManager.cc b/src/raft/RaftManager.cc index 605e4d1a7c..2d4589f513 100644 --- a/src/raft/RaftManager.cc +++ b/src/raft/RaftManager.cc @@ -1112,3 +1112,37 @@ int RaftManager::xmlrpc_request_vote(int follower_id, unsigned int lindex, return xml_rc; } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +std::string& RaftManager::to_xml(std::string& raft_xml) +{ + Nebula& nd = Nebula::instance(); + LogDB * logdb = nd.get_logdb(); + + unsigned int lindex, lterm; + + std::ostringstream oss; + + logdb->get_last_record_index(lindex, lterm); + + pthread_mutex_lock(&mutex); + + oss << "" + << "" << server_id << "" + << "" << state << "" + << "" << term << "" + << "" << votedfor << "" + << "" << commit << "" + << "" << lindex << "" + << "" << lterm << "" + << ""; + + pthread_mutex_unlock(&mutex); + + raft_xml = oss.str(); + + return raft_xml; +} + + diff --git a/src/rm/RequestManager.cc b/src/rm/RequestManager.cc index a1a11fb5ab..7ad01a8897 100644 --- a/src/rm/RequestManager.cc +++ b/src/rm/RequestManager.cc @@ -789,6 +789,7 @@ void RequestManager::register_xml_methods() xmlrpc_c::methodPtr zone_delserver(zone_delserver_pt); xmlrpc_c::methodPtr zone_replicatelog(new ZoneReplicateLog()); xmlrpc_c::methodPtr zone_voterequest(new ZoneVoteRequest()); + xmlrpc_c::methodPtr zone_raftstatus(new ZoneRaftStatus()); xmlrpc_c::methodPtr zone_info(new ZoneInfo()); xmlrpc_c::methodPtr zonepool_info(new ZonePoolInfo()); @@ -800,6 +801,7 @@ void RequestManager::register_xml_methods() RequestManagerRegistry.addMethod("one.zone.rename", zone_rename); RequestManagerRegistry.addMethod("one.zone.replicate",zone_replicatelog); RequestManagerRegistry.addMethod("one.zone.voterequest",zone_voterequest); + RequestManagerRegistry.addMethod("one.zone.raftstatus", zone_raftstatus); RequestManagerRegistry.addMethod("one.zone.addserver", zone_addserver); RequestManagerRegistry.addMethod("one.zone.delserver", zone_delserver); diff --git a/src/rm/RequestManagerZone.cc b/src/rm/RequestManagerZone.cc index dd6c4420a2..244a6d18d0 100644 --- a/src/rm/RequestManagerZone.cc +++ b/src/rm/RequestManagerZone.cc @@ -303,4 +303,25 @@ void ZoneVoteRequest::request_execute(xmlrpc_c::paramList const& paramList, success_response(static_cast(current_term), att); } +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void ZoneRaftStatus::request_execute(xmlrpc_c::paramList const& paramList, + RequestAttributes& att) +{ + Nebula& nd = Nebula::instance(); + + RaftManager * raftm = nd.get_raftm(); + + std::string raft_xml; + + if ( basic_authorization(nd.get_zone_id(), att) == false ) + { + return; + } + + raftm->to_xml(raft_xml); + + success_response(raft_xml, att); +}