X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=python%2Fovs%2Fdaemon.py;h=650d2504034b6cced33c0e3d6f0f4e90861ff4f0;hb=1804d25a21dcdec83437ab1ebf9daf683d7e50da;hp=a14be820a62838518f836d4dab5a11d1f099c236;hpb=cadc9871c2b0962e7d8497d643f49b4e1176c5c0;p=openvswitch diff --git a/python/ovs/daemon.py b/python/ovs/daemon.py index a14be820..650d2504 100644 --- a/python/ovs/daemon.py +++ b/python/ovs/daemon.py @@ -1,4 +1,4 @@ -# Copyright (c) 2010, 2011 Nicira Networks +# Copyright (c) 2010, 2011 Nicira, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,7 +14,6 @@ import errno import fcntl -import logging import os import resource import signal @@ -28,6 +27,9 @@ import ovs.process import ovs.socket_util import ovs.timeval import ovs.util +import ovs.vlog + +vlog = ovs.vlog.Vlog("daemon") # --detach: Should we run in the background? _detach = False @@ -121,7 +123,7 @@ def set_monitor(): def _fatal(msg): - logging.error(msg) + vlog.err(msg) sys.stderr.write("%s\n" % msg) sys.exit(1) @@ -139,25 +141,25 @@ def _make_pidfile(): # This is global to keep Python from garbage-collecting and # therefore closing our file after this function exits. That would # unlock the lock for us, and we don't want that. - global file + global file_handle - file = open(tmpfile, "w") + file_handle = open(tmpfile, "w") except IOError, e: _fatal("%s: create failed (%s)" % (tmpfile, e.strerror)) try: - s = os.fstat(file.fileno()) + s = os.fstat(file_handle.fileno()) except IOError, e: _fatal("%s: fstat failed (%s)" % (tmpfile, e.strerror)) try: - file.write("%s\n" % pid) - file.flush() + file_handle.write("%s\n" % pid) + file_handle.flush() except OSError, e: _fatal("%s: write failed: %s" % (tmpfile, e.strerror)) try: - fcntl.lockf(file, fcntl.LOCK_EX | fcntl.LOCK_NB) + fcntl.lockf(file_handle, fcntl.LOCK_EX | fcntl.LOCK_NB) except IOError, e: _fatal("%s: fcntl failed: %s" % (tmpfile, e.strerror)) @@ -243,13 +245,19 @@ def _fork_and_wait_for_startup(): break if len(s) != 1: retval, status = _waitpid(pid, 0) - if (retval == pid and - os.WIFEXITED(status) and os.WEXITSTATUS(status)): - # Child exited with an error. Convey the same error to - # our parent process as a courtesy. - sys.exit(os.WEXITSTATUS(status)) + if retval == pid: + if os.WIFEXITED(status) and os.WEXITSTATUS(status): + # Child exited with an error. Convey the same error to + # our parent process as a courtesy. + sys.exit(os.WEXITSTATUS(status)) + else: + sys.stderr.write("fork child failed to signal " + "startup (%s)\n" + % ovs.process.status_msg(status)) else: - sys.stderr.write("fork child failed to signal startup\n") + assert retval < 0 + sys.stderr.write("waitpid failed (%s)\n" + % os.strerror(-retval)) sys.exit(1) os.close(rfd) @@ -306,13 +314,13 @@ def _monitor_daemon(daemon_pid): try: resource.setrlimit(resource.RLIMIT_CORE, (0, 0)) except resource.error: - logging.warning("failed to disable core dumps") + vlog.warn("failed to disable core dumps") # Throttle restarts to no more than once every 10 seconds. if (last_restart is not None and ovs.timeval.msec() < last_restart + 10000): - logging.warning("%s, waiting until 10 seconds since last " - "restart" % status_msg) + vlog.warn("%s, waiting until 10 seconds since last " + "restart" % status_msg) while True: now = ovs.timeval.msec() wakeup = last_restart + 10000 @@ -322,12 +330,12 @@ def _monitor_daemon(daemon_pid): time.sleep((wakeup - now) / 1000.0) last_restart = ovs.timeval.msec() - logging.error("%s, restarting" % status_msg) + vlog.err("%s, restarting" % status_msg) daemon_pid = _fork_and_wait_for_startup() if not daemon_pid: break else: - logging.info("%s, exiting" % status_msg) + vlog.info("%s, exiting" % status_msg) sys.exit(0) # Running in new daemon process. @@ -407,66 +415,68 @@ def __read_pidfile(pidfile, delete_if_stale): pass try: - file = open(pidfile, "r+") + file_handle = open(pidfile, "r+") except IOError, e: if e.errno == errno.ENOENT and delete_if_stale: return 0 - logging.warning("%s: open: %s" % (pidfile, e.strerror)) + vlog.warn("%s: open: %s" % (pidfile, e.strerror)) return -e.errno # Python fcntl doesn't directly support F_GETLK so we have to just try # to lock it. try: - fcntl.lockf(file, fcntl.LOCK_EX | fcntl.LOCK_NB) + fcntl.lockf(file_handle, fcntl.LOCK_EX | fcntl.LOCK_NB) # pidfile exists but wasn't locked by anyone. Now we have the lock. if not delete_if_stale: - file.close() - logging.warning("%s: pid file is stale" % pidfile) + file_handle.close() + vlog.warn("%s: pid file is stale" % pidfile) return -errno.ESRCH # Is the file we have locked still named 'pidfile'? try: raced = False s = os.stat(pidfile) - s2 = os.fstat(file.fileno()) + s2 = os.fstat(file_handle.fileno()) if s.st_ino != s2.st_ino or s.st_dev != s2.st_dev: raced = True except IOError: raced = True if raced: - logging.warning("%s: lost race to delete pidfile" % pidfile) + vlog.warn("%s: lost race to delete pidfile" % pidfile) return -errno.EALREADY # We won the right to delete the stale pidfile. try: os.unlink(pidfile) except IOError, e: - logging.warning("%s: failed to delete stale pidfile (%s)" + vlog.warn("%s: failed to delete stale pidfile (%s)" % (pidfile, e.strerror)) return -e.errno else: - logging.debug("%s: deleted stale pidfile" % pidfile) - file.close() + vlog.dbg("%s: deleted stale pidfile" % pidfile) + file_handle.close() return 0 except IOError, e: if e.errno not in [errno.EACCES, errno.EAGAIN]: - logging.warn("%s: fcntl: %s" % (pidfile, e.strerror)) + vlog.warn("%s: fcntl: %s" % (pidfile, e.strerror)) return -e.errno # Someone else has the pidfile locked. try: try: - return int(file.readline()) + error = int(file_handle.readline()) except IOError, e: - logging.warning("%s: read: %s" % (pidfile, e.strerror)) - return -e.errno + vlog.warn("%s: read: %s" % (pidfile, e.strerror)) + error = -e.errno except ValueError: - logging.warning("%s does not contain a pid" % pidfile) - return -errno.EINVAL + vlog.warn("%s does not contain a pid" % pidfile) + error = -errno.EINVAL + + return error finally: try: - file.close() + file_handle.close() except IOError: pass @@ -485,26 +495,43 @@ def _check_already_running(): _fatal("%s: pidfile check failed (%s), aborting" % (_pidfile, os.strerror(pid))) -# XXX Python's getopt does not support options with optional arguments, so we -# have to separate --pidfile (with no argument) from --pidfile-name (with an -# argument). Need to write our own getopt I guess. -LONG_OPTIONS = ["detach", "no-chdir", "pidfile", "pidfile-name=", - "overwrite-pidfile", "monitor"] + +def add_args(parser): + """Populates 'parser', an ArgumentParser allocated using the argparse + module, with the command line arguments required by the daemon module.""" + + pidfile = make_pidfile_name(None) + + group = parser.add_argument_group(title="Daemon Options") + group.add_argument("--detach", action="store_true", + help="Run in background as a daemon.") + group.add_argument("--no-chdir", action="store_true", + help="Do not chdir to '/'.") + group.add_argument("--monitor", action="store_true", + help="Monitor %s process." % ovs.util.PROGRAM_NAME) + group.add_argument("--pidfile", nargs="?", const=pidfile, + help="Create pidfile (default %s)." % pidfile) + group.add_argument("--overwrite-pidfile", action="store_true", + help="With --pidfile, start even if already running.") -def parse_opt(option, arg): - if option == '--detach': +def handle_args(args): + """Handles daemon module settings in 'args'. 'args' is an object + containing values parsed by the parse_args() method of ArgumentParser. The + parent ArgumentParser should have been prepared by add_args() before + calling parse_args().""" + + if args.detach: set_detach() - elif option == '--no-chdir': + + if args.no_chdir: set_no_chdir() - elif option == '--pidfile': - set_pidfile(None) - elif option == '--pidfile-name': - set_pidfile(arg) - elif option == '--overwrite-pidfile': + + if args.pidfile: + set_pidfile(args.pidfile) + + if args.overwrite_pidfile: ignore_existing_pidfile() - elif option == '--monitor': + + if args.monitor: set_monitor() - else: - return False - return True