-
-
Save abg/9626615 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import ConfigParser | |
import logging | |
import optparse | |
import sys | |
import pyrax | |
error = logging.error | |
warn = logging.warn | |
info = logging.info | |
debug = logging.debug | |
class ConfigError(Exception): | |
"""Raised if an error is encountered parsing the configuration file""" | |
def load_config(path): | |
parser = ConfigParser.ConfigParser() | |
try: | |
with open(path, 'rb') as fileobj: | |
try: | |
parser.readfp(fileobj) | |
except ConfigParser.Error as exc: | |
raise ConfigError("manager.cfg error on parse: %s" % exc) | |
except IOError as exc: | |
raise ConfigError("Failed to open manager.cfg: %s" % exc) | |
# basic error checking | |
if not parser.has_section("auth"): | |
raise ConfigError("No [auth] section provided in %s" % path) | |
if not parser.has_section("lb"): | |
raise ConfigError("No [lb] section provided in %s" % path) | |
config = dict(auth={"user": "", "apikey": ""}, | |
lb={"master-id": "", "slave-id": ""}) | |
for name in parser.sections(): | |
# skip unknown sections | |
if not name in config: | |
warn("Warning: skipping section [%s]", name) | |
continue | |
config[name].update(parser.items(name)) | |
return config | |
def print_config(lb): | |
info("%s (%s) %s SRC %s", lb.name, lb.id, lb.virtual_ips[0].address, | |
lb.sourceAddresses['ipv4Servicenet']) | |
for node in lb.nodes: | |
info(" -- %s: %s (Server is currently %s)", | |
node.address, node.condition, node.status) | |
def verify_master(lb, master_address): | |
hit_count = 0 | |
errors = [] | |
writable_slaves = [] | |
for node in lb.nodes: | |
if node.address == master_address: | |
hit_count += 1 | |
if node.condition != 'ENABLED': | |
errors.append(1) | |
else: | |
if node.condition == 'ENABLED': | |
errors.append(2) | |
writable_slaves.append(node.address) | |
if hit_count != 1 or errors != []: | |
if hit_count == 0: | |
error("Master Address %s not found in LB %s. " | |
"Is this the correct IP / Load Balancer?", | |
master_address, lb.name) | |
for err in errors: | |
if err == 1: | |
error("Master Address %s is not listed as enabled", | |
master_address) | |
if err == 2: | |
error("Slave(s) are listed as enabled: %s", | |
', '.join(writable_slaves)) | |
return 1 | |
else: | |
info("All checks completed successfully") | |
return 0 | |
def _set_node_status(lb, address, status): | |
debug("setting node %s to %s on Load Balancer %s", | |
address, status, lb.name) | |
for node in lb.nodes: | |
if node.address != address: | |
continue | |
if node.condition != status: | |
node.condition = status | |
node.update() | |
pyrax.utils.wait_until(lb, "status", "ACTIVE", | |
interval=1, attempts=30, verbose=True) | |
info("Success: Node condition change complete") | |
return 0 | |
else: | |
warn("Warning: Target node (%s) is already set to condition %s", | |
address, status) | |
return 0 | |
error("%s not found in load balancer", address) | |
return 1 | |
def disable_node(lb, address): | |
return _set_node_status(lb, address, 'DISABLED') | |
def enable_node(lb, address): | |
return _set_node_status(lb, address, 'ENABLED') | |
def auth(auth_profile): | |
pyrax.set_setting("identity_type", "rackspace") | |
pyrax.set_credentials(auth_profile['user'], auth_profile['apikey']) | |
def main(): | |
logging.basicConfig(level=logging.DEBUG, | |
format='[%(levelname)s] %(asctime)s %(message)s') | |
mha_options = [ | |
'command', 'ssh_user', 'orig_master_host', | |
'orig_master_ip', 'orig_master_port', 'new_master_host', | |
'new_master_ip', 'new_master_port', 'new_master_user', | |
'new_master_password' | |
] | |
optparser = optparse.OptionParser() | |
for name in mha_options: | |
optparser.add_option("--" + name) | |
optparser.add_option("--address") | |
optparser.add_option("--config", "-c", | |
default="/etc/masterha/ip_manager.cnf", | |
help="Config file to use (default: %default)") | |
options, _ = optparser.parse_args() | |
command = options.command | |
orig_master_ip = options.orig_master_ip | |
new_master_ip = options.new_master_ip | |
try: | |
config = load_config(options.config) | |
except ConfigError as exc: | |
error("%s", exc) | |
return 1 | |
auth(config['auth']) | |
lb_master = pyrax.cloud_loadbalancers.get(config['lb']['master-id']) | |
lb_slave = pyrax.cloud_loadbalancers.get(config['lb']['slave-id']) | |
print_config(lb_master) | |
print_config(lb_slave) | |
if command == 'status': | |
return verify_master(lb_master, orig_master_ip) | |
elif command == 'stop' or command == 'stopssh': | |
lb_master_status = disable_node(lb_master, orig_master_ip) | |
lb_slave_status = disable_node(lb_slave, orig_master_ip) | |
return max(lb_master_status, lb_slave_status) | |
elif command == 'start': | |
lb_master_status = enable_node(lb_master, new_master_ip) | |
lb_slave_status = enable_node(lb_slave, new_master_ip) | |
return max(lb_master_status, lb_slave_status) | |
if __name__ == '__main__': | |
sys.exit(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment