-
Notifications
You must be signed in to change notification settings - Fork 0
/
DaemonProxy.py
123 lines (105 loc) · 4.55 KB
/
DaemonProxy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# __BEGIN_LICENSE__
# Copyright (C) 2008-2010 United States Government as represented by
# the Administrator of the National Aeronautics and Space Administration.
# All Rights Reserved.
# __END_LICENSE__
import optparse, imp, sys, traceback, socket, os, platform, time
from geocamPycroCom.SharedScheduler import scheduler
from geocamPycroCom.Dispatcher import Dispatcher
from geocamPycroraptor import commandLineOptions
from geocamPycroraptor.Printable import Printable
from geocamPycroraptor import anyjson as json
class DaemonProxy:
"""Example usage: p = DaemonProxy(); p.start('bc')"""
def __init__(self, opts=None, dispatcher=None, lineHandler=None,
connectHandler=None, **kwargs):
if dispatcher == None:
dispatcher = Dispatcher(moduleName = 'client-%s-%d' % (platform.node(), os.getpid()))
if opts == None:
opts, args = commandLineOptions.getClientOptsArgs(['pyrterm'])
for k, v in kwargs.iteritems():
setattr(opts, k, v)
self._opts = opts
self._lineHandler = lineHandler
self._connectHandler = connectHandler
self._dispatcher = dispatcher
serverLoc = opts.daemons[0].strip()
self._conns = {}
self._currentConn = None
self._counter = 0
self._responseIdToWaitFor = None
self._opened = False
def handleLine(self, sock, line):
if self._responseIdToWaitFor != None:
msg = json.loads(line)
if msg[0] == 'response' and msg[1] == self._responseIdToWaitFor:
self._lastMatchingMessage = msg
if self._lineHandler:
self._lineHandler(sock, line)
def open(self):
if not self._opened:
if self._opts.notificationService:
self._dispatcher.connectToNotificationService(self._opts.notificationService,
serviceHandler=self.comHandleService)
self._dispatcher.findServices(self._opts.notificationService)
if self._opts.daemons:
self._connectDaemon(self._opts.daemons[0])
self._opened = True
def _connectDaemon(self, endpoint):
if not self._conns.has_key(endpoint):
newConn = (self._dispatcher.connect
(endpoint,
connectHandler = self.comHandleConnect,
lineHandler = self.handleLine))
self._conns[endpoint] = newConn
if len(self._conns) == 1:
self._currentConn = newConn
def comHandleService(self, finder, serviceName, serviceEvent):
if serviceName.startswith('pyraptord'):
self._connectDaemon(serviceEvent)
def comHandleConnect(self, sock):
# asyncore should set connected flag earlier -- avoid infinite loop
sock.connected = True
if self._connectHandler:
self._connectHandler(sock)
def send(self, cmdString):
if not (self._currentConn and self._currentConn.connected):
self.open()
def _check():
if self._currentConn.connected:
return True
else:
return None
self._dispatcher.waitForResponse(_check)
self._currentConn.write(cmdString+'\n')
def sendObject(self, cmdObject):
self.send(json.dumps(cmdObject))
def sendCommand(self, cmd):
self.sendObject(['command', self._counter] + cmd)
ret = self._counter
self._counter += 1
return ret
def sendStart(self, *processes):
return self.sendCommand(['start'] + list(processes))
def sendStop(self, *processes):
return self.sendCommand(['stop'] + list(processes))
def sendRestart(self, *processes):
return self.sendCommand(['restart'] + list(processes))
def sendGet(self, var):
return self.sendCommand(['get', var])
def sendSubStatus(self, *processes):
return self.sendCommand(['sub', 'status'] + list(processes))
def returnGetResponse(self, var):
return self.waitForResponse(self.sendGet(var))
def waitForResponse(self, responseId):
self._responseIdToWaitFor = responseId
self._lastMatchingMessage = None
response = self._dispatcher.waitForResponse(lambda: self._lastMatchingMessage)
self._responseIdToWaitFor = None
return response[2:]
def close(self):
if self._opened:
self._dispatcher.close()
self._conns = {}
self._currentConn = None
self._opened = False