James E. Blair | 1f4c2bb | 2013-04-26 08:40:46 -0700 | [diff] [blame] | 1 | #!/usr/bin/env python |
James E. Blair | 1ce97ad | 2012-05-29 15:38:19 -0700 | [diff] [blame] | 2 | # Copyright 2012 Hewlett-Packard Development Company, L.P. |
James E. Blair | 4795838 | 2013-01-10 17:26:02 -0800 | [diff] [blame] | 3 | # Copyright 2013 OpenStack Foundation |
James E. Blair | 1ce97ad | 2012-05-29 15:38:19 -0700 | [diff] [blame] | 4 | # |
| 5 | # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| 6 | # not use this file except in compliance with the License. You may obtain |
| 7 | # a copy of the License at |
| 8 | # |
| 9 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | # |
| 11 | # Unless required by applicable law or agreed to in writing, software |
| 12 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 13 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 14 | # License for the specific language governing permissions and limitations |
| 15 | # under the License. |
| 16 | |
James E. Blair | ee74361 | 2012-05-29 14:49:32 -0700 | [diff] [blame] | 17 | import argparse |
James E. Blair | d3bbe00 | 2012-05-31 13:06:31 -0700 | [diff] [blame] | 18 | import daemon |
Monty Taylor | a94bf17 | 2012-11-25 13:00:03 -0800 | [diff] [blame] | 19 | import extras |
Antoine Musso | 80925f5 | 2012-09-22 21:37:45 +0200 | [diff] [blame] | 20 | |
Monty Taylor | a94bf17 | 2012-11-25 13:00:03 -0800 | [diff] [blame] | 21 | # as of python-daemon 1.6 it doesn't bundle pidlockfile anymore |
| 22 | # instead it depends on lockfile-0.9.1 which uses pidfile. |
James E. Blair | 138d336 | 2012-11-30 15:10:43 -0800 | [diff] [blame] | 23 | pid_file_module = extras.try_imports(['daemon.pidlockfile', 'daemon.pidfile']) |
Antoine Musso | 80925f5 | 2012-09-22 21:37:45 +0200 | [diff] [blame] | 24 | |
Clark Boylan | fba9b24 | 2013-08-20 10:11:17 -0700 | [diff] [blame] | 25 | import logging |
James E. Blair | ee74361 | 2012-05-29 14:49:32 -0700 | [diff] [blame] | 26 | import os |
James E. Blair | 4795838 | 2013-01-10 17:26:02 -0800 | [diff] [blame] | 27 | import sys |
James E. Blair | e9d45c3 | 2012-05-31 09:56:45 -0700 | [diff] [blame] | 28 | import signal |
Antoine Musso | 3775875 | 2014-04-05 23:01:35 +0200 | [diff] [blame] | 29 | |
| 30 | import zuul.cmd |
James E. Blair | ee74361 | 2012-05-29 14:49:32 -0700 | [diff] [blame] | 31 | |
James E. Blair | 3266340 | 2012-06-01 10:04:18 -0700 | [diff] [blame] | 32 | # No zuul imports here because they pull in paramiko which must not be |
| 33 | # imported until after the daemonization. |
| 34 | # https://github.com/paramiko/paramiko/issues/59 |
James E. Blair | dda083b | 2014-01-09 07:04:37 +0800 | [diff] [blame] | 35 | # Similar situation with gear and statsd. |
James E. Blair | ee74361 | 2012-05-29 14:49:32 -0700 | [diff] [blame] | 36 | |
James E. Blair | ee74361 | 2012-05-29 14:49:32 -0700 | [diff] [blame] | 37 | |
James E. Blair | 5f0f514 | 2017-02-14 15:36:31 -0800 | [diff] [blame] | 38 | class Scheduler(zuul.cmd.ZuulApp): |
James E. Blair | e9d45c3 | 2012-05-31 09:56:45 -0700 | [diff] [blame] | 39 | def __init__(self): |
James E. Blair | 5f0f514 | 2017-02-14 15:36:31 -0800 | [diff] [blame] | 40 | super(Scheduler, self).__init__() |
James E. Blair | 922a9f6 | 2013-05-22 14:44:58 -0700 | [diff] [blame] | 41 | self.gear_server_pid = None |
James E. Blair | 1e8dd89 | 2012-05-30 09:15:05 -0700 | [diff] [blame] | 42 | |
James E. Blair | e9d45c3 | 2012-05-31 09:56:45 -0700 | [diff] [blame] | 43 | def parse_arguments(self): |
| 44 | parser = argparse.ArgumentParser(description='Project gating system.') |
| 45 | parser.add_argument('-c', dest='config', |
| 46 | help='specify the config file') |
James E. Blair | 4795838 | 2013-01-10 17:26:02 -0800 | [diff] [blame] | 47 | parser.add_argument('-l', dest='layout', |
| 48 | help='specify the layout file') |
James E. Blair | d3bbe00 | 2012-05-31 13:06:31 -0700 | [diff] [blame] | 49 | parser.add_argument('-d', dest='nodaemon', action='store_true', |
| 50 | help='do not run as a daemon') |
James E. Blair | 04948c7 | 2013-07-25 23:03:17 -0700 | [diff] [blame] | 51 | parser.add_argument('-t', dest='validate', nargs='?', const=True, |
| 52 | metavar='JOB_LIST', |
| 53 | help='validate layout file syntax (optionally ' |
| 54 | 'providing the path to a file with a list of ' |
| 55 | 'available job names)') |
Antoine Musso | aabb686 | 2014-01-14 17:32:09 +0100 | [diff] [blame] | 56 | parser.add_argument('--version', dest='version', action='version', |
| 57 | version=self._get_version(), |
Antoine Musso | 26b1fb8 | 2013-03-21 16:31:40 +0100 | [diff] [blame] | 58 | help='show zuul version') |
James E. Blair | e9d45c3 | 2012-05-31 09:56:45 -0700 | [diff] [blame] | 59 | self.args = parser.parse_args() |
James E. Blair | ee74361 | 2012-05-29 14:49:32 -0700 | [diff] [blame] | 60 | |
James E. Blair | e9d45c3 | 2012-05-31 09:56:45 -0700 | [diff] [blame] | 61 | def reconfigure_handler(self, signum, frame): |
| 62 | signal.signal(signal.SIGHUP, signal.SIG_IGN) |
Joshua Hesketh | 352264b | 2015-08-11 23:42:08 +1000 | [diff] [blame] | 63 | self.log.debug("Reconfiguration triggered") |
James E. Blair | e9d45c3 | 2012-05-31 09:56:45 -0700 | [diff] [blame] | 64 | self.read_config() |
James E. Blair | f9eeb94 | 2013-06-18 08:36:07 -0700 | [diff] [blame] | 65 | self.setup_logging('zuul', 'log_config') |
Evgeny Antyshev | 0051cd4 | 2015-07-03 11:39:10 +0000 | [diff] [blame] | 66 | try: |
| 67 | self.sched.reconfigure(self.config) |
| 68 | except Exception: |
| 69 | self.log.exception("Reconfiguration failed:") |
James E. Blair | e9d45c3 | 2012-05-31 09:56:45 -0700 | [diff] [blame] | 70 | signal.signal(signal.SIGHUP, self.reconfigure_handler) |
James E. Blair | 1e8dd89 | 2012-05-30 09:15:05 -0700 | [diff] [blame] | 71 | |
James E. Blair | 5d5bc2b | 2012-07-06 10:24:01 -0700 | [diff] [blame] | 72 | def exit_handler(self, signum, frame): |
| 73 | signal.signal(signal.SIGUSR1, signal.SIG_IGN) |
| 74 | self.sched.exit() |
James E. Blair | 6767905 | 2013-08-26 17:05:00 -0700 | [diff] [blame] | 75 | self.sched.join() |
| 76 | self.stop_gear_server() |
James E. Blair | 5d5bc2b | 2012-07-06 10:24:01 -0700 | [diff] [blame] | 77 | |
James E. Blair | 922a9f6 | 2013-05-22 14:44:58 -0700 | [diff] [blame] | 78 | def term_handler(self, signum, frame): |
| 79 | self.stop_gear_server() |
| 80 | os._exit(0) |
| 81 | |
James E. Blair | 04948c7 | 2013-07-25 23:03:17 -0700 | [diff] [blame] | 82 | def test_config(self, job_list_path): |
James E. Blair | 4795838 | 2013-01-10 17:26:02 -0800 | [diff] [blame] | 83 | # See comment at top of file about zuul imports |
| 84 | import zuul.scheduler |
James E. Blair | 1f4c2bb | 2013-04-26 08:40:46 -0700 | [diff] [blame] | 85 | import zuul.launcher.gearman |
James E. Blair | 4795838 | 2013-01-10 17:26:02 -0800 | [diff] [blame] | 86 | import zuul.trigger.gerrit |
| 87 | |
| 88 | logging.basicConfig(level=logging.DEBUG) |
James E. Blair | e4d229c | 2016-05-25 15:25:41 -0700 | [diff] [blame] | 89 | self.sched = zuul.scheduler.Scheduler(self.config, |
| 90 | testonly=True) |
Joshua Hesketh | 352264b | 2015-08-11 23:42:08 +1000 | [diff] [blame] | 91 | self.configure_connections() |
Joshua Hesketh | 9a25675 | 2016-04-04 13:38:51 +1000 | [diff] [blame] | 92 | self.sched.registerConnections(self.connections, load=False) |
James E. Blair | 04948c7 | 2013-07-25 23:03:17 -0700 | [diff] [blame] | 93 | layout = self.sched.testConfig(self.config.get('zuul', |
Joshua Hesketh | 352264b | 2015-08-11 23:42:08 +1000 | [diff] [blame] | 94 | 'layout_config'), |
| 95 | self.connections) |
James E. Blair | 04948c7 | 2013-07-25 23:03:17 -0700 | [diff] [blame] | 96 | if not job_list_path: |
| 97 | return False |
| 98 | |
| 99 | failure = False |
| 100 | path = os.path.expanduser(job_list_path) |
| 101 | if not os.path.exists(path): |
| 102 | raise Exception("Unable to find job list: %s" % path) |
| 103 | jobs = set() |
James E. Blair | b47a3ae | 2014-03-21 11:21:10 -0700 | [diff] [blame] | 104 | jobs.add('noop') |
James E. Blair | 04948c7 | 2013-07-25 23:03:17 -0700 | [diff] [blame] | 105 | for line in open(path): |
| 106 | v = line.strip() |
| 107 | if v: |
| 108 | jobs.add(v) |
| 109 | for job in sorted(layout.jobs): |
| 110 | if job not in jobs: |
Doug Hellmann | 8122328 | 2016-01-25 15:41:35 -0500 | [diff] [blame] | 111 | print("FAILURE: Job %s not defined" % job) |
James E. Blair | 04948c7 | 2013-07-25 23:03:17 -0700 | [diff] [blame] | 112 | failure = True |
| 113 | return failure |
James E. Blair | 4795838 | 2013-01-10 17:26:02 -0800 | [diff] [blame] | 114 | |
James E. Blair | 922a9f6 | 2013-05-22 14:44:58 -0700 | [diff] [blame] | 115 | def start_gear_server(self): |
| 116 | pipe_read, pipe_write = os.pipe() |
| 117 | child_pid = os.fork() |
| 118 | if child_pid == 0: |
| 119 | os.close(pipe_write) |
| 120 | self.setup_logging('gearman_server', 'log_config') |
James E. Blair | d437159 | 2016-06-08 16:55:04 -0700 | [diff] [blame] | 121 | import zuul.lib.gearserver |
James E. Blair | a77f28c | 2014-02-21 08:02:00 -0800 | [diff] [blame] | 122 | statsd_host = os.environ.get('STATSD_HOST') |
| 123 | statsd_port = int(os.environ.get('STATSD_PORT', 8125)) |
James E. Blair | 0ac452e | 2015-07-22 09:05:16 -0700 | [diff] [blame] | 124 | if self.config.has_option('gearman_server', 'listen_address'): |
| 125 | host = self.config.get('gearman_server', 'listen_address') |
| 126 | else: |
| 127 | host = None |
James E. Blair | d437159 | 2016-06-08 16:55:04 -0700 | [diff] [blame] | 128 | zuul.lib.gearserver.GearServer(4730, |
| 129 | host=host, |
| 130 | statsd_host=statsd_host, |
| 131 | statsd_port=statsd_port, |
| 132 | statsd_prefix='zuul.geard') |
James E. Blair | a77f28c | 2014-02-21 08:02:00 -0800 | [diff] [blame] | 133 | |
James E. Blair | 922a9f6 | 2013-05-22 14:44:58 -0700 | [diff] [blame] | 134 | # Keep running until the parent dies: |
| 135 | pipe_read = os.fdopen(pipe_read) |
| 136 | pipe_read.read() |
| 137 | os._exit(0) |
| 138 | else: |
| 139 | os.close(pipe_read) |
| 140 | self.gear_server_pid = child_pid |
| 141 | self.gear_pipe_write = pipe_write |
| 142 | |
| 143 | def stop_gear_server(self): |
| 144 | if self.gear_server_pid: |
| 145 | os.kill(self.gear_server_pid, signal.SIGKILL) |
| 146 | |
James E. Blair | e9d45c3 | 2012-05-31 09:56:45 -0700 | [diff] [blame] | 147 | def main(self): |
James E. Blair | 3266340 | 2012-06-01 10:04:18 -0700 | [diff] [blame] | 148 | # See comment at top of file about zuul imports |
| 149 | import zuul.scheduler |
Joshua Hesketh | 0c54b2a | 2016-04-11 21:23:33 +1000 | [diff] [blame] | 150 | import zuul.launcher.client |
James E. Blair | 4076e2b | 2014-01-28 12:42:20 -0800 | [diff] [blame] | 151 | import zuul.merger.client |
James E. Blair | 8d69239 | 2016-04-08 17:47:58 -0700 | [diff] [blame] | 152 | import zuul.nodepool |
Joshua Hesketh | 36c3fa5 | 2014-01-22 11:40:52 +1100 | [diff] [blame] | 153 | import zuul.lib.swift |
James E. Blair | 1f4c2bb | 2013-04-26 08:40:46 -0700 | [diff] [blame] | 154 | import zuul.webapp |
James E. Blair | ad28e91 | 2013-11-27 10:43:22 -0800 | [diff] [blame] | 155 | import zuul.rpclistener |
Paul Belanger | bbb4875 | 2017-02-21 10:56:40 -0500 | [diff] [blame^] | 156 | import zuul.zk |
James E. Blair | 3266340 | 2012-06-01 10:04:18 -0700 | [diff] [blame] | 157 | |
Antoine Musso | 29eab01 | 2014-10-28 21:35:22 +0100 | [diff] [blame] | 158 | signal.signal(signal.SIGUSR2, zuul.cmd.stack_dump_handler) |
James E. Blair | 922a9f6 | 2013-05-22 14:44:58 -0700 | [diff] [blame] | 159 | if (self.config.has_option('gearman_server', 'start') and |
| 160 | self.config.getboolean('gearman_server', 'start')): |
| 161 | self.start_gear_server() |
| 162 | |
| 163 | self.setup_logging('zuul', 'log_config') |
James E. Blair | 5f0f514 | 2017-02-14 15:36:31 -0800 | [diff] [blame] | 164 | self.log = logging.getLogger("zuul.Scheduler") |
James E. Blair | 922a9f6 | 2013-05-22 14:44:58 -0700 | [diff] [blame] | 165 | |
Joshua Hesketh | 352264b | 2015-08-11 23:42:08 +1000 | [diff] [blame] | 166 | self.sched = zuul.scheduler.Scheduler(self.config) |
| 167 | # TODO(jhesketh): Move swift into a connection? |
Joshua Hesketh | 36c3fa5 | 2014-01-22 11:40:52 +1100 | [diff] [blame] | 168 | self.swift = zuul.lib.swift.Swift(self.config) |
James E. Blair | ee74361 | 2012-05-29 14:49:32 -0700 | [diff] [blame] | 169 | |
Joshua Hesketh | 0c54b2a | 2016-04-11 21:23:33 +1000 | [diff] [blame] | 170 | gearman = zuul.launcher.client.LaunchClient(self.config, self.sched, |
| 171 | self.swift) |
James E. Blair | 4076e2b | 2014-01-28 12:42:20 -0800 | [diff] [blame] | 172 | merger = zuul.merger.client.MergeClient(self.config, self.sched) |
James E. Blair | 8d69239 | 2016-04-08 17:47:58 -0700 | [diff] [blame] | 173 | nodepool = zuul.nodepool.Nodepool(self.sched) |
Joshua Hesketh | 850ccb6 | 2014-11-27 11:31:02 +1100 | [diff] [blame] | 174 | |
Paul Belanger | bbb4875 | 2017-02-21 10:56:40 -0500 | [diff] [blame^] | 175 | zookeeper = zuul.zk.ZooKeeper() |
| 176 | if self.config.has_option('zuul', 'zookeeper_hosts'): |
| 177 | zookeeper_hosts = self.config.get('zuul', 'zookeeper_hosts') |
| 178 | else: |
| 179 | zookeeper_hosts = '127.0.0.1:2181' |
| 180 | |
| 181 | zookeeper.connect(zookeeper_hosts) |
| 182 | |
Clark Boylan | e0b4bdb | 2014-06-03 17:01:25 -0700 | [diff] [blame] | 183 | if self.config.has_option('zuul', 'status_expiry'): |
| 184 | cache_expiry = self.config.getint('zuul', 'status_expiry') |
| 185 | else: |
| 186 | cache_expiry = 1 |
Paul Belanger | 88ef0ea | 2015-12-23 11:57:02 -0500 | [diff] [blame] | 187 | |
| 188 | if self.config.has_option('webapp', 'listen_address'): |
| 189 | listen_address = self.config.get('webapp', 'listen_address') |
| 190 | else: |
| 191 | listen_address = '0.0.0.0' |
| 192 | |
| 193 | if self.config.has_option('webapp', 'port'): |
| 194 | port = self.config.getint('webapp', 'port') |
| 195 | else: |
| 196 | port = 8001 |
| 197 | |
| 198 | webapp = zuul.webapp.WebApp( |
| 199 | self.sched, port=port, cache_expiry=cache_expiry, |
| 200 | listen_address=listen_address) |
James E. Blair | ad28e91 | 2013-11-27 10:43:22 -0800 | [diff] [blame] | 201 | rpc = zuul.rpclistener.RPCListener(self.config, self.sched) |
James E. Blair | 1e8dd89 | 2012-05-30 09:15:05 -0700 | [diff] [blame] | 202 | |
James E. Blair | fef7894 | 2016-03-11 16:28:56 -0800 | [diff] [blame] | 203 | self.configure_connections() |
James E. Blair | 1f4c2bb | 2013-04-26 08:40:46 -0700 | [diff] [blame] | 204 | self.sched.setLauncher(gearman) |
James E. Blair | 4076e2b | 2014-01-28 12:42:20 -0800 | [diff] [blame] | 205 | self.sched.setMerger(merger) |
James E. Blair | 8d69239 | 2016-04-08 17:47:58 -0700 | [diff] [blame] | 206 | self.sched.setNodepool(nodepool) |
Paul Belanger | bbb4875 | 2017-02-21 10:56:40 -0500 | [diff] [blame^] | 207 | self.sched.setZooKeeper(zookeeper) |
James E. Blair | ee74361 | 2012-05-29 14:49:32 -0700 | [diff] [blame] | 208 | |
Antoine Musso | 8f30d57 | 2014-01-15 21:57:09 +0100 | [diff] [blame] | 209 | self.log.info('Starting scheduler') |
James E. Blair | 99f9310 | 2017-02-20 17:27:40 -0500 | [diff] [blame] | 210 | try: |
| 211 | self.sched.start() |
| 212 | self.sched.registerConnections(self.connections) |
| 213 | self.sched.reconfigure(self.config) |
| 214 | self.sched.resume() |
| 215 | except Exception: |
| 216 | self.log.exception("Error starting Zuul:") |
| 217 | # TODO(jeblair): If we had all threads marked as daemon, |
| 218 | # we might be able to have a nicer way of exiting here. |
| 219 | sys.exit(1) |
Antoine Musso | 8f30d57 | 2014-01-15 21:57:09 +0100 | [diff] [blame] | 220 | self.log.info('Starting Webapp') |
James E. Blair | 1f4c2bb | 2013-04-26 08:40:46 -0700 | [diff] [blame] | 221 | webapp.start() |
Antoine Musso | 8f30d57 | 2014-01-15 21:57:09 +0100 | [diff] [blame] | 222 | self.log.info('Starting RPC') |
James E. Blair | ad28e91 | 2013-11-27 10:43:22 -0800 | [diff] [blame] | 223 | rpc.start() |
James E. Blair | 1f4c2bb | 2013-04-26 08:40:46 -0700 | [diff] [blame] | 224 | |
James E. Blair | e9d45c3 | 2012-05-31 09:56:45 -0700 | [diff] [blame] | 225 | signal.signal(signal.SIGHUP, self.reconfigure_handler) |
James E. Blair | 5d5bc2b | 2012-07-06 10:24:01 -0700 | [diff] [blame] | 226 | signal.signal(signal.SIGUSR1, self.exit_handler) |
James E. Blair | 922a9f6 | 2013-05-22 14:44:58 -0700 | [diff] [blame] | 227 | signal.signal(signal.SIGTERM, self.term_handler) |
James E. Blair | e9d45c3 | 2012-05-31 09:56:45 -0700 | [diff] [blame] | 228 | while True: |
Antoine Musso | 6ad5d5b | 2012-09-24 13:25:28 +0200 | [diff] [blame] | 229 | try: |
| 230 | signal.pause() |
| 231 | except KeyboardInterrupt: |
Morgan Fainberg | 4c6a774 | 2016-05-27 08:42:17 -0700 | [diff] [blame] | 232 | print("Ctrl + C: asking scheduler to exit nicely...\n") |
Monty Taylor | 7df9e7f | 2012-11-25 12:12:28 -0800 | [diff] [blame] | 233 | self.exit_handler(signal.SIGINT, None) |
James E. Blair | ee74361 | 2012-05-29 14:49:32 -0700 | [diff] [blame] | 234 | |
Monty Taylor | 7df9e7f | 2012-11-25 12:12:28 -0800 | [diff] [blame] | 235 | |
| 236 | def main(): |
James E. Blair | 5f0f514 | 2017-02-14 15:36:31 -0800 | [diff] [blame] | 237 | scheduler = Scheduler() |
| 238 | scheduler.parse_arguments() |
Antoine Musso | 26b1fb8 | 2013-03-21 16:31:40 +0100 | [diff] [blame] | 239 | |
James E. Blair | 5f0f514 | 2017-02-14 15:36:31 -0800 | [diff] [blame] | 240 | scheduler.read_config() |
James E. Blair | d3bbe00 | 2012-05-31 13:06:31 -0700 | [diff] [blame] | 241 | |
James E. Blair | 5f0f514 | 2017-02-14 15:36:31 -0800 | [diff] [blame] | 242 | if scheduler.args.layout: |
| 243 | scheduler.config.set('zuul', 'layout_config', scheduler.args.layout) |
James E. Blair | 4795838 | 2013-01-10 17:26:02 -0800 | [diff] [blame] | 244 | |
James E. Blair | 5f0f514 | 2017-02-14 15:36:31 -0800 | [diff] [blame] | 245 | if scheduler.args.validate: |
| 246 | path = scheduler.args.validate |
James E. Blair | 04948c7 | 2013-07-25 23:03:17 -0700 | [diff] [blame] | 247 | if path is True: |
| 248 | path = None |
James E. Blair | 5f0f514 | 2017-02-14 15:36:31 -0800 | [diff] [blame] | 249 | sys.exit(scheduler.test_config(path)) |
James E. Blair | 4795838 | 2013-01-10 17:26:02 -0800 | [diff] [blame] | 250 | |
James E. Blair | 5f0f514 | 2017-02-14 15:36:31 -0800 | [diff] [blame] | 251 | if scheduler.config.has_option('zuul', 'pidfile'): |
| 252 | pid_fn = os.path.expanduser(scheduler.config.get('zuul', 'pidfile')) |
James E. Blair | d3bbe00 | 2012-05-31 13:06:31 -0700 | [diff] [blame] | 253 | else: |
Clark Boylan | b80fae0 | 2017-02-20 16:26:43 -0500 | [diff] [blame] | 254 | pid_fn = '/var/run/zuul-scheduler/zuul-scheduler.pid' |
Antoine Musso | 80925f5 | 2012-09-22 21:37:45 +0200 | [diff] [blame] | 255 | pid = pid_file_module.TimeoutPIDLockFile(pid_fn, 10) |
James E. Blair | d3bbe00 | 2012-05-31 13:06:31 -0700 | [diff] [blame] | 256 | |
James E. Blair | 5f0f514 | 2017-02-14 15:36:31 -0800 | [diff] [blame] | 257 | if scheduler.args.nodaemon: |
| 258 | scheduler.main() |
James E. Blair | d3bbe00 | 2012-05-31 13:06:31 -0700 | [diff] [blame] | 259 | else: |
| 260 | with daemon.DaemonContext(pidfile=pid): |
James E. Blair | 5f0f514 | 2017-02-14 15:36:31 -0800 | [diff] [blame] | 261 | scheduler.main() |
James E. Blair | 1f4c2bb | 2013-04-26 08:40:46 -0700 | [diff] [blame] | 262 | |
| 263 | |
| 264 | if __name__ == "__main__": |
| 265 | sys.path.insert(0, '.') |
| 266 | main() |