[Cluster-devel] conga/ricci/modules/cluster/clumon/src common/ ...

kupcevic at sourceware.org kupcevic at sourceware.org
Tue Aug 15 00:12:34 UTC 2006


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> cluster(new Cluster(name, alias, minQuorum));
+  String cl_version = clu.get_attr("cluster_version");
+  counting_auto_ptr<Cluster> cluster(new Cluster(name, 
+						 alias, 
+						 cl_version, 
+						 minQuorum));
   
   // nodes
   for (list<XMLObject>::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 <sys/sysinfo.h>
 
 #include <algorithm>
+#include <fstream>
 
 
 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<String> clustered_nodes = this->clustered_nodes();
   for (list<XMLObject>::const_iterator iter = cluster.children().begin();
@@ -244,25 +255,38 @@
 XMLObject 
 Monitor::parse_cluster_conf()
 {
-  int status;
-  String out, err;
-  vector<String> 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<String, String>::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<XMLObject>::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> 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<Cluster> (new Cluster(name, alias));
+    cluster_ret = counting_auto_ptr<Cluster> (new Cluster(name, alias, clu_version));
   else
-    cluster_ret = counting_auto_ptr<Cluster> (new Cluster(name, alias, minQuorum));
+    cluster_ret = counting_auto_ptr<Cluster> (new Cluster(name, alias, clu_version, minQuorum));
   // nodes
   for (list<XMLObject>::const_iterator iter = cluster.children().begin();
        iter != cluster.children().end();
@@ -454,46 +483,87 @@
 vector<String> 
 Monitor::clustered_nodes()
 {
-  String out, err;
-  int status;
-  vector<String> 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<String>();
-  
-  // split out by lines
-  vector<String> 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<String> running;
-  for (vector<String>::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<String> 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<String>();
+    vector<String>::size_type Sts_idx = 0;
+    vector<String> lines = utils::split(out, "\n");
+    for (vector<String>::iterator iter = lines.begin();
+	 iter != lines.end();
+	 iter++) {
+      vector<String> words = utils::split(utils::strip(*iter));
+      if (words.size() < Sts_idx+1)
+	continue;
+      if (words[0] == "Node") {
+	// update Sts_idx
+	for (vector<String>::size_type i=0; i<words.size(); i++) 
+	  if (words[i] == "Sts")
+	    Sts_idx = i;
+      } else if (words[Sts_idx] == "M")
+	running.push_back(words.back());
     }
-  }
+  } else if (_cl_version == "4") {
+    String out, err;
+    int status;
+    vector<String> 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<String>();
+    vector<String> lines = utils::split(out, "\n");
+    for (vector<String>::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<String>& nodenames)
 {
+  if (_cman_locking) {
+    String out, err;
+    int status;
+    vector<String> 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<String> lines = utils::split(utils::strip(out), "\n");
+    for (vector<String>::const_iterator iter = lines.begin();
+	 iter != lines.end();
+	 iter++) {
+      vector<String> 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<String>(), 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<XMLObject>();
+      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<XMLObject>();
+      throw String("services_info(): `clustat -x` failed");
     
     XMLObject clustat = parseXML(out);
     for (list<XMLObject>::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<String> 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<String> lines = utils::split(out, "\n");
+    for (vector<String>::const_iterator iter = lines.begin();
+	 iter != lines.end();
+	 iter++) {
+      vector<String> 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<String> 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<String> lines = utils::split(out, "\n");
-  for (vector<String>::const_iterator iter = lines.begin();
-       iter != lines.end();
-       iter++) {
-    vector<String> words = utils::split(*iter);
-    if (words.size() != 2)
-      continue;
-    if (words[0] == "Quorum:")
-      return words[1];
-  }
-  throw String("quorum not found");
+  vector<String> 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<String> get_local_info(String& nodename,
-					  String& clustername,
-					  String& msg);
+				     String& clustername,
+				     String& msg);
   counting_auto_ptr<Cluster> 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<String, counting_auto_ptr<Node> > _nodes;
 




More information about the Cluster-devel mailing list