diff --git a/Makefile.am b/Makefile.am index 603d386b50..71b9a37627 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,146 +1,146 @@ # # linux-ha: Linux-HA code # # Copyright (C) 2002 Alan Robertson # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ##auxdir = @ac_aux_dir@ ##AUX_DIST = $(auxdir)/install-sh $(auxdir)/missing \ ## $(auxdir)/mkinstalldirs ##AUX_DIST_EXTRA = $(auxdir)/readline.m4 $(auxdir)/sys_errlist.m4 \ ## $(auxdir)/sys_siglist.m4 EXTRA_DIST = bootstrap rc.config.heartbeat \ heartbeat.spec.in heartbeat.spec \ ConfigureMe README.in libltdl.tar RPMREL = @RPMREL@ RPM = @RPM@ -RPMFLAGS = -ta --nodeps +RPMFLAGS = -ta TARFILE = @TARFILE@ AM_TAR = tar RPMDIR=$(HOME)/rpms WEBDIR=/home/alanr/ha-web/download HBWEBDIR=/home/alanr/ha-web/heartbeat RPMSRC=$(DESTDIR)$(RPMDIR)/SRPMS/$(PACKAGE)-$(VERSION)-$(RPMREL).src.rpm RPM386=$(DESTDIR)$(RPMDIR)/RPMS/i586/$(PACKAGE)-$(VERSION)-$(RPMREL).i586.rpm RPMstonith=$(DESTDIR)$(RPMDIR)/RPMS/i586/$(PACKAGE)-stonith-$(VERSION)-$(RPMREL).i586.rpm RPMpils=$(DESTDIR)$(RPMDIR)/RPMS/i586/$(PACKAGE)-pils-$(VERSION)-$(RPMREL).i586.rpm RPMldir=$(DESTDIR)$(RPMDIR)/RPMS/i586/$(PACKAGE)-ldirectord-$(VERSION)-$(RPMREL).i586.rpm SHAREDIR=@HA_DATADIR@ HBSHAREDIR=@HA_NOARCHDATAHBDIR@ ALL_RPMS = $(RPMSRC) $(RPM386) $(RPMstonith) $(RPMldir) $(RPMpils) AUTOMAKE_OPTIONS = foreign ##ACLOCAL = aclocal -I $(auxdir) MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure DRF/config-h.in \ DRF/stamp-h.in libtool.m4 ltdl.m4 libltdl.tar coredir = @HA_COREDIR@ hauser = @HA_CCMUSER@ ## proc-ha is left out from SUBDIRS (completely obsolete) if SNMP_SUBAGENT_BUILD SNMP_SUBAGENT_DIR = snmp_subagent endif if MGMT_BUILD MGMT_DIR = mgmt endif if CIM_PROVIDER_BUILD CIM_PROVIDER_DIR = cim endif if TSA_PLUGIN_BUILD TSA_PLUGIN_DIR = tsa_plugin endif if LDIRECTORD_BUILD LDIRECTORD_DIR = ldirectord endif SUBDIRS = $(LIBLTDL_DIR) debian pkg port replace include lib \ heartbeat membership telecom contrib resources lrm $(CRM_DIR) \ fencing logd $(SNMP_SUBAGENT_DIR) tools doc cts $(MGMT_DIR) \ $(CIM_PROVIDER_DIR) $(LDIRECTORD_DIR) config $(TSA_PLUGIN_DIR) HANDY_DOCS = doc/ChangeLog doc/GettingStarted.html doc/DirectoryMap.txt HBDOCS = doc/heartbeat_api.html # Pass these to configure when running "make distcheck" DISTCHECK_CONFIGURE_FLAGS = --with-initdir=prefix rpm: dist - $(RPM) --nodeps $(RPMFLAGS) $(TARFILE) * Copyright (c) 2004 International Business Machines * * This code implements the Resource Agent Plugin Module for LSB style. * It's a part of Local Resource Manager. Currently it's used by lrmd only. */ #include #include #include #include #include #include #include #include #include #include #include #include +#include #include #include #include /* Add it for compiling on OSX */ #include # define PIL_PLUGINTYPE RA_EXEC_TYPE # define PIL_PLUGINTYPE_S "RAExec" # define PIL_PLUGINLICENSE LICENSE_PUBDOM # define PIL_PLUGINLICENSEURL URL_PUBDOM # define PIL_PLUGIN ocf # define PIL_PLUGIN_S "ocf" /* * Are there multiple paths? Now according to OCF spec, the answer is 'no'. * But actually or for future? */ static const char * RA_PATH = OCF_RA_DIR; /* The begin of exported function list */ static int execra(const char * rsc_id, const char * rsc_type, const char * provider, const char * op_type, const int timeout, GHashTable * params); static uniform_ret_execra_t map_ra_retvalue(int ret_execra, const char * op_type, const char * std_output); static int get_resource_list(GList ** rsc_info); static char* get_resource_meta(const char* rsc_type, const char* provider); static int get_provider_list(const char* ra_type, GList ** providers); /* The end of exported function list */ /* The begin of internal used function & data list */ #define HADEBUGVAL "HA_DEBUG" static void add_OCF_prefix(GHashTable * params, GHashTable * new_params); static void add_OCF_env_vars(GHashTable * env, const char * rsc_id, const char * rsc_type, const char * provider); static void add_prefix_foreach(gpointer key, gpointer value, gpointer user_data); static void hash_to_str(GHashTable * , GString *); static void hash_to_str_foreach(gpointer key, gpointer value, gpointer user_data); static int raexec_setenv(GHashTable * env_params); static void set_env(gpointer key, gpointer value, gpointer user_data); static gboolean let_remove_eachitem(gpointer key, gpointer value, gpointer user_data); static int get_providers(const char* class_path, const char* op_type, GList ** providers); static void merge_string_list(GList** old, GList* new); static gint compare_str(gconstpointer a, gconstpointer b); /* The end of internal function & data list */ /* Rource agent execution plugin operations */ static struct RAExecOps raops = { execra, map_ra_retvalue, get_resource_list, get_provider_list, get_resource_meta }; PIL_PLUGIN_BOILERPLATE2("1.0", Debug) static const PILPluginImports* PluginImports; static PILPlugin* OurPlugin; static PILInterface* OurInterface; static void* OurImports; static void* interfprivate; /* * Our plugin initialization and registration function * It gets called when the plugin gets loaded. */ PIL_rc PIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports* imports); PIL_rc PIL_PLUGIN_INIT(PILPlugin * us, const PILPluginImports* imports) { /* Force the compiler to do a little type checking */ (void)(PILPluginInitFun)PIL_PLUGIN_INIT; PluginImports = imports; OurPlugin = us; /* Register ourself as a plugin */ imports->register_plugin(us, &OurPIExports); /* Register our interfaces */ return imports->register_interface(us, PIL_PLUGINTYPE_S, PIL_PLUGIN_S, &raops, NULL, &OurInterface, &OurImports, interfprivate); } /* * The function to execute a RA. */ static int execra(const char * rsc_id, const char * rsc_type, const char * provider, const char * op_type, const int timeout, GHashTable * params) { uniform_ret_execra_t exit_value; char ra_pathname[RA_MAX_NAME_LENGTH]; GHashTable * tmp_for_setenv; GString * params_gstring; char * inherit_debuglevel = NULL; get_ra_pathname(RA_PATH, rsc_type, provider, ra_pathname); /* Setup environment correctly */ tmp_for_setenv = g_hash_table_new(g_str_hash, g_str_equal); add_OCF_prefix(params, tmp_for_setenv); add_OCF_env_vars(tmp_for_setenv, rsc_id, rsc_type, provider); raexec_setenv(tmp_for_setenv); g_hash_table_foreach_remove(tmp_for_setenv, let_remove_eachitem, NULL); g_hash_table_destroy(tmp_for_setenv); /* let this log show only high loglevel. */ inherit_debuglevel = getenv(HADEBUGVAL); if ((inherit_debuglevel != NULL) && (atoi(inherit_debuglevel) > 1)) { params_gstring = g_string_new(""); hash_to_str(params, params_gstring); cl_log(LOG_DEBUG, "RA instance %s executing: OCF::%s %s. Parameters: " "{%s}", rsc_id, rsc_type, op_type, params_gstring->str); g_string_free(params_gstring, TRUE); } /* execute the RA */ execl(ra_pathname, ra_pathname, op_type, (const char *)NULL); cl_perror("(%s:%s:%d) execl failed for %s" , __FILE__, __FUNCTION__, __LINE__, ra_pathname); switch (errno) { case ENOENT: /* No such file or directory */ case EISDIR: /* Is a directory */ exit_value = EXECRA_NOT_INSTALLED; break; default: exit_value = EXECRA_EXEC_UNKNOWN_ERROR; } exit(exit_value); } static uniform_ret_execra_t map_ra_retvalue(int ret_execra, const char * op_type, const char * std_output) { /* Because the UNIFORM_RET_EXECRA is compatible with OCF standard, * no actual mapping except validating, which ensure the return code * will be in the range 0 to 7. Too strict? */ if (ret_execra < 0 || ret_execra > 9) { cl_log(LOG_WARNING, "mapped the invalid return code %d." , ret_execra); ret_execra = EXECRA_UNKNOWN_ERROR; } return ret_execra; } static gint compare_str(gconstpointer a, gconstpointer b) { return strncmp(a,b,RA_MAX_NAME_LENGTH); } static int get_resource_list(GList ** rsc_info) { struct dirent **namelist; GList* item; int file_num; char subdir[FILENAME_MAX+1]; if ( rsc_info == NULL ) { cl_log(LOG_ERR, "Parameter error: get_resource_list"); return -2; } if ( *rsc_info != NULL ) { cl_log(LOG_ERR, "Parameter error: get_resource_list."\ "will cause memory leak."); *rsc_info = NULL; } file_num = scandir(RA_PATH, &namelist, 0, alphasort); if (file_num < 0) { return -2; } while (file_num--) { GList* ra_subdir = NULL; struct stat prop; if ('.' == namelist[file_num]->d_name[0]) { free(namelist[file_num]); continue; } stat(namelist[file_num]->d_name, &prop); if (S_ISDIR(prop.st_mode)) { free(namelist[file_num]); continue; } snprintf(subdir,FILENAME_MAX,"%s/%s", RA_PATH, namelist[file_num]->d_name); get_runnable_list(subdir,&ra_subdir); merge_string_list(rsc_info,ra_subdir); while (NULL != (item = g_list_first(ra_subdir))) { ra_subdir = g_list_remove_link(ra_subdir, item); g_free(item->data); g_list_free_1(item); } free(namelist[file_num]); } free(namelist); return 0; } static void merge_string_list(GList** old, GList* new) { GList* item = NULL; char* newitem; for( item=g_list_first(new); NULL!=item; item=g_list_next(item)){ if (!g_list_find_custom(*old, item->data,compare_str)){ newitem = g_strndup(item->data,RA_MAX_NAME_LENGTH); *old = g_list_append(*old, newitem); } } } static int get_provider_list(const char* ra_type, GList ** providers) { int ret; ret = get_providers(RA_PATH, ra_type, providers); if (0>ret) { cl_log(LOG_ERR, "scandir failed in OCF RA plugin"); } return ret; } static char* get_resource_meta(const char* rsc_type, const char* provider) { const int BUFF_LEN=4096; int read_len = 0; char buff[BUFF_LEN]; char* data = NULL; GString* g_str_tmp = NULL; char ra_pathname[RA_MAX_NAME_LENGTH]; FILE* file = NULL; GHashTable * tmp_for_setenv; get_ra_pathname(RA_PATH, rsc_type, provider, ra_pathname); strncat(ra_pathname, " meta-data",RA_MAX_NAME_LENGTH-strlen(ra_pathname)-1); tmp_for_setenv = g_hash_table_new(g_str_hash, g_str_equal); add_OCF_env_vars(tmp_for_setenv, "DUMMY_INSTANCE", rsc_type, provider); raexec_setenv(tmp_for_setenv); g_hash_table_foreach_remove(tmp_for_setenv, let_remove_eachitem, NULL); g_hash_table_destroy(tmp_for_setenv); file = popen(ra_pathname, "r"); if (NULL==file) { return NULL; } g_str_tmp = g_string_new(""); while(!feof(file)) { - memset(buff, 0, BUFF_LEN); + *buff = '\0'; read_len = fread(buff, 1, BUFF_LEN - 1, file); if (0len) { pclose(file); return NULL; } data = (char*)g_new(char, g_str_tmp->len+1); data[0] = data[g_str_tmp->len] = 0; strncpy(data, g_str_tmp->str, g_str_tmp->len); g_string_free(g_str_tmp, TRUE); pclose(file); return data; } static void add_OCF_prefix(GHashTable * env_params, GHashTable * new_env_params) { if (env_params) { g_hash_table_foreach(env_params, add_prefix_foreach, new_env_params); } } static void add_prefix_foreach(gpointer key, gpointer value, gpointer user_data) { const int MAX_LENGTH_OF_ENV = 50; int prefix = STRLEN_CONST("OCF_RESKEY_"); GHashTable * new_hashtable = (GHashTable *) user_data; char * newkey; int keylen = strnlen((char*)key, MAX_LENGTH_OF_ENV-prefix)+prefix+1; newkey = g_new(gchar, keylen); strncpy(newkey, "OCF_RESKEY_", keylen); strncat(newkey, key, keylen-strlen(newkey)-1); g_hash_table_insert(new_hashtable, (gpointer)newkey, g_strdup(value)); } static void hash_to_str(GHashTable * params , GString * str) { if (params) { g_hash_table_foreach(params, hash_to_str_foreach, str); } } static void hash_to_str_foreach(gpointer key, gpointer value, gpointer user_data) { char buffer_tmp[60]; GString * str = (GString *)user_data; snprintf(buffer_tmp, 60, "%s=%s ", (char *)key, (char *)value); str = g_string_append(str, buffer_tmp); } static gboolean let_remove_eachitem(gpointer key, gpointer value, gpointer user_data) { g_free(key); g_free(value); return TRUE; } static int raexec_setenv(GHashTable * env_params) { if (env_params) { g_hash_table_foreach(env_params, set_env, NULL); } return 0; } static void set_env(gpointer key, gpointer value, gpointer user_data) { if (setenv(key, value, 1) != 0) { cl_log(LOG_ERR, "setenv failed in raexecocf."); } } static int get_providers(const char* class_path, const char* ra_type, GList ** providers) { struct dirent **namelist; int file_num; if ( providers == NULL ) { cl_log(LOG_ERR, "Parameter error: get_providers"); return -2; } if ( *providers != NULL ) { cl_log(LOG_ERR, "Parameter error: get_providers."\ "will cause memory leak."); *providers = NULL; } file_num = scandir(class_path, &namelist, 0, alphasort); if (file_num < 0) { return -2; }else{ char tmp_buffer[FILENAME_MAX+1]; struct stat prop; while (file_num--) { if ('.' == namelist[file_num]->d_name[0]) { free(namelist[file_num]); continue; } snprintf(tmp_buffer,FILENAME_MAX,"%s/%s", class_path, namelist[file_num]->d_name); stat(tmp_buffer, &prop); if (!S_ISDIR(prop.st_mode)) { free(namelist[file_num]); continue; } snprintf(tmp_buffer,FILENAME_MAX,"%s/%s/%s", class_path, namelist[file_num]->d_name, ra_type); if ( filtered(tmp_buffer) == TRUE ) { *providers = g_list_append(*providers, g_strdup(namelist[file_num]->d_name)); } free(namelist[file_num]); } free(namelist); } return g_list_length(*providers); } static void add_OCF_env_vars(GHashTable * env, const char * rsc_id, const char * rsc_type, const char * provider) { if ( env == NULL ) { cl_log(LOG_WARNING, "env should not be a NULL pointer."); return; } g_hash_table_insert(env, g_strdup("OCF_RA_VERSION_MAJOR"), g_strdup("1")); g_hash_table_insert(env, g_strdup("OCF_RA_VERSION_MINOR"), g_strdup("0")); g_hash_table_insert(env, g_strdup("OCF_ROOT"), g_strdup(OCF_ROOT_DIR)); if ( rsc_id != NULL ) { g_hash_table_insert(env, g_strdup("OCF_RESOURCE_INSTANCE"), g_strdup(rsc_id)); } /* Currently the rsc_type=="the filename of the RA script/executable", * It seems always correct even in the furture. ;-) */ if ( rsc_type != NULL ) { g_hash_table_insert(env, g_strdup("OCF_RESOURCE_TYPE"), g_strdup(rsc_type)); } /* Notes: this is not added to specification yet. Sept 10,2004 */ if ( provider != NULL ) { g_hash_table_insert(env, g_strdup("OCF_RESOURCE_PROVIDER"), g_strdup(provider)); } } diff --git a/tools/haresources2cib.py.in b/tools/haresources2cib.py.in index a7e9659514..5b00056d71 100755 --- a/tools/haresources2cib.py.in +++ b/tools/haresources2cib.py.in @@ -1,488 +1,517 @@ #!@PYTHON@ '''haresources2cib.py.in, convert the haresources file of heartbeat 1.x to cib.xml for heartbeat 2.x ''' __copyright__=''' Author: Huang Zhen Copyright (C) 2005 International Business Machines ''' # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. import sys,string,os import xml.dom.minidom using_ocf = 1 using_mon = 1 enable_stonith = False ocf_ra_setting = { - "apache" :{"params":["configfile","httpd","port","statusurl","options"],"time":["120s","60s"]}, - "IPaddr" :{"params":["ip","netmask","nic","broadcast"],"time":["5s","5s"]}, - "IPaddr2" :{"params":["ip","netmask","nic","broadcast"],"time":["5s","5s"]}, - "db2" :{"params":["instance"],"time":["120s","60s"]}, - "oracle" :{"params":["sid","home","user"],"time":["120s","60s"]}, + "apache" :{"params":["configfile","httpd","port","statusurl","options","testregex"],"time":["120s","60s"]}, + "IPaddr" :{"params":["ip","nic","cidr_netmask","broadcast","iflabel","lvs_support","local_stop_script","local_start_script","ARP_INTERVAL_MS","ARP_REPEAT","ARP_BACKGROUND","ARP_NETMASK"],"time":["5s","5s"]}, + "IPaddr2" :{"params":["ip","nic","cidr_netmask","broadcast","iflabel","lvs_support","mac","clusterip_hash","arp_interval","arp_count","arp_bg","arp_mac"],"time":["5s","5s"]}, + "db2" :{"params":["instance","admin"],"time":["120s","60s"]}, + "oracle" :{"params":["sid","home","user","ipcrm"],"time":["120s","60s"]}, "oralsnr" :{"params":["sid","home","user","listener"],"time":["120s","60s"]}, "AudibleAlarm":{"params":["nodelist"],"time":["120s","60s"]}, - "Delay" :{"params":["delay","stopdelay"],"time":["120s","60s"]}, - "Filesystem":{"params":["device","directory","fstype","options"],"time":["120s","60s"]}, + "Delay" :{"params":["startdelay","stopdelay","mondelay"],"time":["120s","60s"]}, + "Filesystem":{"params":["device","directory","fstype","options","ocfs2_cluster","ocfs2_configfs"],"time":["120s","60s"]}, "ICP" :{"params":["driveid","device"],"time":["120s","60s"]}, "IPsrcaddr" :{"params":["ipaddress"],"time":["5s","5s"]}, "IPv6addr" :{"params":["ipv6addr"],"time":["5s","5s"]}, "LinuxSCSI" :{"params":["scsi"],"time":["120s","60s"]}, "LVM" :{"params":["volgrpname"],"time":["120s","60s"]}, "MailTo" :{"params":["email","subject"],"time":["120s","60s"]}, "portblock" :{"params":["protocol","portno","action"],"time":["120s","60s"]}, "Raid1" :{"params":["raidconf","raiddev"],"time":["120s","60s"]}, "ServeRAID" :{"params":["serveraid","mergegroup"],"time":["120s","60s"]}, "WinPopup" :{"params":["hostfile"],"time":["120s","60s"]}, - "Xinetd" :{"params":["service"],"time":["120s","60s"]} + "Xinetd" :{"params":["service"],"time":["120s","60s"]}, + "ClusterMon" :{"params":["user","update","extra_options","pidfile","htmlfile"],"time":["120s","60s"]}, + "Dummy" :{"params":["state"],"time":["120s","60s"]}, + "EvmsSCC" :{"params":[],"time":["120s","60s"]}, + "Evmsd" :{"params":[],"time":["120s","60s"]}, + "ManageRAID" :{"params":["raidname"],"time":["120s","60s"]}, + "ManageVE" :{"params":["veid"],"time":["120s","60s"]}, + "Pure-FTPd" :{"params":["script","conffile"],"time":["120s","60s"]}, + "SAPDatabase" :{"params":["SID","DIR_EXECUTABLE","DBTYPE","NETSERVICENAME","DBJ2EE_ONLY","DIR_BOOTSTRAP","DIR_SECSTORE"],"time":["120s","60s"]}, + "SAPInstance" :{"params":["InstanceName","DIR_EXECUTABLE","DIR_PROFILE","START_PROFILE"],"time":["120s","60s"]}, + "SendArp" :{"params":["ip","nic"],"time":["120s","60s"]}, + "Stateful" :{"params":["state"],"time":["120s","60s"]}, + "SysInfo" :{"params":["pidfile","delay"],"time":["120s","60s"]}, + "VIPArip" :{"params":["ip","nic"],"time":["120s","60s"]}, + "WAS" :{"params":["config","port"],"time":["120s","60s"]}, + "WAS6" :{"params":["profile"],"time":["120s","60s"]}, + "Xen" :{"params":["xmfile"],"time":["120s","60s"]}, + "drbd" :{"params":["drbd_resource","drbdconf","clone_overrides_hostname","clone_max","clone_node_max","master_max","master_node_max"],"time":["120s","60s"]}, + "eDir88" :{"params":["eDir_config_file","eDir_monitor_ldap","eDir_monitor_idm","eDir_jvm_initial_heap","eDir_jvm_max_heap","eDir_jvm_options"],"time":["120s","60s"]}, + "ids" :{"params":["informixdir","informixserver","onconfig","dbname","sqltestquery"],"time":["120s","60s"]}, + "mysql" :{"params":["binary","config","datadir","user","group","test_table","test_user","test_passwd","enable_creation"],"time":["120s","60s"]}, + "o2cb" :{"params":["netdev","port","ocfs2_cluster"],"time":["120s","60s"]}, + "pgsql" :{"params":[],"time":["120s","60s"]}, + "pingd" :{"params":["pidfile","user","dampen","set","name","section","multiplier","host_list"],"time":["120s","60s"]}, + "rsyncd" :{"params":["binpath","conffile","bwlimit"],"time":["120s","60s"]} } config_defaults = [ "symmetric-cluster=true", "no-quorum-policy=stop", "default-resource-stickiness=0", "default-resource-failure-stickiness=0", "stonith-enabled=false", "stonith-action=reboot", + "startup-fencing=true", "stop-orphan-resources=true", "stop-orphan-actions=true", "remove-after-stop=false", "short-resource-names=true", "transition-idle-timeout=5min", "default-action-timeout=15s", "is-managed-default=true", + "cluster-delay=60s", + "pe-error-series-max=-1", + "pe-warn-series-max=-1", + "pe-input-series-max=-1", ] def create_cib() : doc = xml.dom.minidom.Document() cib = doc.createElement("cib") doc.appendChild(cib) configuration = doc.createElement("configuration") cib.appendChild(configuration) cib.setAttribute("admin_epoch","0") cib.setAttribute("epoch","0") cib.setAttribute("num_updates","0") crm_config = doc.createElement("crm_config") configuration.appendChild(crm_config) option_set = doc.createElement("cluster_property_set") option_set.setAttribute("id","cib-bootstrap-options") crm_config.appendChild(option_set) attr_list = doc.createElement("attributes") option_set.appendChild(attr_list) for option in config_defaults: option_details = string.split(option, '=') nvpair = doc.createElement("nvpair") attr_list.appendChild(nvpair) nvpair.setAttribute("id", "cib-bootstrap-options-"+option_details[0]) nvpair.setAttribute("name", option_details[0]) nvpair.setAttribute("value", option_details[1]) if option_details[0] == "stonith_enabled" and enable_stonith: nvpair.setAttribute("value", "true") configuration.appendChild(doc.createElement("nodes")) resources = doc.createElement("resources") configuration.appendChild(resources) constraints = doc.createElement("constraints") configuration.appendChild(constraints) status = doc.createElement("status") cib.appendChild(status) return doc, resources, constraints def get_ra_class(type) : if os.path.exists("@HB_RA_DIR@"+"/"+type) : return "heartbeat" if os.path.exists("@LSB_RA_DIR@"+"/"+type) : return "lsb" sys.stderr.write(type+" is an unknown Resource Agent. " \ "Please refer to http://www.linux-ha.org/ResourceAgent\n") return "UNKNOWN" def cib_resource(doc,user_res_id,index, rsc): id, type, params = None, None, None #if no parameters in rsc, like "apache", "192.168.0.11" if string.find(rsc, "::") == -1 : #if there is a IP address in rsc, like "192.168.0.11" if len(string.split(string.split(rsc,'/')[0],'.')) == 4 : type = "IPaddr" params = [rsc] #no IP address, like "apache" else : type = rsc #else there have "::" in rsc, #like "IPaddr::192.168.0.11", "IPaddr2::192.168.0.11" else : if string.find(rsc, "IPaddr") == 0 : type = string.split(rsc, "::")[0] params = [string.split(rsc, "::")[1]] else : fields = string.split(rsc,"::") type = fields[0] params = fields[1:] if user_res_id == "" : if type == "IPaddr" : id = type+"_"+string.replace(string.split(params[0],'/')[0],'.','_') else : id = type+"_"+str(index) else : id = user_res_id resource = doc.createElement("primitive") resource.setAttribute("id",id) resource.setAttribute("type",type) if using_ocf and type in ocf_ra_setting: resource.setAttribute("class","ocf") else : ra_class = get_ra_class(type) resource.setAttribute("class",ra_class) resource.setAttribute("provider","heartbeat") if using_mon : operations = doc.createElement("operations") resource.appendChild(operations) mon_op = doc.createElement("op") operations.appendChild(mon_op) mon_op.setAttribute("id", id + "_mon") mon_op.setAttribute("name","monitor") interval = "120s" timeout = "60s" if using_ocf and type in ocf_ra_setting : interval = ocf_ra_setting[type]["time"][0] timeout = ocf_ra_setting[type]["time"][1] mon_op.setAttribute("interval", interval) mon_op.setAttribute("timeout", timeout) if params != None and len(params) != 0: instance_attributes = doc.createElement("instance_attributes") instance_attributes.setAttribute("id", id + "_inst_attr") resource.appendChild(instance_attributes) attributes = doc.createElement("attributes") instance_attributes.appendChild(attributes) if using_ocf and type in ocf_ra_setting : if type in ["IPaddr", "IPaddr2"] : unsort = string.split(params[0], "/") params = [None, None, None, None] #ip params[0] = unsort[0] for param in unsort[1:] : if len(string.split(param, ".")) == 4 : #broadcast params[3] = param break try : int(param) #netmask bits params[1] = param except ValueError: #nic params[2] = param for i in range(0,len(params)) : if params[i] == None : continue nvpair = doc.createElement("nvpair") name = ocf_ra_setting[type]["params"][i] nvpair.setAttribute("id",id + "_attr_" + str(i)) nvpair.setAttribute("name",name) if i == len(ocf_ra_setting[type]["params"]) - 1 : nvpair.setAttribute("value",string.join(params[i:])) attributes.appendChild(nvpair) break else : nvpair.setAttribute("value",str(params[i])) attributes.appendChild(nvpair) else : i = 1 for param in params : nvpair = doc.createElement("nvpair") nvpair.setAttribute("id",id + "_attr_" + str(i)) nvpair.setAttribute("name",str(i)) nvpair.setAttribute("value",str(param)) attributes.appendChild(nvpair) i += 1 return id, resource def cib_rsc_order(doc, args): rsc_order = doc.createElement("rsc_order") rsc_order.setAttribute("id","rsc_order_"+args[0]+"_"+args[3]) rsc_order.setAttribute("from",args[0]) rsc_order.setAttribute("action",args[1]) rsc_order.setAttribute("type",args[2]) rsc_order.setAttribute("to",args[3]) rsc_order.setAttribute("symmetrical","true") return rsc_order def cib_rsc_colocation(doc, args): if len(args) != 3 : sys.stderr.write("rsc_colocation: bad usage\n") return rsc_colocation = doc.createElement("rsc_colocation") rsc_colocation.setAttribute("id","rsc_colocation_"+args[0]+"_"+args[1]) rsc_colocation.setAttribute("from",args[0]) rsc_colocation.setAttribute("to",args[1]) rsc_colocation.setAttribute("score",args[2]) return rsc_colocation def cib_rsc_location(doc, id, node): rsc_location = doc.createElement("rsc_location") rsc_location.setAttribute("id","rsc_location_"+id) rsc_location.setAttribute("rsc",id) rule = doc.createElement("rule") rule.setAttribute("id","prefered_location_"+id) rule.setAttribute("score","100") rsc_location.appendChild(rule) expression = doc.createElement("expression") expression.setAttribute("id","prefered_location_"+id+"_expr") expression.setAttribute("attribute","#uname") expression.setAttribute("operation","eq") expression.setAttribute("value", node) rule.appendChild(expression) return rsc_location def cib_resource_group(doc, id): resource_group = doc.createElement("group") resource_group.setAttribute("id",id) return resource_group def cib_resource_clone(doc, id, clone_max, clone_node_max): resource_clone = doc.createElement("clone") resource_clone.setAttribute("id",id) instance_attributes = doc.createElement("instance_attributes") instance_attributes.setAttribute("id", id + "_inst_attr") resource_clone.appendChild(instance_attributes) attributes = doc.createElement("attributes") instance_attributes.appendChild(attributes) nvpair = doc.createElement("nvpair") nvpair.setAttribute("id",id + "_attr_1") nvpair.setAttribute("name", "clone_max") nvpair.setAttribute("value", str(clone_max)) attributes.appendChild(nvpair) nvpair = doc.createElement("nvpair") nvpair.setAttribute("id",id + "_attr_2") nvpair.setAttribute("name", "clone_node_max") nvpair.setAttribute("value", str(clone_node_max)) attributes.appendChild(nvpair) return resource_clone def add_resource(cib,user_res_id,index,node,rsc): id,resource = cib_resource(cib[0],user_res_id,index,rsc) cib[1].appendChild(resource) rsc_location = cib_rsc_location(cib[0],id,node) cib[2].appendChild(rsc_location) def add_resource_group(cib,user_res_id,index,node,rscs): if user_res_id == "" : groupid = "group_"+str(group_index) else : groupid = user_res_id resource_group = cib_resource_group(cib[0],groupid) cib[1].appendChild(resource_group) for rsc in rscs : rid,resource = cib_resource(cib[0],"",index,rsc) resource_group.appendChild(resource) index += 1 rsc_location = cib_rsc_location(cib[0],groupid,node) cib[2].appendChild(rsc_location) def add_clone(cib,user_res_id, index,rsc) : if user_res_id == "" : cloneid = "clone_"+str(index) else : cloneid = user_res_id clone = cib_resource_clone(cib[0], cloneid, node_num, 1) cib[1].appendChild(clone) id,resource = cib_resource(cib[0],"",index,rsc) clone.appendChild(resource) def add_stonith_clone(cib, index, params, node_num) : clone = cib_resource_clone(cib[0], "clone_"+str(index), node_num, 1) cib[1].appendChild(clone) id, stonith = cib_stonith(cib[0], index, params) clone.appendChild(stonith) def cib_stonith(doc, index, params): id = "stonith_"+str(index) resource = doc.createElement("primitive") resource.setAttribute("id",id) resource.setAttribute("type",params[1]) resource.setAttribute("class","stonith") resource.setAttribute("provider","heartbeat") if using_mon : operations = doc.createElement("operations") resource.appendChild(operations) mon_op = doc.createElement("op") operations.appendChild(mon_op) mon_op.setAttribute("id", id + "_mon") mon_op.setAttribute("name","monitor") mon_op.setAttribute("interval", "5s") mon_op.setAttribute("timeout", "20s") mon_op.setAttribute("prereq", "nothing") start_op = doc.createElement("op") operations.appendChild(start_op) start_op.setAttribute("id", id + "_start") start_op.setAttribute("name","start") start_op.setAttribute("timeout", "20s") start_op.setAttribute("prereq", "nothing") if len(params) > 2 : instance_attributes = doc.createElement("instance_attributes") instance_attributes.setAttribute("id", id + "_inst_attr") resource.appendChild(instance_attributes) attributes = doc.createElement("attributes") instance_attributes.appendChild(attributes) names = string.split(os.popen("stonith -n -t "+params[1]).readline()) for i in range(2, len(params)) : nvpair = doc.createElement("nvpair") nvpair.setAttribute("id", id + "_attr_" + str(i)) nvpair.setAttribute("name", names[i-2]) nvpair.setAttribute("value", params[i]) attributes.appendChild(nvpair) return id, resource def add_stonith_host(cib, stonith_host, index, node_num) : params = string.split(stonith_host)[1:] if params[0] == "*" : add_stonith_clone(cib, index, params, node_num) else : id, resource = cib_stonith(cib[0], index, params) cib[1].appendChild(resource) stonith_location = cib_rsc_location(cib[0],id,params[0]) cib[2].appendChild(stonith_location) def get_directive_list(config, directive) : directive_list = [] for line in config : line = line.lstrip() if len (line) == 0 or line[0] == "#" : continue if string.split(line)[0] == directive : directive_list.append(line) return directive_list if __name__=="__main__" : resource_file = "@HA_HBCONF_DIR@/haresources" config_file = "@HA_HBCONF_DIR@/ha.cf" target_file = "@HA_VARLIBHBDIR@/crm/cib.xml" to_stdout = False # Process arguments... skipthis = None args = sys.argv[1:] for i in range(0, len(args)) : if skipthis : skipthis = None continue elif args[i] == "--no-ocf" : using_ocf = 0 elif args[i] == "--stdout" : to_stdout = True elif args[i] == "--no-monitor" : using_mon = 0 elif args[i] == "--config" or args[i] == "-c" : skipthis = True config_file = args[i+1] elif args[i] == "--help" or args[i] == "-h" : print "usage: " + sys.argv[0] \ + " [--no-ocf]"\ + " [--stdout]"\ + " [--no-monitor]"\ + " [--config|-c configfile]"\ + " [--help|-h]"\ + " [resourcefile]" sys.exit(1) else: resource_file = args[i] config = open(config_file, "r").readlines() node_list = get_directive_list(config, "node") node_num = 0 for nodes in node_list : node_num += len(string.split(nodes)) -1 stonith_host_list = get_directive_list(config, "stonith_host") if len(stonith_host_list) != 0 : enable_stonith = True file = open(resource_file, "r") cib = create_cib() pre_line = "" id_index = 1 group_index = 1 for line in file.readlines() : line = string.strip(line) if len (line) == 0 : continue if line[0] == '#' and string.find(line,"#rsc_order") != 0 and string.find(line,"#rsc_colocation") != 0 : continue if line[-1] == '\\' : pre_line += line[:-1] + " " continue else : line = pre_line + line pre_line = "" fields = string.split(line) if fields[len(fields)-1][0] == '#' : user_res_id = fields[len(fields)-1][1:] fields.pop() else : user_res_id = "" if fields[0] == "#rsc_order" and len(fields) == 5 : rsc_order = cib_rsc_order(cib[0],fields[1:]) cib[2].appendChild(rsc_order) elif fields[0] == "#rsc_colocation" and len(fields) == 4 : rsc_colocation = cib_rsc_colocation(cib[0],fields[1:]) cib[2].appendChild(rsc_colocation) elif string.find(user_res_id, "clone:") == 0 : add_clone(cib, user_res_id[len("clone:"):], group_index, fields[1]) group_index += 10 id_index += 1 elif len(fields) == 2 : add_resource(cib, user_res_id, id_index, fields[0], fields[1]) id_index += 1 elif len(fields) > 2 : add_resource_group(cib, user_res_id, group_index, fields[0], fields[1:]) group_index += 10 id_index += len(fields) else : sys.stderr.write("can not parse this line:"+line+"\n") if enable_stonith : for stonith_host in stonith_host_list : add_stonith_host(cib, stonith_host, id_index, node_num) id_index += 1 if to_stdout : print cib[0].toprettyxml() elif os.access(target_file, os.F_OK) or os.access(target_file+".sig", os.F_OK) : sys.stderr.write("cib.xml or cib.xml.sig exist in @HA_VARLIBHBDIR@/crm/\n") sys.stderr.write("please remove them before generating new cib.xml\n") else : cib_file = open(target_file, "w") cib_file.write(cib[0].toprettyxml()) cib_file.close() os.system("chown @HA_CCMUSER@.@HA_APIGROUP@ "+target_file)