[copr] skvidal-backend: - add option parsing for config file, exit_on_worker, daemonize and pidfile - try out daemonize support (2840524)

skvidal at fedoraproject.org skvidal at fedoraproject.org
Wed Dec 5 19:25:32 UTC 2012


Repository : http://git.fedorahosted.org/cgit/copr.git

On branch  : skvidal-backend

>---------------------------------------------------------------

commit 28405241f3b747ddae19f143ff486c86431cd20a
Author: Seth Vidal <skvidal at fedoraproject.org>
Date:   Wed Dec 5 14:22:57 2012 -0500

    - add option parsing for config file, exit_on_worker, daemonize and pidfile
    - try out daemonize support


>---------------------------------------------------------------

 copr-be.py |   81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 75 insertions(+), 6 deletions(-)

diff --git a/copr-be.py b/copr-be.py
index 73ab70a..4fd48af 100644
--- a/copr-be.py
+++ b/copr-be.py
@@ -10,6 +10,7 @@ from backend.dispatcher import Worker
 from backend import errors
 from bunch import Bunch
 import ConfigParser
+import optparse
 
 def _get_conf(cp, section, option, default):
     """to make returning items from config parser less irritating"""
@@ -59,6 +60,8 @@ class CoprBackend(object):
             opts.terminate_playbook = _get_conf(cp,'backend','terminate_playbook', '/etc/copr/terminate_playbook.yml')
             opts.jobsdir = _get_conf(cp, 'backend', 'jobsdir', None)
             opts.destdir = _get_conf(cp, 'backend', 'destdir', None)
+            opts.daemonize = _get_conf(cp, 'backend', 'daemonize', True)
+            opts.exit_on_worker = _get_conf(cp, 'backend', 'exit_on_worker', False)
             opts.sleeptime = int(_get_conf(cp, 'backend', 'sleeptime', 10))
             opts.num_workers = int(_get_conf(cp, 'backend', 'num_workers', 8))
             opts.timeout = int(_get_conf(cp, 'builder', 'timeout', 1800))
@@ -80,8 +83,12 @@ class CoprBackend(object):
         
     def log(self, msg):
         now = time.time()
+        output = str(now) + ':' + msg
+        if not self.opts.daemonize:
+            print output
+            
         try:
-            open(self.logfile, 'a').write(str(now) + ':' + msg + '\n')
+            open(self.logfile, 'a').write(output + '\n')
         except (IOError, OSError), e:
             print >>sys.stderr, 'Could not write to logfile %s - %s' % (self.logfile, str(e))
 
@@ -120,17 +127,79 @@ class CoprBackend(object):
             # check for dead workers and abort
             for w in self.workers:
                 if not w.is_alive():
-                    raise errors.CoprBackendError, "Worker died unexpectedly"
+                    self.log('Worker %d died unexpectedly' % w.worker_num)
+                    if self.opts.exit_on_worker:
+                        raise errors.CoprBackendError, "Worker died unexpectedly, exiting"
+                    
 
             time.sleep(self.opts.sleeptime)
 
+# lifted from certmaster
+def daemonize(pidfile=None): 
+    """
+    Daemonize this process with the UNIX double-fork trick.
+    Writes the new PID to the provided file name if not None.
+    """
     
-def main(args):
-    if len(args) < 1 or not os.path.exists(args[0]):
-        print 'Must pass in config file'
+    pid = os.fork()
+    if pid > 0:
+        sys.exit(0)
+    os.chdir("/")
+    os.setsid()
+    os.umask(077)
+    pid = os.fork()
+
+    os.close(0)
+    os.close(1)
+    os.close(2)
+
+    # The standard I/O file descriptors are redirected to /dev/null by default.
+    if (hasattr(os, "devnull")):  
+        REDIRECT_TO = os.devnull
+    else:
+        REDIRECT_TO = "/dev/null"
+
+    # based on http://code.activestate.com/recipes/278731/
+    os.open(REDIRECT_TO, os.O_RDWR)     # standard input (0)
+
+    os.dup2(0, 1)                       # standard output (1)
+    os.dup2(0, 2)                       # standard error (2)
+
+
+
+    if pid > 0:
+        if pidfile is not None:
+            open(pidfile, "w").write(str(pid))
+        sys.exit(0)
+
+def parse_args(args):
+    parser = optparse.OptionParser('\ncopr-be [options]')
+    parser.add_option('-c', '--config', default='/etc/copr-be.conf', dest='config_file',
+            help="config file to use for copr-be run")
+    parser.add_option('-d' '--daemonize', default=False, dest='daemonize',
+            action='store_true', help="daemonize or not")
+    parser.add_option('-p', '--pidfile', default='/var/run/copr-be.pid', dest='pidfile',
+            help="pid file to use for copr-be if daemonized")
+    parser.add_option('-x', '--exit', default=False, dest='exit_on_worker',
+            action='store_true', help="exit on worker failure")
+            
+    opts, args = parser.parse_args(args)
+    if not os.path.exists(opts.config_file):
+        print "No config file found at: %s" % opts.config_file
         sys.exit(1)
+    
+    return opts,args
+    
+    
+    
+def main(args):
+    opts,args = parse_args(args)
+    
     try:
-        cbe = CoprBackend(args[0])
+        cbe = CoprBackend(opts.config_file)
+        cbe.opts.daemonize = opts.daemonize # just so we have it on hand
+        cbe.opts.exit_on_worker = opts.exit_on_worker
+        daemonize(opts.pidfile)
         cbe.run()
     except Exception, e:
         print 'Killing/Dying'



More information about the copr-devel mailing list