def cluster_localnode(argv): if len(argv) != 2: usage.cluster() exit(1) elif argv[0] == "add": node = argv[1] if not utils.is_rhel6(): success = utils.addNodeToCorosync(node) else: success = utils.addNodeToClusterConf(node) if success: print "%s: successfully added!" % node else: utils.err("unable to add %s" % node) elif argv[0] in ["remove","delete"]: node = argv[1] if not utils.is_rhel6(): success = utils.removeNodeFromCorosync(node) else: success = utils.removeNodeFromClusterConf(node) if success: print "%s: successfully removed!" % node else: utils.err("unable to remove %s" % node) else: usage.cluster() exit(1)
def stop_cluster(argv): if len(argv) > 0: failure = False errors = "" for node in argv: (retval, err) = utils.stopCluster(node) if retval != 0: failure = True errors = errors + err+"\n" if failure: utils.err("unable to stop all nodes\n" + errors.rstrip()) return print "Stopping Cluster..." output, retval = utils.run(["service", "pacemaker","stop"]) if retval != 0: print output, utils.err("unable to stop pacemaker") if utils.is_rhel6(): output, retval = utils.run(["service", "cman","stop"]) if retval != 0: print output, utils.err("unable to stop cman") else: output, retval = utils.run(["service", "corosync","stop"]) if retval != 0: print output, utils.err("unable to stop corosync")
def start_cluster(argv): if len(argv) > 0: failure = False errors = "" for node in argv: (retval, err) = utils.startCluster(node) if retval != 0: failure = True errors = errors + err + "\n" if failure: utils.err("unable to start all nodes\n" + errors.rstrip()) return print "Starting Cluster..." if utils.is_rhel6(): # Verify that CMAN_QUORUM_TIMEOUT is set, if not, then we set it to 0 retval, output = commands.getstatusoutput( 'source /etc/sysconfig/cman ; [ -z "$CMAN_QUORUM_TIMEOUT" ]') if retval == 0: with open("/etc/sysconfig/cman", "a") as cman_conf_file: cman_conf_file.write("\nCMAN_QUORUM_TIMEOUT=0\n") output, retval = utils.run(["service", "cman", "start"]) if retval != 0: print output utils.err("unable to start cman") else: output, retval = utils.run(["service", "corosync", "start"]) if retval != 0: print output utils.err("unable to start corosync") output, retval = utils.run(["service", "pacemaker", "start"]) if retval != 0: print output utils.err("unable to start pacemaker")
def stop_cluster(argv): if len(argv) > 0: failure = False errors = "" for node in argv: (retval, err) = utils.stopCluster(node) if retval != 0: failure = True errors = errors + err + "\n" if failure: utils.err("unable to stop all nodes\n" + errors.rstrip()) return print "Stopping Cluster..." output, retval = utils.run(["service", "pacemaker", "stop"]) if retval != 0: print output, utils.err("unable to stop pacemaker") if utils.is_rhel6(): output, retval = utils.run(["service", "cman", "stop"]) if retval != 0: print output, utils.err("unable to stop cman") else: output, retval = utils.run(["service", "corosync", "stop"]) if retval != 0: print output, utils.err("unable to stop corosync")
def cluster_destroy(argv): if "--all" in utils.pcs_options: threads = {} for node in utils.getNodesFromCorosyncConf(): threads[node] = DestroyClusterThread(node) threads[node].start() for thread in threads.values(): thread.join() else: print "Shutting down pacemaker/corosync services..." print os.system("service pacemaker stop") print os.system("service corosync stop") print "Killing any remaining services..." os.system( "killall -q -9 corosync aisexec heartbeat pacemakerd ccm stonithd ha_logd lrmd crmd pengine attrd pingd mgmtd cib fenced dlm_controld gfs_controld" ) print "Removing all cluster configuration files..." if utils.is_rhel6(): os.system("rm /etc/cluster/cluster.conf") else: os.system("rm /etc/corosync/corosync.conf") state_files = [ "cib.xml*", "cib-*", "core.*", "hostcache", "cts.*", "pe*.bz2", "cib.*" ] for name in state_files: os.system("find /var/lib -name '" + name + "' -exec rm -f \{\} \;")
def full_status(): if "--full" in utils.pcs_options: (output, retval) = utils.run(["crm_mon", "-1", "-r", "-R", "-A", "-f"]) else: (output, retval) = utils.run(["crm_mon", "-1", "-r"]) if (retval != 0): utils.err("cluster is not currently running on this node") if not utils.usefile or "--corosync_conf" in utils.pcs_options: cluster_name = utils.getClusterName() print "Cluster name: %s" % cluster_name if utils.stonithCheck(): print("WARNING: no stonith devices and stonith-enabled is not false") if utils.corosyncPacemakerNodeCheck(): print("WARNING: corosync and pacemaker node names do not match (IPs used in setup?)") print output if not utils.usefile: if not utils.is_rhel6(): print "PCSD Status:" cluster.cluster_gui_status([],True) print "" utils.serviceStatus(" ")
def cluster_destroy(argv): if "--all" in utils.pcs_options: threads = {} for node in utils.getNodesFromCorosyncConf(): threads[node] = DestroyClusterThread(node) threads[node].start() for thread in threads.values(): thread.join() else: print "Shutting down pacemaker/corosync services..." print os.system("service pacemaker stop") print os.system("service corosync stop") print "Killing any remaining services..." os.system("killall -q -9 corosync aisexec heartbeat pacemakerd ccm stonithd ha_logd lrmd crmd pengine attrd pingd mgmtd cib fenced dlm_controld gfs_controld") utils.disableServices() print "Removing all cluster configuration files..." if utils.is_rhel6(): os.system("rm /etc/cluster/cluster.conf") else: os.system("rm /etc/corosync/corosync.conf") state_files = ["cib.xml*", "cib-*", "core.*", "hostcache", "cts.*", "pe*.bz2","cib.*"] for name in state_files: os.system("find /var/lib -name '"+name+"' -exec rm -f \{\} \;")
def start_cluster(argv): if len(argv) > 0: failure = False errors = "" for node in argv: (retval, err) = utils.startCluster(node) if retval != 0: failure = True errors = errors + err+"\n" if failure: utils.err("unable to start all nodes\n" + errors.rstrip()) return print "Starting Cluster..." if utils.is_rhel6(): # Verify that CMAN_QUORUM_TIMEOUT is set, if not, then we set it to 0 retval, output = commands.getstatusoutput('source /etc/sysconfig/cman ; [ -z "$CMAN_QUORUM_TIMEOUT" ]') if retval == 0: with open("/etc/sysconfig/cman", "a") as cman_conf_file: cman_conf_file.write("\nCMAN_QUORUM_TIMEOUT=0\n") output, retval = utils.run(["service", "cman","start"]) if retval != 0: print output utils.err("unable to start cman") else: output, retval = utils.run(["service", "corosync","start"]) if retval != 0: print output utils.err("unable to start corosync") output, retval = utils.run(["service", "pacemaker", "start"]) if retval != 0: print output utils.err("unable to start pacemaker")
def start_cluster(argv): if len(argv) > 0: start_cluster_nodes(argv) return print "Starting Cluster..." if utils.is_rhel6(): # Verify that CMAN_QUORUM_TIMEOUT is set, if not, then we set it to 0 retval, output = commands.getstatusoutput('source /etc/sysconfig/cman ; [ -z "$CMAN_QUORUM_TIMEOUT" ]') if retval == 0: with open("/etc/sysconfig/cman", "a") as cman_conf_file: cman_conf_file.write("\nCMAN_QUORUM_TIMEOUT=0\n") output, retval = utils.run(["service", "cman","start"]) if retval != 0: print output utils.err("unable to start cman") else: output, retval = utils.run(["service", "corosync","start"]) if retval != 0: print output utils.err("unable to start corosync") output, retval = utils.run(["service", "pacemaker", "start"]) if retval != 0: print output utils.err("unable to start pacemaker")
def corosync_setup(argv,returnConfig=False): fedora_config = not utils.is_rhel6() if len(argv) < 2: usage.cluster() exit(1) if not returnConfig and "--start" in utils.pcs_options and not "--local" in utils.pcs_options and fedora_config: sync_start(argv) return elif not returnConfig and not "--local" in utils.pcs_options and fedora_config: sync(argv) return else: nodes = argv[1:] cluster_name = argv[0] # Verify that all nodes are resolvable otherwise problems may occur for node in nodes: try: socket.gethostbyname(node) except socket.error: print "Warning: Unable to resolve hostname: %s" % node if fedora_config == True: f = open(COROSYNC_CONFIG_FEDORA_TEMPLATE, 'r') corosync_config = f.read() f.close() i = 1 new_nodes_section = "" for node in nodes: new_nodes_section += " node {\n" new_nodes_section += " ring0_addr: %s\n" % (node) new_nodes_section += " nodeid: %d\n" % (i) new_nodes_section += " }\n" i = i+1 corosync_config = corosync_config.replace("@@nodes", new_nodes_section) corosync_config = corosync_config.replace("@@cluster_name",cluster_name) if returnConfig: return corosync_config utils.setCorosyncConf(corosync_config) else: output, retval = utils.run(["/usr/sbin/ccs", "-i", "-f", "/etc/cluster/cluster.conf", "--createcluster", cluster_name]) if retval != 0: print output print "Error creating cluster:", cluster_name sys.exit(1) for node in nodes: output, retval = utils.run(["/usr/sbin/ccs", "-f", "/etc/cluster/cluster.conf", "--addnode", node]) if retval != 0: print output print "Error adding node:", node sys.exit(1) if "--start" in utils.pcs_options: start_cluster([])
def config_restore_remote(infile_name, infile_obj): extracted = { "version.txt": "", "corosync.conf": "", "cluster.conf": "", } try: tarball = tarfile.open(infile_name, "r|*", infile_obj) while True: tar_member_info = tarball.next() if tar_member_info is None: break if tar_member_info.name in extracted: tar_member = tarball.extractfile(tar_member_info) extracted[tar_member_info.name] = tar_member.read() tar_member.close() tarball.close() except (tarfile.TarError, EnvironmentError) as e: utils.err("unable to read the tarball: %s" % e) config_backup_check_version(extracted["version.txt"]) node_list = utils.getNodesFromCorosyncConf( extracted["cluster.conf" if utils.is_rhel6() else "corosync.conf"] ) if not node_list: utils.err("no nodes found in the tarball") for node in node_list: try: retval, output = utils.checkStatus(node) if retval != 0: utils.err("unable to determine status of the node %s" % node) status = json.loads(output) if status["corosync"] or status["pacemaker"] or status["cman"]: utils.err( "Cluster is currently running on node %s. You need to stop " "the cluster in order to restore the configuration." % node ) except (ValueError, NameError): utils.err("unable to determine status of the node %s" % node) if infile_obj: infile_obj.seek(0) tarball_data = infile_obj.read() else: with open(infile_name, "r") as tarball: tarball_data = tarball.read() error_list = [] for node in node_list: retval, error = utils.restoreConfig(node, tarball_data) if retval != 0: error_list.append(error) if error_list: utils.err("unable to restore all nodes\n" + "\n".join(error_list))
def testIPV6(self): if utils.is_rhel6(): print "WARNING: not testing IPV6 due to RHEL6" return o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name cnam rh7-1 rh7-2 --ipv6") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cnam\ntransport: udpu\nip_version: ipv6\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n')
def config_backup_path_list(with_uid_gid=False, force_rhel6=None): rhel6 = utils.is_rhel6() if force_rhel6 is None else force_rhel6 corosync_attrs = { "mtime": int(time.time()), "mode": 0644, "uname": "root", "gname": "root", "uid": 0, "gid": 0, }
def config_backup_path_list(with_uid_gid=False, force_rhel6=None): rhel6 = utils.is_rhel6() if force_rhel6 is None else force_rhel6 root_attrs = { "mtime": int(time.time()), "mode": 0644, "uname": "root", "gname": "root", "uid": 0, "gid": 0, }
def config_restore_remote(infile_name, infile_obj): extracted = { "version.txt": "", "corosync.conf": "", "cluster.conf": "", } try: tarball = tarfile.open(infile_name, "r|*", infile_obj) while True: tar_member_info = tarball.next() if tar_member_info is None: break if tar_member_info.name in extracted: tar_member = tarball.extractfile(tar_member_info) extracted[tar_member_info.name] = tar_member.read() tar_member.close() tarball.close() except (tarfile.TarError, EnvironmentError) as e: utils.err("unable to read the tarball: %s" % e) config_backup_check_version(extracted["version.txt"]) node_list = utils.getNodesFromCorosyncConf( extracted["cluster.conf" if utils.is_rhel6() else "corosync.conf"]) if not node_list: utils.err("no nodes found in the tarball") for node in node_list: try: retval, output = utils.checkStatus(node) if retval != 0: utils.err("unable to determine status of the node %s" % node) status = json.loads(output) if status["corosync"] or status["pacemaker"] or status["cman"]: utils.err( "Cluster is currently running on node %s. You need to stop " "the cluster in order to restore the configuration." % node) except (ValueError, NameError): utils.err("unable to determine status of the node %s" % node) if infile_obj: infile_obj.seek(0) tarball_data = infile_obj.read() else: with open(infile_name, "r") as tarball: tarball_data = tarball.read() error_list = [] for node in node_list: retval, error = utils.restoreConfig(node, tarball_data) if retval != 0: error_list.append(error) if error_list: utils.err("unable to restore all nodes\n" + "\n".join(error_list))
def config_backup_path_list(with_uid_gid=False, force_rhel6=None): rhel6 = utils.is_rhel6() if force_rhel6 is None else force_rhel6 corosync_attrs = { "mtime": int(time.time()), "mode": 0o644, "uname": "root", "gname": "root", "uid": 0, "gid": 0, } cib_attrs = { "mtime": int(time.time()), "mode": 0o600, "uname": settings.pacemaker_uname, "gname": settings.pacemaker_gname, } if with_uid_gid: try: cib_attrs["uid"] = pwd.getpwnam(cib_attrs["uname"]).pw_uid except KeyError: utils.err( "Unable to determine uid of user '%s'" % cib_attrs["uname"] ) try: cib_attrs["gid"] = grp.getgrnam(cib_attrs["gname"]).gr_gid except KeyError: utils.err( "Unable to determine gid of group '%s'" % cib_attrs["gname"] ) file_list = { "cib.xml": { "path": os.path.join(settings.cib_dir, "cib.xml"), "required": True, "attrs": dict(cib_attrs), }, } if rhel6: file_list["cluster.conf"] = { "path": settings.cluster_conf_file, "required": True, "attrs": dict(corosync_attrs), } else: file_list["corosync.conf"] = { "path": settings.corosync_conf_file, "required": True, "attrs": dict(corosync_attrs), } file_list["uidgid.d"] = { "path": settings.corosync_uidgid_dir.rstrip("/"), "required": False, "attrs": dict(corosync_attrs), } return file_list
def testTotemOptions(self): if utils.is_rhel6(): print "WARNING: Not testing totem options due to RHEL6" return o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name test99 rh7-1 rh7-2 --token 20000 --join 20001 --consensus 20002 --miss_count_const 20003 --fail_recv_const 20004 --token_coefficient 20005") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: test99\ntransport: udpu\ntoken: 20000\ntoken_coefficient: 20005\njoin: 20001\nconsensus: 20002\nmiss_count_const: 20003\nfail_recv_const: 20004\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n')
def testTotemOptions(self): if utils.is_rhel6(): print "WARNING: Not testing totem options due to RHEL6" return o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name test99 rh7-1 rh7-2 --token 20000 --join 20001 --consensus 20002 --miss_count_const 20003 --fail_recv_const 20004") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: test99\ntransport: udpu\ntoken: 20000\njoin: 20001\nconsensus: 20002\nmiss_count_const: 20003\nfail_recv_const: 20004\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n')
def cluster_uidgid(argv, silent_list = False): if utils.is_rhel6(): cluster_uidgid_rhel6(argv, silent_list) return if len(argv) == 0: found = False uid_gid_files = os.listdir(settings.corosync_uidgid_dir) for ug_file in uid_gid_files: uid_gid_dict = utils.read_uid_gid_file(ug_file) if "uid" in uid_gid_dict or "gid" in uid_gid_dict: line = "UID/GID: uid=" if "uid" in uid_gid_dict: line += uid_gid_dict["uid"] line += " gid=" if "gid" in uid_gid_dict: line += uid_gid_dict["gid"] print line found = True if not found and not silent_list: print "No uidgids configured in cluster.conf" return command = argv.pop(0) uid="" gid="" if (command == "add" or command == "rm") and len(argv) > 0: for arg in argv: if arg.find('=') == -1: utils.err("uidgid options must be of the form uid=<uid> gid=<gid>") (k,v) = arg.split('=',1) if k != "uid" and k != "gid": utils.err("%s is not a valid key, you must use uid or gid" %k) if k == "uid": uid = v if k == "gid": gid = v if uid == "" and gid == "": utils.err("you must set either uid or gid") if command == "add": utils.write_uid_gid_file(uid,gid) elif command == "rm": retval = utils.remove_uid_gid_file(uid,gid) if retval == False: utils.err("no uidgid files with uid=%s and gid=%s found" % (uid,gid)) else: usage.cluster(["uidgid"]) exit(1)
def config_backup_path_list(with_uid_gid=False, force_rhel6=None): rhel6 = utils.is_rhel6() if force_rhel6 is None else force_rhel6 corosync_attrs = { "mtime": int(time.time()), "mode": 0o644, "uname": "root", "gname": "root", "uid": 0, "gid": 0, } cib_attrs = { "mtime": int(time.time()), "mode": 0o600, "uname": settings.pacemaker_uname, "gname": settings.pacemaker_gname, } if with_uid_gid: try: cib_attrs["uid"] = pwd.getpwnam(cib_attrs["uname"]).pw_uid except KeyError: utils.err("Unable to determine uid of user '%s'" % cib_attrs["uname"]) try: cib_attrs["gid"] = grp.getgrnam(cib_attrs["gname"]).gr_gid except KeyError: utils.err("Unable to determine gid of group '%s'" % cib_attrs["gname"]) file_list = { "cib.xml": { "path": os.path.join(settings.cib_dir, "cib.xml"), "required": True, "attrs": dict(cib_attrs), }, } if rhel6: file_list["cluster.conf"] = { "path": settings.cluster_conf_file, "required": True, "attrs": dict(corosync_attrs), } else: file_list["corosync.conf"] = { "path": settings.corosync_conf_file, "required": True, "attrs": dict(corosync_attrs), } file_list["uidgid.d"] = { "path": settings.corosync_uidgid_dir.rstrip("/"), "required": False, "attrs": dict(corosync_attrs), } return file_list
def test_stonith_create_provides_unfencing_rhel6(self): if not utils.is_rhel6(): return output, returnVal = pcs( temp_cib, "stonith create f1 fence_mpath key=abc" ) ac(output, "") self.assertEqual(0, returnVal) output, returnVal = pcs( temp_cib, "stonith create f2 fence_mpath key=abc meta provides=unfencing" ) ac(output, "") self.assertEqual(0, returnVal) output, returnVal = pcs( temp_cib, "stonith create f3 fence_mpath key=abc meta provides=something" ) ac(output, "") self.assertEqual(0, returnVal) output, returnVal = pcs( temp_cib, "stonith create f4 fence_xvm meta provides=something" ) ac(output, "") self.assertEqual(0, returnVal) output, returnVal = pcs(temp_cib, "stonith show --full") ac(output, """\ Resource: f1 (class=stonith type=fence_mpath) Attributes: key=abc Meta Attrs: provides=unfencing Operations: monitor interval=60s (f1-monitor-interval-60s) Resource: f2 (class=stonith type=fence_mpath) Attributes: key=abc Meta Attrs: provides=unfencing Operations: monitor interval=60s (f2-monitor-interval-60s) Resource: f3 (class=stonith type=fence_mpath) Attributes: key=abc Meta Attrs: provides=unfencing Operations: monitor interval=60s (f3-monitor-interval-60s) Resource: f4 (class=stonith type=fence_xvm) Meta Attrs: provides=something Operations: monitor interval=60s (f4-monitor-interval-60s) """) self.assertEqual(0, returnVal)
def cluster_gui_status(argv,dont_exit = False): bad_nodes = False if len(argv) == 0: nodes = utils.getNodesFromCorosyncConf() if len(nodes) == 0: if utils.is_rhel6(): utils.err("no nodes found in cluster.conf") else: utils.err("no nodes found in corosync.conf") bad_nodes = check_nodes(nodes, " ") else: bad_nodes = check_nodes(argv, " ") if bad_nodes and not dont_exit: sys.exit(1)
def testCreation(self): if utils.is_rhel6(): return output, returnVal = pcs(temp_cib, "cluster") assert returnVal == 1 assert output.startswith("\nUsage: pcs cluster [commands]...") output, returnVal = pcs(temp_cib, "cluster setup --local --corosync_conf=corosync.conf.tmp cname rh7-1 rh7-2") assert returnVal == 1 assert output.startswith("Error: A cluster name (--name <name>) is required to setup a cluster\n") # Setup a 2 node cluster and make sure the two node config is set, then add a # node and make sure that it's unset, then remove a node and make sure it's # set again output, returnVal = pcs(temp_cib, "cluster setup --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2") assert output == "" assert returnVal == 0 with open("corosync.conf.tmp") as f: data = f.read() assert data == 'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n',[data] output, returnVal = pcs(temp_cib, "cluster localnode add --corosync_conf=corosync.conf.tmp rh7-3") assert returnVal == 0 assert output == "rh7-3: successfully added!\n",output with open("corosync.conf.tmp") as f: data = f.read() assert data == 'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n node {\n ring0_addr: rh7-3\n nodeid: 3\n }\n}\n\nquorum {\nprovider: corosync_votequorum\n}\n\nlogging {\nto_syslog: yes\n}\n',[data] output, returnVal = pcs(temp_cib, "cluster localnode remove --corosync_conf=corosync.conf.tmp rh7-3") assert returnVal == 0 assert output == "rh7-3: successfully removed!\n",output with open("corosync.conf.tmp") as f: data = f.read() assert data == 'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n',[data] output, returnVal = pcs(temp_cib, "cluster setup --local --corosync_conf=corosync.conf2.tmp --name cname rh7-1 rh7-2 rh7-3") assert returnVal == 0 assert output == "" with open("corosync.conf2.tmp") as f: data = f.read() assert data == 'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n node {\n ring0_addr: rh7-3\n nodeid: 3\n }\n}\n\nquorum {\nprovider: corosync_votequorum\n\n}\n\nlogging {\nto_syslog: yes\n}\n',[data]
def cluster_get_corosync_conf(argv): if utils.is_rhel6(): utils.err("corosync.conf is not supported on RHEL6") if len(argv) > 1: usage.cluster() exit(1) if len(argv) == 0: print utils.getCorosyncConf() return node = argv[0] retval, output = utils.getCorosyncConfig(node) if retval != 0: utils.err(output) else: print output
def full_status(): (output, retval) = utils.run(["crm_mon", "-1", "-r"]) if (retval != 0): utils.err("cluster is not currently running on this node") cluster_name = utils.getClusterName() print "Cluster name: %s" % cluster_name if utils.stonithCheck(): print("WARNING: no stonith devices and stonith-enabled is not false") print output print "" if not utils.is_rhel6(): print "PCSD Status:" cluster.cluster_gui_status([], True) print "" utils.serviceStatus(" ")
def full_status(): (output, retval) = utils.run(["crm_mon", "-1", "-r"]) if (retval != 0): utils.err("cluster is not currently running on this node") cluster_name = utils.getClusterName() print "Cluster name: %s" % cluster_name if utils.stonithCheck(): print("WARNING: no stonith devices and stonith-enabled is not false") print output print "" if not utils.is_rhel6(): print "PCSD Status:" cluster.cluster_gui_status([],True) print "" utils.serviceStatus(" ")
def stop_cluster(argv): if len(argv) > 0: stop_cluster_nodes(argv) return print "Stopping Cluster..." output, retval = utils.run(["service", "pacemaker","stop"]) if retval != 0: print output, utils.err("unable to stop pacemaker") if utils.is_rhel6(): output, retval = utils.run(["service", "cman","stop"]) if retval != 0: print output, utils.err("unable to stop cman") else: output, retval = utils.run(["service", "corosync","stop"]) if retval != 0: print output, utils.err("unable to stop corosync")
def start_cluster(argv): if len(argv) > 0: for node in argv: utils.startCluster(node) return print "Starting Cluster..." if utils.is_rhel6(): output, retval = utils.run(["service", "cman","start"]) if retval != 0: print output utils.err("unable to start cman") else: output, retval = utils.run(["service", "corosync","start"]) if retval != 0: print output utils.err("unable to start corosync") output, retval = utils.run(["service", "pacemaker", "start"]) if retval != 0: print output utils.err("unable to start pacemaker")
def config_backup_path_list(): file_list = { "cib.xml": { "path": os.path.join(settings.cib_dir, "cib.xml"), "required": True, }, } if utils.is_rhel6(): file_list["cluster.conf"] = { "path": settings.cluster_conf_file, "required": True, } else: file_list["corosync.conf"] = { "path": settings.corosync_conf_file, "required": True, } file_list["uidgid.d"] = { "path": settings.corosync_uidgid_dir.rstrip("/"), "required": False, } return file_list
def full_status(): if "--full" in utils.pcs_options: (output, retval) = utils.run(["crm_mon", "-1", "-r", "-R"]) else: (output, retval) = utils.run(["crm_mon", "-1", "-r"]) if (retval != 0): utils.err("cluster is not currently running on this node") if not utils.usefile or "--corosync_conf" in utils.pcs_options: cluster_name = utils.getClusterName() print "Cluster name: %s" % cluster_name if utils.stonithCheck(): print("WARNING: no stonith devices and stonith-enabled is not false") print output if not utils.usefile: if not utils.is_rhel6(): print "PCSD Status:" cluster.cluster_gui_status([], True) print "" utils.serviceStatus(" ")
def stop_cluster(argv): if len(argv) > 0: for node in argv: utils.stopCluster(node) return print "Stopping Cluster..." output, retval = utils.run(["service", "pacemaker","stop"]) if retval != 0: print output, print "Error: unable to stop pacemaker" sys.exit(1) if utils.is_rhel6(): output, retval = utils.run(["service", "cman","stop"]) if retval != 0: print output, print "Error: unable to stop cman" sys.exit(1) else: output, retval = utils.run(["service", "corosync","stop"]) if retval != 0: print output, print "Error: unable to stop corosync" sys.exit(1)
def corosync_setup(argv,returnConfig=False): fedora_config = not utils.is_rhel6() failure = False primary_nodes = [] # If node contains a ',' we only care about the first address for node in argv[1:]: if "," in node: primary_nodes.append(node.split(',')[0]) else: primary_nodes.append(node) if len(argv) < 2: usage.cluster() exit(1) if not returnConfig and "--start" in utils.pcs_options and not "--local" in utils.pcs_options:# and fedora_config: sync_start(argv, primary_nodes) if "--enable" in utils.pcs_options: enable_cluster(primary_nodes) return elif not returnConfig and not "--local" in utils.pcs_options:# and fedora_config: sync(argv, primary_nodes) if "--enable" in utils.pcs_options: enable_cluster(primary_nodes) return else: nodes = argv[1:] cluster_name = argv[0] # Verify that all nodes are resolvable otherwise problems may occur udpu_rrp = False for node in nodes: try: if "," in node: socket.getaddrinfo(node.split(",")[0],None) socket.getaddrinfo(node.split(",")[1],None) udpu_rrp = True else: socket.getaddrinfo(node,None) except socket.error: print "Warning: Unable to resolve hostname: %s" % node failure = True if udpu_rrp: for node in nodes: if "," not in node: utils.err("if one node is configured for RRP, all nodes must configured for RRP") if failure and "--force" not in utils.pcs_options: utils.err("Unable to resolve all hostnames (use --force to override).") if fedora_config == True: if os.path.exists(settings.corosync_conf_file) and not "--force" in utils.pcs_options: utils.err("%s already exists, use --force to overwrite" % settings.corosync_conf_file) if not ("--corosync_conf" in utils.pcs_options and "--local" in utils.pcs_options): cib_path = os.path.join(settings.cib_dir, "cib.xml") if os.path.exists(cib_path) and not "--force" in utils.pcs_options: utils.err("%s already exists, use --force to overwrite" % cib_path) if "--corosync_conf" not in utils.pcs_options: cluster_destroy([]) f = open(COROSYNC_CONFIG_FEDORA_TEMPLATE, 'r') corosync_config = f.read() f.close() i = 1 new_nodes_section = "" for node in nodes: new_nodes_section += " node {\n" if udpu_rrp: new_nodes_section += " ring0_addr: %s\n" % (node.split(",")[0]) new_nodes_section += " ring1_addr: %s\n" % (node.split(",")[1]) else: new_nodes_section += " ring0_addr: %s\n" % (node) new_nodes_section += " nodeid: %d\n" % (i) new_nodes_section += " }\n" i = i+1 two_node_section = "" if len(nodes) == 2: two_node_section = "two_node: 1" quorum_options = "" if "--wait_for_all" in utils.pcs_options: quorum_options += "wait_for_all: " + utils.pcs_options["--wait_for_all"] + "\n" if "--auto_tie_breaker" in utils.pcs_options: quorum_options += "auto_tie_breaker: " + utils.pcs_options["--auto_tie_breaker"] + "\n" if "--last_man_standing" in utils.pcs_options: quorum_options += "last_man_standing: " + utils.pcs_options["--last_man_standing"] + "\n" if "--last_man_standing_window" in utils.pcs_options: quorum_options += "last_man_standing_window: " + utils.pcs_options["--last_man_standing_window"] + "\n" transport = "udpu" if "--transport" in utils.pcs_options: transport = utils.pcs_options["--transport"] ir = "" if transport == "udpu" and ("--addr0" in utils.pcs_options or "--addr1" in utils.pcs_options): utils.err("--addr0 and --addr1 can only be used with --transport=udp") if "--rrpmode" in utils.pcs_options or udpu_rrp or "--addr0" in utils.pcs_options: rrpmode = "passive" if "--rrpmode" in utils.pcs_options: rrpmode = utils.pcs_options["--rrpmode"] if rrpmode == "active" and "--force" not in utils.pcs_options: utils.err("using a RRP mode of 'active' is not supported or tested, use --force to override") elif rrpmode != "passive" and "--force" not in utils.pcs_options: utils.err("%s is an unknown RRP mode, use --force to override" % rrpmode) ir += "rrp_mode: " + rrpmode + "\n" if transport == "udp": if "--addr0" in utils.pcs_options: ir += utils.generate_rrp_corosync_config(0) if "--addr1" in utils.pcs_options: ir += utils.generate_rrp_corosync_config(1) if "--ipv6" in utils.pcs_options: ip_version = "ip_version: ipv6\n" else: ip_version = "" totem_options = "" if "--token" in utils.pcs_options: totem_options += "token: " + utils.pcs_options["--token"] + "\n" if "--token_coefficient" in utils.pcs_options: totem_options += "token_coefficient: " + utils.pcs_options["--token_coefficient"] + "\n" if "--join" in utils.pcs_options: totem_options += "join: " + utils.pcs_options["--join"] + "\n" if "--consensus" in utils.pcs_options: totem_options += "consensus: " + utils.pcs_options["--consensus"] + "\n" if "--miss_count_const" in utils.pcs_options: totem_options += "miss_count_const: " + utils.pcs_options["--miss_count_const"] + "\n" if "--fail_recv_const" in utils.pcs_options: totem_options += "fail_recv_const: " + utils.pcs_options["--fail_recv_const"] + "\n" corosync_config = corosync_config.replace("@@nodes", new_nodes_section) corosync_config = corosync_config.replace("@@cluster_name",cluster_name) corosync_config = corosync_config.replace("@@quorum_options\n",quorum_options) corosync_config = corosync_config.replace("@@two_node",two_node_section) corosync_config = corosync_config.replace("@@transport",transport) corosync_config = corosync_config.replace("@@interfaceandrrpmode\n",ir) corosync_config = corosync_config.replace("@@ip_version\n",ip_version) corosync_config = corosync_config.replace("@@totem_options\n",totem_options) if returnConfig: return corosync_config utils.setCorosyncConf(corosync_config) else: cluster_conf_location = "/etc/cluster/cluster.conf" if returnConfig: cc_temp = tempfile.NamedTemporaryFile('w+b', -1, ".pcs") cluster_conf_location = cc_temp.name if os.path.exists("/etc/cluster/cluster.conf") and not "--force" in utils.pcs_options and not returnConfig: print "Error: /etc/cluster/cluster.conf already exists, use --force to overwrite" sys.exit(1) output, retval = utils.run(["/usr/sbin/ccs", "-i", "-f", cluster_conf_location, "--createcluster", cluster_name]) if retval != 0: print output utils.err("error creating cluster: %s" % cluster_name) output, retval = utils.run(["/usr/sbin/ccs", "-i", "-f", cluster_conf_location, "--addfencedev", "pcmk-redirect", "agent=fence_pcmk"]) if retval != 0: print output utils.err("error creating fence dev: %s" % cluster_name) if len(nodes) == 2: output, retval = utils.run(["/usr/sbin/ccs", "-f", cluster_conf_location, "--setcman", "two_node=1", "expected_votes=1"]) if retval != 0: print output utils.err("error adding node: %s" % node) for node in nodes: output, retval = utils.run(["/usr/sbin/ccs", "-f", cluster_conf_location, "--addnode", node]) if retval != 0: print output utils.err("error adding node: %s" % node) output, retval = utils.run(["/usr/sbin/ccs", "-i", "-f", cluster_conf_location, "--addmethod", "pcmk-method", node]) if retval != 0: print output utils.err("error adding fence method: %s" % node) output, retval = utils.run(["/usr/sbin/ccs", "-i", "-f", cluster_conf_location, "--addfenceinst", "pcmk-redirect", node, "pcmk-method", "port="+node]) if retval != 0: print output utils.err("error adding fence instance: %s" % node) if returnConfig: cc_temp.seek(0) cluster_conf_data = cc_temp.read() cc_temp.close() return cluster_conf_data if "--start" in utils.pcs_options: start_cluster([]) if "--enable" in utils.pcs_options: enable_cluster([])
def config_export_pcs_commands(argv, verbose=False): if no_clufter: utils.err( "Unable to perform export due to missing python-clufter package" ) # parse options debug = "--debug" in utils.pcs_options force = "--force" in utils.pcs_options interactive = "--interactive" in utils.pcs_options invalid_args = False output_file = None for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "output": output_file = value else: invalid_args = True else: invalid_args = True if invalid_args or not output_file: usage.config(["export", "pcs-commands"]) sys.exit(1) # prepare convertor options clufter_args = { "nocheck": force, "batch": True, "sys": "linux", # Make it work on RHEL6 as well for sure "color": "always" if sys.stdout.isatty() else "never", "coro": settings.corosync_conf_file, "ccs": settings.cluster_conf_file, "output": {"passin": "bytestring"}, "start_wait": "60", "tmp_cib": "tmp-cib.xml", "force": force, "text_width": "80", "silent": True, "noguidance": True, } if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if utils.usefile: clufter_args["cib"] = os.path.abspath(utils.filename) else: clufter_args["cib"] = ("bytestring", utils.get_cib()) if verbose: clufter_args["text_width"] = "-1" clufter_args["silent"] = False clufter_args["noguidance"] = False clufter_args_obj = type(str("ClufterOptions"), (object, ), clufter_args) cmd_name = "pcs2pcscmd-flatiron" if utils.is_rhel6() else "pcs2pcscmd-needle" # run convertor run_clufter( cmd_name, clufter_args_obj, debug, force, "Error: unable to export cluster configuration" ) # save commands ok, message = utils.write_file( output_file, clufter_args_obj.output["passout"] ) if not ok: utils.err(message)
def config_import_cman(argv): if no_clufter: utils.err("Unable to perform a CMAN cluster conversion due to missing python-clufter package") # prepare convertor options cluster_conf = settings.cluster_conf_file dry_run_output = None output_format = "cluster.conf" if utils.is_rhel6() else "corosync.conf" invalid_args = False for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "input": cluster_conf = value elif name == "output": dry_run_output = value elif name == "output-format": if value in ( "cluster.conf", "corosync.conf", "pcs-commands", "pcs-commands-verbose", ): output_format = value else: invalid_args = True else: invalid_args = True else: invalid_args = True if ( output_format not in ("pcs-commands", "pcs-commands-verbose") and (dry_run_output and not dry_run_output.endswith(".tar.bz2")) ): dry_run_output += ".tar.bz2" if invalid_args or not dry_run_output: usage.config(["import-cman"]) sys.exit(1) debug = "--debug" in utils.pcs_options force = "--force" in utils.pcs_options interactive = "--interactive" in utils.pcs_options clufter_args = { "input": str(cluster_conf), "cib": {"passin": "bytestring"}, "nocheck": force, "batch": True, "sys": "linux", # Make it work on RHEL6 as well for sure "color": "always" if sys.stdout.isatty() else "never" } if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if output_format == "cluster.conf": clufter_args["ccs_pcmk"] = {"passin": "bytestring"} clufter_args["dist"] = "redhat,6.7,Santiago" cmd_name = "ccs2pcs-flatiron" elif output_format == "corosync.conf": clufter_args["coro"] = {"passin": "struct"} clufter_args["dist"] = "redhat,7.1,Maipo" cmd_name = "ccs2pcs-needle" elif output_format in ("pcs-commands", "pcs-commands-verbose"): clufter_args["output"] = {"passin": "bytestring"} clufter_args["start_wait"] = "60" clufter_args["tmp_cib"] = "tmp-cib.xml" clufter_args["force"] = force clufter_args["text_width"] = "80" clufter_args["silent"] = True clufter_args["noguidance"] = True if output_format == "pcs-commands-verbose": clufter_args["text_width"] = "-1" clufter_args["silent"] = False clufter_args["noguidance"] = False cmd_name = "ccs2pcscmd-flatiron" clufter_args_obj = type(str("ClufterOptions"), (object, ), clufter_args) # run convertor run_clufter( cmd_name, clufter_args_obj, debug, force, "Error: unable to import cluster configuration" ) # save commands if output_format in ("pcs-commands", "pcs-commands-verbose"): ok, message = utils.write_file( dry_run_output, clufter_args_obj.output["passout"] ) if not ok: utils.err(message) return # put new config files into tarball file_list = config_backup_path_list( force_rhel6=(output_format == "cluster.conf") ) for file_item in file_list.values(): file_item["attrs"]["uname"] = "root" file_item["attrs"]["gname"] = "root" file_item["attrs"]["uid"] = 0 file_item["attrs"]["gid"] = 0 file_item["attrs"]["mode"] = 0o600 tar_data = BytesIO() try: tarball = tarfile.open(fileobj=tar_data, mode="w|bz2") config_backup_add_version_to_tarball(tarball) utils.tar_add_file_data( tarball, clufter_args_obj.cib["passout"].encode("utf-8"), "cib.xml", **file_list["cib.xml"]["attrs"] ) if output_format == "cluster.conf": utils.tar_add_file_data( tarball, clufter_args_obj.ccs_pcmk["passout"].encode("utf-8"), "cluster.conf", **file_list["cluster.conf"]["attrs"] ) else: # put uidgid into separate files fmt_simpleconfig = clufter.format_manager.FormatManager.init_lookup( 'simpleconfig' ).plugins['simpleconfig'] corosync_struct = [] uidgid_list = [] for section in clufter_args_obj.coro["passout"][2]: if section[0] == "uidgid": uidgid_list.append(section[1]) else: corosync_struct.append(section) corosync_conf_data = fmt_simpleconfig( "struct", ("corosync", (), corosync_struct) )("bytestring") utils.tar_add_file_data( tarball, corosync_conf_data.encode("utf-8"), "corosync.conf", **file_list["corosync.conf"]["attrs"] ) for uidgid in uidgid_list: uid = "" gid = "" for item in uidgid: if item[0] == "uid": uid = item[1] if item[0] == "gid": gid = item[1] filename = utils.get_uid_gid_file_name(uid, gid) uidgid_data = fmt_simpleconfig( "struct", ("corosync", (), [("uidgid", uidgid, None)]) )("bytestring") utils.tar_add_file_data( tarball, uidgid_data.encode("utf-8"), "uidgid.d/" + filename, **file_list["uidgid.d"]["attrs"] ) tarball.close() except (tarfile.TarError, EnvironmentError) as e: utils.err("unable to create tarball: %s" % e) tar_data.seek(0) #save tarball / remote restore if dry_run_output: ok, message = utils.write_file( dry_run_output, tar_data.read(), permissions=0o600, binary=True ) if not ok: utils.err(message) else: config_restore_remote(None, tar_data) tar_data.close()
def config_restore_remote(infile_name, infile_obj): extracted = { "version.txt": "", "corosync.conf": "", "cluster.conf": "", } try: tarball = tarfile.open(infile_name, "r|*", infile_obj) while True: # next(tarball) does not work in python2.6 tar_member_info = tarball.next() if tar_member_info is None: break if tar_member_info.name in extracted: tar_member = tarball.extractfile(tar_member_info) extracted[tar_member_info.name] = tar_member.read() tar_member.close() tarball.close() except (tarfile.TarError, EnvironmentError) as e: utils.err("unable to read the tarball: %s" % e) config_backup_check_version(extracted["version.txt"]) node_list = utils.getNodesFromCorosyncConf( extracted["cluster.conf" if utils.is_rhel6() else "corosync.conf"].decode("utf-8") ) if not node_list: utils.err("no nodes found in the tarball") err_msgs = [] for node in node_list: try: retval, output = utils.checkStatus(node) if retval != 0: err_msgs.append(output) continue status = json.loads(output) if status["corosync"] or status["pacemaker"] or status["cman"]: err_msgs.append( "Cluster is currently running on node %s. You need to stop " "the cluster in order to restore the configuration." % node ) continue except (ValueError, NameError): err_msgs.append("unable to determine status of the node %s" % node) if err_msgs: for msg in err_msgs: utils.err(msg, False) sys.exit(1) # Temporarily disable config files syncing thread in pcsd so it will not # rewrite restored files. 10 minutes should be enough time to restore. # If node returns HTTP 404 it does not support config syncing at all. for node in node_list: retval, output = utils.pauseConfigSyncing(node, 10 * 60) if not (retval == 0 or output.endswith("(HTTP error: 404)")): utils.err(output) if infile_obj: infile_obj.seek(0) tarball_data = infile_obj.read() else: with open(infile_name, "rb") as tarball: tarball_data = tarball.read() error_list = [] for node in node_list: retval, error = utils.restoreConfig(node, tarball_data) if retval != 0: error_list.append(error) if error_list: utils.err("unable to restore all nodes\n" + "\n".join(error_list))
def testRRPConfig(self): if utils.is_rhel6(): print "WARNING: not testing RRPConfig due to RHEL6" return o,r = pcs("cluster setup --transport udp --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --addr1 1.1.2.0") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udp\nrrp_mode: passive\n interface {\n ringnumber: 0\n bindnetaddr: 1.1.1.0\n mcastaddr: 239.255.1.1\n mcastport: 5405\n }\n interface {\n ringnumber: 1\n bindnetaddr: 1.1.2.0\n mcastaddr: 239.255.2.1\n mcastport: 5405\n }\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --transport udp --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --mcast0 8.8.8.8 --addr1 1.1.2.0 --mcast1 9.9.9.9") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udp\nrrp_mode: passive\n interface {\n ringnumber: 0\n bindnetaddr: 1.1.1.0\n mcastaddr: 8.8.8.8\n mcastport: 5405\n }\n interface {\n ringnumber: 1\n bindnetaddr: 1.1.2.0\n mcastaddr: 9.9.9.9\n mcastport: 5405\n }\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --transport udp --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --mcastport0 9999 --mcastport1 9998 --addr1 1.1.2.0") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udp\nrrp_mode: passive\n interface {\n ringnumber: 0\n bindnetaddr: 1.1.1.0\n mcastaddr: 239.255.1.1\n mcastport: 9999\n }\n interface {\n ringnumber: 1\n bindnetaddr: 1.1.2.0\n mcastaddr: 239.255.2.1\n mcastport: 9998\n }\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --addr1 1.1.2.0 --ttl0 4 --ttl1 5 --transport udp") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udp\nrrp_mode: passive\n interface {\n ringnumber: 0\n bindnetaddr: 1.1.1.0\n mcastaddr: 239.255.1.1\n mcastport: 5405\n ttl: 4\n }\n interface {\n ringnumber: 1\n bindnetaddr: 1.1.2.0\n mcastaddr: 239.255.2.1\n mcastport: 5405\n ttl: 5\n }\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --addr1 1.1.2.0 --rrpmode active --transport udp") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udp\nrrp_mode: active\n interface {\n ringnumber: 0\n bindnetaddr: 1.1.1.0\n mcastaddr: 239.255.1.1\n mcastport: 5405\n }\n interface {\n ringnumber: 1\n bindnetaddr: 1.1.2.0\n mcastaddr: 239.255.2.1\n mcastport: 5405\n }\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --addr1 1.1.2.0 --rrpmode active --broadcast0 --transport udp") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udp\nrrp_mode: active\n interface {\n ringnumber: 0\n bindnetaddr: 1.1.1.0\n broadcast: yes\n }\n interface {\n ringnumber: 1\n bindnetaddr: 1.1.2.0\n mcastaddr: 239.255.2.1\n mcastport: 5405\n }\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1,192.168.99.1 rh7-2,192.168.99.2") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udpu\nrrp_mode: passive\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n ring1_addr: 192.168.99.1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n ring1_addr: 192.168.99.2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --local --corosync_conf=corosync.conf.tmp --name cname rh7-1,192.168.99.1 rh7-2") ac(o,"Error: if one node is configured for RRP, all nodes must configured for RRP\n") assert r == 1 o,r = pcs("cluster setup --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --addr0 1.1.2.0") assert r == 1 ac(o, "Error: --addr0 can only be used once\n") o,r = pcs("cluster setup --local --corosync_conf=corosync.conf.tmp --name cname nonexistant-address") assert r == 1 ac(o,"Error: Unable to resolve all hostnames (use --force to override).\nWarning: Unable to resolve hostname: nonexistant-address\n") o,r = pcs("cluster setup --local --corosync_conf=corosync.conf.tmp --name cname nonexistant-address --force") assert r == 0 ac(o,"Warning: Unable to resolve hostname: nonexistant-address\n") o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name test99 rh7-1 rh7-2 --wait_for_all=2 --auto_tie_breaker=3 --last_man_standing=4 --last_man_standing_window=5") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: test99\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\nwait_for_all: 2\nauto_tie_breaker: 3\nlast_man_standing: 4\nlast_man_standing_window: 5\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name test99 rh7-1 rh7-2 --wait_for_all=1 --auto_tie_breaker=1 --last_man_standing=1 --last_man_standing_window=12000") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: test99\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\nwait_for_all: 1\nauto_tie_breaker: 1\nlast_man_standing: 1\nlast_man_standing_window: 12000\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --force --local --name test99 rh7-1 rh7-2 --addr0 1.1.1.1") assert r == 1 ac(o,"Error: --addr0 and --addr1 can only be used with --transport=udp\n") os.remove("corosync.conf.tmp") o,r = pcs("cluster setup --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --addr1 1.1.2.0 --rrpmode active --broadcast0 --transport udp") assert r == 1 ac("Error: using a RRP mode of 'active' is not supported or tested, use --force to override\n",o) o,r = pcs("cluster setup --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --addr1 1.1.2.0 --rrpmode blah --broadcast0 --transport udp") assert r == 1 ac("Error: blah is an unknown RRP mode, use --force to override\n", o) o,r = pcs("cluster setup --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --addr1 1.1.2.0 --rrpmode passive --broadcast0 --transport udp") assert r == 0 ac("", o) os.remove("corosync.conf.tmp") o,r = pcs("cluster setup --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --addr1 1.1.2.0 --broadcast0 --transport udp") assert r == 0 ac("", o)
def config_import_cman(argv): if no_clufter: utils.err( "Unable to perform a CMAN cluster conversion due to missing python-clufter package" ) # prepare convertor options cluster_conf = settings.cluster_conf_file dry_run_output = None rhel6 = utils.is_rhel6() invalid_args = False for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "input": cluster_conf = value elif name == "output": dry_run_output = value if not dry_run_output.endswith(".tar.bz2"): dry_run_output += ".tar.bz2" elif name == "output-format": if value == "corosync.conf": rhel6 = False elif value == "cluster.conf": rhel6 = True else: invalid_args = True else: invalid_args = True else: invalid_args = True if invalid_args or not dry_run_output: usage.config(["import-cman"]) sys.exit(1) debug = "--debug" in utils.pcs_options force = "--force" in utils.pcs_options interactive = "--interactive" in utils.pcs_options clufter_args = { "input": cluster_conf, "cib": { "passin": "bytestring" }, "nocheck": force, "batch": True, "sys": "linux", } if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if rhel6: clufter_args["ccs_pcmk"] = {"passin": "bytestring"} clufter_args["dist"] = "redhat,6.7,Santiago" else: clufter_args["coro"] = {"passin": "struct"} clufter_args["dist"] = "redhat,7.1,Maipo" clufter_args_obj = type('ClufterOptions', (object, ), clufter_args) # run convertor try: cmd_name = "ccs2pcs-flatiron" if rhel6 else "ccs2pcs-needle" result = None cmd_manager = clufter.command_manager.CommandManager.init_lookup( cmd_name) result = cmd_manager.commands[cmd_name](clufter_args_obj) error_message = "" except Exception as e: error_message = str(e) if error_message or result != 0: hints = [] hints.append("--interactive to solve the issues manually") if not debug: hints.append("--debug to get more information") if not force: hints.append("--force to override") hints_string = "\nTry using %s." % ", ".join(hints) if hints else "" sys.stderr.write("Error: unable to import cluster configuration" + (": %s" % error_message if error_message else "") + hints_string + "\n") sys.exit(1 if result is None else result) # put new config files into tarball file_list = config_backup_path_list(force_rhel6=rhel6) for file_item in file_list.values(): file_item["attrs"]["uname"] = "root" file_item["attrs"]["gname"] = "root" file_item["attrs"]["uid"] = 0 file_item["attrs"]["gid"] = 0 file_item["attrs"]["mode"] = 0o600 tar_data = cStringIO.StringIO() try: tarball = tarfile.open(fileobj=tar_data, mode="w|bz2") config_backup_add_version_to_tarball(tarball) utils.tar_add_file_data(tarball, clufter_args_obj.cib["passout"], "cib.xml", **file_list["cib.xml"]["attrs"]) if rhel6: utils.tar_add_file_data(tarball, clufter_args_obj.ccs_pcmk["passout"], "cluster.conf", **file_list["cluster.conf"]["attrs"]) else: # put uidgid into separate files fmt_simpleconfig = clufter.format_manager.FormatManager.init_lookup( 'simpleconfig').plugins['simpleconfig'] corosync_struct = [] uidgid_list = [] for section in clufter_args_obj.coro["passout"][2]: if section[0] == "uidgid": uidgid_list.append(section[1]) else: corosync_struct.append(section) corosync_conf_data = fmt_simpleconfig( "struct", ("corosync", (), corosync_struct))("bytestring") utils.tar_add_file_data(tarball, corosync_conf_data, "corosync.conf", **file_list["corosync.conf"]["attrs"]) for uidgid in uidgid_list: uid = "" gid = "" for item in uidgid: if item[0] == "uid": uid = item[1] if item[0] == "gid": gid = item[1] filename = utils.get_uid_gid_file_name(uid, gid) uidgid_data = fmt_simpleconfig( "struct", ("corosync", (), [("uidgid", uidgid, None)]))("bytestring") utils.tar_add_file_data(tarball, uidgid_data, "uidgid.d/" + filename, **file_list["uidgid.d"]["attrs"]) tarball.close() except (tarfile.TarError, EnvironmentError) as e: utils.err("unable to create tarball: %s" % e) tar_data.seek(0) #save tarball / remote restore if dry_run_output: ok, message = utils.write_file(dry_run_output, tar_data.read(), 0o600) if not ok: utils.err(message) else: config_restore_remote(None, tar_data) tar_data.close()
def config_restore_remote(infile_name, infile_obj): extracted = { "version.txt": "", "corosync.conf": "", "cluster.conf": "", } try: tarball = tarfile.open(infile_name, "r|*", infile_obj) while True: tar_member_info = next(tarball) if tar_member_info is None: break if tar_member_info.name in extracted: tar_member = tarball.extractfile(tar_member_info) extracted[tar_member_info.name] = tar_member.read() tar_member.close() tarball.close() except (tarfile.TarError, EnvironmentError) as e: utils.err("unable to read the tarball: %s" % e) config_backup_check_version(extracted["version.txt"]) node_list = utils.getNodesFromCorosyncConf( extracted["cluster.conf" if utils.is_rhel6() else "corosync.conf"]) if not node_list: utils.err("no nodes found in the tarball") err_msgs = [] for node in node_list: try: retval, output = utils.checkStatus(node) if retval != 0: err_msgs.append(output) continue status = json.loads(output) if status["corosync"] or status["pacemaker"] or status["cman"]: err_msgs.append( "Cluster is currently running on node %s. You need to stop " "the cluster in order to restore the configuration." % node) continue except (ValueError, NameError): err_msgs.append("unable to determine status of the node %s" % node) if err_msgs: for msg in err_msgs: utils.err(msg, False) sys.exit(1) # Temporarily disable config files syncing thread in pcsd so it will not # rewrite restored files. 10 minutes should be enough time to restore. # If node returns HTTP 404 it does not support config syncing at all. for node in node_list: retval, output = utils.pauseConfigSyncing(node, 10 * 60) if not (retval == 0 or output.endswith("(HTTP error: 404)")): utils.err(output) if infile_obj: infile_obj.seek(0) tarball_data = infile_obj.read() else: with open(infile_name, "r") as tarball: tarball_data = tarball.read() error_list = [] for node in node_list: retval, error = utils.restoreConfig(node, tarball_data) if retval != 0: error_list.append(error) if error_list: utils.err("unable to restore all nodes\n" + "\n".join(error_list))
def corosync_setup(argv,returnConfig=False): fedora_config = not utils.is_rhel6() failure = False if len(argv) < 2: usage.cluster() exit(1) if not returnConfig and "--start" in utils.pcs_options and not "--local" in utils.pcs_options and fedora_config: sync_start(argv) if "--enable" in utils.pcs_options: enable_cluster(argv[1:]) return elif not returnConfig and not "--local" in utils.pcs_options and fedora_config: sync(argv) if "--enable" in utils.pcs_options: enable_cluster(argv[1:]) return else: nodes = argv[1:] cluster_name = argv[0] # Verify that all nodes are resolvable otherwise problems may occur for node in nodes: try: socket.gethostbyname(node) except socket.error: print "Warning: Unable to resolve hostname: %s" % node failure = True if failure: utils.err("Unable to resolve all hostnames.") if fedora_config == True: f = open(COROSYNC_CONFIG_FEDORA_TEMPLATE, 'r') corosync_config = f.read() f.close() i = 1 new_nodes_section = "" for node in nodes: new_nodes_section += " node {\n" new_nodes_section += " ring0_addr: %s\n" % (node) new_nodes_section += " nodeid: %d\n" % (i) new_nodes_section += " }\n" i = i+1 two_node_section = "" if len(nodes) == 2: two_node_section = "two_node: 1" corosync_config = corosync_config.replace("@@nodes", new_nodes_section) corosync_config = corosync_config.replace("@@cluster_name",cluster_name) corosync_config = corosync_config.replace("@@two_node",two_node_section) if returnConfig: return corosync_config utils.setCorosyncConf(corosync_config) else: if os.path.exists("/etc/cluster/cluster.conf") and not "--force" in utils.pcs_options: print "Error: /etc/cluster/cluster.conf already exists, use --force to overwrite" sys.exit(1) output, retval = utils.run(["/usr/sbin/ccs", "-i", "-f", "/etc/cluster/cluster.conf", "--createcluster", cluster_name]) if retval != 0: print output utils.err("error creating cluster: %s" % cluster_name) output, retval = utils.run(["/usr/sbin/ccs", "-i", "-f", "/etc/cluster/cluster.conf", "--addfencedev", "pcmk-redirect", "agent=fence_pcmk"]) if retval != 0: print output utils.err("error creating fence dev: %s" % cluster_name) if len(nodes) == 2: output, retval = utils.run(["/usr/sbin/ccs", "-f", "/etc/cluster/cluster.conf", "--setcman", "two_node=1", "expected_votes=1"]) if retval != 0: print output utils.err("error adding node: %s" % node) for node in nodes: output, retval = utils.run(["/usr/sbin/ccs", "-f", "/etc/cluster/cluster.conf", "--addnode", node]) if retval != 0: print output utils.err("error adding node: %s" % node) output, retval = utils.run(["/usr/sbin/ccs", "-i", "-f", "/etc/cluster/cluster.conf", "--addmethod", "pcmk-method", node]) if retval != 0: print output utils.err("error adding fence method: %s" % node) output, retval = utils.run(["/usr/sbin/ccs", "-i", "-f", "/etc/cluster/cluster.conf", "--addfenceinst", "pcmk-redirect", node, "pcmk-method", "port="+node]) if retval != 0: print output utils.err("error adding fence instance: %s" % node) if "--start" in utils.pcs_options: start_cluster([]) if "--enable" in utils.pcs_options: enable_cluster([])
def config_import_cman(argv): if no_clufter: utils.err("Unable to perform a CMAN cluster conversion due to missing python-clufter package") # prepare convertor options cluster_conf = settings.cluster_conf_file dry_run_output = None rhel6 = utils.is_rhel6() invalid_args = False for arg in argv: if "=" in arg: name, value = arg.split("=", 1) if name == "input": cluster_conf = value elif name == "output": dry_run_output = value if not dry_run_output.endswith(".tar.bz2"): dry_run_output += ".tar.bz2" elif name == "output-format": if value == "corosync.conf": rhel6 = False elif value == "cluster.conf": rhel6 = True else: invalid_args = True else: invalid_args = True else: invalid_args = True if invalid_args or not dry_run_output: usage.config(["import-cman"]) sys.exit(1) debug = "--debug" in utils.pcs_options force = "--force" in utils.pcs_options interactive = "--interactive" in utils.pcs_options clufter_args = { "input": cluster_conf, "cib": {"passin": "bytestring"}, "nocheck": force, "batch": True, } if interactive: if "EDITOR" not in os.environ: utils.err("$EDITOR environment variable is not set") clufter_args["batch"] = False clufter_args["editor"] = os.environ["EDITOR"] if debug: logging.getLogger("clufter").setLevel(logging.DEBUG) if rhel6: clufter_args["ccs_pcmk"] = {"passin": "bytestring"} else: clufter_args["coro"] = {"passin": "struct"} clufter_args_obj = type('ClufterOptions', (object, ), clufter_args) # run convertor try: cmd_name = "ccs2pcs-flatiron" if rhel6 else "ccs2pcs-needle" result = None cmd_manager = clufter.command_manager.CommandManager.init_lookup( cmd_name ) result = cmd_manager.commands[cmd_name](clufter_args_obj) error_message = "" except Exception as e: error_message = str(e) if error_message or result != 0: hints = [] hints.append("--interactive to solve the issues manually") if not debug: hints.append("--debug to get more information") if not force: hints.append("--force to override") hints_string = "\nTry using %s." % ", ".join(hints) if hints else "" sys.stderr.write( "Error: unable to import cluster configuration" + (": %s" % error_message if error_message else "") + hints_string + "\n" ) sys.exit(1 if result is None else result) # put new config files into tarball file_list = config_backup_path_list(with_uid_gid=True, force_rhel6=rhel6) tar_data = cStringIO.StringIO() try: tarball = tarfile.open(fileobj=tar_data, mode="w|bz2") config_backup_add_version_to_tarball(tarball) utils.tar_add_file_data( tarball, clufter_args_obj.cib["passout"], "cib.xml", **file_list["cib.xml"]["attrs"] ) if rhel6: utils.tar_add_file_data( tarball, clufter_args_obj.ccs_pcmk["passout"], "cluster.conf", **file_list["cluster.conf"]["attrs"] ) else: # put uidgid into separate files fmt_simpleconfig = clufter.format_manager.FormatManager.init_lookup( 'simpleconfig' ).plugins['simpleconfig'] corosync_struct = [] uidgid_list = [] for section in clufter_args_obj.coro["passout"][2]: if section[0] == "uidgid": uidgid_list.append(section[1]) else: corosync_struct.append(section) corosync_conf_data = fmt_simpleconfig( "struct", ("corosync", (), corosync_struct) )("bytestring") utils.tar_add_file_data( tarball, corosync_conf_data, "corosync.conf", **file_list["corosync.conf"]["attrs"] ) for uidgid in uidgid_list: uid = "" gid = "" for item in uidgid: if item[0] == "uid": uid = item[1] if item[0] == "gid": gid = item[1] filename = utils.get_uid_gid_file_name(uid, gid) uidgid_data = fmt_simpleconfig( "struct", ("corosync", (), [("uidgid", uidgid, None)]) )("bytestring") utils.tar_add_file_data( tarball, uidgid_data, "uidgid.d/" + filename, **file_list["uidgid.d"]["attrs"] ) tarball.close() except (tarfile.TarError, EnvironmentError) as e: utils.err("unable to create tarball: %s" % e) tar_data.seek(0) #save tarball / remote restore if dry_run_output: ok, message = utils.write_file(dry_run_output, tar_data.read()) if not ok: utils.err(message) else: config_restore_remote(None, tar_data) tar_data.close()
def corosync_setup(argv, returnConfig=False): fedora_config = not utils.is_rhel6() failure = False if len(argv) < 2: usage.cluster() exit(1) if not returnConfig and "--start" in utils.pcs_options and not "--local" in utils.pcs_options and fedora_config: sync_start(argv) return elif not returnConfig and not "--local" in utils.pcs_options and fedora_config: sync(argv) return else: nodes = argv[1:] cluster_name = argv[0] # Verify that all nodes are resolvable otherwise problems may occur for node in nodes: try: socket.gethostbyname(node) except socket.error: print "Warning: Unable to resolve hostname: %s" % node failure = True if failure: utils.err("Unable to resolve all hostnames.") if fedora_config == True: f = open(COROSYNC_CONFIG_FEDORA_TEMPLATE, 'r') corosync_config = f.read() f.close() i = 1 new_nodes_section = "" for node in nodes: new_nodes_section += " node {\n" new_nodes_section += " ring0_addr: %s\n" % (node) new_nodes_section += " nodeid: %d\n" % (i) new_nodes_section += " }\n" i = i + 1 two_node_section = "" if len(nodes) == 2: two_node_section = "two_node: 1" corosync_config = corosync_config.replace("@@nodes", new_nodes_section) corosync_config = corosync_config.replace("@@cluster_name", cluster_name) corosync_config = corosync_config.replace("@@two_node", two_node_section) if returnConfig: return corosync_config utils.setCorosyncConf(corosync_config) else: if os.path.exists("/etc/cluster/cluster.conf" ) and not "--force" in utils.pcs_options: print "Error: /etc/cluster/cluster.conf already exists, use --force to overwrite" sys.exit(1) output, retval = utils.run([ "/usr/sbin/ccs", "-i", "-f", "/etc/cluster/cluster.conf", "--createcluster", cluster_name ]) if retval != 0: print output utils.err("error creating cluster: %s" % cluster_name) output, retval = utils.run([ "/usr/sbin/ccs", "-i", "-f", "/etc/cluster/cluster.conf", "--addfencedev", "pcmk-redirect", "agent=fence_pcmk" ]) if retval != 0: print output utils.err("error creating fence dev: %s" % cluster_name) for node in nodes: output, retval = utils.run([ "/usr/sbin/ccs", "-f", "/etc/cluster/cluster.conf", "--addnode", node ]) if retval != 0: print output utils.err("error adding node: %s" % node) output, retval = utils.run([ "/usr/sbin/ccs", "-i", "-f", "/etc/cluster/cluster.conf", "--addmethod", "pcmk-method", node ]) if retval != 0: print output utils.err("error adding fence method: %s" % node) output, retval = utils.run([ "/usr/sbin/ccs", "-i", "-f", "/etc/cluster/cluster.conf", "--addfenceinst", "pcmk-redirect", node, "pcmk-method", "port=" + node ]) if retval != 0: print output utils.err("error adding fence instance: %s" % node) if "--start" in utils.pcs_options: start_cluster([])
def testRRPConfig(self): if utils.is_rhel6(): print "WARNING: not testing RRPConfig due to RHEL6" return o,r = pcs("cluster setup --transport udp --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --addr1 1.1.2.0") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udp\nrrp_mode: passive\n interface {\n ringnumber: 0\n bindnetaddr: 1.1.1.0\n mcastaddr: 239.255.1.1\n mcastport: 5405\n }\n interface {\n ringnumber: 1\n bindnetaddr: 1.1.2.0\n mcastaddr: 239.255.2.1\n mcastport: 5405\n }\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --transport udp --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --mcast0 8.8.8.8 --addr1 1.1.2.0 --mcast1 9.9.9.9") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udp\nrrp_mode: passive\n interface {\n ringnumber: 0\n bindnetaddr: 1.1.1.0\n mcastaddr: 8.8.8.8\n mcastport: 5405\n }\n interface {\n ringnumber: 1\n bindnetaddr: 1.1.2.0\n mcastaddr: 9.9.9.9\n mcastport: 5405\n }\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --transport udp --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --mcastport0 9999 --mcastport1 9998 --addr1 1.1.2.0") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udp\nrrp_mode: passive\n interface {\n ringnumber: 0\n bindnetaddr: 1.1.1.0\n mcastaddr: 239.255.1.1\n mcastport: 9999\n }\n interface {\n ringnumber: 1\n bindnetaddr: 1.1.2.0\n mcastaddr: 239.255.2.1\n mcastport: 9998\n }\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --addr1 1.1.2.0 --ttl0 4 --ttl1 5 --transport udp") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udp\nrrp_mode: passive\n interface {\n ringnumber: 0\n bindnetaddr: 1.1.1.0\n mcastaddr: 239.255.1.1\n mcastport: 5405\n ttl: 4\n }\n interface {\n ringnumber: 1\n bindnetaddr: 1.1.2.0\n mcastaddr: 239.255.2.1\n mcastport: 5405\n ttl: 5\n }\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --addr1 1.1.2.0 --rrpmode active --transport udp") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udp\nrrp_mode: active\n interface {\n ringnumber: 0\n bindnetaddr: 1.1.1.0\n mcastaddr: 239.255.1.1\n mcastport: 5405\n }\n interface {\n ringnumber: 1\n bindnetaddr: 1.1.2.0\n mcastaddr: 239.255.2.1\n mcastport: 5405\n }\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --addr1 1.1.2.0 --rrpmode active --broadcast0 --transport udp") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udp\nrrp_mode: active\n interface {\n ringnumber: 0\n bindnetaddr: 1.1.1.0\n broadcast: yes\n }\n interface {\n ringnumber: 1\n bindnetaddr: 1.1.2.0\n mcastaddr: 239.255.2.1\n mcastport: 5405\n }\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1,192.168.99.1 rh7-2,192.168.99.2") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udpu\nrrp_mode: passive\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n ring1_addr: 192.168.99.1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n ring1_addr: 192.168.99.2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --local --corosync_conf=corosync.conf.tmp --name cname rh7-1,192.168.99.1 rh7-2") ac(o,"Error: if one node is configured for RRP, all nodes must configured for RRP\n") assert r == 1 o,r = pcs("cluster setup --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --addr0 1.1.1.0 --addr0 1.1.2.0") assert r == 1 ac(o, "Error: --addr0 can only be used once\n") o,r = pcs("cluster setup --local --name cname nonexistant-address") assert r == 1 ac(o,"Error: Unable to resolve all hostnames (use --force to override).\nWarning: Unable to resolve hostname: nonexistant-address\n") o,r = pcs("cluster setup --local --name cname nonexistant-address --force") assert r == 0 ac(o,"Warning: Unable to resolve hostname: nonexistant-address\n") o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name test99 rh7-1 rh7-2 --wait_for_all=2 --auto_tie_breaker=3 --last_man_standing=4 --last_man_standing_window=5") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: test99\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\nwait_for_all: 2\nauto_tie_breaker: 3\nlast_man_standing: 4\nlast_man_standing_window: 5\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') # Reset local corosync.conf o,r = pcs("cluster setup --local --name test99 rh7-1 rh7-2") o,r = pcs("cluster setup --force --local --corosync_conf=corosync.conf.tmp --name test99 rh7-1 rh7-2 --wait_for_all=1 --auto_tie_breaker=1 --last_man_standing=1 --last_man_standing_window=12000") ac(o,"") assert r == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: test99\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\nwait_for_all: 1\nauto_tie_breaker: 1\nlast_man_standing: 1\nlast_man_standing_window: 12000\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs("cluster setup --force --local --name test99 rh7-1 rh7-2 --addr0 1.1.1.1") assert r == 1 ac(o,"Error: --addr0 and --addr1 can only be used with --transport=udp\n") # Reset local corosync.conf o,r = pcs("cluster setup --local --name test99 rh7-1 rh7-2")
def testUIDGID(self): if utils.is_rhel6(): os.system("cp /etc/cluster/cluster.conf cluster.conf.testbak") o,r = pcs("cluster uidgid") assert r == 0 ac(o, "No uidgids configured in cluster.conf\n") o,r = pcs("cluster uidgid blah") assert r == 1 assert o.startswith("\nUsage:") o,r = pcs("cluster uidgid rm") assert r == 1 assert o.startswith("\nUsage:") o,r = pcs("cluster uidgid add") assert r == 1 assert o.startswith("\nUsage:") o,r = pcs("cluster uidgid add blah") assert r == 1 ac(o, "Error: uidgid options must be of the form uid=<uid> gid=<gid>\n") o,r = pcs("cluster uidgid rm blah") assert r == 1 ac(o, "Error: uidgid options must be of the form uid=<uid> gid=<gid>\n") o,r = pcs("cluster uidgid add uid=zzz") assert r == 0 ac(o, "") o,r = pcs("cluster uidgid add uid=zzz") assert r == 1 ac(o, "Error: unable to add uidgid\nError: uidgid entry already exists with uid=zzz, gid=\n") o,r = pcs("cluster uidgid add gid=yyy") assert r == 0 ac(o, "") o,r = pcs("cluster uidgid add uid=aaa gid=bbb") assert r == 0 ac(o, "") o,r = pcs("cluster uidgid") assert r == 0 ac(o, "UID/GID: gid=, uid=zzz\nUID/GID: gid=yyy, uid=\nUID/GID: gid=bbb, uid=aaa\n") o,r = pcs("cluster uidgid rm gid=bbb") assert r == 1 ac(o, "Error: unable to remove uidgid\nError: unable to find uidgid with uid=, gid=bbb\n") o,r = pcs("cluster uidgid rm uid=aaa gid=bbb") assert r == 0 ac(o, "") o,r = pcs("cluster uidgid") assert r == 0 ac(o, "UID/GID: gid=, uid=zzz\nUID/GID: gid=yyy, uid=\n") o,r = pcs("cluster uidgid rm uid=zzz") assert r == 0 ac(o, "") o,r = pcs("config") assert r == 0 assert o.find("UID/GID: gid=yyy, uid=") != -1 o,r = pcs("cluster uidgid rm gid=yyy") assert r == 0 ac(o, "") o,r = pcs("config") assert r == 0 assert o.find("No uidgids") == -1 else: o,r = pcs("cluster uidgid") assert r == 0 ac(o, "No uidgids configured in cluster.conf\n") o,r = pcs("cluster uidgid add") assert r == 1 assert o.startswith("\nUsage:") o,r = pcs("cluster uidgid rm") assert r == 1 assert o.startswith("\nUsage:") o,r = pcs("cluster uidgid xx") assert r == 1 assert o.startswith("\nUsage:") o,r = pcs("cluster uidgid add uid=testuid gid=testgid") assert r == 0 ac(o, "") o,r = pcs("cluster uidgid add uid=testuid gid=testgid") assert r == 1 ac(o, "Error: uidgid file with uid=testuid and gid=testgid already exists\n") o,r = pcs("cluster uidgid rm uid=testuid2 gid=testgid2") assert r == 1 ac(o, "Error: no uidgid files with uid=testuid2 and gid=testgid2 found\n") o,r = pcs("cluster uidgid rm uid=testuid gid=testgid2") assert r == 1 ac(o, "Error: no uidgid files with uid=testuid and gid=testgid2 found\n") o,r = pcs("cluster uidgid rm uid=testuid2 gid=testgid") assert r == 1 ac(o, "Error: no uidgid files with uid=testuid2 and gid=testgid found\n") o,r = pcs("cluster uidgid") assert r == 0 ac(o, "UID/GID: uid=testuid gid=testgid\n") o,r = pcs("cluster uidgid rm uid=testuid gid=testgid") assert r == 0 ac(o, "") o,r = pcs("cluster uidgid") assert r == 0 ac(o, "No uidgids configured in cluster.conf\n")
def testCreation(self): if utils.is_rhel6(): return output, returnVal = pcs(temp_cib, "cluster") assert returnVal == 1 assert output.startswith("\nUsage: pcs cluster [commands]...") output, returnVal = pcs(temp_cib, "cluster setup --local --corosync_conf=corosync.conf.tmp cname rh7-1 rh7-2") assert returnVal == 1 assert output.startswith("Error: A cluster name (--name <name>) is required to setup a cluster\n") # Setup a 2 node cluster and make sure the two node config is set, then add a # node and make sure that it's unset, then remove a node and make sure it's # set again output, returnVal = pcs(temp_cib, "cluster setup --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2") ac (output,"") assert returnVal == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') output, returnVal = pcs(temp_cib, "cluster localnode add --corosync_conf=corosync.conf.tmp rh7-3") ac(output,"rh7-3: successfully added!\n") assert returnVal == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n node {\n ring0_addr: rh7-3\n nodeid: 3\n }\n}\n\nquorum {\nprovider: corosync_votequorum\n}\n\nlogging {\nto_syslog: yes\n}\n') output, returnVal = pcs(temp_cib, "cluster localnode remove --corosync_conf=corosync.conf.tmp rh7-3") assert returnVal == 0 assert output == "rh7-3: successfully removed!\n",output with open("corosync.conf.tmp") as f: data = f.read() assert data == 'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n',[data] o,r = pcs(temp_cib, "cluster localnode add --corosync_conf=corosync.conf.tmp rh7-3,192.168.1.3") assert r == 0 assert o == "rh7-3,192.168.1.3: successfully added!\n",[o] with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n node {\n ring0_addr: rh7-3\n ring1_addr: 192.168.1.3\n nodeid: 3\n }\n}\n\nquorum {\nprovider: corosync_votequorum\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs(temp_cib, "cluster localnode remove --corosync_conf=corosync.conf.tmp rh7-2") assert r == 0 assert o == "rh7-2: successfully removed!\n",[o] with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-3\n ring1_addr: 192.168.1.3\n nodeid: 3\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') o,r = pcs(temp_cib, "cluster localnode remove --corosync_conf=corosync.conf.tmp rh7-3,192.168.1.3") assert r == 0 assert o == "rh7-3,192.168.1.3: successfully removed!\n",[o] with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n') output, returnVal = pcs(temp_cib, "cluster setup --force --local --corosync_conf=corosync.conf2.tmp --name cname rh7-1 rh7-2 rh7-3") ac(output,"") assert returnVal == 0 with open("corosync.conf2.tmp") as f: data = f.read() assert data == 'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udpu\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n node {\n ring0_addr: rh7-3\n nodeid: 3\n }\n}\n\nquorum {\nprovider: corosync_votequorum\n\n}\n\nlogging {\nto_syslog: yes\n}\n',[data] ## Test to make transport is set output, returnVal = pcs(temp_cib, "cluster setup --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --transport udp") ac(output,"Error: corosync.conf.tmp already exists, use --force to overwrite\n") assert returnVal == 1 output, returnVal = pcs(temp_cib, "cluster setup --force --local --corosync_conf=corosync.conf.tmp --name cname rh7-1 rh7-2 --transport udp") ac(output,"") assert returnVal == 0 with open("corosync.conf.tmp") as f: data = f.read() ac(data,'totem {\nversion: 2\nsecauth: off\ncluster_name: cname\ntransport: udp\n}\n\nnodelist {\n node {\n ring0_addr: rh7-1\n nodeid: 1\n }\n node {\n ring0_addr: rh7-2\n nodeid: 2\n }\n}\n\nquorum {\nprovider: corosync_votequorum\ntwo_node: 1\n}\n\nlogging {\nto_syslog: yes\n}\n')