Package Products :: Package ZenHub :: Package services :: Module RenderConfig |
[hide private]
[frames] | no frames]

# Source Code for Module Products.ZenHub.services.RenderConfig

      1  ###########################################################################
      2  #
      3  # This program is part of Zenoss Core, an open source monitoring platform.
      4  # Copyright (C) 2009, 2011 Zenoss Inc.
      5  #
      6  # This program is free software; you can redistribute it and/or modify it
      7  # under the terms of the GNU General Public License version 2 or (at your
      8  # option) any later version as published by the Free Software Foundation.
      9  #
     10  # For complete information please visit: http://www.zenoss.com/oss/
     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  # Global variable
     31  htmlResource = None
     32
     33
     34 -class Render(resource.Resource):
     35
     36      isLeaf = True
     37
     38 -    def __init__(self):
     39          resource.Resource.__init__(self)
     40          self.renderers = {}
     41
     42 -    def render_GET(self, request):
     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
    115 -    def getChild(self, unused, ignored):
    116          "Handle all paths"
    117          return self, ()
    118
    119 -    def addRenderer(self, renderer):
    120          self.renderers[renderer.instance] = renderer
    121
    122
    123 -class RenderConfig(NullConfigService):
    124 -    def __init__(self, dmd, instance):
    125          from Products.ZenHub.zenhub import ZENHUB_ZENRENDER
    126          if instance == ZENHUB_ZENRENDER:
    127              self.dmd = dmd
    128              self.instance = instance
    129          else:
    130              NullConfigService.__init__(self, dmd, instance)
    131
    132          global htmlResource
    133          try:
    134              if not htmlResource:
    135                  htmlResource = Render()
    136                  log.info("Starting graph retrieval listener on port 8090")
    137                  reactor.listenTCP(8090, server.Site(htmlResource))
    138              htmlResource.addRenderer(self)
    139          except CannotListenError, e:
    140              # Probably in a hub worker; no big deal
    141              log.debug("Not starting render listener because the port is "
    142                        "already in use.")
    143