def gen_authkey(): if not os.path.isfile(COROSYNC_AUTH): rc, out, err = crm_script.sudo_call(['corosync-keygen', '-l']) if rc != 0: crm_script.exit_fail("Error generating key: %s" % (err)) elif stat.S_IMODE(os.stat(COROSYNC_AUTH)[stat.ST_MODE]) != stat.S_IRUSR: os.chmod(COROSYNC_AUTH, stat.S_IRUSR)
def start_new_node(): if host not in add_nodes: crm_script.exit_ok(host) rc, _, err = crm_script.call(['crm', 'cluster', 'start']) if rc == 0: crm_script.exit_ok(host) crm_script.exit_fail(err)
def check_results(parallax, results): failures = [] for host, result in results.items(): if isinstance(result, parallax.Error): failures.add("%s: %s" % (host, str(result))) if failures: crm_script.exit_fail(', '.join(failures))
def check_services(): for host, info in data.iteritems(): for svc in info['services']: if svc['name'] == 'pacemaker' and svc['active'] == 'active': crm_script.exit_fail("%s already running pacemaker" % (host)) if svc['name'] == 'corosync' and svc['active'] == 'active': crm_script.exit_fail("%s already running corosync" % (host))
def run_corosync(): # create corosync.conf nodelist = crm_script.output(2).keys() nodelist_txt = "" for i, node in enumerate(nodelist): nodelist_txt += """ node { ring0_addr: %s nodeid: %s } """ % (node, i + 1) quorum_txt = "" if len(nodelist) == 1: quorum_txt = '' if len(nodelist) == 2: quorum_txt = """ two_node: 1 """ else: quorum_txt = """ provider: corosync_votequorum expected_votes: %s """ % ((len(nodelist) / 2) + 1) try: crm_script.save_template('./corosync.conf.template', '/etc/corosync/corosync.conf', bindnetaddr=make_bindnetaddr(), mcastaddr=crm_script.param('mcastaddr'), mcastport=crm_script.param('mcastport'), transport=crm_script.param('transport'), nodelist=nodelist_txt, quorum=quorum_txt) except Exception, e: crm_script.exit_fail(str(e))
def check_services(): for host, info in data.items(): for svc in info['services']: if svc['name'] == 'pacemaker' and svc['active'] == 'active': crm_script.exit_fail("%s already running pacemaker" % (host)) if svc['name'] == 'corosync' and svc['active'] == 'active': crm_script.exit_fail("%s already running corosync" % (host))
def check_results(pssh, results): failures = [] for host, result in results.items(): if isinstance(result, pssh.Error): failures.add("%s: %s" % (host, str(result))) if failures: crm_script.exit_fail(', '.join(failures))
def run_corosync(): # create corosync.conf nodelist = crm_script.output(1).keys() nodelist_txt = "" for i, node in enumerate(nodelist): nodelist_txt += """ node { ring0_addr: %s nodeid: %s } """ % (node, i + 1) quorum_txt = "" if len(nodelist) == 1: quorum_txt = '' if len(nodelist) == 2: quorum_txt = """ two_node: 1 """ else: quorum_txt = """ provider: corosync_votequorum expected_votes: %s """ % ((len(nodelist) / 2) + 1) try: crm_script.save_template('./corosync.conf.template', '/etc/corosync/corosync.conf', bindnetaddr=make_bindnetaddr(), mcastaddr=crm_script.param('mcastaddr'), mcastport=crm_script.param('mcastport'), transport=crm_script.param('transport'), nodelist=nodelist_txt, quorum=quorum_txt) except Exception, e: crm_script.exit_fail(str(e))
def run_validate(): data = crm_script.output(1) for node in remove_nodes: if data.get(node) != node: crm_script.exit_fail("%s not found or not responding: %s" % (node, data.get(node))) if host == node: crm_script.exit_fail("Call from another node: %s = %s" % (node, host)) crm_script.exit_ok(host)
def check_diskspace(): for host, info in data.iteritems(): for mount, percent in info['disk']: interesting = (mount == '/' or mount.startswith('/var/log') or mount.startswith('/tmp')) if interesting and percent > 90: crm_script.exit_fail("Not enough space on %s:%s" % (host, mount))
def run_collect(): if host not in add_nodes: crm_script.exit_ok(host) rc, out, err = crm_script.service('pacemaker', 'is-active') if rc == 0 and out.strip() == 'active': crm_script.exit_fail("Pacemaker already running on %s" % (host)) crm_script.exit_ok(crm_init.info())
def check_diskspace(): for host, info in data.items(): for mount, percent in info['disk']: interesting = (mount == '/' or mount.startswith('/var/log') or mount.startswith('/tmp')) if interesting and percent > 90: crm_script.exit_fail("Not enough space on %s:%s" % (host, mount))
def run_validate(): try: from psshlib import api except ImportError: crm_script.exit_fail("Command node needs pssh installed") if host in add_nodes: crm_script.exit_fail("Run script from node in cluster") crm_script.exit_ok(host)
def run_validate(): try: import parallax except ImportError: crm_script.exit_fail("Command node needs parallax installed") if host in add_nodes: crm_script.exit_fail("Run script from node in cluster") crm_script.exit_ok(host)
def run_copy(): try: import parallax as pssh except ImportError: crm_script.exit_fail("Command node needs parallax installed") opts = make_opts() results = pssh.copy(others, COROSYNC_AUTH, COROSYNC_AUTH, opts) check_results(pssh, results) results = pssh.call(others, "chown root:root %s;chmod 400 %s" % (COROSYNC_AUTH, COROSYNC_AUTH), opts) check_results(pssh, results)
def run_copy(): try: import parallax except ImportError: crm_script.exit_fail("Command node needs parallax installed") opts = make_opts() results = parallax.copy(others, COROSYNC_AUTH, COROSYNC_AUTH, opts) check_results(parallax, results) results = parallax.call(others, "chown root:root %s;chmod 400 %s" % (COROSYNC_AUTH, COROSYNC_AUTH), opts) check_results(parallax, results)
def run_copy(): try: from psshlib import api as pssh except ImportError: crm_script.exit_fail("Command node needs pssh installed") opts = make_opts() results = pssh.copy(others, COROSYNC_AUTH, COROSYNC_AUTH, opts) check_results(pssh, results) results = pssh.call(others, "chown root:root %s;chmod 400 %s" % (COROSYNC_AUTH, COROSYNC_AUTH), opts) check_results(pssh, results)
def configure_firewall(): _SUSE_FW_TEMPLATE = """## Name: HAE cluster ports ## Description: opens ports for HAE cluster services TCP="%(tcp)s" UDP="%(udp)s" """ corosync_mcastport = crm_script.param('mcastport') if not corosync_mcastport: rc, out, err = crm_script.call(['crm', 'corosync', 'get', 'totem.interface.mcastport']) if rc == 0: corosync_mcastport = out.strip() FW = '/etc/sysconfig/SuSEfirewall2' FW_CLUSTER = '/etc/sysconfig/SuSEfirewall2.d/services/cluster' tcp_ports = '30865 5560 7630 21064' udp_ports = '%s %s' % (corosync_mcastport, int(corosync_mcastport) - 1) if is_service_enabled('SuSEfirewall2'): if os.path.isfile(FW_CLUSTER): tmpl = open(FW_CLUSTER).read() tmpl = re.sub(r'^TCP="(.*)"', 'TCP="%s"' % (tcp_ports), tmpl, flags=re.M) tmpl = re.sub(r'^UDP="(.*)"', 'UDP="%s"' % (udp_ports), tmpl, flags=re.M) with open(FW_CLUSTER, 'w') as f: f.write(tmpl) elif os.path.isdir(os.path.dirname(FW_CLUSTER)): with open(FW_CLUSTER, 'w') as fwc: fwc.write(_SUSE_FW_TEMPLATE % {'tcp': tcp_ports, 'udp': udp_ports}) else: # neither the cluster file nor the services # directory exists crm_script.exit_fail("SUSE firewall is configured but %s does not exist" % os.path.dirname(FW_CLUSTER)) # add cluster to FW_CONFIGURATIONS_EXT if os.path.isfile(FW): txt = open(FW).read() m = re.search(r'^FW_CONFIGURATIONS_EXT="(.*)"', txt, re.M) if m: services = m.group(1).split() if 'cluster' not in services: services.append('cluster') txt = re.sub(r'^FW_CONFIGURATIONS_EXT="(.*)"', r'FW_CONFIGURATIONS_EXT="%s"' % (' '.join(services)), txt, flags=re.M) else: txt += '\nFW_CONFIGURATIONS_EXT="cluster"' with open(FW, 'w') as fw: fw.write(txt) if is_service_active('SuSEfirewall2'): crm_script.service('SuSEfirewall2', 'restart')
def run_apply(): for node in remove_nodes: rc, out, err = crm_script.call(['ssh', '-o', 'PasswordAuthentication=no', 'root@%s' % (node), 'systemctl stop corosync.service']) if rc != 0: crm_script.exit_fail("Failed to stop corosync on %s: %s" % (node, err)) rc, out, err = crm_script.call(['crm', 'node', 'delete', node]) if rc != 0: crm_script.exit_fail("Failed to remove %s from CIB: %s" % (node, err)) crm_script.exit_ok({"removed": remove_nodes})
def run_apply(): for node in remove_nodes: rc, out, err = crm_script.call([ 'ssh', '-o', 'PasswordAuthentication=no', 'root@%s' % (node), 'systemctl stop corosync.service' ]) if rc != 0: crm_script.exit_fail("Failed to stop corosync on %s: %s" % (node, err)) rc, out, err = crm_script.call(['crm', 'node', 'delete', node]) if rc != 0: crm_script.exit_fail("Failed to remove %s from CIB: %s" % (node, err)) crm_script.exit_ok({"removed": remove_nodes})
def select_interfaces(user_iface, data): selections = dict([(host, user_iface) for host in data.keys()]) if not user_iface: for host, info in data.iteritems(): for i in info['net']['interfaces']: if i.get('Destination') == '0.0.0.0': selections[host] = i['Iface'] break def invalid(host, iface): for i in data[host]['net']['interfaces']: if i['Iface'] == iface: return False return True for host, iface in selections.iteritems(): if not iface or invalid(host, iface): crm_script.exit_fail("No usable network interface on %s: %s" % (host, iface)) return user_iface
def select_interfaces(user_iface, data): selections = dict([(host, user_iface) for host in data.keys()]) if not user_iface: for host, info in data.iteritems(): for i in info["net"]["interfaces"]: if i.get("Destination") == "0.0.0.0": selections[host] = i["Iface"] break def invalid(host, iface): for i in data[host]["net"]["interfaces"]: if i["Iface"] == iface: return False return True for host, iface in selections.iteritems(): if not iface or invalid(host, iface): crm_script.exit_fail("No usable network interface on %s: %s" % (host, iface)) return user_iface
def run_ssh(): try: crm_script.service('sshd', 'start') rc, _, _ = crm_script.sudo_call( ["mkdir", "-m", "700", "-p", "/root/.ssh"]) if rc != 0: crm_script.exit_fail("Failed to create /root/.ssh directory") keypath = None for key in ('id_rsa', 'id_dsa', 'id_ecdsa'): if os.path.exists(os.path.join('/root/.ssh', key)): keypath = os.path.join('/root/.ssh', key) break if not keypath: keypath = os.path.join('/root/.ssh', 'id_rsa') keygen = [ 'ssh-keygen', '-q', '-f', keypath, '-C', 'Cluster Internal', '-N', '' ] rc, out, err = crm_script.sudo_call(keygen) if rc != 0: crm_script.exit_fail("Failed to generate SSH key") _authorize_key(keypath) crm_script.exit_ok(True) except IOError, e: crm_script.exit_fail(str(e))
def run_copy(): try: import parallax except ImportError: crm_script.exit_fail("Command node needs parallax installed") opts = make_opts() has_auth = os.path.isfile(COROSYNC_AUTH) if has_auth: results = parallax.copy(add_nodes, COROSYNC_AUTH, COROSYNC_AUTH, opts) check_results(parallax, results) results = parallax.call( add_nodes, "chown root:root %s;chmod 400 %s" % (COROSYNC_AUTH, COROSYNC_AUTH), opts) check_results(parallax, results) # Add new nodes to corosync.conf before copying for node in add_nodes: rc, _, err = crm_script.call(['crm', 'corosync', 'add-node', node]) if rc != 0: crm_script.exit_fail('Failed to add %s to corosync.conf: %s' % (node, err)) results = parallax.copy(add_nodes, COROSYNC_CONF, COROSYNC_CONF, opts) check_results(parallax, results) # reload corosync config here? rc, _, err = crm_script.call(['crm', 'corosync', 'reload']) if rc != 0: crm_script.exit_fail('Failed to reload corosync configuration: %s' % (err)) crm_script.exit_ok(host)
def run_copy(): try: from psshlib import api as pssh except ImportError: crm_script.exit_fail("Command node needs pssh installed") opts = make_opts() has_auth = os.path.isfile(COROSYNC_AUTH) if has_auth: results = pssh.copy(add_nodes, COROSYNC_AUTH, COROSYNC_AUTH, opts) check_results(pssh, results) results = pssh.call(add_nodes, "chown root:root %s;chmod 400 %s" % (COROSYNC_AUTH, COROSYNC_AUTH), opts) check_results(pssh, results) # Add new nodes to corosync.conf before copying for node in add_nodes: rc, _, err = crm_script.call(['crm', 'corosync', 'add-node', node]) if rc != 0: crm_script.exit_fail('Failed to add %s to corosync.conf: %s' % (node, err)) results = pssh.copy(add_nodes, COROSYNC_CONF, COROSYNC_CONF, opts) check_results(pssh, results) # reload corosync config here? rc, _, err = crm_script.call(['crm', 'corosync', 'reload']) if rc != 0: crm_script.exit_fail('Failed to reload corosync configuration: %s' % (err)) crm_script.exit_ok(host)
def run_ssh(): try: crm_script.service('sshd', 'start') rc, _, _ = crm_script.sudo_call(["mkdir", "-m", "700", "-p", "/root/.ssh"]) if rc != 0: crm_script.exit_fail("Failed to create /root/.ssh directory") keypath = None for key in ('id_rsa', 'id_dsa', 'id_ecdsa'): if os.path.exists(os.path.join('/root/.ssh', key)): keypath = os.path.join('/root/.ssh', key) break if not keypath: keypath = os.path.join('/root/.ssh', 'id_rsa') keygen = ['ssh-keygen', '-q', '-f', keypath, '-C', 'Cluster Internal', '-N', ''] rc, out, err = crm_script.sudo_call(keygen) if rc != 0: crm_script.exit_fail("Failed to generate SSH key") _authorize_key(keypath) crm_script.exit_ok(True) except IOError, e: crm_script.exit_fail(str(e))
crm_script.exit_fail("No usable network interface on %s: %s" % (host, iface)) return user_iface def make_mcastaddr(): import random random.seed() b, c, d = random.randint(1, 254), random.randint(1, 254), random.randint(1, 254) return "%d.%d.%d.%d" % (239, b, c, d) try: data = crm_script.output(1) crm_init.verify(data) ret = {} ret['iface'] = select_interfaces(crm_script.param('iface'), data) if not crm_script.param('mcastaddr'): ret['mcastaddr'] = make_mcastaddr() crm_script.exit_ok(ret) except Exception, e: crm_script.exit_fail("Verification failed: %s" % (e))
try: crm_script.save_template('./corosync.conf.template', '/etc/corosync/corosync.conf', bindnetaddr=make_bindnetaddr(), mcastaddr=crm_script.param('mcastaddr'), mcastport=crm_script.param('mcastport'), transport=crm_script.param('transport'), nodelist=nodelist_txt, quorum=quorum_txt) except Exception, e: crm_script.exit_fail(str(e)) # start cluster rc, out, err = crm_script.call(['crm', 'cluster', 'start']) if rc != 0: crm_script.exit_fail("Failed to start cluster: %s" % (err)) crm_script.exit_ok(True) if __name__ == "__main__": if len(sys.argv) < 2: crm_script.exit_fail("Missing argument to configure.py") elif sys.argv[1] == 'install': run_install() elif sys.argv[1] == 'corosync': run_corosync() else: crm_script.exit_fail("Bad argument to configure.py: %s" % (sys.argv[1]))
crm_script.exit_ok(host) def run_apply(): for node in remove_nodes: rc, out, err = crm_script.call([ 'ssh', '-o', 'PasswordAuthentication=no', 'root@%s' % (node), 'systemctl stop corosync.service' ]) if rc != 0: crm_script.exit_fail("Failed to stop corosync on %s: %s" % (node, err)) rc, out, err = crm_script.call(['crm', 'node', 'delete', node]) if rc != 0: crm_script.exit_fail("Failed to remove %s from CIB: %s" % (node, err)) crm_script.exit_ok({"removed": remove_nodes}) if __name__ == "__main__": if len(sys.argv) < 2 or sys.argv[1] == 'collect': run_collect() elif sys.argv[1] == 'validate': run_validate() elif sys.argv[1] == 'apply': run_apply() else: crm_script.exit_fail("Unknown argument: %s" % sys.argv[1])
#!/usr/bin/python3 import crm_script try: uptime = open('/proc/uptime').read().split()[0] crm_script.exit_ok(uptime) except Exception as e: crm_script.exit_fail("Couldn't open /proc/uptime: %s" % (e))
def verify_host(host, info): if host != info['system']['hostname']: crm_script.exit_fail("Hostname mismatch: %s is not %s" % (host, info['system']['hostname']))
def install_packages(packages): for pkg in packages: try: crm_script.package(pkg, 'latest') except Exception, e: crm_script.exit_fail("Failed to install %s: %s" % (pkg, e))
#!/usr/bin/env python import crm_script rc, _, err = crm_script.call(['crm', 'cluster', 'wait_for_startup', '30']) if rc != 0: crm_script.exit_fail("Cluster not responding") def check_for_primitives(): rc, out, err = crm_script.call( "crm configure show type:primitive | grep primitive", shell=True) if rc == 0 and out: return True return False if check_for_primitives(): crm_script.debug("Joined existing cluster - will not reconfigure") crm_script.exit_ok(True) try: nodelist = crm_script.param('nodes') crm_script.save_template('./basic.cib.template', './basic.cib') except IOError, e: crm_script.exit_fail("IO error: %s" % (str(e))) except ValueError, e: crm_script.exit_fail("Value error: %s" % (str(e))) rc, _, err = crm_script.call( ['crm', 'configure', 'load', 'replace', './basic.cib']) if rc != 0:
try: crm_script.save_template('./corosync.conf.template', '/etc/corosync/corosync.conf', bindnetaddr=make_bindnetaddr(), mcastaddr=crm_script.param('mcastaddr'), mcastport=crm_script.param('mcastport'), transport=crm_script.param('transport'), nodelist=nodelist_txt, quorum=quorum_txt) except Exception, e: crm_script.exit_fail(str(e)) # start cluster rc, out, err = crm_script.call(['crm', 'cluster', 'start']) if rc != 0: crm_script.exit_fail("Failed to start cluster: %s" % (err)) crm_script.exit_ok(True) if __name__ == "__main__": if len(sys.argv) < 2: crm_script.exit_fail("Missing argument to configure.py") elif sys.argv[1] == 'ssh': run_ssh() elif sys.argv[1] == 'install': run_install() elif sys.argv[1] == 'corosync': run_corosync() else: crm_script.exit_fail("Bad argument to configure.py: %s" % (sys.argv[1]))
crm_script.exit_fail("%s not found or not responding: %s" % (node, data.get(node))) if host == node: crm_script.exit_fail("Call from another node: %s = %s" % (node, host)) crm_script.exit_ok(host) def run_apply(): for node in remove_nodes: rc, out, err = crm_script.call(['ssh', '-o', 'PasswordAuthentication=no', 'root@%s' % (node), 'systemctl stop corosync.service']) if rc != 0: crm_script.exit_fail("Failed to stop corosync on %s: %s" % (node, err)) rc, out, err = crm_script.call(['crm', 'node', 'delete', node]) if rc != 0: crm_script.exit_fail("Failed to remove %s from CIB: %s" % (node, err)) crm_script.exit_ok({"removed": remove_nodes}) if __name__ == "__main__": if len(sys.argv) < 2 or sys.argv[1] == 'collect': run_collect() elif sys.argv[1] == 'validate': run_validate() elif sys.argv[1] == 'apply': run_apply() else: crm_script.exit_fail("Unknown argument: %s" % sys.argv[1])
def install_packages(packages): for pkg in packages: try: crm_script.package(pkg, 'latest') except Exception as e: crm_script.exit_fail("Failed to install %s: %s" % (pkg, e))
#!/usr/bin/env python import crm_script rc, _, err = crm_script.call(['crm', 'cluster', 'wait_for_startup', '30']) if rc != 0: crm_script.exit_fail("Cluster not responding") def check_for_primitives(): rc, out, err = crm_script.call("crm configure show type:primitive | grep primitive", shell=True) if rc == 0 and out: return True return False if check_for_primitives(): crm_script.debug("Joined existing cluster - will not reconfigure") crm_script.exit_ok(True) try: nodelist = crm_script.param('nodes') crm_script.save_template('./basic.cib.template', './basic.cib') except IOError, e: crm_script.exit_fail("IO error: %s" % (str(e))) except ValueError, e: crm_script.exit_fail("Value error: %s" % (str(e))) rc, _, err = crm_script.call(['crm', 'configure', 'load', 'replace', './basic.cib']) if rc != 0: crm_script.exit_fail("Failed to load CIB configuration: %s" % (err)) crm_script.exit_ok(True)
def check(value, msg): vals = set([system[value] for host, system in systems]) if len(vals) > 1: info = ', '.join('%s: %s' % (h, system[value]) for h, system in systems) crm_script.exit_fail("%s: %s" % (msg, info))
'/etc/sysconfig/sbd', '/etc/sysconfig/SuSEfirewall2', '/etc/sysconfig/SuSEfirewall2.d/services/cluster' ] def files_info(): ret = {} for f in FILES: if os.path.isfile(f): try: ret[f] = hashlib.sha1(open(f).read()).hexdigest() except IOError, e: ret[f] = "error: %s" % (e) else: ret[f] = "" return ret try: data = { 'rpm': rpm_info(), 'logrotate': logrotate_info(), 'system': sys_info(), 'disk': disk_info(), 'files': files_info() } crm_script.exit_ok(data) except Exception, e: crm_script.exit_fail(str(e))
for host, iface in selections.iteritems(): if not iface or invalid(host, iface): crm_script.exit_fail("No usable network interface on %s: %s" % (host, iface)) return user_iface def make_mcastaddr(): import random random.seed() b, c, d = random.randint(1, 254), random.randint(1, 254), random.randint(1, 254) return "%d.%d.%d.%d" % (239, b, c, d) try: data = crm_script.output(2) crm_init.verify(data) ret = {} ret["iface"] = select_interfaces(crm_script.param("iface"), data) if not crm_script.param("mcastaddr"): ret["mcastaddr"] = make_mcastaddr() crm_script.exit_ok(ret) except Exception, e: crm_script.exit_fail("Verification failed: %s" % (e))