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

# Source Code for Module Products.ZenModel.ZenPackManager

      1  ###########################################################################
      2  #
      3  # This program is part of Zenoss Core, an open source monitoring platform.
      4  # Copyright (C) 2008, 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__="""ZenPackManager
     15  ZenPackManager is a Zope Product that helps manage ZenPacks
     16  """
     17
     18  from Globals import InitializeClass
     19  from ZenModelRM import ZenModelRM
     20  from Products.ZenRelations.RelSchema import *
     21  from AccessControl import ClassSecurityInfo
     22  from ZenossSecurity import ZEN_MANAGE_DMD
     23  from Products.ZenUtils.Utils import binPath
     24  from Products.ZenWidgets import messaging
     25  import os
     26
     27 -def manage_addZenPackManager(context, newId='', REQUEST=None):
     28      """
     29      Create a ZenPackManager instance
     30      """
     31      if not newId:
     32          newId = 'ZenPackManager'
     33      zpm = ZenPackManager(newId)
     34      context._setObject(newId, zpm)
     35      zpm = context._getOb(newId)
     36      if REQUEST is not None:
     37          REQUEST.RESPONSE.redirect(context.absolute_url() + '/manage_main')
     38
     39
     40 -class ZenPackManager(ZenModelRM):
     41      """
     42      ZenPackManager is responsibe for managing ZenPacks
     43      """
     44
     45      portal_type = meta_type = 'ZenPackManager'
     46
     47      default_catalog = 'zenPackNameSearch'
     48
     49      _relations = ZenModelRM._relations + (
     50          ('packs', ToManyCont(ToOne, 'Products.ZenModel.ZenPack', 'manager')),
     51          )
     52
     53      factory_type_information = (
     54          {
     55              'immediate_view' : 'viewZenPacks',
     56              'actions'        :
     57              (
     58                  { 'id'            : 'settings'
     59                  , 'name'          : 'Settings'
     60                  , 'action'        : '../editSettings'
     61                  , 'permissions'   : ( "Manage DMD", )
     62                  },
     63                  { 'id'            : 'manage'
     64                  , 'name'          : 'Commands'
     65                  , 'action'        : '../dataRootManage'
     66                  , 'permissions'   : ('Manage DMD',)
     67                  },
     68                  { 'id'            : 'users'
     69                  , 'name'          : 'Users'
     70                  , 'action'        : '../ZenUsers/manageUserFolder'
     71                  , 'permissions'   : ( 'Manage DMD', )
     72                  },
     73                  { 'id'            : 'packs'
     74                  , 'name'          : 'ZenPacks'
     75                  , 'action'        : 'viewZenPacks'
     76                  , 'permissions'   : ( "Manage DMD", )
     77                  },
     78                  { 'id'            : 'jobs'
     79                  , 'name'          : 'Jobs'
     80                  , 'action'        : '../joblist'
     81                  , 'permissions'   : ( "Manage DMD", )
     82                  },
     83                  { 'id'            : 'menus'
     84                  , 'name'          : 'Menus'
     85                  , 'action'        : '../editMenus'
     86                  , 'permissions'   : ( "Manage DMD", )
     87                  },
     88                  { 'id'            : 'portlets'
     89                  , 'name'          : 'Portlets'
     90                  , 'action'        : '../editPortletPerms'
     91                  , 'permissions'   : ( "Manage DMD", )
     92                  },
     93                  { 'id'            : 'daemons'
     94                  , 'name'          : 'Daemons'
     95                  , 'action'        : '../About/zenossInfo'
     96                  , 'permissions'   : ( "Manage DMD", )
     97                  },
     98                  { 'id'            : 'versions'
     99                  , 'name'          : 'Versions'
    100                  , 'action'        : '../About/zenossVersions'
    101                  , 'permissions'   : ( "Manage DMD", )
    102                  },
    103                  { 'id'            : 'backups'
    104                  , 'name'          : 'Backups'
    105                  , 'action'        : '../backupInfo'
    106                  , 'permissions'   : ( "Manage DMD", )
    107                  },
    108              )
    109           },
    110          )
    111
    112      security = ClassSecurityInfo()
    113
    114
    115      security.declareProtected(ZEN_MANAGE_DMD, 'manage_addZenPack')
    116 -    def manage_addZenPack(self, packId, REQUEST=None):
    117          """
    118          Create a new zenpack on the filesystem with the given info.
    119          Install the pack.  If REQUEST then render the REQUEST otherwise
    120          return the new zenpack.
    121          """
    122          import Products.ZenUtils.ZenPackCmd as ZenPackCmd
    123
    124          if not getattr(self.dmd, 'ZenPackManager'):
    125              msg = 'Your Zenoss database appears to be out of date. Try ' \
    126                      'running zenmigrate to update.'
    127              if REQUEST:
    128                  messaging.IMessageSender(self).sendToBrowser(
    129                      'Error', msg, priority=messaging.WARNING)
    130                  return self.callZenScreen(REQUEST)
    131              from ZenPack import ZenPackNeedMigrateException
    132              raise ZenPackNeedMigrateException(msg)
    133
    134          # Make sure a zenpack can be created with given info
    135          canCreate, msgOrId = ZenPackCmd.CanCreateZenPack(self, packId)
    136          if canCreate:
    137              packId = msgOrId
    138          else:
    139              if REQUEST:
    140                  messaging.IMessageSender(self).sendToBrowser(
    141                      'Add ZenPack', msgOrId)
    142                  return self.callZenScreen(REQUEST, redirect=False)
    143              from ZenPack import ZenPackException
    144              raise ZenPackException(msgOrId)
    145
    146          # Create it
    147          zpDir = ZenPackCmd.CreateZenPack(packId)
    148
    149          # Install it
    150          zenPacks = ZenPackCmd.InstallEggAndZenPack(self.dmd, zpDir, link=True)
    151          zenPack = self.packs._getOb(packId, None)
    152          if REQUEST:
    153              if zenPack:
    154                  return REQUEST['RESPONSE'].redirect(zenPack.getPrimaryUrlPath())
    155              messaging.IMessageSender(self).sendToBrowser(
    156                  'Error', 'There was an error creating the ZenPack.',
    157                  priority=messaging.WARNING)
    158              return self.callZenScreen(REQUEST)
    159          return zenPack
    160
    161
    162      security.declareProtected(ZEN_MANAGE_DMD, 'manage_removeZenPacks')
    163 -    def manage_removeZenPacks(self, ids=(), REQUEST=None):
    164          """
    165          Uninstall the given zenpacks.  Uninstall the zenpack egg.  If not in
    166          development mode then also delete the egg from the filesystem.
    167          """
    168          import Products.ZenUtils.ZenPackCmd as ZenPackCmd
    169
    170          if not getattr(self.dmd, 'ZenPackManager'):
    171              msg = 'Your Zenoss database appears to be out of date. Try ' \
    172                      'running zenmigrate to update.'
    173              if REQUEST:
    174                  messaging.IMessageSender(self).sendToBrowser(
    175                      'Error', msg, priority=messaging.WARNING)
    176                  return self.callZenScreen(REQUEST)
    177              from ZenPack import ZenPackNeedMigrateException
    178              raise ZenPackNeedMigrateException(msg)
    179
    180          canRemove, dependents = ZenPackCmd.CanRemoveZenPacks(self.dmd, ids)
    181          if not canRemove:
    182              msg = 'The following ZenPacks depend on one or more of the ' + \
    183                  ' ZenPacks you are trying to remove: %s' % ','.join(dependents)
    184              if REQUEST:
    185                  messaging.IMessageSender(self).sendToBrowser(
    186                      'Error', msg, priority=messaging.WARNING)
    187                  return self.callZenScreen(REQUEST)
    188              from ZenPack import ZenPackDependentsException
    189              raise ZenPackDependentsException(msg)
    190          for zpId in ids:
    191              zp = self.packs._getOb(zpId, None)
    192              if zp:
    193                  if zp.isEggPack():
    194                      ZenPackCmd.RemoveZenPack(self.dmd, zpId, skipDepsCheck=True)
    195                  else:
    196                      os.system('%s --remove %s' % (
    197                                              binPath('zenpack'), zpId))
    198                      self._p_jar.sync()
    199          if REQUEST:
    200              return self.callZenScreen(REQUEST)
    201
    202
    203      security.declareProtected(ZEN_MANAGE_DMD, 'fetchZenPack')
    204 -    def fetchZenPack(self, packName, packVersion=''):
    205          """
    206          Retrieve the given zenpack from Zenoss.net and install.
    207          """
    208          import Products.ZenUtils.ZenPackCmd as ZenPackCmd
    209          zp = ZenPackCmd.FetchAndInstallZenPack(self.dmd, packName, packVersion)
    210          if REQUEST:
    211              return REQUEST['RESPONSE'].redirect(zp.getPrimaryUrlPath())
    212          return zp
    213
    214
    215
    216      security.declareProtected(ZEN_MANAGE_DMD, 'manage_installZenPack')
    217 -    def manage_installZenPack(self, zenpack=None, REQUEST=None):
    218          """
    219          Installs the given zenpack.  Zenpack is a file upload from the browser.
    220          """
    221          import tempfile
    222          import fcntl
    223          import popen2
    224          import signal
    225          import time
    226          import select
    227
    228          ZENPACK_INSTALL_TIMEOUT = 120
    229
    230          if not getattr(self.dmd, 'ZenPackManager'):
    231              msg = 'Your Zenoss database appears to be out of date. Try ' \
    232                      'running zenmigrate to update.'
    233              if REQUEST:
    234                  messaging.IMessageSender(self).sendToBrowser(
    235                      'Error', msg, priority=messaging.WARNING)
    236                  return self.callZenScreen(REQUEST)
    237              from ZenPack import ZenPackNeedMigrateException
    238              raise ZenPackNeedMigrateException(msg)
    239
    240          if REQUEST:
    241              REQUEST['cmd'] = ''
    242              header, footer = self.commandOutputTemplate().split('OUTPUT_TOKEN')
    243              REQUEST.RESPONSE.write(str(header))
    244              out = REQUEST.RESPONSE
    245          else:
    246              out = None
    247
    248          tFile = None
    249          child = None
    250          try:
    251              try:
    252                  # Write the zenpack to the filesystem
    253                  tDir = tempfile.gettempdir()
    254                  tFile = open(os.path.join(tDir, zenpack.filename), 'wb')
    255                  tFile.write(zenpack.read())
    256                  tFile.close()
    257
    258                  cmd = 'zenpack --install %s' % tFile.name
    259                  child = popen2.Popen4(cmd)
    260                  flags = fcntl.fcntl(child.fromchild, fcntl.F_GETFL)
    261                  fcntl.fcntl(child.fromchild, fcntl.F_SETFL, flags | os.O_NDELAY)
    262                  endtime = time.time() + ZENPACK_INSTALL_TIMEOUT
    263                  self.write(out, '%s' % cmd)
    264                  self.write(out, '')
    265                  pollPeriod = 1
    266                  firstPass = True
    267                  while time.time() < endtime and (firstPass or child.poll()==-1):
    268                      firstPass = False
    269                      r, w, e = select.select([child.fromchild],[],[], pollPeriod)
    270                      if r:
    271                          t = child.fromchild.read()
    272                          #We are sometimes getting to this point without any data
    273                          # from child.fromchild. I don't think that should happen
    274                          # but the conditional below seems to be necessary.
    275                          if t:
    276                              self.write(out, t)
    277                  if child.poll() == -1:
    278                      self.write(out,
    279                                 'Command timed out for %s' % cmd +
    280                                 ' (timeout is %s seconds)' %
    281                                 ZENPACK_INSTALL_TIMEOUT)
    282              except:
    283                  self.write(out, 'Error installing ZenPack.')
    284                  self.write(
    285                      out, 'type: %s  value: %s' % tuple(sys.exc_info()[:2]))
    286                  self.write(out, '')
    287          finally:
    288              if child and child.poll() == -1:
    289                  os.kill(child.pid, signal.SIGKILL)
    290
    291          self.write(out, '')
    292          self.write(out, 'Done installing ZenPack.')
    293          if REQUEST:
    294              REQUEST.RESPONSE.write(footer)
    295
    296
    297 -    def getZnetProjectOptions(self):
    298          """
    299          Return a list of 2-tuples of (option value, option name) for the
    300          user to select a Zenoss.net project from.
    301          """
    302          projects = self.getZnetProjectsList()
    303          return [(p, p.split('/')[-1]) for p in projects]
    304
    305
    306 -    def getZnetProjectsList(self):
    307          """
    308          Return a list of the zenoss.net projects.
    309          """
    310          import simplejson
    311          import Products.ZenUtils.DotNetCommunication as DotNetCommunication
    312          userSettings = self.dmd.ZenUsers.getUserSettings()
    313          session = DotNetCommunication.getDotNetSession(
    314                      userSettings.zenossNetUser,
    315                      userSettings.zenossNetPassword)
    316          projects = session.retrieve('projectList')
    317          projects = simplejson.loads(projects)
    318          return projects
    319
    320
    321 -    def getBrokenPackName(self, ob):
    322          ''' Extract the zenpack name from the broken module
    323          '''
    324          return ob.__class__.__module__
    325
    326
    327  InitializeClass(ZenPackManager)
    328