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