Package ZenModel :: Module ZenPack
[hide private]
[frames] | no frames]

Source Code for Module ZenModel.ZenPack

  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  import zope.interface 
 14   
 15  from Globals import InitializeClass 
 16  from Products.ZenModel.ZenModelRM import ZenModelRM 
 17  from Products.ZenModel import interfaces 
 18  from Products.ZenRelations.RelSchema import * 
 19  from Products.ZenUtils.Utils import importClass, zenPath 
 20  from Products.ZenModel.migrate import Migrate 
 21  from Products.ZenUtils.Version import getVersionTupleFromString 
 22  from Products.ZenModel.migrate.Migrate import Version 
 23  from Products.ZenModel.ZenPackLoader import * 
 24   
 25  import transaction 
 26   
 27  import os 
 28   
 29  __doc__="ZenPacks base definitions" 
 30   
31 -def eliminateDuplicates(objs):
32 def compare(x, y): 33 return cmp(x.getPrimaryPath(), y.getPrimaryPath())
34 objs.sort(compare) 35 result = [] 36 for obj in objs: 37 for alreadyInList in result: 38 path = alreadyInList.getPrimaryPath() 39 if obj.getPrimaryPath()[:len(path)] == path: 40 break 41 else: 42 result.append(obj) 43 return result 44 45
46 -class ZenPackMigration:
47 version = Version(0, 0, 0) 48
49 - def migrate(self, pack): pass
50
51 - def recover(self, pack): pass
52 53
54 -class ZenPack(ZenModelRM):
55 '''The root of all ZenPacks: has no implementation, 56 but sits here to be the target of the Relation''' 57 58 objectPaths = None 59 author = '' 60 organization = '' 61 url = '' 62 version = '0.1' 63 64 requires = () 65 66 loaders = (ZPLObject(), ZPLReport(), ZPLDaemons(), ZPLBin(), ZPLLibExec(), 67 ZPLSkins(), ZPLDataSources(), ZPLLibraries(), ZPLAbout()) 68 69 _properties = ZenModelRM._properties + ( 70 {'id':'objectPaths','type':'lines','mode':'w'}, 71 {'id':'author', 'type':'string', 'mode':'w'}, 72 {'id':'organization', 'type':'string', 'mode':'w'}, 73 {'id':'version', 'type':'string', 'mode':'w'}, 74 {'id':'url', 'type':'string', 'mode':'w'}, 75 ) 76 77 _relations = ( 78 ('root', ToOne(ToManyCont, 'Products.ZenModel.DataRoot', 'packs')), 79 ("packables", ToMany(ToOne, "Products.ZenModel.ZenPackable", "pack")), 80 ) 81 82 factory_type_information = ( 83 { 'immediate_view' : 'viewPackDetail', 84 'factory' : 'manage_addZenPack', 85 'actions' : 86 ( 87 { 'id' : 'viewPackDetail' 88 , 'name' : 'Detail' 89 , 'action' : 'viewPackDetail' 90 , 'permissions' : ( "Manage DMD", ) 91 }, 92 ) 93 }, 94 ) 95 96 packZProperties = [ 97 ] 98 99
100 - def path(self, *args):
101 return zenPackPath(self.id, *args)
102 103
104 - def install(self, app):
105 for loader in self.loaders: 106 loader.load(self, app) 107 self.createZProperties(app)
108 109
110 - def upgrade(self, app):
111 for loader in self.loaders: 112 loader.upgrade(self, app) 113 self.createZProperties(app) 114 self.migrate()
115 116
117 - def remove(self, app):
118 for loader in self.loaders: 119 loader.unload(self, app) 120 self.removeZProperties(app)
121 122
123 - def migrate(self):
124 import sys 125 instances = [] 126 # find all the migrate modules 127 root = self.path("migrate") 128 for p, ds, fs in os.walk(root): 129 for f in fs: 130 if f.endswith('.py') and not f.startswith("__"): 131 path = os.path.join(p[len(root) + 1:], f) 132 log.debug("Loading %s", path) 133 sys.path.insert(0, p) 134 try: 135 try: 136 c = importClass(path[:-3].replace("/", ".")) 137 instances.append(c()) 138 finally: 139 sys.path.remove(p) 140 except ImportError, ex: 141 log.exception("Problem loading migration step %s", path) 142 # sort them by version number 143 instances.sort() 144 # install those that are newer than our pack version 145 current = getVersionTupleFromString(self.version) 146 recover = [] 147 try: 148 for instance in instances: 149 if instance.version >= current: 150 recover.append(instance) 151 instance.migrate(self) 152 except Exception, ex: 153 # give the pack a chance to recover from problems 154 recover.reverse() 155 for r in recover: 156 r.recover() 157 raise ex
158 159
160 - def list(self, app):
161 result = [] 162 for loader in self.loaders: 163 result.append((loader.name, 164 [item for item in loader.list(self, app)])) 165 return result
166 167
168 - def createZProperties(self, app):
169 for name, value, pType in self.packZProperties: 170 if not app.zport.dmd.Devices.hasProperty(name): 171 app.zport.dmd.Devices._setProperty(name, value, pType)
172 173
174 - def removeZProperties(self, app):
175 for name, value, pType in self.packZProperties: 176 app.zport.dmd.Devices._delProperty(name)
177 178
179 - def manage_deletePackable(self, packables=(), REQUEST=None):
180 "Delete objects from this ZenPack" 181 from sets import Set 182 packables = Set(packables) 183 for obj in self.packables(): 184 if obj.getPrimaryUrlPath() in packables: 185 self.packables.removeRelation(obj) 186 if REQUEST: 187 REQUEST['message'] = 'Deleted objects from ZenPack %s' % self.id 188 return self.callZenScreen(REQUEST)
189
190 - def manage_exportPack(self, REQUEST=None):
191 "Export the ZenPack to the /export directory" 192 from StringIO import StringIO 193 from Acquisition import aq_base 194 xml = StringIO() 195 196 # Write out packable objects 197 xml.write("""<?xml version="1.0"?>\n""") 198 xml.write("<objects>\n") 199 packables = eliminateDuplicates(self.packables()) 200 for obj in packables: 201 obj = aq_base(obj) 202 xml.write('<!-- %r -->\n' % (obj.getPrimaryPath(),)) 203 obj.exportXml(xml,['devices','networks', 'pack'],True) 204 xml.write("</objects>\n") 205 path = zenPackPath(self.id, 'objects') 206 if not os.path.isdir(path): 207 os.mkdir(path, 0750) 208 objects = file(os.path.join(path, 'objects.xml'), 'w') 209 objects.write(xml.getvalue()) 210 objects.close() 211 212 # Create skins dir if not there 213 path = zenPackPath(self.id, 'skins') 214 if not os.path.isdir(path): 215 os.makeDirs(path, 0750) 216 217 # Create __init__.py 218 init = zenPackPath(self.id, '__init__.py') 219 if not os.path.isfile(init): 220 fp = file(init, 'w') 221 fp.write( 222 ''' 223 import Globals 224 from Products.CMFCore.DirectoryView import registerDirectory 225 registerDirectory("skins", globals()) 226 ''') 227 fp.close() 228 229 # Create about.txt 230 about = zenPackPath(self.id, CONFIG_FILE) 231 values = {} 232 parser = ConfigParser.SafeConfigParser() 233 if os.path.isfile(about): 234 try: 235 parser.read(about) 236 values = dict(parser.items(CONFIG_SECTION_ABOUT)) 237 except ConfigParser.Error: 238 pass 239 current = [(p['id'], str(getattr(self, p['id'], '') or '')) 240 for p in self._properties] 241 values.update(dict(current)) 242 if not parser.has_section(CONFIG_SECTION_ABOUT): 243 parser.add_section(CONFIG_SECTION_ABOUT) 244 for key, value in values.items(): 245 parser.set(CONFIG_SECTION_ABOUT, key, value) 246 fp = file(about, 'w') 247 try: 248 parser.write(fp) 249 finally: 250 fp.close() 251 252 # Create the zip file 253 path = zenPath('export') 254 if not os.path.isdir(path): 255 os.makeDirs(path, 0750) 256 from zipfile import ZipFile, ZIP_DEFLATED 257 zf = ZipFile(os.path.join(path, '%s.zip' % self.id), 'w', ZIP_DEFLATED) 258 base = zenPackPath() 259 for p, ds, fd in os.walk(zenPackPath(self.id)): 260 if p.split('/')[-1].startswith('.'): continue 261 for f in fd: 262 if f.startswith('.'): continue 263 if f.endswith('.pyc'): continue 264 filename = os.path.join(p, f) 265 zf.write(filename, filename[len(base)+1:]) 266 zf.close() 267 if REQUEST: 268 REQUEST['message'] = '%s has been exported' % self.id 269 return self.callZenScreen(REQUEST)
270
271 - def _getClassesByPath(self, name):
272 dsClasses = [] 273 for path, dirs, files in os.walk(self.path(name)): 274 dirs[:] = [d for d in dirs if not d.startswith('.')] 275 for f in files: 276 if not f.startswith('.') \ 277 and f.endswith('.py') \ 278 and not f == '__init__.py': 279 parts = path.split('/') + [f[:-3]] 280 parts = parts[parts.index('Products'):] 281 dsClasses.append(importClass('.'.join(parts))) 282 return dsClasses
283
284 - def getDataSourceClasses(self):
285 return self._getClassesByPath('datasources')
286
287 - def getThresholdClasses(self):
288 return self._getClassesByPath('thresholds')
289 290
291 -def zenPackPath(*parts):
292 return zenPath('Products', *parts)
293 294 295 # ZenPackBase is here for backwards compatibility with older installed 296 # zenpacks that used it. ZenPackBase was rolled into ZenPack when we 297 # started using about.txt files instead of ZenPack subclasses to set 298 # zenpack metadata. 299 ZenPackBase = ZenPack 300 301 InitializeClass(ZenPack) 302