From mboxrd@z Thu Jan 1 00:00:00 1970 From: kupcevic@sourceware.org Date: 15 Aug 2006 00:12:34 -0000 Subject: [Cluster-devel] conga/ricci/modules/cluster/clumon/src common/ ... Message-ID: <20060815001234.20531.qmail@sourceware.org> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit CVSROOT: /cvs/cluster Module name: conga Changes by: kupcevic at sourceware.org 2006-08-15 00:12:33 Modified files: ricci/modules/cluster/clumon/src/common: Cluster.cpp ricci/modules/cluster/clumon/src/daemon: Makefile Monitor.cpp Monitor.h ricci/modules/cluster/clumon/src/include: Cluster.h Log message: modclusterd: add support for CS5, fix clustered_nodes() probe if not quorate Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/common/Cluster.cpp.diff?cvsroot=cluster&r1=1.5&r2=1.6 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/daemon/Makefile.diff?cvsroot=cluster&r1=1.5&r2=1.6 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/daemon/Monitor.cpp.diff?cvsroot=cluster&r1=1.5&r2=1.6 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/daemon/Monitor.h.diff?cvsroot=cluster&r1=1.3&r2=1.4 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/ricci/modules/cluster/clumon/src/include/Cluster.h.diff?cvsroot=cluster&r1=1.5&r2=1.6 --- conga/ricci/modules/cluster/clumon/src/common/Cluster.cpp 2006/08/10 22:53:08 1.5 +++ conga/ricci/modules/cluster/clumon/src/common/Cluster.cpp 2006/08/15 00:12:32 1.6 @@ -29,9 +29,13 @@ using namespace ClusterMonitoring; -Cluster::Cluster(const String &name, const String &alias, unsigned int minQuorum) : +Cluster::Cluster(const String &name, + const String &alias, + const String &cluster_version, + unsigned int minQuorum) : _name(name), _alias(alias), + _cl_version(cluster_version), _minQuorum(minQuorum) { // add no-node node @@ -55,6 +59,12 @@ return _alias; } +String +Cluster::version() +{ + return _cl_version; +} + unsigned int Cluster::votes() { @@ -240,6 +250,7 @@ XMLObject clu("cluster"); clu.set_attr("name", cluster.name()); clu.set_attr("alias", cluster.alias()); + clu.set_attr("cluster_version", cluster.version()); sprintf(buff, "%u", cluster.votes()); clu.set_attr("votes", buff); sprintf(buff, "%u", cluster.minQuorum()); @@ -299,7 +310,11 @@ if (sscanf(clu.get_attr("minQuorum").c_str(), "%u", &minQuorum) != 1) throw String("xml2cluster(): invalid value for cluster's minQuorum"); String alias = clu.get_attr("alias"); - counting_auto_ptr cluster(new Cluster(name, alias, minQuorum)); + String cl_version = clu.get_attr("cluster_version"); + counting_auto_ptr cluster(new Cluster(name, + alias, + cl_version, + minQuorum)); // nodes for (list::const_iterator iter = clu.children().begin(); --- conga/ricci/modules/cluster/clumon/src/daemon/Makefile 2006/08/09 20:53:22 1.5 +++ conga/ricci/modules/cluster/clumon/src/daemon/Makefile 2006/08/15 00:12:33 1.6 @@ -40,6 +40,7 @@ rebuild: clean all +*.o: *.h $(TARGET): $(OBJECTS) $(CXX) -o $@ $(LDFLAGS) $(OBJECTS) --- conga/ricci/modules/cluster/clumon/src/daemon/Monitor.cpp 2006/08/10 22:53:08 1.5 +++ conga/ricci/modules/cluster/clumon/src/daemon/Monitor.cpp 2006/08/15 00:12:33 1.6 @@ -31,6 +31,7 @@ #include #include +#include using namespace ClusterMonitoring; @@ -53,15 +54,23 @@ #define EXECUTE_TIMEOUT 3000 +#define CCS_TOOL_PATH "/sbin/ccs_tool" static XMLObject merge_xmls(const XMLObject& what, const XMLObject& with); +static String +cluster_version(); +static String +get_cman_tool_path(); Monitor::Monitor(unsigned short port) : - _comm(port, *this) + _comm(port, *this), + _cl_version(cluster_version()), + _cman_tool_path(get_cman_tool_path()), + _cman_locking(_cl_version == "5") { log("Monitor created", LogMonitor); } @@ -159,7 +168,7 @@ _cache[hostname] = data; } } - // TODO other msgs + // TODO: other msgs } } catch ( ... ) {} } @@ -189,6 +198,8 @@ cluster.set_attr("minQuorum", probe_quorum()); } catch ( ... ) {} + cluster.set_attr("cluster_version", _cl_version); + // insert current node info const vector clustered_nodes = this->clustered_nodes(); for (list::const_iterator iter = cluster.children().begin(); @@ -244,25 +255,38 @@ XMLObject Monitor::parse_cluster_conf() { - int status; - String out, err; - vector args; - args.push_back("/etc/cluster/cluster.conf"); - if (execute("/bin/cat", args, out, err, status, EXECUTE_TIMEOUT)) - throw String("parse_cluster_conf(): missing cluster.conf"); - if (status) - throw String("parse_cluster_conf(): missing cluster.conf"); + XMLObject cluster_conf; + char* buff = 0; + try { + if (access("/etc/cluster/cluster.conf", R_OK)) + throw String("missing /etc/cluster/cluster.conf"); + ifstream is("/etc/cluster/cluster.conf"); + is.seekg(0, ios::end); + unsigned int length = is.tellg(); + is.seekg(0, ios::beg); + if (length < 5) + throw String("cluster.conf too short"); + buff = new char[length]; + is.read(buff, length); + String conf(buff, length); + delete [] buff; buff = 0; + cluster_conf = parseXML(conf); + if (cluster_conf.tag() != "cluster" || + utils::strip(cluster_conf.get_attr("name")).empty()) + throw String("parse_cluster_conf(): invalid cluster.conf"); + } catch ( ... ) { + delete [] buff; + throw; + } - XMLObject cluster_conf = parseXML(out); - if (cluster_conf.tag() != "cluster") - throw String("parse_cluster_conf(): invalid cluster.conf"); XMLObject cluster("cluster"); - cluster.set_attr("alias", ""); for (map::const_iterator iter = cluster_conf.attrs().begin(); iter != cluster_conf.attrs().end(); iter++) cluster.set_attr(iter->first, iter->second); + if (utils::strip(cluster.get_attr("alias")).empty()) + cluster.set_attr("alias", cluster.get_attr("name")); for (list::const_iterator iter = cluster_conf.children().begin(); iter != cluster_conf.children().end(); @@ -305,6 +329,10 @@ } } + if (_cl_version == "5") + cluster.set_attr("locking", "cman"); + _cman_locking = (cluster.get_attr("locking") == "cman"); + return cluster; } @@ -355,11 +383,12 @@ counting_auto_ptr cluster_ret; String name = cluster.get_attr("name"); String alias = cluster.get_attr("alias"); + String clu_version = cluster.get_attr("cluster_version"); unsigned int minQuorum = 0; if (sscanf(cluster.get_attr("minQuorum").c_str(), "%u", &minQuorum) != 1) - cluster_ret = counting_auto_ptr (new Cluster(name, alias)); + cluster_ret = counting_auto_ptr (new Cluster(name, alias, clu_version)); else - cluster_ret = counting_auto_ptr (new Cluster(name, alias, minQuorum)); + cluster_ret = counting_auto_ptr (new Cluster(name, alias, clu_version, minQuorum)); // nodes for (list::const_iterator iter = cluster.children().begin(); iter != cluster.children().end(); @@ -454,46 +483,87 @@ vector Monitor::clustered_nodes() { - String out, err; - int status; - vector args; - args.push_back("members"); - if (execute("/sbin/magma_tool", args, out, err, status, EXECUTE_TIMEOUT)) - throw String("clustered_nodes(): missing magma_tool"); - if (status) - return vector(); - - // split out by lines - vector lines; - while (out.size()) { - String::size_type idx = out.find('\n'); - lines.push_back(out.substr(0, idx)); - if (idx == out.npos) - out = ""; - else - out = out.substr(idx+1); - } - vector running; - for (vector::iterator iter = lines.begin(); - iter != lines.end(); - iter++) { - String& line = *iter; - if (line.find("Member ID") != line.npos) { - String t = line.substr(line.find(": ") + 2); - String::size_type idx = t.find(','); - String name = t.substr(0, idx); - String rest = t.substr(idx); - if (rest.find("UP") != rest.npos) - running.push_back(name); + + if (_cman_locking) { + String out, err; + int status; + vector args; + args.push_back("nodes"); + if (execute(_cman_tool_path, args, out, err, status, EXECUTE_TIMEOUT)) + throw String("clustered_nodes(): missing cman_tool"); + if (status) + return vector(); + vector::size_type Sts_idx = 0; + vector lines = utils::split(out, "\n"); + for (vector::iterator iter = lines.begin(); + iter != lines.end(); + iter++) { + vector words = utils::split(utils::strip(*iter)); + if (words.size() < Sts_idx+1) + continue; + if (words[0] == "Node") { + // update Sts_idx + for (vector::size_type i=0; i args; + args.push_back("members"); + if (execute("/sbin/magma_tool", args, out, err, status, EXECUTE_TIMEOUT)) + throw String("clustered_nodes(): missing magma_tool"); + if (status) + return vector(); + vector lines = utils::split(out, "\n"); + for (vector::iterator iter = lines.begin(); + iter != lines.end(); + iter++) { + String line = utils::strip(*iter); + if (line.find("Member ID") != line.npos) { + String t = line.substr(line.find(": ") + 2); + String::size_type idx = t.find(','); + String name = t.substr(0, idx); + String rest = t.substr(idx); + if (rest.find("UP") != rest.npos) + running.push_back(name); + } + } + } else + throw String("cluster version ") + _cl_version + " not supported"; + return running; } String Monitor::nodename(const vector& nodenames) { + if (_cman_locking) { + String out, err; + int status; + vector args(1, "status"); + if (execute(_cman_tool_path, args, out, err, status, EXECUTE_TIMEOUT)) + throw String("nodename(): missing ") + _cman_tool_path; + if (status) + // cman not running, match using address + out.clear(); + + vector lines = utils::split(utils::strip(out), "\n"); + for (vector::const_iterator iter = lines.begin(); + iter != lines.end(); + iter++) { + vector words = utils::split(utils::strip(*iter)); + if (words.size() != 3) + continue; + if (words[0] + " " + words[1] == "Node name:") + return words[2]; + } + } + String out, err; int status; if (execute("/sbin/ifconfig", vector(), out, err, status, EXECUTE_TIMEOUT)) @@ -513,6 +583,7 @@ return nodename; } } + return ""; } @@ -531,7 +602,7 @@ if (execute("/usr/sbin/clustat", args, out, err, status, EXECUTE_TIMEOUT)) throw String("services_info(): missing clustat"); if (status) - return vector(); + throw String("services_info(): `clustat -h` failed"); if (out.find("-f") != out.npos) fast_available = true; @@ -542,7 +613,7 @@ if (execute("/usr/sbin/clustat", args, out, err, status, EXECUTE_TIMEOUT)) throw String("services_info(): missing clustat"); if (status) - return vector(); + throw String("services_info(): `clustat -x` failed"); XMLObject clustat = parseXML(out); for (list::const_iterator iter_c = clustat.children().begin(); @@ -619,32 +690,63 @@ String Monitor::probe_quorum() const { + if (_cman_locking) { + int status; + String out, err; + vector args; + args.push_back("status"); + if (execute(_cman_tool_path, args, out, err, status, EXECUTE_TIMEOUT)) + throw _cman_tool_path + " status failed"; + if (status) + throw _cman_tool_path + " status failed"; + + vector lines = utils::split(out, "\n"); + for (vector::const_iterator iter = lines.begin(); + iter != lines.end(); + iter++) { + vector words = utils::split(*iter); + if (words.size() < 2) + continue; + if (words[0] == "Quorum:") + return words[1]; + } + } else { + // TODO: implement quorum detection on GULM clusters + throw String("GULM quorum detection not yet implemented"); + } + throw String("quorum not found"); +} + + +String +cluster_version() +{ int status; String out, err; vector args; - args.push_back("/proc/cluster/status"); - if (execute("/bin/cat", args, out, err, status, EXECUTE_TIMEOUT)) - throw String("no /proc/cluster/status"); + args.push_back("-V"); + if (execute(CCS_TOOL_PATH, args, out, err, status, EXECUTE_TIMEOUT)) + throw String("missing ") + CCS_TOOL_PATH; if (status) - throw String("no /proc/cluster/status"); + throw String(CCS_TOOL_PATH) + " -V failed"; - vector lines = utils::split(out, "\n"); - for (vector::const_iterator iter = lines.begin(); - iter != lines.end(); - iter++) { - vector words = utils::split(*iter); - if (words.size() != 2) - continue; - if (words[0] == "Quorum:") - return words[1]; - } - throw String("quorum not found"); + vector words = utils::split(utils::strip(out)); + if (words.size() < 2) + throw String(CCS_TOOL_PATH) + " -V failed"; + if (utils::strip(words[0]) != CCS_TOOL_PATH) + throw String(CCS_TOOL_PATH) + " -V failed"; + String version = utils::strip(words[1]); + if (version.size() < 5) + throw String(CCS_TOOL_PATH) + ": unrecognizable version format"; + if (version[0] == '1') + return "4"; + else if (version[0] == '2') + return "5"; + else + throw String(CCS_TOOL_PATH) + ": unsupported version"; } - - - XMLObject merge_xmls(const XMLObject& what, const XMLObject& with) { @@ -690,3 +792,14 @@ return new_xml; } + + + +String +get_cman_tool_path() +{ + String path = "/sbin/cman_tool"; + if (access(path.c_str(), X_OK)) + path = "/usr/sbin/cman_tool"; + return path; +} --- conga/ricci/modules/cluster/clumon/src/daemon/Monitor.h 2006/08/10 22:53:08 1.3 +++ conga/ricci/modules/cluster/clumon/src/daemon/Monitor.h 2006/08/15 00:12:33 1.4 @@ -58,10 +58,22 @@ Communicator _comm; + /* + cluster versions: + RHEL3 = "3" + RHEL4, FC4, FC5 = "4" + RHEL5, FC6 = "5" + */ + const String _cl_version; + + const String _cman_tool_path; + + bool _cman_locking; + // return (nodenames - my_nodename) std::vector get_local_info(String& nodename, - String& clustername, - String& msg); + String& clustername, + String& msg); counting_auto_ptr merge_data(const String& clustername); XMLObject parse_cluster_conf(); --- conga/ricci/modules/cluster/clumon/src/include/Cluster.h 2006/08/10 22:53:08 1.5 +++ conga/ricci/modules/cluster/clumon/src/include/Cluster.h 2006/08/15 00:12:33 1.6 @@ -48,11 +48,15 @@ class Cluster { public: - Cluster(const String& name, const String& alias, unsigned int minQuorum=0); + Cluster(const String& name, + const String& alias, + const String& cluster_version, + unsigned int minQuorum=0); virtual ~Cluster(); String name(); String alias(); + String version(); unsigned int votes(); unsigned int minQuorum(); bool quorate(); @@ -81,6 +85,7 @@ private: String _name; String _alias; + String _cl_version; unsigned int _minQuorum; std::map > _nodes;