LGTM, thanks
On Mon, May 12, 2014 at 6:08 PM, 'Klaus Aehlig' via ganeti-devel < [email protected]> wrote: > This daemon does not do anything anymore, so we > can as well get rid of it. > > Signed-off-by: Klaus Aehlig <[email protected]> > Reviewed-by: Hrvoje Ribicic <[email protected]> > --- > Makefile.am | 3 - > daemons/daemon-util.in | 7 - > doc/examples/ganeti.default | 1 - > doc/examples/ganeti.default-debug | 1 - > doc/examples/systemd/ganeti-masterd.service.in | 18 --- > doc/examples/systemd/ganeti-rapi.service.in | 2 +- > lib/server/masterd.py | 214 > ------------------------- > man/ganeti-masterd.rst | 96 ----------- > qa/qa_env.py | 1 - > 9 files changed, 1 insertion(+), 342 deletions(-) > delete mode 100644 doc/examples/systemd/ganeti-masterd.service.in > delete mode 100644 man/ganeti-masterd.rst > > diff --git a/Makefile.am b/Makefile.am > index e25e9c5..2d2a898 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -348,7 +348,6 @@ BUILT_EXAMPLES = \ > doc/examples/systemd/ganeti-confd.service \ > doc/examples/systemd/ganeti-kvmd.service \ > doc/examples/systemd/ganeti-luxid.service \ > - doc/examples/systemd/ganeti-masterd.service \ > doc/examples/systemd/ganeti-metad.service \ > doc/examples/systemd/ganeti-mond.service \ > doc/examples/systemd/ganeti-noded.service \ > @@ -1078,7 +1077,6 @@ gnt_python_sbin_SCRIPTS = \ > gntpython_SCRIPTS = $(gnt_scripts) > > PYTHON_BOOTSTRAP_SBIN = \ > - daemons/ganeti-masterd \ > daemons/ganeti-noded \ > daemons/ganeti-rapi \ > daemons/ganeti-watcher > @@ -1322,7 +1320,6 @@ man_MANS = \ > man/ganeti-luxid.8 \ > man/ganeti-listrunner.8 \ > man/ganeti-kvmd.8 \ > - man/ganeti-masterd.8 \ > man/ganeti-mond.8 \ > man/ganeti-noded.8 \ > man/ganeti-os-interface.7 \ > diff --git a/daemons/daemon-util.in b/daemons/daemon-util.in > index a87fc36..a77f1d3 100644 > --- a/daemons/daemon-util.in > +++ b/daemons/daemon-util.in > @@ -30,7 +30,6 @@ readonly defaults_file="$SYSCONFDIR/default/ganeti" > DAEMONS=( > ganeti-wconfd > ganeti-noded > - ganeti-masterd > ganeti-rapi > ganeti-luxid > ) > @@ -62,7 +61,6 @@ fi > ALL_DAEMONS=( ${DAEMONS[@]} ${ON_DEMAND_DAEMONS[@]} ) > > NODED_ARGS= > -MASTERD_ARGS= > CONFD_ARGS= > WCONFD_ARGS= > LUXID_ARGS= > @@ -90,9 +88,6 @@ _daemon_executable() { > > _daemon_usergroup() { > case "$1" in > - masterd) > - echo "@GNTMASTERUSER@:@GNTMASTERDGROUP@" > - ;; > confd) > echo "@GNTCONFDUSER@:@GNTCONFDGROUP@" > ;; > @@ -346,7 +341,6 @@ start_master() { > systemctl start ganeti-master.target > else > start ganeti-wconfd > - start ganeti-masterd > start ganeti-rapi > start ganeti-luxid > fi > @@ -359,7 +353,6 @@ stop_master() { > else > stop ganeti-luxid > stop ganeti-rapi > - stop ganeti-masterd > stop ganeti-wconfd > fi > } > diff --git a/doc/examples/ganeti.default b/doc/examples/ganeti.default > index f80d823..281423b 100644 > --- a/doc/examples/ganeti.default > +++ b/doc/examples/ganeti.default > @@ -1,6 +1,5 @@ > # Default arguments for Ganeti daemons > NODED_ARGS="" > -MASTERD_ARGS="" > RAPI_ARGS="" > CONFD_ARGS="" > WCONFD_ARGS="" > diff --git a/doc/examples/ganeti.default-debug > b/doc/examples/ganeti.default-debug > index 94bd360..e53edec 100644 > --- a/doc/examples/ganeti.default-debug > +++ b/doc/examples/ganeti.default-debug > @@ -1,6 +1,5 @@ > # Default arguments for Ganeti daemons (debug mode) > NODED_ARGS="-d" > -MASTERD_ARGS="-d" > RAPI_ARGS="-d" > CONFD_ARGS="-d" > WCONFD_ARGS="-d" > diff --git > a/doc/examples/systemd/ganeti-masterd.service.inb/doc/examples/systemd/ > ganeti-masterd.service.in > deleted file mode 100644 > index 2547dd3..0000000 > --- a/doc/examples/systemd/ganeti-masterd.service.in > +++ /dev/null > @@ -1,18 +0,0 @@ > -[Unit] > -Description = Ganeti master daemon (masterd) > -Documentation = man:ganeti-masterd(8) > -Requires = ganeti-common.service > -After = ganeti-common.service > -PartOf = ganeti-master.target > -ConditionPathExists = @LOCALSTATEDIR@/lib/ganeti/config.data > - > -[Service] > -Type = simple > -User = @GNTMASTERUSER@ > -Group = @GNTMASTERDGROUP@ > -ExecStart = @SBINDIR@/ganeti-masterd -f > -Restart = on-failure > -SuccessExitStatus = 0 11 > - > -[Install] > -WantedBy = ganeti-master.target ganeti.target > diff --git > a/doc/examples/systemd/ganeti-rapi.service.inb/doc/examples/systemd/ > ganeti-rapi.service.in > index 260473b..a2ce1f5 100644 > --- a/doc/examples/systemd/ganeti-rapi.service.in > +++ b/doc/examples/systemd/ganeti-rapi.service.in > @@ -2,7 +2,7 @@ > Description = Ganeti RAPI daemon (rapi) > Documentation = man:ganeti-rapi(8) > Requires = ganeti-common.service > -Requisite = ganeti-masterd.service > +Requisite = ganeti-luxid.service > After = ganeti-common.service > PartOf = ganeti-master.target > ConditionPathExists = @LOCALSTATEDIR@/lib/ganeti/rapi.pem > diff --git a/lib/server/masterd.py b/lib/server/masterd.py > index 9f84478..652645f 100644 > --- a/lib/server/masterd.py > +++ b/lib/server/masterd.py > @@ -29,16 +29,13 @@ inheritance from parent classes requires it. > # pylint: disable=C0103 > # C0103: Invalid name ganeti-masterd > > -import grp > import os > -import pwd > import sys > import socket > import time > import tempfile > import logging > > -from optparse import OptionParser > > from ganeti import config > from ganeti import constants > @@ -51,20 +48,14 @@ from ganeti import luxi > import ganeti.rpc.errors as rpcerr > from ganeti import utils > from ganeti import errors > -from ganeti import ssconf > from ganeti import workerpool > import ganeti.rpc.node as rpc > import ganeti.rpc.client as rpccl > -from ganeti import bootstrap > -from ganeti import netutils > from ganeti import objects > from ganeti import query > from ganeti import runtime > -from ganeti import pathutils > from ganeti import ht > > -from ganeti.utils import version > - > > CLIENT_REQUEST_WORKERS = 16 > > @@ -556,208 +547,3 @@ def _SetWatcherPause(context, ec_id, until): > " on the following node(s): %s" % errmsg) > > return until > - > - > [email protected] > -def CheckAgreement(): > - """Check the agreement on who is the master. > - > - The function uses a very simple algorithm: we must get more positive > - than negative answers. Since in most of the cases we are the master, > - we'll use our own config file for getting the node list. In the > - future we could collect the current node list from our (possibly > - obsolete) known nodes. > - > - In order to account for cold-start of all nodes, we retry for up to > - a minute until we get a real answer as the top-voted one. If the > - nodes are more out-of-sync, for now manual startup of the master > - should be attempted. > - > - Note that for a even number of nodes cluster, we need at least half > - of the nodes (beside ourselves) to vote for us. This creates a > - problem on two-node clusters, since in this case we require the > - other node to be up too to confirm our status. > - > - """ > - myself = netutils.Hostname.GetSysName() > - # Create a livelock file > - livelock = utils.livelock.LiveLock("masterd_check_agreement") > - #temp instantiation of a config writer, used only to get the node list > - cfg = config.GetConfig(None, livelock) > - node_names = cfg.GetNodeNames(cfg.GetNodeList()) > - del cfg > - retries = 6 > - while retries > 0: > - votes = bootstrap.GatherMasterVotes(node_names) > - if not votes: > - # empty node list, this is a one node cluster > - return True > - if votes[0][0] is None: > - retries -= 1 > - time.sleep(10) > - continue > - break > - if retries == 0: > - logging.critical("Cluster inconsistent, most of the nodes didn't > answer" > - " after multiple retries. Aborting startup") > - logging.critical("Use the --no-voting option if you understand what" > - " effects it has on the cluster state") > - return False > - # here a real node is at the top of the list > - all_votes = sum(item[1] for item in votes) > - top_node, top_votes = votes[0] > - > - result = False > - if top_node != myself: > - logging.critical("It seems we are not the master (top-voted node" > - " is %s with %d out of %d votes)", top_node, > top_votes, > - all_votes) > - elif top_votes < all_votes - top_votes: > - logging.critical("It seems we are not the master (%d votes for," > - " %d votes against)", top_votes, all_votes - > top_votes) > - else: > - result = True > - > - return result > - > - > [email protected] > -def ActivateMasterIP(): > - # activate ip > - # Create a livelock file > - livelock = utils.livelock.LiveLock("masterd_activate_ip") > - cfg = config.GetConfig(None, livelock) > - master_params = cfg.GetMasterNetworkParameters() > - ems = cfg.GetUseExternalMipScript() > - runner = rpc.BootstrapRunner() > - # we use the node name, as the configuration is only available here yet > - result = runner.call_node_activate_master_ip( > - cfg.GetNodeName(master_params.uuid), master_params, ems) > - > - msg = result.fail_msg > - if msg: > - logging.error("Can't activate master IP address: %s", msg) > - > - > -def CheckMasterd(options, args): > - """Initial checks whether to run or exit with a failure. > - > - """ > - if args: # masterd doesn't take any arguments > - print >> sys.stderr, ("Usage: %s [-f] [-d]" % sys.argv[0]) > - sys.exit(constants.EXIT_FAILURE) > - > - ssconf.CheckMaster(options.debug) > - > - try: > - options.uid = pwd.getpwnam(constants.MASTERD_USER).pw_uid > - options.gid = grp.getgrnam(constants.DAEMONS_GROUP).gr_gid > - except KeyError: > - print >> sys.stderr, ("User or group not existing on system: %s:%s" % > - (constants.MASTERD_USER, > constants.DAEMONS_GROUP)) > - sys.exit(constants.EXIT_FAILURE) > - > - # Determine static runtime architecture information > - runtime.InitArchInfo() > - > - # Check the configuration is sane before anything else > - try: > - livelock = utils.livelock.LiveLock("masterd_check") > - config.GetConfig(None, livelock) > - except errors.ConfigVersionMismatch, err: > - v1 = "%s.%s.%s" % version.SplitVersion(err.args[0]) > - v2 = "%s.%s.%s" % version.SplitVersion(err.args[1]) > - print >> sys.stderr, \ > - ("Configuration version mismatch. The current Ganeti software" > - " expects version %s, but the on-disk configuration file has" > - " version %s. This is likely the result of upgrading the" > - " software without running the upgrade procedure. Please contact" > - " your cluster administrator or complete the upgrade using the" > - " cfgupgrade utility, after reading the upgrade notes." % > - (v1, v2)) > - sys.exit(constants.EXIT_FAILURE) > - except errors.ConfigurationError, err: > - print >> sys.stderr, \ > - ("Configuration error while opening the configuration file: %s\n" > - "This might be caused by an incomplete software upgrade or" > - " by a corrupted configuration file. Until the problem is fixed" > - " the master daemon cannot start." % str(err)) > - sys.exit(constants.EXIT_FAILURE) > - > - # If CheckMaster didn't fail we believe we are the master, but we have > to > - # confirm with the other nodes. > - if options.no_voting: > - if not options.yes_do_it: > - sys.stdout.write("The 'no voting' option has been selected.\n") > - sys.stdout.write("This is dangerous, please confirm by" > - " typing uppercase 'yes': ") > - sys.stdout.flush() > - > - confirmation = sys.stdin.readline().strip() > - if confirmation != "YES": > - print >> sys.stderr, "Aborting." > - sys.exit(constants.EXIT_FAILURE) > - > - else: > - # CheckAgreement uses RPC and threads, hence it needs to be run in > - # a separate process before we call utils.Daemonize in the current > - # process. > - if not utils.RunInSeparateProcess(CheckAgreement): > - sys.exit(constants.EXIT_FAILURE) > - > - # ActivateMasterIP also uses RPC/threads, so we run it again via a > - # separate process. > - > - # TODO: decide whether failure to activate the master IP is a fatal > error > - utils.RunInSeparateProcess(ActivateMasterIP) > - > - > -def PrepMasterd(options, _): > - """Prep master daemon function, executed with the PID file held. > - > - """ > - # This is safe to do as the pid file guarantees against > - # concurrent execution. > - utils.RemoveFile(pathutils.MASTER_SOCKET) > - > - mainloop = daemon.Mainloop() > - master = MasterServer(pathutils.MASTER_SOCKET, options.uid, options.gid) > - return (mainloop, master) > - > - > -def ExecMasterd(options, args, prep_data): # pylint: disable=W0613 > - """Main master daemon function, executed with the PID file held. > - > - """ > - (mainloop, master) = prep_data > - try: > - rpc.Init() > - try: > - master.setup_context() > - try: > - mainloop.Run(shutdown_wait_fn=master.WaitForShutdown) > - finally: > - master.server_cleanup() > - finally: > - rpc.Shutdown() > - finally: > - utils.RemoveFile(pathutils.MASTER_SOCKET) > - > - logging.info("Clean master daemon shutdown") > - > - > -def Main(): > - """Main function""" > - parser = OptionParser(description="Ganeti master daemon", > - usage="%prog [-f] [-d]", > - version="%%prog (ganeti) %s" % > - constants.RELEASE_VERSION) > - parser.add_option("--no-voting", dest="no_voting", > - help="Do not check that the nodes agree on this node" > - " being the master and start the daemon > unconditionally", > - default=False, action="store_true") > - parser.add_option("--yes-do-it", dest="yes_do_it", > - help="Override interactive check for --no-voting", > - default=False, action="store_true") > - daemon.GenericMain(constants.MASTERD, parser, CheckMasterd, PrepMasterd, > - ExecMasterd, multithreaded=True) > diff --git a/man/ganeti-masterd.rst b/man/ganeti-masterd.rst > deleted file mode 100644 > index 2502d65..0000000 > --- a/man/ganeti-masterd.rst > +++ /dev/null > @@ -1,96 +0,0 @@ > -ganeti-masterd(8) Ganeti | Version @GANETI_VERSION@ > -=================================================== > - > -Name > ----- > - > -ganeti-masterd - Ganeti master daemon > - > -Synopsis > --------- > - > -**ganeti-masterd** [-f] [-d] [\--no-voting] > - > -DESCRIPTION > ------------ > - > -The **ganeti-masterd** is the daemon which is responsible for the > -overall cluster coordination. Without it, no change can be > -performed on the cluster. > - > -For testing purposes, you can give the ``-f`` option and the > -program won't detach from the running terminal. > - > -Debug-level message can be activated by giving the ``-d`` option. > - > -ROLE > -~~~~ > - > -The role of the master daemon is to coordinate all the actions that > -change the state of the cluster. Things like accepting new jobs, > -coordinating the changes on nodes (via RPC calls to the respective > -node daemons), maintaining the configuration and so on are done via > -this daemon. > - > -The only action that can be done without the master daemon is the > -failover of the master role to another node in the cluster, via the > -**gnt-cluster master-failover** command. > - > -If the master daemon is stopped, the instances are not affected, > -but they won't be restarted automatically in case of failure. > - > -STARTUP > -~~~~~~~ > - > -At startup, the master daemon will confirm with the node daemons > -that the node it is running is indeed the master node of the > -cluster. It will abort if it doesn't get half plus one positive > -answers (offline nodes are queried too, just in case our > -configuration is stale). > - > -For small clusters with a number of nodes down, and especially for > -two-node clusters where the other has gone done, this creates a > -problem. In this case the ``--no-voting`` option can be used to > -skip this process. The option requires interactive confirmation, as > -having two masters on the same cluster is a very dangerous > -situation and will most likely lead to data loss. > - > -SHUTDOWN > -~~~~~~~~ > - > -When the master daemon receives a ``SIGINT`` (Ctrl-C) or ``SIGTERM`` > -signal, it stops accepting new jobs and prepares to shut down shortly > -after jobs running at the time finish. Meanwhile it still responds to > -LUXI requests. Pending jobs are re-queued after the daemon is started > -again. When a second signal is received, the master daemon terminates > -without waiting (it might still need to wait for some threads to > -finish). Note that the latter, as well as sending ``SIGKILL``, may leave > -the cluster in an inconsistent state. > - > -JOB QUEUE > -~~~~~~~~~ > - > -The master daemon maintains a job queue (located under the directory > -``@LOCALSTATEDIR@/lib/ganeti/queue``) in which all current jobs are > -stored, one job per file serialized in JSON format; in this directory > -a subdirectory called ``archive`` holds archived job files. > - > -The moving of jobs from the current to the queue directory is done > -via a request to the master; this can be accomplished from the > -command line with the **gnt-job archive** or > -**gnt-job autoarchive** commands. In case of problems with the > -master, a job file can simply be moved away or deleted (but this > -might leave the cluster inconsistent). > - > -COMMUNICATION PROTOCOL > -~~~~~~~~~~~~~~~~~~~~~~ > - > -The master accepts commands over a Unix socket, using JSON > -serialized messages separated by a specific byte sequence. For more > -details, see the design documentation supplied with Ganeti. > - > -.. vim: set textwidth=72 : > -.. Local Variables: > -.. mode: rst > -.. fill-column: 72 > -.. End: > diff --git a/qa/qa_env.py b/qa/qa_env.py > index b7fde8f..5529f9e 100644 > --- a/qa/qa_env.py > +++ b/qa/qa_env.py > @@ -49,7 +49,6 @@ def TestGanetiCommands(): > ["gnt-job", "--version"], > ["gnt-node", "--version"], > ["gnt-os", "--version"], > - ["ganeti-masterd", "--version"], > ["ganeti-noded", "--version"], > ["ganeti-rapi", "--version"], > ["ganeti-watcher", "--version"], > -- > 1.9.1.423.g4596e3a > >
