Package Products :: Package ZenModel :: Module ZenPackLoader |
[hide private]
[frames] | no frames]

# Source Code for Module Products.ZenModel.ZenPackLoader

      1  ###########################################################################
      2  #
      3  # This program is part of Zenoss Core, an open source monitoring platform.
      4  # Copyright (C) 2007, 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 as published by
      8  # the Free Software Foundation.
      9  #
     10  # For complete information please visit: http://www.zenoss.com/oss/
     11  #
     12  ###########################################################################
     13
     14  __doc__='Base Classes for loading gunk in a ZenPack'
     15
     16  import Globals
     17  from Products.ZenReports.ReportLoader import ReportLoader
     18  from Products.ZenUtils.Utils import zenPath, binPath
     19
     20  import os
     21  import ConfigParser
     22  import subprocess
     23  import logging
     24  log = logging.getLogger('zen.ZPLoader')
     25
     26  CONFIG_FILE = 'about.txt'
     27  CONFIG_SECTION_ABOUT = 'about'
     28
     29 -def findFiles(pack, directory, filter=None):
     30      result = []
     31      if isinstance(pack, basestring):
     32          path = os.path.join(pack, directory)
     33      else:
     34          path = pack.path(directory)
     35      for p, ds, fs in os.walk(path):
     36          if not os.path.split(p)[-1].startswith('.'):
     37              for f in fs:
     38                  if filter is None or filter(f):
     39                      result.append(os.path.join(p, f))
     40      return result
     41
     42 -def findDirectories(pack, directory):
     43      result = []
     44      for p, ds, fs in os.walk(pack.path(directory)):
     45          if not os.path.split(p)[-1].startswith('.'):
     46              for d in ds:
     47                  result.append(os.path.join(p, d))
     48      return result
     49
     50 -def branchAfter(filename, directory, prefix = ""):
     51      "return the branch after the given directory name"
     52      path = filename.split('/')
     53      return prefix + '/'.join(path[path.index(directory)+1:])
     54
     55
     56 -class ZenPackLoader:
     57
     58      name = "Set This Name"
     59
     60 -    def load(self, pack, app):
     61          """Load things from the ZenPack and put it
     62          into the app"""
     63
     64 -    def unload(self, pack, app, leaveObjects=False):
     65          """Remove things from Zenoss defined in the ZenPack"""
     66
     67 -    def list(self, pack, app):
     68          "List the items that would be loaded from the given (unpacked) ZenPack"
     69
     70 -    def upgrade(self, pack, app):
     71          "Run an upgrade on an existing pack"
     72
     73  from xml.sax import make_parser
     74
     75 -class ZPLObject(ZenPackLoader):
     76
     77      name = "Objects"
     78
     79 -    def load(self, pack, app):
     80          from Products.ZenRelations.ImportRM import ImportRM
     81          class AddToPack(ImportRM):
     82              def endElement(self, name):
     83                  if name == 'object':
     84                      obj = self.objstack[-1]
     85                      log.debug('Now adding %s', obj.getPrimaryUrlPath())
     86                      try:
     87                          obj.buildRelations()
     88                          obj.removeRelation('pack')
     89                          obj.addRelation('pack', pack)
     90                      except Exception, ex:
     91                          log.exception("Error adding pack to %s",
     92                                        obj.getPrimaryUrlPath())
     93
     94                  ImportRM.endElement(self, name)
     95          importer = AddToPack(noopts=True, app=app)
     96          importer.options.noindex = True
     97          for f in self.objectFiles(pack):
     98              log.info("Loading %s", f)
     99              importer.loadObjectFromXML(xmlfile=f)
    100
    101
    102 -    def parse(self, filename, handler):
    103          parser = make_parser()
    104          parser.setContentHandler(handler)
    105          parser.parse(open(filename))
    106
    107
    108 -    def unload(self, pack, app, leaveObjects=False):
    109          if leaveObjects:
    110              return
    111          from Products.ZenRelations.Exceptions import ObjectNotFound
    112          dmd = app.zport.dmd
    113          objs = pack.packables()
    114          objs.sort(lambda x, y: cmp(x.getPrimaryPath(), y.getPrimaryPath()))
    115          objs.reverse()
    116          for obj in objs:
    117              path = obj.getPrimaryPath()
    118              path, id = path[:-1], path[-1]
    119              obj = dmd.getObjByPath(path)
    120              if len(path) > 3:           # leave /Services, /Devices, etc.
    121                  try:
    122                      try:
    123                          obj._delObject(id)
    124                      except ObjectNotFound:
    125                          obj._delOb(id)
    126                  except (AttributeError, KeyError), ex:
    127                      log.warning("Unable to remove %s on %s", id,
    128                                  '/'.join(path))
    129
    130 -    def list(self, pack, unused):
    131          return [obj.getPrimaryUrlPath() for obj in pack.packables()]
    132
    133
    134 -    def objectFiles(self, pack):
    135          def isXml(f): return f.endswith('.xml')
    136          return findFiles(pack, 'objects', isXml)
    137
    138
    139 -class ZPLReport(ZPLObject):
    140
    141      name = "Reports"
    142
    143 -    def load(self, pack, app):
    144          class HookReportLoader(ReportLoader):
    145              def loadFile(self, root, id, fullname):
    146                  rpt = ReportLoader.loadFile(self, root, id, fullname)
    147                  rpt.addRelation('pack', pack)
    148                  return rpt
    149          rl = HookReportLoader(noopts=True, app=app)
    150          rl.options.force = True
    151          rl.loadDirectory(pack.path('reports'))
    152
    153 -    def upgrade(self, pack, app):
    154          self.unload(pack, app)
    155          self.load(pack, app)
    156
    157 -    def list(self, pack, unused):
    158          return [branchAfter(r, 'reports') for r in findFiles(pack, 'reports')]
    159
    160
    161 -class ZPLDaemons(ZenPackLoader):
    162
    163      name = "Daemons"
    164
    165      extensionsToIgnore = ('.svn-base', '.pyc' '~')
    166 -    def filter(self, f):
    167          for ext in self.extensionsToIgnore:
    168              if f.endswith(ext):
    169                  return False
    170          return True
    171
    172
    173 -    def binPath(self, daemon):
    174          return zenPath('bin', os.path.basename(daemon))
    175
    176
    177 -    def _genConfFile(self, pack):
    178          """
    179          Attempt to generate a conf file for any daemons.
    180          """
    181          # We just go on with business, not waiting for this to finish
    182          # nor caring if it throws an exception.  The conf file is nice
    183          # to provide, but not important.
    184          try:
    185              subprocess.Popen(binPath('create_sample_config.sh'),
    186                              stdout=subprocess.PIPE,
    187                              stderr=subprocess.PIPE,
    188                              cwd=pack.path())
    189          except OSError:
    190              pass
    191
    192
    193 -    def load(self, pack, unused):
    194          for fs in findFiles(pack, 'daemons', filter=self.filter):
    195              os.chmod(fs, 0755)
    196              path = self.binPath(fs)
    197              if os.path.lexists(path):
    198                  os.remove(path)
    199              os.symlink(fs, path)
    200          self._genConfFile(pack)
    201
    202
    203 -    def upgrade(self, pack, app):
    204          self.unload(pack, app)
    205          self.load(pack, app)
    206
    207
    208 -    def unload(self, pack, unused, leaveObjects=False):
    209          for fs in findFiles(pack, 'daemons', filter=self.filter):
    210              try:
    211                  os.remove(self.binPath(fs))
    212              except OSError:
    213                  pass
    214
    215 -    def list(self, pack, unused):
    216          return [branchAfter(d, 'daemons')
    217                  for d in findFiles(pack, 'daemons', filter=self.filter)]
    218
    219
    220 -class ZPLBin(ZenPackLoader):
    221
    222      name = "Bin"
    223
    224      extensionsToIgnore = ('.svn-base', '.pyc' '~')
    225 -    def filter(self, f):
    226          for ext in self.extensionsToIgnore:
    227              if f.endswith(ext):
    228                  return False
    229          return True
    230
    231 -    def load(self, pack, unused):
    232          for fs in findFiles(pack, 'bin', filter=self.filter):
    233              os.chmod(fs, 0755)
    234
    235 -    def upgrade(self, pack, app):
    236          self.unload(pack, app)
    237          self.load(pack, app)
    238
    239 -    def list(self, pack, unused):
    240          return [branchAfter(d, 'bin')
    241                  for d in findFiles(pack, 'bin', filter=self.filter)]
    242
    243
    244 -class ZPLLibExec(ZenPackLoader):
    245
    246      name = "LibExec"
    247
    248      extensionsToIgnore = ('.svn-base', '.pyc' '~')
    249 -    def filter(self, f):
    250          for ext in self.extensionsToIgnore:
    251              if f.endswith(ext):
    252                  return False
    253          return True
    254
    255 -    def load(self, pack, unused):
    256          for fs in findFiles(pack, 'libexec', filter=self.filter):
    257              os.chmod(fs, 0755)
    258
    259 -    def upgrade(self, pack, app):
    260          self.unload(pack, app)
    261          self.load(pack, app)
    262
    263 -    def list(self, pack, unused):
    264          return [branchAfter(d, 'libexec')
    265                  for d in findFiles(pack, 'libexec', filter=self.filter)]
    266
    267
    268 -class ZPLModelers(ZenPackLoader):
    269
    270      name = "Modeler Plugins"
    271
    272
    273 -    def list(self, pack, unused):
    274          return [branchAfter(d, 'plugins')
    275                  for d in findFiles(pack, 'modeler/plugins')]
    276
    277
    278 -class ZPLSkins(ZenPackLoader):
    279
    280      name = "Skins"
    281
    282
    283 -    def load(self, pack, app):
    284          from Products.ZenUtils.Skins import registerSkin
    285          skinsDir = pack.path('')
    286          if os.path.isdir(skinsDir):
    287              registerSkin(app.zport.dmd, skinsDir)
    288
    289
    290 -    def upgrade(self, pack, app):
    291          self.unload(pack, app)
    292          return self.load(pack, app)
    293
    294
    295 -    def unload(self, pack, app, leaveObjects=False):
    296          from Products.ZenUtils.Skins import unregisterSkin
    297          skinsDir = pack.path('')
    298          if os.path.isdir(skinsDir):
    299              unregisterSkin(app.zport.dmd, skinsDir)
    300
    301
    302 -    def list(self, pack, unused):
    303          return [branchAfter(d, 'skins') for d in findDirectories(pack, 'skins')]
    304
    305
    306 -class ZPLDataSources(ZenPackLoader):
    307
    308      name = "DataSources"
    309
    310
    311 -    def list(self, pack, unused):
    312          return [branchAfter(d, 'datasources')
    313                  for d in findFiles(pack, 'datasources',
    314                  lambda f: not f.endswith('.pyc') and f != '__init__.py')]
    315
    316
    317
    318 -class ZPLLibraries(ZenPackLoader):
    319
    320      name = "Libraries"
    321
    322
    323 -    def list(self, pack, unused):
    324          d = pack.path('lib')
    325          if os.path.isdir(d):
    326              return [l for l in os.listdir(d)]
    327          return []
    328
    329 -class ZPLAbout(ZenPackLoader):
    330
    331      name = "About"
    332
    333 -    def getAttributeValues(self, pack):
    334          about = pack.path(CONFIG_FILE)
    335          result = []
    336          if os.path.exists(about):
    337              parser = ConfigParser.SafeConfigParser()
    338              parser.read(about)
    339              result = []
    340              for key, value in parser.items(CONFIG_SECTION_ABOUT):
    341                  try:
    342                      value = eval(value)
    343                  except:
    344                      # Blanket exception catchers like this are evil.
    345                      pass
    346                  result.append((key, value))
    347          return result
    348
    349
    350 -    def load(self, pack, unused):
    351          for name, value in self.getAttributeValues(pack):
    352              setattr(pack, name, value)
    353
    354
    355 -    def upgrade(self, pack, app):
    356          self.load(pack, app)
    357
    358
    359 -    def list(self, pack, unused):
    360          return [('%s %s' % av) for av in self.getAttributeValues(pack)]
    361