#!/usr/bin/python # # Copyright (C) 2006, 2007 Google Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. """Ganeti master script Exit codes, for both start and stop: - 0: master setup successful - 1: some generic error (this exit code can also be thrown by exceptions) - 11: node is not master, nothing to do - 12: node setup incomplete, cannot start - 13: node should be master, but someone has the ip address already Only exit codes 0 and 11 represent an ok state. Code 1 was left for generic errors as other python code can cause exit with code 1. """ import os import sys from optparse import OptionParser from ganeti import constants from ganeti import errors from ganeti import ssconf from ganeti import utils EXIT_OK = 0 EXIT_SOME_ERROR = 1 EXIT_NOTMASTER = constants.EXIT_NOTMASTER EXIT_NODESETUP_ERROR = constants.EXIT_NODESETUP_ERROR EXIT_DUPLICATE_IP = 13 EXIT_ARGS_ERROR = 14 def ParseOptions(): """Parse the command line options. Returns: (options, args) as from OptionParser.parse_args() """ parser = OptionParser(description="Ganeti master", usage="%prog [-d]", version="%%prog (ganeti) %s" % constants.RELEASE_VERSION) parser.add_option("-d", "--debug", dest="debug", help="Enable some debug messages", default=False, action="store_true") options, args = parser.parse_args() if len(args) != 1 or args[0] not in ("start", "stop"): sys.stderr.write("Usage: %s [-d] start|stop\n" % sys.argv[0]) sys.exit(EXIT_ARGS_ERROR) return options, args def CheckNodeSetup(debug): """Checks the node setup. If the node setup if ok, this function will return the tuple (master_hostname, master_netdev, master_ip). Otherwise the return value will be None. """ for fname in (constants.SSL_CERT_FILE,): if not os.path.isfile(fname): if debug: sys.stderr.write("Missing config file %s.\n" % fname) return None try: ss = ssconf.SimpleStore() port = ss.GetNodeDaemonPort() pwdata = ss.GetNodeDaemonPassword() master_name = ss.GetMasterNode() master_netdev = ss.GetMasterNetdev() master_ip = ss.GetMasterIP() except errors.ConfigurationError, err: if debug: sys.stderr.write("Cluster configuration incomplete: '%s'\n" % str(err)) return None return (master_name, master_netdev, master_ip) def StartMaster(master_netdev, master_ip, debug): """Starts the master. """ if utils.TcpPing(utils.HostInfo().name, master_ip, constants.DEFAULT_NODED_PORT): if utils.TcpPing(constants.LOCALHOST_IP_ADDRESS, master_ip, constants.DEFAULT_NODED_PORT): # we already have the ip: if debug: sys.stderr.write("Notice: already started.\n") return EXIT_OK else: return EXIT_DUPLICATE_IP result = utils.RunCmd(["ip", "address", "add", "%s/32" % master_ip, "dev", master_netdev, "label", "%s:0" % master_netdev]) if result.failed: if debug: sys.stderr.write("Can't activate master IP: %s\n" % result.output) return EXIT_SOME_ERROR result = utils.RunCmd(["arping", "-q", "-U", "-c 3", "-I", master_netdev, "-s", master_ip, master_ip]) # we'll ignore the exit code of arping return EXIT_OK def StopMaster(master_netdev, master_ip, debug): """Stops the master. """ result = utils.RunCmd(["ip", "address", "del", "%s/32" % master_ip, "dev", master_netdev]) if result.failed: if debug: sys.stderr.write("Can't remove the master IP, error: %s" % result.output) # but otherwise ignore the failure return EXIT_OK def main(): """Main function. """ options, args = ParseOptions() debug = options.debug try: myself = utils.HostInfo() except errors.ResolverError, err: sys.stderr.write("Cannot resolve my own name (%s)\n" % err.args[0]) return EXIT_NODESETUP_ERROR result = CheckNodeSetup(debug) if not result: if debug: sys.stderr.write("Node configuration incomplete.\n") return EXIT_NODESETUP_ERROR master_node, master_netdev, master_ip = result if myself.name != master_node and args[0] == "start": if debug: sys.stderr.write("Not master, ignoring request.\n") return EXIT_NOTMASTER if args[0] == "start": fn = StartMaster else: fn = StopMaster result = fn(master_netdev, master_ip, debug) sys.exit(result) if __name__ == '__main__': main()