comparison py/tempserver.py @ 532:9b1d71310c83

better arg parser. seems close to ready
author Matt Johnston <matt@ucc.asn.au>
date Sat, 11 Apr 2015 23:32:59 +0800
parents fd0fd9f947a1
children fd29ae905d1b
comparison
equal deleted inserted replaced
531:fd0fd9f947a1 532:9b1d71310c83
4 import os 4 import os
5 import logging 5 import logging
6 import time 6 import time
7 import signal 7 import signal
8 import asyncio 8 import asyncio
9 import argparse
9 10
10 import lockfile.pidlockfile 11 import lockfile.pidlockfile
11 import daemon 12 import daemon
12 13
13 import utils 14 import utils
18 import params 19 import params
19 import uploader 20 import uploader
20 21
21 22
22 class Tempserver(object): 23 class Tempserver(object):
23 def __init__(self): 24 def __init__(self, test_mode):
24 self.readings = [] 25 self.readings = []
25 self.current = (None, None) 26 self.current = (None, None)
26 self.fridge = None 27 self.fridge = None
27 self._wakeup = asyncio.Condition() 28 self._wakeup = asyncio.Event()
29 self._test_mode = test_mode
28 30
29 def __enter__(self): 31 def __enter__(self):
30 self.params = params.Params() 32 self.params = params.Params()
31 self.fridge = fridge.Fridge(self) 33 self.fridge = fridge.Fridge(self)
32 self.uploader = uploader.Uploader(self) 34 self.uploader = uploader.Uploader(self)
51 self.sensors.run(), 53 self.sensors.run(),
52 self.uploader.run(), 54 self.uploader.run(),
53 ) 55 )
54 56
55 loop = asyncio.get_event_loop() 57 loop = asyncio.get_event_loop()
56 result_tasks = loop.run_until_complete(asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION)) 58 try:
57 # use the results so that exceptions get thrown 59 result_tasks = loop.run_until_complete(asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION))
58 [t.result() for x in result_tasks for t in x] 60 # use the results so that exceptions get thrown
61 [t.result() for x in result_tasks for t in x]
62 except KeyboardInterrupt:
63 print('ctrl-c')
64 pass
65 finally:
66 loop.close()
59 67
60 def now(self): 68 def now(self):
61 return utils.monotonic_time() 69 return utils.monotonic_time()
62 70
63 def set_sensors(self, sensors): 71 def set_sensors(self, sensors):
96 def sleep(self, timeout): 104 def sleep(self, timeout):
97 """ sleeps for timeout seconds, though wakes if the server's config is updated """ 105 """ sleeps for timeout seconds, though wakes if the server's config is updated """
98 # XXX fixme - we should wake on _wakeup but asyncio Condition with wait_for is a bit broken? 106 # XXX fixme - we should wake on _wakeup but asyncio Condition with wait_for is a bit broken?
99 # https://groups.google.com/forum/#!topic/python-tulip/eSm7rZAe9LM 107 # https://groups.google.com/forum/#!topic/python-tulip/eSm7rZAe9LM
100 # For now we just sleep, ignore the _wakeup 108 # For now we just sleep, ignore the _wakeup
101 yield from asyncio.sleep(timeout) 109 try:
110 yield from asyncio.wait_for(self._wakeup.wait(), timeout=timeout)
111 except asyncio.TimeoutError:
112 pass
102 113
103 @asyncio.coroutine
104 def _reload_signal(self): 114 def _reload_signal(self):
105 try: 115 try:
106 self.params.load() 116 self.params.load()
107 L("Reloaded.") 117 L("Reloaded.")
108 yield from self._wakeup.acquire() 118 self._wakeup.set()
109 self._wakeup.notify_all() 119 self._wakeup.clear()
110 self._wakeup.release()
111 except Error as e: 120 except Error as e:
112 W("Problem reloading: %s" % str(e)) 121 W("Problem reloading: %s" % str(e))
113 122
114 def setup_logging(): 123 def test_mode(self):
124 return self._test_mode
125
126 def setup_logging(debug = False):
127 level = logging.INFO
128 if debug:
129 level = logging.DEBUG
115 logging.basicConfig(format='%(asctime)s %(message)s', 130 logging.basicConfig(format='%(asctime)s %(message)s',
116 datefmt='%m/%d/%Y %I:%M:%S %p', 131 datefmt='%m/%d/%Y %I:%M:%S %p',
117 level=logging.DEBUG) 132 level=level)
118 logging.getLogger("asyncio").setLevel(logging.DEBUG) 133 #logging.getLogger("asyncio").setLevel(logging.DEBUG)
119 134
120 def start(): 135 def start(test_mode):
121 with Tempserver() as server: 136 with Tempserver(test_mode) as server:
122 server.run() 137 server.run()
123 138
124 def main(): 139 def main():
125 setup_logging() 140 parser = argparse.ArgumentParser()
141 parser.add_argument('--hup', action='store_true')
142 parser.add_argument('--new', action='store_true')
143 parser.add_argument('--daemon', action='store_true')
144 parser.add_argument('-d', '--debug', action='store_true')
145 parser.add_argument('-t', '--test', action='store_true')
146 args = parser.parse_args()
147
148 setup_logging(args.debug)
126 149
127 heredir = os.path.abspath(os.path.dirname(__file__)) 150 heredir = os.path.abspath(os.path.dirname(__file__))
128 pidpath = os.path.join(heredir, 'tempserver.pid') 151 pidpath = os.path.join(heredir, 'tempserver.pid')
129 pidf = lockfile.pidlockfile.PIDLockFile(pidpath, threaded=False) 152 pidf = lockfile.pidlockfile.PIDLockFile(pidpath, threaded=False)
130 do_hup = '--hup' in sys.argv 153
154
131 try: 155 try:
132 pidf.acquire(1) 156 pidf.acquire(1)
133 pidf.release() 157 pidf.release()
134 except (lockfile.AlreadyLocked, lockfile.LockTimeout) as e: 158 except (lockfile.AlreadyLocked, lockfile.LockTimeout) as e:
135 pid = pidf.read_pid() 159 pid = pidf.read_pid()
136 if do_hup: 160 if args.hup:
137 try: 161 try:
138 os.kill(pid, signal.SIGHUP) 162 os.kill(pid, signal.SIGHUP)
139 print("Sent SIGHUP to process %d" % pid, file=sys.stderr) 163 print("Sent SIGHUP to process %d" % pid, file=sys.stderr)
140 sys.exit(0) 164 sys.exit(0)
141 except OSError: 165 except OSError:
144 168
145 print("Locked by PID %d" % pid, file=sys.stderr) 169 print("Locked by PID %d" % pid, file=sys.stderr)
146 170
147 stale = False 171 stale = False
148 if pid > 0: 172 if pid > 0:
149 if '--new' in sys.argv: 173 if args.new:
150 try: 174 try:
151 os.kill(pid, 0) 175 os.kill(pid, 0)
152 except OSError: 176 except OSError:
153 stale = True 177 stale = True
154 178
169 if stale: 193 if stale:
170 # isn't still running, steal the lock 194 # isn't still running, steal the lock
171 print("Unlinking stale lockfile %s for pid %d" % (pidpath, pid), file=sys.stderr) 195 print("Unlinking stale lockfile %s for pid %d" % (pidpath, pid), file=sys.stderr)
172 pidf.break_lock() 196 pidf.break_lock()
173 197
174 if do_hup: 198 if args.hup:
175 print("Doesn't seem to be running", file=sys.stderr) 199 print("Doesn't seem to be running", file=sys.stderr)
176 sys.exit(1) 200 sys.exit(1)
177 201
178 if '--daemon' in sys.argv: 202 if args.daemon:
179 logpath = os.path.join(os.path.dirname(__file__), 'tempserver.log') 203 logpath = os.path.join(os.path.dirname(__file__), 'tempserver.log')
180 logf = open(logpath, 'a+') 204 logf = open(logpath, 'a+')
181 with daemon.DaemonContext(pidfile=pidf, stdout=logf, stderr = logf): 205 with daemon.DaemonContext(pidfile=pidf, stdout=logf, stderr = logf):
182 start() 206 start(args.test)
183 else: 207 else:
184 with pidf: 208 with pidf:
185 start() 209 start(args.test)
186 210
187 if __name__ == '__main__': 211 if __name__ == '__main__':
188 main() 212 main()