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 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__="""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                  { 'id'            : 'eventConfig'
    109                  , 'name'          : 'Events'
    110                  , 'action'        : 'eventConfig'
    111                  , 'permissions'   : ( "Manage DMD", )
    112                  },
    113              )
    114           },
    115          )
    116
    117      security = ClassSecurityInfo()
    118
    119
    120      security.declareProtected(ZEN_MANAGE_DMD, 'manage_addZenPack')
    121 -    def manage_addZenPack(self, packId, REQUEST=None):
    122          """
    123          Create a new zenpack on the filesystem with the given info.
    124          Install the pack.  If REQUEST then render the REQUEST otherwise
    125          return the new zenpack.
    126          """
    127          import Products.ZenUtils.ZenPackCmd as ZenPackCmd
    128
    129          if not getattr(self.dmd, 'ZenPackManager'):
    130              msg = 'Your Zenoss database appears to be out of date. Try ' \
    131                      'running zenmigrate to update.'
    132              if REQUEST:
    133                  messaging.IMessageSender(self).sendToBrowser(
    134                      'Error', msg, priority=messaging.WARNING)
    135                  return self.callZenScreen(REQUEST)
    136              from ZenPack import ZenPackNeedMigrateException
    137              raise ZenPackNeedMigrateException(msg)
    138
    139          # Make sure a zenpack can be created with given info
    140          canCreate, msgOrId = ZenPackCmd.CanCreateZenPack(self, packId)
    141          if canCreate:
    142              packId = msgOrId
    143          else:
    144              if REQUEST:
    145                  messaging.IMessageSender(self).sendToBrowser(
    146                      'Add ZenPack', msgOrId)
    147                  return self.callZenScreen(REQUEST, redirect=False)
    148              from ZenPack import ZenPackException
    149              raise ZenPackException(msgOrId)
    150
    151          # Create it
    152          zpDir = ZenPackCmd.CreateZenPack(packId)
    153
    154          # Install it
    155          zenPacks = ZenPackCmd.InstallEggAndZenPack(self.dmd, zpDir, link=True,
    156                                                     forceRunExternal=True)
    157          zenPack = self.packs._getOb(packId, None)
    158          if REQUEST:
    159              if zenPack:
    160                  return REQUEST['RESPONSE'].redirect(zenPack.getPrimaryUrlPath())
    161              messaging.IMessageSender(self).sendToBrowser(
    162                  'Error', 'There was an error creating the ZenPack.',
    163                  priority=messaging.WARNING)
    164              return self.callZenScreen(REQUEST)
    165          return zenPack
    166
    167
    168      security.declareProtected(ZEN_MANAGE_DMD, 'manage_removeZenPacks')
    169 -    def manage_removeZenPacks(self, ids=(), REQUEST=None):
    170          """
    171          Uninstall the given zenpacks.  Uninstall the zenpack egg.  If not in
    172          development mode then also delete the egg from the filesystem.
    173          """
    174          import Products.ZenUtils.ZenPackCmd as ZenPackCmd
    175
    176          if not getattr(self.dmd, 'ZenPackManager'):
    177              msg = 'Your Zenoss database appears to be out of date. Try ' \
    178                      'running zenmigrate to update.'
    179              if REQUEST:
    180                  messaging.IMessageSender(self).sendToBrowser(
    181                      'Error', msg, priority=messaging.WARNING)
    182                  return self.callZenScreen(REQUEST)
    183              from ZenPack import ZenPackNeedMigrateException
    184              raise ZenPackNeedMigrateException(msg)
    185
    186          canRemove, dependents = ZenPackCmd.CanRemoveZenPacks(self.dmd, ids)
    187          if not canRemove:
    188              msg = 'The following ZenPacks depend on one or more of the ' + \
    189                  ' ZenPacks you are trying to remove: %s' % ','.join(dependents)
    190              if REQUEST:
    191                  messaging.IMessageSender(self).sendToBrowser(
    192                      'Error', msg, priority=messaging.WARNING)
    193                  return self.callZenScreen(REQUEST)
    194              from ZenPack import ZenPackDependentsException
    195              raise ZenPackDependentsException(msg)
    196          for zpId in ids:
    197              zp = self.packs._getOb(zpId, None)
    198              if zp:
    199                  if zp.isEggPack():
    200                      ZenPackCmd.RemoveZenPack(self.dmd, zpId, skipDepsCheck=True)
    201                  else:
    202                      os.system('%s --remove %s' % (
    203                                              binPath('zenpack'), zpId))
    204                      self._p_jar.sync()
    205          if REQUEST:
    206              return self.callZenScreen(REQUEST)
    207
    208
    209      security.declareProtected(ZEN_MANAGE_DMD, 'fetchZenPack')
    210 -    def fetchZenPack(self, packName, packVersion=''):
    211          """
    212          Retrieve the given zenpack from Zenoss.net and install.
    213          """
    214          import Products.ZenUtils.ZenPackCmd as ZenPackCmd
    215          zp = ZenPackCmd.FetchAndInstallZenPack(self.dmd, packName, packVersion)
    216          if REQUEST:
    217              return REQUEST['RESPONSE'].redirect(zp.getPrimaryUrlPath())
    218          return zp
    219
    220
    221
    222      security.declareProtected(ZEN_MANAGE_DMD, 'manage_installZenPack')
    223 -    def manage_installZenPack(self, zenpack=None, REQUEST=None):
    224          """
    225          Installs the given zenpack.  Zenpack is a file upload from the browser.
    226          """
    227          import os
    228          import re
    229          from subprocess import Popen, PIPE, STDOUT
    230          import time
    231
    232          from Products.ZenUtils.Utils import get_temp_dir
    233
    234          ZENPACK_INSTALL_TIMEOUT = 10 * 60 # 10 minutes
    235
    236          if not getattr(self.dmd, 'ZenPackManager'):
    237              msg = 'Your Zenoss database appears to be out of date. Try ' \
    238                      'running zenmigrate to update.'
    239              if REQUEST:
    240                  messaging.IMessageSender(self).sendToBrowser(
    241                      'Error', msg, priority=messaging.WARNING)
    242                  return self.callZenScreen(REQUEST)
    243              from ZenPack import ZenPackNeedMigrateException
    244              raise ZenPackNeedMigrateException(msg)
    245
    246          msg = ''
    247          with get_temp_dir() as tempDir:
    248              # zenpack.filename gives us filename of the zenpack with the
    249              # path as it exists on the client. We need just the filename.
    250              base_filename = re.split(r"\\|/", zenpack.filename)[-1]
    251              # Macs (and other broswers/OSs) always append a .zip to files they
    252              # believe to be zip files. Remedy that:
    253              if base_filename.endswith('.egg.zip'):
    254                  base_filename = base_filename[:-7] + 'egg'
    255
    256              # Write the zenpack to the filesystem
    257              tFile = open(os.path.join(tempDir, base_filename), 'wb')
    258              tFile.write(zenpack.read())
    259              tFile.close()
    260
    261              p = None # zenpack install process
    262              try:
    263                  # Run zenpack install
    264                  cmd = 'zenpack --install %s' % tFile.name
    265                  p = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT)
    266                  endWait = time.time() + ZENPACK_INSTALL_TIMEOUT
    267                  # Wait for install to complete or fail
    268                  while p.poll() is None and time.time() < endWait:
    269                      time.sleep(1)
    270                  if p.poll() is not None:
    271                      msg = p.stdout.read()
    272              finally:
    273                  if p and p.poll() is None:
    274                      p.kill()
    275                      msg += 'Zenpack install killed due to timeout'
    276
    277          if REQUEST:
    278              # format command result for HTML
    279              msg = '<br>'.join(line.strip() for line in msg.split('\n') if line.strip())
    280              messaging.IMessageSender(self).sendToBrowser('Zenpack', msg,
    281                  priority = messaging.CRITICAL if 'ERROR' in msg
    282                                                else messaging.INFO)
    283              return self.callZenScreen(REQUEST)
    284
    285
    286 -    def getZnetProjectOptions(self):
    287          """
    288          Return a list of 2-tuples of (option value, option name) for the
    289          user to select a Zenoss.net project from.
    290          """
    291          projects = self.getZnetProjectsList()
    292          return [(p, p.split('/')[-1]) for p in projects]
    293
    294
    295 -    def getZnetProjectsList(self):
    296          """
    297          Return a list of the zenoss.net projects.
    298          """
    299          import json
    300          import Products.ZenUtils.DotNetCommunication as DotNetCommunication
    301          userSettings = self.dmd.ZenUsers.getUserSettings()
    302          session = DotNetCommunication.getDotNetSession(
    303                      userSettings.zenossNetUser,
    304                      userSettings.zenossNetPassword)
    305          projects = session.retrieve('projectList')
    306          projects = json.loads(projects)
    307          return projects
    308
    309
    310 -    def getBrokenPackName(self, ob):
    311          ''' Extract the zenpack name from the broken module
    312          '''
    313          return ob.id if ob.id else ob.__class__.__module__
    314
    315
    316  InitializeClass(ZenPackManager)
    317