Changeset 1130
- Timestamp:
- 10/02/03 22:23:18 (21 years ago)
- Location:
- pykota/trunk
- Files:
-
- 8 modified
Legend:
- Unmodified
- Added
- Removed
-
pykota/trunk/conf/pykota.conf.sample
r1114 r1130 51 51 storageuser: pykotauser 52 52 # storageuserpw: Comment out if unused, or set to Quota Storage user password 53 54 # Should the database caching mechanism be enabled or not ? 55 # If unset, caching is disabled. Possible values Y/N/YES/NO 56 # caching mechanism works with both PostgreSQL and OpenLDAP backends 57 # but may be interesting only with OpenLDAP. 58 storagecaching: No 53 59 54 60 # LDAP example, uncomment and adapt it to your own configuration : -
pykota/trunk/NEWS
r1123 r1130 21 21 22 22 PyKota NEWS : 23 24 - 1.15alpha5 : 25 26 - Caching mechanism for all database queries. 23 27 24 28 - 1.15alpha4 : -
pykota/trunk/pykota/config.py
r1111 r1130 21 21 # 22 22 # $Log$ 23 # Revision 1.36 2003/10/02 20:23:18 jalet 24 # Storage caching mechanism added. 25 # 23 26 # Revision 1.35 2003/07/29 09:54:03 jalet 24 27 # Added configurable LDAP mail attribute support … … 401 404 else : 402 405 return 0 406 407 def getCaching(self) : 408 """Returns 1 if database caching is enabled, else 0.""" 409 caching = self.getGlobalOption("storagecaching", ignore=1) 410 if (caching is not None) and (caching.upper().strip() in ['Y', 'YES', '1', 'ON', 'O']) : 411 return 1 412 else : 413 return 0 -
pykota/trunk/pykota/storage.py
r1087 r1130 21 21 # 22 22 # $Log$ 23 # Revision 1.20 2003/10/02 20:23:18 jalet 24 # Storage caching mechanism added. 25 # 23 26 # Revision 1.19 2003/07/16 21:53:07 jalet 24 27 # Really big modifications wrt new configuration file's location and content. … … 298 301 self.JobSize = jobsize 299 302 303 class BaseStorage : 304 def __init__(self, pykotatool) : 305 """Opens the LDAP connection.""" 306 # raise PyKotaStorageError, "Sorry, the LDAP backend for PyKota is not yet implemented !" 307 self.closed = 1 308 self.tool = pykotatool 309 self.usecache = pykotatool.config.getCaching() 310 if self.usecache : 311 self.tool.logdebug("Caching enabled.") 312 self.caches = { "USERS" : {}, "GROUPS" : {}, "PRINTERS" : {}, "USERPQUOTAS" : {}, "GROUPPQUOTAS" : {}, "JOBS" : {}, "LASTJOBS" : {} } 313 314 def __del__(self) : 315 """Ensures that the database connection is closed.""" 316 self.close() 317 318 def getFromCache(self, cachetype, key) : 319 """Tries to extract something from the cache.""" 320 if self.usecache : 321 entry = self.caches[cachetype].get(key) 322 if entry is not None : 323 self.tool.logdebug("Cache hit (%s->%s)" % (cachetype, key)) 324 else : 325 self.tool.logdebug("Cache miss (%s->%s)" % (cachetype, key)) 326 return entry 327 328 def cacheEntry(self, cachetype, key, value) : 329 """Puts an entry in the cache.""" 330 if self.usecache : 331 self.caches[cachetype][key] = value 332 333 def getUser(self, username) : 334 """Returns the user from cache.""" 335 user = self.getFromCache("USERS", username) 336 if user is None : 337 user = self.getUserFromBackend(username) 338 self.cacheEntry("USERS", username, user) 339 return user 340 341 def getGroup(self, groupname) : 342 """Returns the group from cache.""" 343 group = self.getFromCache("GROUPS", groupname) 344 if group is None : 345 group = self.getGroupFromBackend(groupname) 346 self.cacheEntry("GROUPS", groupname, group) 347 return group 348 349 def getPrinter(self, printername) : 350 """Returns the printer from cache.""" 351 printer = self.getFromCache("PRINTERS", printername) 352 if printer is None : 353 printer = self.getPrinterFromBackend(printername) 354 self.cacheEntry("PRINTERS", printername, printer) 355 return printer 356 357 def getUserPQuota(self, user, printer) : 358 """Returns the user quota information from cache.""" 359 useratprinter = "%s@%s" % (user.Name, printer.Name) 360 upquota = self.getFromCache("USERPQUOTAS", useratprinter) 361 if upquota is None : 362 upquota = self.getUserPQuotaFromBackend(user, printer) 363 self.cacheEntry("USERPQUOTAS", useratprinter, upquota) 364 return upquota 365 366 def getGroupPQuota(self, group, printer) : 367 """Returns the group quota information from cache.""" 368 groupatprinter = "%s@%s" % (group.Name, printer.Name) 369 gpquota = self.getFromCache("GROUPPQUOTAS", groupatprinter) 370 if gpquota is None : 371 gpquota = self.getGroupPQuotaFromBackend(group, printer) 372 self.cacheEntry("GROUPPQUOTAS", groupatprinter, gpquota) 373 return gpquota 374 375 def getPrinterLastJob(self, printer) : 376 """Extracts last job information for a given printer from cache.""" 377 lastjob = self.getFromCache("LASTJOBS", printer.Name) 378 if lastjob is None : 379 lastjob = self.getPrinterLastJobFromBackend(printer) 380 self.cacheEntry("LASTJOBS", printer.Name, lastjob) 381 return lastjob 382 300 383 def openConnection(pykotatool) : 301 384 """Returns a connection handle to the appropriate Quota Storage Database.""" -
pykota/trunk/pykota/storages/ldapstorage.py
r1119 r1130 21 21 # 22 22 # $Log$ 23 # Revision 1.26 2003/10/02 20:23:18 jalet 24 # Storage caching mechanism added. 25 # 23 26 # Revision 1.25 2003/08/20 15:56:24 jalet 24 27 # Better user and group deletion … … 116 119 import md5 117 120 118 from pykota.storage import PyKotaStorageError 119 from pykota.storage import StorageObject,StorageUser,StorageGroup,StoragePrinter,StorageLastJob,StorageUserPQuota,StorageGroupPQuota 121 from pykota.storage import PyKotaStorageError,BaseStorage,StorageObject,StorageUser,StorageGroup,StoragePrinter,StorageLastJob,StorageUserPQuota,StorageGroupPQuota 120 122 121 123 try : … … 127 129 raise PyKotaStorageError, "This python version (%s) doesn't seem to have the python-ldap module installed correctly." % sys.version.split()[0] 128 130 129 class Storage :131 class Storage(BaseStorage) : 130 132 def __init__(self, pykotatool, host, dbname, user, passwd) : 131 133 """Opens the LDAP connection.""" 132 134 # raise PyKotaStorageError, "Sorry, the LDAP backend for PyKota is not yet implemented !" 133 self.closed = 1 134 self.tool = pykotatool 135 self.debug = pykotatool.config.getDebug() 135 BaseStorage.__init__(self, pykotatool) 136 136 self.info = pykotatool.config.getLDAPInfo() 137 137 try : … … 145 145 else : 146 146 self.closed = 0 147 if self.debug : 148 self.tool.logger.log_message("Database opened (host=%s, dbname=%s, user=%s)" % (host, dbname, user), "debug") 149 150 def __del__(self) : 151 """Ensures that the database connection is closed.""" 152 self.close() 153 147 self.tool.logdebug("Database opened (host=%s, dbname=%s, user=%s)" % (host, dbname, user)) 148 154 149 def close(self) : 155 150 """Closes the database connection.""" … … 157 152 del self.database 158 153 self.closed = 1 159 if self.debug : 160 self.tool.logger.log_message("Database closed.", "debug") 154 self.tool.logdebug("Database closed.") 161 155 162 156 def genUUID(self) : … … 169 163 def beginTransaction(self) : 170 164 """Starts a transaction.""" 171 if self.debug : 172 self.tool.logger.log_message("Transaction begins... WARNING : No transactions in LDAP !", "debug") 165 self.tool.logdebug("Transaction begins... WARNING : No transactions in LDAP !") 173 166 174 167 def commitTransaction(self) : 175 168 """Commits a transaction.""" 176 if self.debug : 177 self.tool.logger.log_message("Transaction committed. WARNING : No transactions in LDAP !", "debug") 169 self.tool.logdebug("Transaction committed. WARNING : No transactions in LDAP !") 178 170 179 171 def rollbackTransaction(self) : 180 172 """Rollbacks a transaction.""" 181 if self.debug : 182 self.tool.logger.log_message("Transaction aborted. WARNING : No transaction in LDAP !", "debug") 173 self.tool.logdebug("Transaction aborted. WARNING : No transaction in LDAP !") 183 174 184 175 def doSearch(self, key, fields=None, base="", scope=ldap.SCOPE_SUBTREE) : … … 186 177 try : 187 178 base = base or self.basedn 188 if self.debug : 189 self.tool.logger.log_message("QUERY : Filter : %s, BaseDN : %s, Scope : %s, Attributes : %s" % (key, base, scope, fields), "debug") 179 self.tool.logdebug("QUERY : Filter : %s, BaseDN : %s, Scope : %s, Attributes : %s" % (key, base, scope, fields)) 190 180 result = self.database.search_s(base or self.basedn, scope, key, fields) 191 181 except ldap.LDAPError : 192 182 raise PyKotaStorageError, _("Search for %s(%s) from %s(scope=%s) returned no answer.") % (key, fields, base, scope) 193 183 else : 194 if self.debug : 195 self.tool.logger.log_message("QUERY : Result : %s" % result, "debug") 184 self.tool.logdebug("QUERY : Result : %s" % result) 196 185 return result 197 186 … … 199 188 """Adds an entry in the LDAP directory.""" 200 189 try : 201 if self.debug : 202 self.tool.logger.log_message("QUERY : ADD(%s, %s)" % (dn, str(fields)), "debug") 190 self.tool.logdebug("QUERY : ADD(%s, %s)" % (dn, str(fields))) 203 191 self.database.add_s(dn, modlist.addModlist(fields)) 204 192 except ldap.LDAPError : … … 210 198 """Deletes an entry from the LDAP directory.""" 211 199 try : 212 if self.debug : 213 self.tool.logger.log_message("QUERY : Delete(%s)" % dn, "debug") 200 self.tool.logdebug("QUERY : Delete(%s)" % dn) 214 201 self.database.delete_s(dn) 215 202 except ldap.LDAPError : … … 220 207 try : 221 208 oldentry = self.doSearch("objectClass=*", base=dn, scope=ldap.SCOPE_BASE) 222 if self.debug : 223 self.tool.logger.log_message("QUERY : Modify(%s, %s ==> %s)" % (dn, oldentry[0][1], fields), "debug") 209 self.tool.logdebug("QUERY : Modify(%s, %s ==> %s)" % (dn, oldentry[0][1], fields)) 224 210 self.database.modify_s(dn, modlist.modifyModlist(oldentry[0][1], fields, ignore_oldexistent=ignoreold)) 225 211 except ldap.LDAPError : … … 228 214 return dn 229 215 230 def getUser (self, username) :216 def getUserFromBackend(self, username) : 231 217 """Extracts user information given its name.""" 232 218 user = StorageUser(self, username) … … 262 248 return user 263 249 264 def getGroup (self, groupname) :250 def getGroupFromBackend(self, groupname) : 265 251 """Extracts group information given its name.""" 266 252 group = StorageGroup(self, groupname) … … 282 268 return group 283 269 284 def getPrinter (self, printername) :270 def getPrinterFromBackend(self, printername) : 285 271 """Extracts printer information given its name.""" 286 272 printer = StoragePrinter(self, printername) … … 294 280 printer.Exists = 1 295 281 return printer 296 297 def getUserGroups(self, user) : 298 """Returns the user's groups list.""" 299 groups = [] 300 result = self.doSearch("(&(objectClass=pykotaGroup)(%s=%s))" % (self.info["groupmembers"], user.Name), [self.info["grouprdn"]], base=self.info["groupbase"]) 301 if result : 302 for (groupid, fields) in result : 303 groups.append(self.getGroup(fields.get(self.info["grouprdn"])[0])) 304 return groups 305 306 def getGroupMembers(self, group) : 307 """Returns the group's members list.""" 308 groupmembers = [] 309 result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (group.Name, self.info["grouprdn"], group.Name), [self.info["groupmembers"]], base=self.info["groupbase"]) 310 if result : 311 for username in result[0][1].get(self.info["groupmembers"], []) : 312 groupmembers.append(self.getUser(username)) 313 return groupmembers 314 315 def getUserPQuota(self, user, printer) : 282 283 def getUserPQuotaFromBackend(self, user, printer) : 316 284 """Extracts a user print quota.""" 317 285 userpquota = StorageUserPQuota(self, user, printer) … … 344 312 return userpquota 345 313 346 def getGroupPQuota (self, group, printer) :314 def getGroupPQuotaFromBackend(self, group, printer) : 347 315 """Extracts a group print quota.""" 348 316 grouppquota = StorageGroupPQuota(self, group, printer) … … 383 351 return grouppquota 384 352 385 def getPrinterLastJob (self, printer) :353 def getPrinterLastJobFromBackend(self, printer) : 386 354 """Extracts a printer's last job information.""" 387 355 lastjob = StorageLastJob(self, printer) … … 409 377 lastjob.Exists = 1 410 378 return lastjob 379 380 def getUserGroups(self, user) : 381 """Returns the user's groups list.""" 382 groups = [] 383 result = self.doSearch("(&(objectClass=pykotaGroup)(%s=%s))" % (self.info["groupmembers"], user.Name), [self.info["grouprdn"]], base=self.info["groupbase"]) 384 if result : 385 for (groupid, fields) in result : 386 groups.append(self.getGroup(fields.get(self.info["grouprdn"])[0])) 387 return groups 388 389 def getGroupMembers(self, group) : 390 """Returns the group's members list.""" 391 groupmembers = [] 392 result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (group.Name, self.info["grouprdn"], group.Name), [self.info["groupmembers"]], base=self.info["groupbase"]) 393 if result : 394 for username in result[0][1].get(self.info["groupmembers"], []) : 395 groupmembers.append(self.getUser(username)) 396 return groupmembers 411 397 412 398 def getMatchingPrinters(self, printerpattern) : -
pykota/trunk/pykota/storages/pgstorage.py
r1115 r1130 21 21 # 22 22 # $Log$ 23 # Revision 1.13 2003/10/02 20:23:18 jalet 24 # Storage caching mechanism added. 25 # 23 26 # Revision 1.12 2003/08/17 14:20:25 jalet 24 27 # Bug fix by Oleg Biteryakov … … 64 67 # 65 68 66 from pykota.storage import PyKotaStorageError 67 from pykota.storage import StorageObject,StorageUser,StorageGroup,StoragePrinter,StorageLastJob,StorageUserPQuota,StorageGroupPQuota 69 from pykota.storage import PyKotaStorageError,BaseStorage,StorageObject,StorageUser,StorageGroup,StoragePrinter,StorageLastJob,StorageUserPQuota,StorageGroupPQuota 68 70 69 71 try : … … 74 76 raise PyKotaStorageError, "This python version (%s) doesn't seem to have the PygreSQL module installed correctly." % sys.version.split()[0] 75 77 76 class Storage :78 class Storage(BaseStorage) : 77 79 def __init__(self, pykotatool, host, dbname, user, passwd) : 78 80 """Opens the PostgreSQL database connection.""" 79 self.tool = pykotatool 80 self.debug = pykotatool.config.getDebug() 81 self.closed = 1 81 BaseStorage.__init__(self, pykotatool) 82 82 try : 83 83 (host, port) = host.split(":") … … 92 92 else : 93 93 self.closed = 0 94 if self.debug : 95 self.tool.logger.log_message("Database opened (host=%s, port=%s, dbname=%s, user=%s)" % (host, port, dbname, user), "debug") 96 97 def __del__(self) : 98 """Ensures that the database connection is closed.""" 99 self.close() 100 94 self.tool.logdebug("Database opened (host=%s, port=%s, dbname=%s, user=%s)" % (host, port, dbname, user)) 95 101 96 def close(self) : 102 97 """Closes the database connection.""" … … 104 99 self.database.close() 105 100 self.closed = 1 106 if self.debug : 107 self.tool.logger.log_message("Database closed.", "debug") 101 self.tool.logdebug("Database closed.") 108 102 109 103 def beginTransaction(self) : 110 104 """Starts a transaction.""" 111 105 self.database.query("BEGIN;") 112 if self.debug : 113 self.tool.logger.log_message("Transaction begins...", "debug") 106 self.tool.logdebug("Transaction begins...") 114 107 115 108 def commitTransaction(self) : 116 109 """Commits a transaction.""" 117 110 self.database.query("COMMIT;") 118 if self.debug : 119 self.tool.logger.log_message("Transaction committed.", "debug") 111 self.tool.logdebug("Transaction committed.") 120 112 121 113 def rollbackTransaction(self) : 122 114 """Rollbacks a transaction.""" 123 115 self.database.query("ROLLBACK;") 124 if self.debug : 125 self.tool.logger.log_message("Transaction aborted.", "debug") 116 self.tool.logdebug("Transaction aborted.") 126 117 127 118 def doSearch(self, query) : … … 131 122 query += ';' 132 123 try : 133 if self.debug : 134 self.tool.logger.log_message("QUERY : %s" % query, "debug") 124 self.tool.logdebug("QUERY : %s" % query) 135 125 result = self.database.query(query) 136 126 except pg.error, msg : … … 146 136 query += ';' 147 137 try : 148 if self.debug : 149 self.tool.logger.log_message("QUERY : %s" % query, "debug") 138 self.tool.logdebug("QUERY : %s" % query) 150 139 result = self.database.query(query) 151 140 except pg.error, msg : … … 164 153 return pg._quote(field, typ) 165 154 166 def getUser (self, username) :155 def getUserFromBackend(self, username) : 167 156 """Extracts user information given its name.""" 168 157 user = StorageUser(self, username) … … 178 167 return user 179 168 180 def getGroup (self, groupname) :169 def getGroupFromBackend(self, groupname) : 181 170 """Extracts group information given its name.""" 182 171 group = StorageGroup(self, groupname) … … 194 183 return group 195 184 196 def getPrinter (self, printername) :185 def getPrinterFromBackend(self, printername) : 197 186 """Extracts printer information given its name.""" 198 187 printer = StoragePrinter(self, printername) … … 206 195 printer.Exists = 1 207 196 return printer 208 209 def getUserGroups(self, user) : 210 """Returns the user's groups list.""" 211 groups = [] 212 result = self.doSearch("SELECT groupname FROM groupsmembers JOIN groups ON groupsmembers.groupid=groups.id WHERE userid=%s" % self.doQuote(user.ident)) 213 if result : 214 for record in result : 215 groups.append(self.getGroup(record.get("groupname"))) 216 return groups 217 218 def getGroupMembers(self, group) : 219 """Returns the group's members list.""" 220 groupmembers = [] 221 result = self.doSearch("SELECT * FROM groupsmembers JOIN users ON groupsmembers.userid=users.id WHERE groupid=%s" % self.doQuote(group.ident)) 222 if result : 223 for record in result : 224 user = StorageUser(self, record.get("username")) 225 user.ident = record.get("userid") 226 user.LimitBy = record.get("limitby") 227 user.AccountBalance = record.get("balance") 228 user.LifeTimePaid = record.get("lifetimepaid") 229 user.Email = record.get("email") 230 user.Exists = 1 231 groupmembers.append(user) 232 return groupmembers 233 234 def getUserPQuota(self, user, printer) : 197 198 def getUserPQuotaFromBackend(self, user, printer) : 235 199 """Extracts a user print quota.""" 236 200 userpquota = StorageUserPQuota(self, user, printer) … … 248 212 return userpquota 249 213 250 def getGroupPQuota (self, group, printer) :214 def getGroupPQuotaFromBackend(self, group, printer) : 251 215 """Extracts a group print quota.""" 252 216 grouppquota = StorageGroupPQuota(self, group, printer) … … 267 231 return grouppquota 268 232 269 def getPrinterLastJob (self, printer) :233 def getPrinterLastJobFromBackend(self, printer) : 270 234 """Extracts a printer's last job information.""" 271 235 lastjob = StorageLastJob(self, printer) … … 282 246 lastjob.Exists = 1 283 247 return lastjob 248 249 def getUserGroups(self, user) : 250 """Returns the user's groups list.""" 251 groups = [] 252 result = self.doSearch("SELECT groupname FROM groupsmembers JOIN groups ON groupsmembers.groupid=groups.id WHERE userid=%s" % self.doQuote(user.ident)) 253 if result : 254 for record in result : 255 groups.append(self.getGroup(record.get("groupname"))) 256 return groups 257 258 def getGroupMembers(self, group) : 259 """Returns the group's members list.""" 260 groupmembers = [] 261 result = self.doSearch("SELECT * FROM groupsmembers JOIN users ON groupsmembers.userid=users.id WHERE groupid=%s" % self.doQuote(group.ident)) 262 if result : 263 for record in result : 264 user = StorageUser(self, record.get("username")) 265 user.ident = record.get("userid") 266 user.LimitBy = record.get("limitby") 267 user.AccountBalance = record.get("balance") 268 user.LifeTimePaid = record.get("lifetimepaid") 269 user.Email = record.get("email") 270 user.Exists = 1 271 groupmembers.append(user) 272 return groupmembers 284 273 285 274 def getMatchingPrinters(self, printerpattern) : -
pykota/trunk/pykota/tool.py
r1113 r1130 21 21 # 22 22 # $Log$ 23 # Revision 1.50 2003/10/02 20:23:18 jalet 24 # Storage caching mechanism added. 25 # 23 26 # Revision 1.49 2003/07/29 20:55:17 jalet 24 27 # 1.14 is out ! … … 234 237 self.config = config.PyKotaConfig("/etc/pykota") 235 238 self.logger = logger.openLogger(self) 239 self.debug = self.config.getDebug() 236 240 self.storage = storage.openConnection(self) 237 241 self.smtpserver = self.config.getSMTPServer() 242 243 def logdebug(self, message) : 244 """Logs something to debug output if debug is enabled.""" 245 if self.debug : 246 self.logger.log_message(message, "debug") 238 247 239 248 def clean(self) : -
pykota/trunk/pykota/version.py
r1123 r1130 21 21 # 22 22 23 __version__ = "1.15alpha 4_unofficial"23 __version__ = "1.15alpha5_unofficial" 24 24 25 25 __doc__ = """PyKota : a complete Printing Quota Solution for CUPS and LPRng."""