1
2
3
4
5
6
7
8
9
10
11
12
13
14 __doc__ = """RenderConfig
15 zenhub service to start looking for requests to render performance graphs
16 """
17
18 import logging
19 log = logging.getLogger('zen.HubService.RenderConfig')
20
21 import Globals
22 from Products.ZenCollector.services.config import NullConfigService
23 from Products.ZenRRD.zenrender import RenderServer
24
25 from twisted.web import resource, server
26 from twisted.internet import reactor
27 from twisted.internet.error import CannotListenError
28 import xmlrpclib, mimetypes
29
30
31 htmlResource = None
32
33
34 -class Render(resource.Resource):
35
36 isLeaf = True
37
39 resource.Resource.__init__(self)
40 self.renderers = {}
41
43 "Deal with http requests"
44 args = request.args.copy()
45 for k, v in args.items():
46 if len(v) == 1:
47 args[k] = v[0]
48
49 command = request.postpath[-1]
50 if command in ('favicon.ico',):
51 log.debug("Received a bad request: %s", command)
52 return ''
53 listener = request.postpath[-2]
54 args.setdefault('ftype', 'PNG')
55 ftype = args['ftype']
56 del args['ftype']
57 mimetype = mimetypes.guess_type('x.%s' % ftype)[0]
58 if mimetype is None:
59 mimetype = 'image/%s' % ftype.lower()
60 request.setHeader('Content-type', mimetype)
61 def write(result):
62 if result:
63 request.write(result)
64 request.finish()
65 def error(reason):
66 log.error("Unable to fetch graph: %s", reason)
67 request.finish()
68 from Products.ZenHub.zenhub import ZENHUB_ZENRENDER
69 renderer = self.renderers.get(listener, False)
70 if renderer and listener == ZENHUB_ZENRENDER:
71 try:
72 rs = RenderServer(listener)
73 renderFn = getattr(rs,command)
74 result = renderFn(**args)
75 reactor.callLater(0,write, result)
76 except Exception as e:
77 log.exception("Exception getting graph")
78 reactor.callLater(0,error, e.msg)
79 else:
80 if not renderer or not renderer.listeners:
81 raise Exception("Renderer %s unavailable" % listener)
82 d = renderer.listeners[0].callRemote(command, **args)
83 d.addCallbacks(write, error)
84 return server.NOT_DONE_YET
85
86 - def render_POST(self, request):
87 "Deal with XML-RPC requests"
88 content = request.content.read()
89 for instance, renderer in self.renderers.items():
90 if instance != request.postpath[-1]: continue
91 for listener in renderer.listeners:
92 try:
93 args, command = xmlrpclib.loads(content)
94 request.setHeader('Content-type', 'text/xml')
95 d = listener.callRemote(str(command), *args)
96 def write(result):
97 try:
98 response = xmlrpclib.dumps((result,),
99 methodresponse=True,
100 allow_none=True)
101 request.write(response)
102 except Exception, ex:
103 log.error("Unable to %s: %s", command, ex)
104 request.finish()
105 def error(reason):
106 log.error("Unable to %s: %s", command, reason)
107 request.finish()
108 d.addCallbacks(write, error)
109 return server.NOT_DONE_YET
110 except Exception, ex:
111 log.exception(ex)
112 log.warning("Skipping renderer %s" % instance)
113 raise Exception("No renderer registered")
114
116 "Handle all paths"
117 return self, ()
118
120 self.renderers[renderer.instance] = renderer
121
122
143