Changeset 1041
- Timestamp:
- 06/25/03 16:10:01 (21 years ago)
- Location:
- pykota/trunk
- Files:
-
- 14 modified
Legend:
- Unmodified
- Added
- Removed
-
pykota/trunk/bin/edpykota
r1031 r1041 23 23 # 24 24 # $Log$ 25 # Revision 1.47 2003/06/25 14:10:01 jalet 26 # Hey, it may work (edpykota --reset excepted) ! 27 # 25 28 # Revision 1.46 2003/06/16 11:59:09 jalet 26 29 # More work on LDAP … … 330 333 def main(self, names, options) : 331 334 """Edit user or group quotas.""" 332 printeradded = 0 333 printers = self.storage.getMatchingPrinters(options["printer"]) 334 if not printers : 335 pname = options["printer"] 336 if options["add"] and pname : 337 if self.isValidName(pname) : 338 printerid = self.storage.addPrinter(pname) 339 printers = [ (printerid, pname) ] 340 printeradded = 1 341 else : 342 raise PyKotaToolError, _("Invalid printer name %s") % pname 343 else : 344 raise PyKotaToolError, _("There's no printer matching %s") % pname 345 335 336 suffix = (options["groups"] and "Group") or "User" 337 346 338 softlimit = hardlimit = None 347 if options["softlimit"] : 348 try : 349 softlimit = int(options["softlimit"].strip()) 350 except ValueError : 351 raise PyKotaToolError, _("Invalid softlimit value %s.") % options["softlimit"] 352 if options["hardlimit"] : 353 try : 354 hardlimit = int(options["hardlimit"].strip()) 355 except ValueError : 356 raise PyKotaToolError, _("Invalid hardlimit value %s.") % options["hardlimit"] 357 if (softlimit is not None) and (hardlimit is not None) and (hardlimit < softlimit) : 358 # error, exchange them 359 self.logger.log_message(_("Hard limit %i is less than soft limit %i, values will be exchanged.") % (hardlimit, softlimit)) 360 (softlimit, hardlimit) = (hardlimit, softlimit) 339 if not options["noquota"] : 340 if options["softlimit"] : 341 try : 342 softlimit = int(options["softlimit"].strip()) 343 except ValueError : 344 raise PyKotaToolError, _("Invalid softlimit value %s.") % options["softlimit"] 345 if options["hardlimit"] : 346 try : 347 hardlimit = int(options["hardlimit"].strip()) 348 except ValueError : 349 raise PyKotaToolError, _("Invalid hardlimit value %s.") % options["hardlimit"] 350 if (softlimit is not None) and (hardlimit is not None) and (hardlimit < softlimit) : 351 # error, exchange them 352 self.logger.log_message(_("Hard limit %i is less than soft limit %i, values will be exchanged.") % (hardlimit, softlimit)) 353 (softlimit, hardlimit) = (hardlimit, softlimit) 361 354 362 if not names :363 if options["add"] and not printeradded :364 raise PyKotaToolError, _("You have to pass user or group names on the command line")365 else :366 names = [ "*" ] # all users367 368 355 balance = options["balance"] 369 356 if balance : … … 394 381 groupnames = [] 395 382 396 uwaschanged = {} # tracks changed made at the user level 397 gwaschanged = {} # tracks changed made at the group level 398 for (printerid, printer) in printers : 383 if options["prototype"] : 384 protoentry = getattr(self.storage, "get%s" % suffix)(options["prototype"]) 385 386 printeradded = 0 387 printers = self.storage.getMatchingPrinters(options["printer"]) 388 if not printers : 389 pname = options["printer"] 390 if options["add"] and pname : 391 if self.isValidName(pname) : 392 printers = [ self.storage.addPrinter(pname) ] 393 if printers[0].Exists : 394 printeradded = 1 395 else : 396 raise PyKotaToolError, _("Impossible to add printer %s") % pname 397 else : 398 raise PyKotaToolError, _("Invalid printer name %s") % pname 399 else : 400 raise PyKotaToolError, _("There's no printer matching %s") % pname 401 if not names : 402 if options["add"] and not printeradded : 403 raise PyKotaToolError, _("You have to pass user or group names on the command line") 404 else : 405 names = [ "*" ] # all users 406 407 changed = {} # tracks changes made at the user/group level 408 for printer in printers : 399 409 if options["charge"] : 400 410 (perpage, perjob) = charges 401 if perjob is None : 402 # we don't want to change this one, get the old value 403 (dummy, perjob) = self.storage.getPrinterPrices(printerid) 404 self.storage.setPrinterPrices(printerid, perpage, perjob) 411 printer.setPrices(perpage, perjob) 412 405 413 if options["prototype"] : 406 if options["groups"] : 407 prototype = self.storage.getGroupPQuota(self.storage.getGroupId(options["prototype"]), printerid) 408 else : 409 # default is user quota edition 410 prototype = self.storage.getUserPQuota(self.storage.getUserId(options["prototype"]), printerid) 411 if prototype is None : 412 self.logger.log_message(_("Prototype %s not found in Quota Storage for printer %s.") % (options["prototype"], printer)) 413 continue # skip this printer 414 else : 415 (softlimit, hardlimit) = (prototype["softlimit"], prototype["hardlimit"]) 416 if hardlimit is None : 417 hardlimit = softlimit 418 if hardlimit is not None : 419 self.logger.log_message(_("Undefined hard limit set to soft limit (%s) on printer %s.") % (str(hardlimit), printer)) 420 if softlimit is None : 421 softlimit = hardlimit 422 if softlimit is not None : 423 self.logger.log_message(_("Undefined soft limit set to hard limit (%s) on printer %s.") % (str(softlimit), printer)) 424 if (not options["ingroups"] and not options["reset"] and not options["noquota"] and not options["prototype"] and not options["limitby"] and not options["balance"] and not options["delete"] and not options["charge"]) and ((hardlimit is None) or (softlimit is None)) : 425 raise PyKotaToolError, _("Both hard and soft limits must be set ! Aborting.") 414 if protoentry.Exists : 415 protoquota = getattr(self.storage, "get%PQuota" % suffix)(protoentry, printer) 416 if not protoquota.Exists : 417 self.logger.log_message(_("Prototype %s not found in Quota Storage for printer %s.") % (protoentry.Name, printer.Name)) 418 continue # skip this printer 419 else : 420 (softlimit, hardlimit) = (protoquota.SoftLimit, protoquota.HardLimit) 421 else : 422 self.logger.log_message(_("Prototype object %s not found in Quota Storage.") % protoentry.Name) 423 if not options["noquota"] : 424 if hardlimit is None : 425 hardlimit = softlimit 426 if hardlimit is not None : 427 self.logger.log_message(_("Undefined hard limit set to soft limit (%s) on printer %s.") % (str(hardlimit), printer.Name)) 428 if softlimit is None : 429 softlimit = hardlimit 430 if softlimit is not None : 431 self.logger.log_message(_("Undefined soft limit set to hard limit (%s) on printer %s.") % (str(softlimit), printer.Name)) 432 426 433 if options["add"] : 427 if options["groups"] : 428 allidnames = [(self.storage.getGroupId(n), n) for n in names] 429 else : 430 allidnames = [(self.storage.getUserId(n), n) for n in names] 434 allentries = [] 435 for name in names : 436 entry = getattr(self.storage, "get%s" % suffix)(name) 437 entrypquota = getattr(self.storage, "get%sPQuota" % suffix)(entry, printer) 438 allentries.append((entry, entrypquota)) 431 439 else : 432 if options["groups"] : 433 allidnames = self.storage.getPrinterGroups(printerid) or [] 434 else : 435 allidnames = self.storage.getPrinterUsers(printerid) or [] 436 for (ident, name) in [(i, n) for (i, n) in allidnames if self.matchString(n, names)]: 437 if options["groups"] : 438 if not gwaschanged.has_key(name) : 439 gwaschanged[name] = {} 440 quota = self.storage.getGroupPQuota(ident, printerid) 441 else : 442 if not uwaschanged.has_key(name) : 443 uwaschanged[name] = {"ingroups": []} 444 quota = self.storage.getUserPQuota(ident, printerid) 445 if quota is None : 440 allentries = getattr(self.storage, "getPrinter%ssAndQuotas" % suffix)(printer) 441 442 for (entry, entrypquota) in [(e, q) for (e, q) in allentries if self.matchString(e.Name, names)] : 443 if not changed.has_key(entry.Name) : 444 changed[entry.Name] = {} 445 if not entrypquota.Exists : 446 446 # not found 447 447 if options["add"] : … … 450 450 # like /etc/passwd because users may be defined 451 451 # only remotely 452 if options["groups"] : 453 if self.isValidName(name) : 454 (ident, printerid) = self.storage.addGroupPQuota(name, printerid) 455 quota = self.storage.getGroupPQuota(ident, printerid) 452 if self.isValidName(entry.Name) : 453 if not entry.Exists : 454 entry = getattr(self.storage, "add%s" % suffix)(entry) 455 entrypquota = getattr(self.storage, "add%sPQuota" % suffix)(entry, printer) 456 else : 457 if options["groups"] : 458 self.logger.log_message(_("Invalid group name %s") % entry.Name) 456 459 else : 457 self.logger.log_message(_("Invalid group name %s") % name) 458 else : 459 if self.isValidName(name) : 460 (ident, printerid) = self.storage.addUserPQuota(name, printerid) 461 quota = self.storage.getUserPQuota(ident, printerid) 462 else : 463 self.logger.log_message(_("Invalid user name %s") % name) 464 if quota is None : 465 self.logger.log_message(_("Quota not found for object %s on printer %s.") % (name, printer)) 460 self.logger.log_message(_("Invalid user name %s") % entry.Name) 461 if not entrypquota.Exists : 462 self.logger.log_message(_("Quota not found for object %s on printer %s.") % (entry.Name, printer.Name)) 466 463 else : 467 464 if options["delete"] : 468 if options["groups"] : 469 self.storage.deleteGroup(ident) 470 else : 471 self.storage.deleteUser(ident) 465 entry.delete() 472 466 else : 473 if options["groups"] : 474 if options["noquota"] or options["prototype"] or ((softlimit is not None) and (hardlimit is not None)) : 475 self.storage.setGroupPQuota(ident, printerid, softlimit, hardlimit) 467 if options["noquota"] or options["prototype"] or ((softlimit is not None) and (hardlimit is not None)) : 468 entrypquota.setLimits(softlimit, hardlimit) 469 if limitby : 470 if changed[entry.Name].get("limitby") is None : 471 entry.setLimitBy(limitby) 472 changed[entry.Name]["limitby"] = limitby 473 474 if not options["groups"] : 476 475 if options["reset"] : 477 self.storage.resetGroupPQuota(ident, printerid) 478 if limitby : 479 if gwaschanged[name].get("limitby") is None : 480 self.storage.limitGroupBy(ident, limitby) 481 gwaschanged[name]["limitby"] = limitby 482 self.warnGroupPQuota(name, printer) 483 else : 484 if options["noquota"] or options["prototype"] or ((softlimit is not None) and (hardlimit is not None)) : 485 self.storage.setUserPQuota(ident, printerid, softlimit, hardlimit) 486 if options["reset"] : 487 self.storage.resetUserPQuota(ident, printerid) 488 if limitby : 489 if uwaschanged[name].get("limitby") is None : 490 self.storage.limitUserBy(ident, limitby) 491 uwaschanged[name]["limitby"] = limitby 476 entrypquota.reset() 477 492 478 if balance : 493 if uwaschanged[name].get("balance") is None :479 if changed[entry.Name].get("balance") is None : 494 480 if balance.startswith("+") or balance.startswith("-") : 495 self.storage.increaseUserBalance(ident,balancevalue)481 entry.consumeAccountBalance(-balancevalue) 496 482 else : 497 self.storage.setUserBalance(ident,balancevalue)498 uwaschanged[name]["balance"] = balance483 entry.consumeAccountBalance(float(entry.AccountBalance or 0.0) - balancevalue) 484 changed[entry.Name]["balance"] = balance 499 485 for groupname in groupnames : 500 if groupname not in uwaschanged[name]["ingroups"] :501 group id = self.storage.getGroupId(groupname)502 if group id is not None:503 self.storage.addUserToGroup( ident, groupid)504 uwaschanged[name]["ingroups"].append(groupname)486 if groupname not in changed[name]["ingroups"] : 487 group = self.storage.getGroup(groupname) 488 if group.Exists : 489 self.storage.addUserToGroup(entry, group) 490 changed[entry.Name]["ingroups"].append(groupname) 505 491 else : 506 492 self.logger.log_message(_("Group %s not found in the PyKota Storage.") % groupname) 507 self.warnUserPQuota(name, printer) 493 494 getattr(self, "warn%sPQuota" % suffix)(entrypquota) 508 495 509 496 if __name__ == "__main__" : -
pykota/trunk/bin/pykota
r1026 r1041 23 23 # 24 24 # $Log$ 25 # Revision 1.35 2003/06/25 14:10:01 jalet 26 # Hey, it may work (edpykota --reset excepted) ! 27 # 25 28 # Revision 1.34 2003/06/13 18:54:17 jalet 26 29 # Bug with remote jobs and LPRng fixed. … … 239 242 240 243 # Get the last page counter and last username from the Quota Storage backend 241 printer id = kotafilter.storage.getPrinterId(kotafilter.printername)242 if printerid is None:244 printer = kotafilter.storage.getPrinter(kotafilter.printername) 245 if not printer.Exists : 243 246 # The printer is unknown from the Quota Storage perspective 244 247 # we let the job pass through, but log a warning message 245 248 kotafilter.logger.log_message(_("Printer %s not registered in the PyKota system") % kotafilter.printername, "warn") 246 249 else : 247 user id = kotafilter.storage.getUserId(kotafilter.username)248 if userid is None:250 user = kotafilter.storage.getUser(kotafilter.username) 251 if not user.Exists : 249 252 # The user is unknown from the Quota Storage perspective 250 253 # Depending on the default policy for this printer, we … … 261 264 else : 262 265 # Now does the accounting and act depending on the result 263 action = kotafilter.accounter.doAccounting(printer id, userid)266 action = kotafilter.accounter.doAccounting(printer, user) 264 267 265 268 # if not allowed to print then die, else proceed. -
pykota/trunk/bin/repykota
r1030 r1041 23 23 # 24 24 # $Log$ 25 # Revision 1.39 2003/06/25 14:10:01 jalet 26 # Hey, it may work (edpykota --reset excepted) ! 27 # 25 28 # Revision 1.38 2003/06/15 22:26:52 jalet 26 29 # More work on LDAP … … 147 150 148 151 import sys 152 import os 153 import pwd 154 import grp 149 155 150 156 from mx import DateTime … … 187 193 188 194 This will print the quota status for all users on all printers. 195 196 $ repykota --printer "laser*" jerome "jo*" 197 198 This will print the quota status for user jerome and all users 199 whose name begins with "jo" on all printers which name begin 200 with "laser" 201 202 If launched by a non-root user, additionnal arguments representing 203 users or groups names are ignored, and only the current user/group 204 is reported. 189 205 190 206 This program is free software; you can redistribute it and/or modify … … 206 222 class RePyKota(PyKotaTool) : 207 223 """A class for repykota.""" 208 def main(self, options) :224 def main(self, ugnames, options) : 209 225 """Print Quota reports generator.""" 226 uid = os.geteuid() 227 if not uid : 228 # root user 229 if not ugnames : 230 # no username, means all usernames 231 ugnames = [ "*" ] 232 else : 233 # not the root user 234 # reports only the current user 235 if options["groups"] : 236 ugnames = [ grp.getgrgid(pwd.getpwuid(uid)[3])[0] ] 237 else : 238 ugnames = [ pwd.getpwuid(uid)[0] ] 239 210 240 printers = self.storage.getMatchingPrinters(options["printer"]) 211 241 if not printers : 212 242 raise PyKotaToolError, _("There's no printer matching %s") % options["printer"] 213 for (printerid, printer) in printers : 214 print _("*** Report for %s quota on printer %s") % ((options["groups"] and "group") or "user", printer) 215 print _("Pages grace time: %i days") % self.config.getGraceDelay(printer) 216 prices = self.storage.getPrinterPrices(printerid) 217 if prices is None : 218 (perpage, perjob) = (None, None) 219 else : 220 (perpage, perjob) = prices 221 if perjob is not None : 222 print _("Price per job: %.3f") % perjob 223 if perpage is not None : 224 print _("Price per page: %.3f") % perpage 243 for printer in printers : 244 print _("*** Report for %s quota on printer %s") % ((options["groups"] and "group") or "user", printer.Name) 245 print _("Pages grace time: %i days") % self.config.getGraceDelay(printer.Name) 246 if printer.PricePerJob is not None : 247 print _("Price per job: %.3f") % printer.PricePerJob 248 if printer.PricePerPage is not None : 249 print _("Price per page: %.3f") % printer.PricePerPage 225 250 total = 0 226 251 totalmoney = 0.0 … … 228 253 print _("Group used soft hard balance grace total paid") 229 254 print "------------------------------------------------------------------------------" 230 for (ident, name) in (self.storage.getPrinterGroups(printerid) or []) : 231 quota = self.storage.getGroupPQuota(ident, printerid) 232 balance = self.storage.getGroupBalance(ident) 233 limitby = self.storage.getGroupLimitBy(ident) 234 (pages, money) = self.printQuota(name, quota, balance, limitby) 255 for (group, grouppquota) in self.storage.getPrinterGroupsAndQuotas(printer, ugnames) : 256 (pages, money) = self.printQuota(group, grouppquota) 235 257 total += pages 236 258 totalmoney += money … … 239 261 print _("User used soft hard balance grace total paid") 240 262 print "------------------------------------------------------------------------------" 241 for (ident, name) in (self.storage.getPrinterUsers(printerid) or []) : 242 quota = self.storage.getUserPQuota(ident, printerid) 243 balance = self.storage.getUserBalance(ident) 244 limitby = self.storage.getUserLimitBy(ident) 245 (pages, money) = self.printQuota(name, quota, balance, limitby) 263 for (user, userpquota) in self.storage.getPrinterUsersAndQuotas(printer, ugnames) : 264 (pages, money) = self.printQuota(user, userpquota) 246 265 total += pages 247 266 totalmoney += money 248 267 if total or totalmoney : 249 268 print (" " * 50) + (_("Total : %9i") % total) + ("%11s" % ("%7.2f" % totalmoney)[:11]) 250 printerpagecounter = self.storage.getPrinterPageCounter(printerid)251 269 try : 252 msg = "%9i" % printer pagecounter["pagecounter"]270 msg = "%9i" % printer.LastJob.PrinterPageCounter 253 271 except TypeError : 254 272 msg = _("unknown") … … 258 276 print _("Totals may be inaccurate if some users are members of several groups.") 259 277 260 def printQuota(self, name, quota, balance, limitby) :278 def printQuota(self, entry, quota) : 261 279 """Prints the quota information.""" 262 if quota is not None : 263 lifepagecounter = quota["lifepagecounter"] or 0 264 pagecounter = quota["pagecounter"] or 0 265 softlimit = quota["softlimit"] 266 hardlimit = quota["hardlimit"] 267 datelimit = quota["datelimit"] 268 if balance is not None : 269 (balance, lifetimepaid) = balance 270 else : 271 (balance, lifetimepaid) = (0.0, 0.0) 272 if datelimit is not None : 273 now = DateTime.now() 274 datelimit = DateTime.ISO.ParseDateTime(datelimit) 275 if now >= datelimit : 276 datelimit = "DENY" 277 else : 278 datelimit = "" 279 if limitby == "balance" : 280 reached = (((balance <= 0) and "+") or "-") + "B" 281 else : 282 reached = (((softlimit is not None) and (pagecounter >= softlimit) and "+") or "-") + "Q" 283 balance = balance or 0.0 284 lifetimepaid = lifetimepaid or 0.0 285 strbalance = ("%5.2f" % balance)[:10] 286 strlifetimepaid = ("%6.2f" % lifetimepaid)[:10] 287 print "%-9.9s %s %7i %7s %7s %10s %-10.10s %8i %10s" % (name, reached, pagecounter, str(softlimit), str(hardlimit), strbalance, str(datelimit)[:10], lifepagecounter, strlifetimepaid) 288 return (lifepagecounter, lifetimepaid) 280 lifepagecounter = int(quota.LifePageCounter or 0) 281 pagecounter = int(quota.PageCounter or 0) 282 balance = float(entry.AccountBalance or 0.0) 283 lifetimepaid = float(entry.LifeTimePaid or 0.0) 284 285 if quota.DateLimit is not None : 286 now = DateTime.now() 287 datelimit = DateTime.ISO.ParseDateTime(quota.DateLimit) 288 if now >= datelimit : 289 datelimit = "DENY" 290 elif (quota.HardLimit is not None) and (pagecounter >= quota.HardLimit) : 291 datelimit = "DENY" 292 elif (quota.HardLimit is None) and (quota.SoftLimit is not None) and (pagecounter >= quota.SoftLimit) : 293 datelimit = "DENY" 289 294 else : 290 return (0, 0) 291 295 datelimit = "" 296 297 if entry.LimitBy.lower() == "balance" : 298 reached = (((balance <= 0) and "+") or "-") + "B" 299 else : 300 reached = (((quota.SoftLimit is not None) and (pagecounter >= quota.SoftLimit) and "+") or "-") + "Q" 301 302 strbalance = ("%5.2f" % balance)[:10] 303 strlifetimepaid = ("%6.2f" % lifetimepaid)[:10] 304 print "%-9.9s %s %7i %7s %7s %10s %-10.10s %8i %10s" % (entry.Name, reached, pagecounter, str(quota.SoftLimit), str(quota.HardLimit), strbalance, str(datelimit)[:10], lifepagecounter, strlifetimepaid) 305 return (lifepagecounter, lifetimepaid) 292 306 293 307 if __name__ == "__main__" : … … 318 332 elif options["users"] and options["groups"] : 319 333 raise PyKotaToolError, _("incompatible options, see help.") 320 elif args :321 raise PyKotaToolError, _("unused arguments [%s]. Aborting.") % ", ".join(args)322 334 else : 323 sys.exit(reporter.main( options))335 sys.exit(reporter.main(args, options)) 324 336 except (PyKotaToolError, PyKotaConfigError, PyKotaStorageError), msg : 325 337 sys.stderr.write("%s\n" % msg) -
pykota/trunk/bin/warnpykota
r975 r1041 23 23 # 24 24 # $Log$ 25 # Revision 1.20 2003/06/25 14:10:01 jalet 26 # Hey, it may work (edpykota --reset excepted) ! 27 # 25 28 # Revision 1.19 2003/04/29 22:03:38 jalet 26 29 # Better error handling. … … 84 87 85 88 import sys 89 import os 90 import pwd 91 import grp 86 92 87 93 from pykota import version … … 96 102 command line usage : 97 103 98 warnpykota [options]104 warnpykota [options] [names] 99 105 100 106 options : … … 125 131 any printer. 126 132 127 $ warnpykota --groups --printer "laserjet*" 128 129 This will warn all users of groups which have exceeded 130 their print quota on any printer which name begins with "laserjet" 133 $ warnpykota --groups --printer "laserjet*" "dev*" 134 135 This will warn all users of groups which names begins with "dev" and 136 who have exceeded their print quota on any printer which name begins 137 with "laserjet" 138 139 If launched by a non-root user, additionnal arguments representing 140 users or groups names are ignored, and only the current user/group 141 is warned. 131 142 132 143 This program is free software; you can redistribute it and/or modify … … 148 159 class WarnPyKota(PyKotaTool) : 149 160 """A class for warnpykota.""" 150 def main(self, options) :161 def main(self, ugnames, options) : 151 162 """Warn users or groups over print quota.""" 163 uid = os.geteuid() 164 if not uid : 165 # root user 166 if not ugnames : 167 # no username, means all usernames 168 ugnames = [ "*" ] 169 else : 170 # not the root user 171 # warns only the current user 172 # the utility of this is discutable, but at least it 173 # protects other users from mail bombing if they are 174 # over quota. 175 if options["groups"] : 176 ugnames = [ grp.getgrgid(pwd.getpwuid(uid)[3])[0] ] 177 else : 178 ugnames = [ pwd.getpwuid(uid)[0] ] 179 152 180 printers = self.storage.getMatchingPrinters(options["printer"]) 153 181 if not printers : 154 182 raise PyKotaToolError, _("There's no printer matching %s") % options["printer"] 155 for (printerid, printer)in printers :183 for printer in printers : 156 184 if options["groups"] : 157 for ( ident, name) in self.storage.getPrinterGroups(printerid) :158 self.warnGroupPQuota( name, printer)185 for (group, grouppquota) in self.storage.getPrinterGroupsAndQuotas(printer, ugnames) : 186 self.warnGroupPQuota(grouppquota) 159 187 else : 160 for ( ident, name) in self.storage.getPrinterUsers(printerid) :161 self.warnUserPQuota( name, printer)188 for (user, userpquota) in self.storage.getPrinterUsersAndQuotas(printer, ugnames) : 189 self.warnUserPQuota(userpquota) 162 190 163 191 if __name__ == "__main__" : … … 188 216 elif options["users"] and options["groups"] : 189 217 raise PyKotaToolError, _("incompatible options, see help.") 190 elif args :191 raise PyKotaToolError, _("unused arguments [%s]. Aborting.") % ", ".join(args)192 218 else : 193 sys.exit(sender.main( options))219 sys.exit(sender.main(args, options)) 194 220 except (PyKotaToolError, PyKotaConfigError, PyKotaStorageError), msg : 195 221 sys.stderr.write("%s\n" % msg) -
pykota/trunk/initscripts/ldap/pykota.schema
r1036 r1041 55 55 attributetype ( 1.3.6.1.4.1.16868.1.1.6 NAME 'pykotaSoftLimit' 56 56 DESC 'Soft limit in maximal number of pages' 57 EQUALITY integerMatch58 SYNTAX 1.3.6.1.4.1.1466.115.121.1.2 7SINGLE-VALUE )57 EQUALITY caseIgnoreIA5Match 58 SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) 59 59 60 60 # pykotaHardLimit 61 61 attributetype ( 1.3.6.1.4.1.16868.1.1.7 NAME 'pykotaHardLimit' 62 62 DESC 'Hard limit in maximal number of pages' 63 EQUALITY integerMatch64 SYNTAX 1.3.6.1.4.1.1466.115.121.1.2 7SINGLE-VALUE )63 EQUALITY caseIgnoreIA5Match 64 SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) 65 65 66 66 # pykotaDateLimit … … 97 97 attributetype ( 1.3.6.1.4.1.16868.1.1.13 NAME 'pykotaJobSize' 98 98 DESC 'Current job size in number of pages in the history' 99 EQUALITY integerMatch100 SYNTAX 1.3.6.1.4.1.1466.115.121.1.2 7SINGLE-VALUE )99 EQUALITY caseIgnoreIA5Match 100 SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) 101 101 102 102 # pykotaAction -
pykota/trunk/NEWS
r1029 r1041 22 22 PyKota NEWS : 23 23 24 - 1.09alpha2 : 25 26 - LDAP schema modified a bit. Please upgrade. 27 28 - LDAP backend works ! 29 30 - repykota and warnpykota allow the root user to pass 31 users or groups names on the command line. Users 32 and groups names may contain wildcards. 33 34 - repykota and warnpykota only reports or warns the 35 current user when launched by non-root users. 36 37 - Minor bug fixes. 38 24 39 - 1.09alpha1 : 25 40 -
pykota/trunk/pykota/accounters/external.py
r1000 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.4 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.3 2003/05/27 23:00:21 jalet 24 27 # Big rewrite of external accounting methods. … … 41 44 42 45 class Accounter(AccounterBase) : 43 def doAccounting(self, printer id, userid) :46 def doAccounting(self, printer, user) : 44 47 """Deletgates the computation of the job size to an external command. 45 48 … … 50 53 51 54 # get last job information for this printer 52 pgc = self.filter.storage.getPrinterPageCounter(printerid) 53 if pgc is None : 55 if not printer.LastJob.Exists : 54 56 # The printer hasn't been used yet, from PyKota's point of view 55 57 counterbeforejob = 0 … … 58 60 # Last lifetime page counter before actual job is 59 61 # last page counter + last job size 60 counterbeforejob = (pgc["pagecounter"] or 0) + (pgc["jobsize"]or 0)62 counterbeforejob = int(printer.LastJob.PrinterPageCounter or 0) + int(printer.LastJob.JobSize or 0) 61 63 62 64 # Is the current user allowed to print at all ? 63 action = self.filter.warnUserPQuota(self.filter.username, self.filter.printername) 65 userpquota = self.filter.storage.getUserPQuota(user, printer) 66 action = self.filter.warnUserPQuota(userpquota) 64 67 65 68 # update the quota for the current user on this printer, if allowed to print … … 67 70 jobsize = 0 68 71 else : 69 self.filter.storage.updateUserPQuota(userid, printerid,jobsize)72 userpquota.increasePagesUsage(jobsize) 70 73 71 74 # adds the current job to history 72 self.filter.storage.addJobToHistory(self.filter.jobid, self.filter.storage.getUserId(self.filter.username), printerid, counterbeforejob, action, jobsize)75 printer.addJobToHistory(self.filter.jobid, user, counterbeforejob, action, jobsize) 73 76 74 77 return action … … 102 105 # launches child process 103 106 command = "%s <%s >%s 2>%s" % (self.arguments, infilename, outfilename, errfilename) 104 o = open("/tmp/comm", "w")105 o.write("%s\n" % command)106 o.close()107 107 retcode = os.system(command) 108 108 -
pykota/trunk/pykota/accounters/querying.py
r988 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.4 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.3 2003/05/06 14:55:47 jalet 24 27 # Missing import ! … … 38 41 from pykota.requester import openRequester, PyKotaRequesterError 39 42 40 MAXTRIES = 6# maximum number of tries to get the printer's internal page counter43 MAXTRIES = 12 # maximum number of tries to get the printer's internal page counter 41 44 TIMETOSLEEP = 10 # number of seconds to sleep between two tries to get the printer's internal page counter 42 45 43 46 class Accounter(AccounterBase) : 44 def doAccounting(self, printer id, userid) :47 def doAccounting(self, printer, user) : 45 48 """Does print accounting and returns if the job status is ALLOW or DENY.""" 46 49 # Get the page counter directly from the printer itself … … 65 68 66 69 # get last job information for this printer 67 pgc = self.filter.storage.getPrinterPageCounter(printerid) 68 if pgc is None : 70 if not printer.LastJob.Exists : 69 71 # The printer hasn't been used yet, from PyKota's point of view 70 lasthistoryid = None 71 lastjobid = self.filter.jobid 72 lastuserid = userid 73 lastusername = self.filter.username 72 lastjob = None 73 lastuser = user 74 74 lastpagecounter = counterbeforejob 75 75 else : 76 76 # get last values from Quota Storage 77 (lasthistoryid, lastjobid, lastuserid, lastusername, lastpagecounter) = (pgc["id"], pgc["jobid"], pgc["userid"], pgc["username"], pgc["pagecounter"]) 77 lastjob = printer.LastJob 78 lastuser = printer.LastJob.User 79 lastpagecounter = printer.LastJob.PrinterPageCounter 78 80 79 81 # if printer is off then we assume the correct counter value is the last one … … 107 109 # For more accurate accounting, don't switch off your HP printers ! 108 110 # explanation at : http://web.mit.edu/source/third/lprng/doc/LPRng-HOWTO-15.html 109 self.filter.logger.log_message(_("Error in page count value %i for user %s on printer %s") % (jobsize, lastuser name, self.filter.printername), "error")111 self.filter.logger.log_message(_("Error in page count value %i for user %s on printer %s") % (jobsize, lastuser.Name, self.filter.printername), "error") 110 112 jobsize = abs(int((10 - abs(jobsize)) / 2)) # Workaround for HP printers' feature ! 111 113 112 114 # update the quota for the previous user on this printer 113 self.filter.storage.updateUserPQuota(lastuserid, printerid, jobsize) 115 lastuserquota = self.filter.storage.getUserPQuota(lastuser, printer) 116 if lastuserquota.Exists : 117 lastuserquota.increasePagesUsage(jobsize) 114 118 115 119 # update the last job size in the history 116 self.filter.storage.updateJobSizeInHistory(lasthistoryid, jobsize) 120 if printer.LastJob.Exists : 121 printer.LastJob.setSize(jobsize) 117 122 118 123 # warns the last user if he is over quota 119 self.filter.warnUserPQuota(lastusername, self.filter.printername) 124 if lastuserquota.Exists : 125 self.filter.warnUserPQuota(lastuserquota) 120 126 121 127 # Is the current user allowed to print at all ? 122 action = self.filter.warnUserPQuota(self.filter. username, self.filter.printername)128 action = self.filter.warnUserPQuota(self.filter.storage.getUserPQuota(user, printer)) 123 129 124 130 # adds the current job to history 125 self.filter.storage.addJobToHistory(self.filter.jobid, self.filter.storage.getUserId(self.filter.username), printerid, counterbeforejob, action)131 printer.addJobToHistory(self.filter.jobid, user, counterbeforejob, action) 126 132 127 133 return action -
pykota/trunk/pykota/accounters/stupid.py
r1000 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.4 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.3 2003/05/27 23:00:21 jalet 24 27 # Big rewrite of external accounting methods. … … 39 42 40 43 class Accounter(AccounterBase) : 41 def doAccounting(self, printer id, userid) :44 def doAccounting(self, printer, user) : 42 45 """Does print accounting by stupidly counting the 'showpage' postscript instructions in the document. 43 46 … … 51 54 52 55 # get last job information for this printer 53 pgc = self.filter.storage.getPrinterPageCounter(printerid) 54 if pgc is None : 56 if not printer.LastJob.Exists : 55 57 # The printer hasn't been used yet, from PyKota's point of view 56 58 counterbeforejob = 0 … … 59 61 # Last lifetime page counter before actual job is 60 62 # last page counter + last job size 61 counterbeforejob = (pgc["pagecounter"] or 0) + (pgc["jobsize"]or 0)63 counterbeforejob = int(printer.LastJob.PrinterPageCounter or 0) + int(printer.LastJob.JobSize or 0) 62 64 63 65 # Is the current user allowed to print at all ? 64 action = self.filter.warnUserPQuota(self.filter.username, self.filter.printername) 66 userpquota = self.filter.storage.getUserPQuota(user, printer) 67 action = self.filter.warnUserPQuota(userpquota) 65 68 66 69 # update the quota for the current user on this printer, if allowed to print … … 68 71 jobsize = 0 69 72 else : 70 self.filter.storage.updateUserPQuota(userid, printerid,jobsize)73 userpquota.increasePagesUsage(jobsize) 71 74 72 75 # adds the current job to history 73 self.filter.storage.addJobToHistory(self.filter.jobid, self.filter.storage.getUserId(self.filter.username), printerid, counterbeforejob, action, jobsize)76 printer.addJobToHistory(self.filter.jobid, user, counterbeforejob, action, jobsize) 74 77 75 78 return action -
pykota/trunk/pykota/config.py
r1029 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.30 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.29 2003/06/14 22:44:21 jalet 24 27 # More work on LDAP storage backend. … … 201 204 ldapinfo = {} 202 205 for option in [ "userbase", "userrdn", \ 206 "balancebase", "balancerdn", \ 203 207 "groupbase", "grouprdn", "groupmembers", \ 204 208 "printerbase", "printerrdn", \ -
pykota/trunk/pykota/storage.py
r1021 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.14 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.13 2003/06/10 16:37:54 jalet 24 27 # Deletion of the second user which is not needed anymore. … … 84 87 __str__ = __repr__ 85 88 89 class StorageObject : 90 """Object present in the Quota Storage.""" 91 def __init__(self, parent) : 92 "Initialize minimal data.""" 93 self.parent = parent 94 self.ident = None 95 self.Exists = 0 96 97 class StorageUser(StorageObject) : 98 """User class.""" 99 def __init__(self, parent, name) : 100 StorageObject.__init__(self, parent) 101 self.Name = name 102 self.LimitBy = None 103 self.AccountBalance = None 104 self.LifeTimePaid = None 105 106 def consumeAccountBalance(self, amount) : 107 """Consumes an amount of money from the user's account balance.""" 108 newbalance = float(self.AccountBalance or 0.0) - amount 109 self.parent.writeUserAccountBalance(self, newbalance) 110 self.AccountBalance = newbalance 111 112 def setAccountBalance(self, balance, lifetimepaid) : 113 """Sets the user's account balance in case he pays more money.""" 114 115 def setLimitBy(self, limitby) : 116 """Sets the user's limiting factor.""" 117 limitby = limitby.lower() 118 if limitby in ["quota", "balance"] : 119 self.parent.writeUserLimitBy(self, limitby) 120 self.LimitBy = limitby 121 122 def delete(self) : 123 """Deletes an user from the Quota Storage.""" 124 self.parent.beginTransaction() 125 try : 126 self.parent.deleteUser(self) 127 except PyKotaStorageError, msg : 128 self.parent.rollbackTransaction() 129 raise PyKotaStorageError, msg 130 else : 131 self.parent.commitTransaction() 132 133 class StorageGroup(StorageObject) : 134 """User class.""" 135 def __init__(self, parent, name) : 136 StorageObject.__init__(self, parent) 137 self.Name = name 138 self.LimitBy = None 139 self.AccountBalance = None 140 self.LifeTimePaid = None 141 142 def setLimitBy(self, limitby) : 143 """Sets the user's limiting factor.""" 144 limitby = limitby.lower() 145 if limitby in ["quota", "balance"] : 146 self.parent.writeGroupLimitBy(self, limitby) 147 self.LimitBy = limitby 148 149 def delete(self) : 150 """Deletes a group from the Quota Storage.""" 151 self.parent.beginTransaction() 152 try : 153 self.parent.deleteGroup(self) 154 except PyKotaStorageError, msg : 155 self.parent.rollbackTransaction() 156 raise PyKotaStorageError, msg 157 else : 158 self.parent.commitTransaction() 159 160 class StoragePrinter(StorageObject) : 161 """Printer class.""" 162 def __init__(self, parent, name) : 163 StorageObject.__init__(self, parent) 164 self.Name = name 165 self.PricePerPage = None 166 self.PricePerJob = None 167 self.LastJob = None 168 169 def addJobToHistory(self, jobid, user, pagecounter, action, jobsize=None) : 170 """Adds a job to the printer's history.""" 171 self.parent.writeJobNew(self, user, jobid, pagecounter, action, jobsize) 172 # TODO : update LastJob object ? Probably not needed. 173 174 def setPrices(self, priceperpage = None, priceperjob = None) : 175 """Sets the printer's prices.""" 176 if priceperpage is None : 177 priceperpage = self.PricePerPage 178 else : 179 self.PricePerPage = float(priceperpage) 180 if priceperjob is None : 181 priceperjob = self.PricePerJob 182 else : 183 self.PricePerJob = float(priceperjob) 184 self.parent.writePrinterPrices(self) 185 186 class StorageUserPQuota(StorageObject) : 187 """User Print Quota class.""" 188 def __init__(self, parent, user, printer) : 189 StorageObject.__init__(self, parent) 190 self.User = user 191 self.Printer = printer 192 self.PageCounter = None 193 self.LifePageCounter = None 194 self.SoftLimit = None 195 self.HardLimit = None 196 self.DateLimit = None 197 198 def setDateLimit(self, datelimit) : 199 """Sets the date limit for this quota.""" 200 date = "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second) 201 self.parent.writeUserPQuotaDateLimit(self, date) 202 self.DateLimit = date 203 204 def setLimits(self, softlimit, hardlimit) : 205 """Sets the soft and hard limit for this quota.""" 206 self.parent.writeUserPQuotaLimits(self, softlimit, hardlimit) 207 self.SoftLimit = softlimit 208 self.HardLimit = hardlimit 209 210 def reset(self) : 211 """Resets page counter to 0.""" 212 self.parent.writeUserPQuotaPagesCounters(self, 0, int(self.LifePageCounter or 0)) 213 self.PageCounter = 0 214 215 def increasePagesUsage(self, nbpages) : 216 """Increase the value of used pages and money.""" 217 if nbpages : 218 jobprice = (float(self.Printer.PricePerPage or 0.0) * nbpages) + float(self.Printer.PricePerJob or 0.0) 219 newpagecounter = int(self.PageCounter or 0) + nbpages 220 newlifepagecounter = int(self.LifePageCounter or 0) + nbpages 221 self.parent.beginTransaction() 222 try : 223 if jobprice : # optimization : don't access the database if unneeded. 224 self.User.consumeAccountBalance(jobprice) 225 self.parent.writeUserPQuotaPagesCounters(self, newpagecounter, newlifepagecounter) 226 except PyKotaStorageError, msg : 227 self.parent.rollbackTransaction() 228 raise PyKotaStorageError, msg 229 else : 230 self.parent.commitTransaction() 231 self.PageCounter = newpagecounter 232 self.LifePageCounter = newlifepagecounter 233 234 class StorageGroupPQuota(StorageObject) : 235 """Group Print Quota class.""" 236 def __init__(self, parent, group, printer) : 237 StorageObject.__init__(self, parent) 238 self.Group = group 239 self.Printer = printer 240 self.PageCounter = None 241 self.LifePageCounter = None 242 self.SoftLimit = None 243 self.HardLimit = None 244 self.DateLimit = None 245 246 def setDateLimit(self, datelimit) : 247 """Sets the date limit for this quota.""" 248 date = "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second) 249 self.parent.writeGroupPQuotaDateLimit(self, date) 250 self.DateLimit = date 251 252 def setLimits(self, softlimit, hardlimit) : 253 """Sets the soft and hard limit for this quota.""" 254 self.parent.writeGroupPQuotaLimits(self, softlimit, hardlimit) 255 self.SoftLimit = softlimit 256 self.HardLimit = hardlimit 257 258 class StorageLastJob(StorageObject) : 259 """Printer's Last Job class.""" 260 def __init__(self, parent, printer) : 261 StorageObject.__init__(self, parent) 262 self.Printer = printer 263 self.JobId = None 264 self.User = None 265 self.PrinterPageCounter = None 266 self.JobSize = None 267 self.JobAction = None 268 self.JobDate = None 269 270 def setSize(self, jobsize) : 271 """Sets the last job's size.""" 272 self.parent.writeLastJobSize(self, jobsize) 273 self.JobSize = jobsize 274 86 275 def openConnection(pykotatool) : 87 276 """Returns a connection handle to the appropriate Quota Storage Database.""" -
pykota/trunk/pykota/storages/ldapstorage.py
r1032 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.11 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.10 2003/06/16 21:55:15 jalet 24 27 # More work on LDAP, again. Problem detected. … … 66 69 import time 67 70 import md5 68 import fnmatch69 71 70 72 from pykota.storage import PyKotaStorageError 73 from pykota.storage import StorageObject,StorageUser,StorageGroup,StoragePrinter,StorageLastJob,StorageUserPQuota,StorageGroupPQuota 71 74 72 75 try : … … 114 117 return md5.md5("%s" % time.time()).hexdigest() 115 118 119 def beginTransaction(self) : 120 """Starts a transaction.""" 121 if self.debug : 122 self.tool.logger.log_message("Transaction begins... WARNING : No transactions in LDAP !", "debug") 123 124 def commitTransaction(self) : 125 """Commits a transaction.""" 126 if self.debug : 127 self.tool.logger.log_message("Transaction committed. WARNING : No transactions in LDAP !", "debug") 128 129 def rollbackTransaction(self) : 130 """Rollbacks a transaction.""" 131 if self.debug : 132 self.tool.logger.log_message("Transaction aborted. WARNING : No transaction in LDAP !", "debug") 133 116 134 def doSearch(self, key, fields=None, base="", scope=ldap.SCOPE_SUBTREE) : 117 135 """Does an LDAP search query.""" … … 119 137 base = base or self.basedn 120 138 if self.debug : 121 self.tool.logger.log_message("QUERY : BaseDN : %s, Scope : %s, Filter : %s, Attributes : %s" % (base, scope, key, fields), "debug")139 self.tool.logger.log_message("QUERY : Filter : %s, BaseDN : %s, Scope : %s, Attributes : %s" % (key, base, scope, fields), "debug") 122 140 result = self.database.search_s(base or self.basedn, scope, key, fields) 123 141 except ldap.LDAPError : … … 139 157 return dn 140 158 141 def doModify(self, dn, fields) : 159 def doDelete(self, dn) : 160 """Deletes an entry from the LDAP directory.""" 161 try : 162 if self.debug : 163 self.tool.logger.log_message("QUERY : Delete(%s)" % dn, "debug") 164 self.database.delete_s(dn) 165 except ldap.LDAPError : 166 raise PyKotaStorageError, _("Problem deleting LDAP entry (%s)") % dn 167 168 def doModify(self, dn, fields, ignoreold=1) : 142 169 """Modifies an entry in the LDAP directory.""" 143 170 try : … … 145 172 if self.debug : 146 173 self.tool.logger.log_message("QUERY : Modify(%s, %s ==> %s)" % (dn, oldentry[0][1], fields), "debug") 147 self.database.modify_s(dn, modlist.modifyModlist(oldentry[0][1], fields, ignore_oldexistent= 1))174 self.database.modify_s(dn, modlist.modifyModlist(oldentry[0][1], fields, ignore_oldexistent=ignoreold)) 148 175 except ldap.LDAPError : 149 176 raise PyKotaStorageError, _("Problem modifying LDAP entry (%s, %s)") % (dn, fields) 150 177 else : 151 178 return dn 179 180 def getUser(self, username) : 181 """Extracts user information given its name.""" 182 user = StorageUser(self, username) 183 result = self.doSearch("(&(objectClass=pykotaAccount)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaLimitBy"], base=self.info["userbase"]) 184 if result : 185 fields = result[0][1] 186 user.ident = result[0][0] 187 user.LimitBy = fields.get("pykotaLimitBy")[0] 188 result = self.doSearch("(&(objectClass=pykotaAccountBalance)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["balancerdn"], username), ["pykotaBalance", "pykotaLifeTimePaid"], base=self.info["balancebase"]) 189 if result : 190 fields = result[0][1] 191 user.idbalance = result[0][0] 192 user.AccountBalance = fields.get("pykotaBalance") 193 if user.AccountBalance is not None : 194 if user.AccountBalance[0].upper() == "NONE" : 195 user.AccountBalance = None 196 else : 197 user.AccountBalance = float(user.AccountBalance[0]) 198 user.AccountBalance = user.AccountBalance or 0.0 199 user.LifeTimePaid = fields.get("pykotaLifeTimePaid") 200 if user.LifeTimePaid is not None : 201 if user.LifeTimePaid[0].upper() == "NONE" : 202 user.LifeTimePaid = None 203 else : 204 user.LifeTimePaid = float(user.LifeTimePaid[0]) 205 user.LifeTimePaid = user.LifeTimePaid or 0.0 206 user.Exists = 1 207 return user 208 209 def getGroup(self, groupname) : 210 """Extracts group information given its name.""" 211 group = StorageGroup(self, groupname) 212 result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), ["pykotaLimitBy"], base=self.info["groupbase"]) 213 if result : 214 fields = result[0][1] 215 group.ident = result[0][0] 216 group.LimitBy = fields.get("pykotaLimitBy")[0] 217 group.AccountBalance = 0.0 218 group.LifeTimePaid = 0.0 219 group.Members = self.getGroupMembers(group) 220 for member in group.Members : 221 group.AccountBalance += member.AccountBalance 222 group.LifeTimePaid += member.LifeTimePaid 223 group.Exists = 1 224 return group 225 226 def getPrinter(self, printername) : 227 """Extracts printer information given its name.""" 228 printer = StoragePrinter(self, printername) 229 result = self.doSearch("(&(objectClass=pykotaPrinter)(|(pykotaPrinterName=%s)(%s=%s)))" % (printername, self.info["printerrdn"], printername), ["pykotaPricePerPage", "pykotaPricePerJob"], base=self.info["printerbase"]) 230 if result : 231 fields = result[0][1] 232 printer.ident = result[0][0] 233 printer.PricePerJob = float(fields.get("pykotaPricePerJob")[0] or 0.0) 234 printer.PricePerPage = float(fields.get("pykotaPricePerPage")[0] or 0.0) 235 printer.LastJob = self.getPrinterLastJob(printer) 236 printer.Exists = 1 237 return printer 238 239 def getUserGroups(self, user) : 240 """Returns the user's groups list.""" 241 groups = [] 242 result = self.doSearch("(&(objectClass=pykotaGroup)(%s=%s))" % (self.info["groupmembers"], user.Name), [self.info["grouprdn"]], base=self.info["groupbase"]) 243 if result : 244 for (groupid, fields) in result : 245 groups.append(self.getGroup(fields.get(self.info["grouprdn"])[0])) 246 return groups 247 248 def getGroupMembers(self, group) : 249 """Returns the group's members list.""" 250 groupmembers = [] 251 result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (group.Name, self.info["grouprdn"], group.Name), [self.info["groupmembers"]], base=self.info["groupbase"]) 252 if result : 253 for username in result[0][1].get(self.info["groupmembers"], []) : 254 groupmembers.append(self.getUser(username)) 255 return groupmembers 256 257 def getUserPQuota(self, user, printer) : 258 """Extracts a user print quota.""" 259 userpquota = StorageUserPQuota(self, user, printer) 260 if user.Exists : 261 result = self.doSearch("(&(objectClass=pykotaUserPQuota)(pykotaUserName=%s)(pykotaPrinterName=%s))" % (user.Name, printer.Name), ["pykotaPageCounter", "pykotaLifePageCounter", "pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit"], base=self.info["userquotabase"]) 262 if result : 263 fields = result[0][1] 264 userpquota.ident = result[0][0] 265 userpquota.PageCounter = int(fields.get("pykotaPageCounter")[0] or 0) 266 userpquota.LifePageCounter = int(fields.get("pykotaLifePageCounter")[0] or 0) 267 userpquota.SoftLimit = fields.get("pykotaSoftLimit") 268 if userpquota.SoftLimit is not None : 269 if userpquota.SoftLimit[0].upper() == "NONE" : 270 userpquota.SoftLimit = None 271 else : 272 userpquota.SoftLimit = int(userpquota.SoftLimit[0]) 273 userpquota.HardLimit = fields.get("pykotaHardLimit") 274 if userpquota.HardLimit is not None : 275 if userpquota.HardLimit[0].upper() == "NONE" : 276 userpquota.HardLimit = None 277 elif userpquota.HardLimit is not None : 278 userpquota.HardLimit = int(userpquota.HardLimit[0]) 279 userpquota.DateLimit = fields.get("pykotaDateLimit") 280 if userpquota.DateLimit is not None : 281 if userpquota.DateLimit[0].upper() == "NONE" : 282 userpquota.DateLimit = None 283 else : 284 userpquota.DateLimit = userpquota.DateLimit[0] 285 userpquota.Exists = 1 286 return userpquota 287 288 def getGroupPQuota(self, group, printer) : 289 """Extracts a group print quota.""" 290 grouppquota = StorageGroupPQuota(self, group, printer) 291 if group.Exists : 292 result = self.doSearch("(&(objectClass=pykotaGroupPQuota)(pykotaGroupName=%s)(pykotaPrinterName=%s))" % (group.Name, printer.Name), ["pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit"], base=self.info["groupquotabase"]) 293 if result : 294 fields = result[0][1] 295 grouppquota.ident = result[0][0] 296 grouppquota.SoftLimit = fields.get("pykotaSoftLimit") 297 if grouppquota.SoftLimit is not None : 298 if grouppquota.SoftLimit[0].upper() == "NONE" : 299 grouppquota.SoftLimit = None 300 else : 301 grouppquota.SoftLimit = int(grouppquota.SoftLimit[0]) 302 grouppquota.HardLimit = fields.get("pykotaHardLimit") 303 if grouppquota.HardLimit is not None : 304 if grouppquota.HardLimit[0].upper() == "NONE" : 305 grouppquota.HardLimit = None 306 else : 307 grouppquota.HardLimit = int(grouppquota.HardLimit[0]) 308 grouppquota.DateLimit = fields.get("pykotaDateLimit") 309 if grouppquota.DateLimit is not None : 310 if grouppquota.DateLimit[0].upper() == "NONE" : 311 grouppquota.DateLimit = None 312 else : 313 grouppquota.DateLimit = grouppquota.DateLimit[0] 314 grouppquota.PageCounter = 0 315 grouppquota.LifePageCounter = 0 316 if (not hasattr(group, "Members")) or (group.Members is None) : 317 group.Members = self.getGroupMembers(group) 318 usernamesfilter = "".join(["(pykotaUserName=%s)" % member.Name for member in group.Members]) 319 result = self.doSearch("(&(objectClass=pykotaUserPQuota)(pykotaPrinterName=%s)(|%s))" % (printer.Name, usernamesfilter), ["pykotaPageCounter", "pykotaLifePageCounter"], base=self.info["userquotabase"]) 320 if result : 321 for userpquota in result : 322 grouppquota.PageCounter += int(userpquota[1].get("pykotaPageCounter")[0] or 0) 323 grouppquota.LifePageCounter += int(userpquota[1].get("pykotaLifePageCounter")[0] or 0) 324 grouppquota.Exists = 1 325 return grouppquota 326 327 def getPrinterLastJob(self, printer) : 328 """Extracts a printer's last job information.""" 329 lastjob = StorageLastJob(self, printer) 330 result = self.doSearch("(&(objectClass=pykotaLastjob)(|(pykotaPrinterName=%s)(%s=%s)))" % (printer.Name, self.info["printerrdn"], printer.Name), ["pykotaLastJobIdent"], base=self.info["lastjobbase"]) 331 if result : 332 lastjob.lastjobident = result[0][0] 333 lastjobident = result[0][1]["pykotaLastJobIdent"][0] 334 result = self.doSearch("objectClass=pykotaJob", ["pykotaUserName", "pykotaJobId", "pykotaPrinterPageCounter", "pykotaJobSize", "pykotaAction", "createTimestamp"], base="cn=%s,%s" % (lastjobident, self.info["jobbase"]), scope=ldap.SCOPE_BASE) 335 if result : 336 fields = result[0][1] 337 lastjob.ident = result[0][0] 338 lastjob.JobId = fields.get("pykotaJobId")[0] 339 lastjob.User = self.getUser(fields.get("pykotaUserName")[0]) 340 lastjob.PrinterPageCounter = int(fields.get("pykotaPrinterPageCounter")[0] or 0) 341 lastjob.JobSize = int(fields.get("pykotaJobSize", [0])[0]) 342 lastjob.JobAction = fields.get("pykotaAction")[0] 343 date = fields.get("createTimestamp")[0] 344 year = int(date[:4]) 345 month = int(date[4:6]) 346 day = int(date[6:8]) 347 hour = int(date[8:10]) 348 minute = int(date[10:12]) 349 second = int(date[12:14]) 350 lastjob.JobDate = "%04i-%02i-%02i %02i:%02i:%02i" % (year, month, day, hour, minute, second) 351 lastjob.Exists = 1 352 return lastjob 152 353 153 354 def getMatchingPrinters(self, printerpattern) : 154 """Returns the list of all printers as tuples (id, name) for printer names which match a certain pattern.""" 155 result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName"], base=self.info["printerbase"]) 156 if result : 157 return [(printerid, printer["pykotaPrinterName"][0]) for (printerid, printer) in result if fnmatch.fnmatchcase(printer["pykotaPrinterName"][0], printerpattern)] 158 159 def getPrinterId(self, printername) : 160 """Returns a printerid given a printername.""" 161 result = self.doSearch("(&(objectClass=pykotaPrinter)(|(pykotaPrinterName=%s)(%s=%s)))" % (printername, self.info["printerrdn"], printername), ["pykotaPrinterName"], base=self.info["printerbase"]) 162 if result : 163 return result[0][0] 164 165 def getPrinterName(self, printerid) : 166 """Returns a printerid given a printer id.""" 167 result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName"], base=printerid, scope=ldap.SCOPE_BASE) 168 if result : 169 return result[0][1]["pykotaPrinterName"][0] 170 171 def getPrinterPrices(self, printerid) : 172 """Returns a printer prices per page and per job given a printerid.""" 173 result = self.doSearch("(|(pykotaPrinterName=*)(%s=*))" % self.info["printerrdn"], ["pykotaPricePerPage", "pykotaPricePerJob"], base=printerid, scope=ldap.SCOPE_BASE) 174 if result : 175 return (float(result[0][1]["pykotaPricePerPage"][0]), float(result[0][1]["pykotaPricePerJob"][0])) 176 177 def setPrinterPrices(self, printerid, perpage, perjob) : 178 """Sets prices per job and per page for a given printer.""" 179 fields = { 180 "pykotaPricePerPage" : str(perpage), 181 "pykotaPricePerJob" : str(perjob), 182 } 183 return self.doModify(printerid, fields) 184 185 def getUserId(self, username) : 186 """Returns a userid given a username.""" 187 result = self.doSearch("(&(objectClass=pykotaAccount)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), [self.info["userrdn"]], base=self.info["userbase"]) 188 if result : 189 return result[0][0] 190 191 def getUserName(self, userid) : 192 """Returns a username given a userid.""" 193 result = self.doSearch("objectClass=pykotaAccount", ["pykotaUserName"], base=userid, scope=ldap.SCOPE_BASE) 194 if result : 195 return result[0][1]["pykotaUserName"][0] 196 197 def getGroupId(self, groupname) : 198 """Returns a groupid given a grupname.""" 199 result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), [self.info["grouprdn"]], base=self.info["groupbase"]) 200 if result is not None : 201 (groupid, dummy) = result[0] 202 return groupid 203 204 def getJobHistoryId(self, jobid, userid, printerid) : 205 """Returns the history line's id given a (jobid, userid, printerid). 206 207 TODO : delete because shouldn't be needed by the LDAP backend 208 """ 209 raise PyKotaStorageError, "Not implemented !" 210 211 def getPrinterUsers(self, printerid) : 212 """Returns the list of userids and usernames which uses a given printer.""" 213 # first get the printer's name from the id 214 result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName", self.info["printerrdn"]], base=printerid, scope=ldap.SCOPE_BASE) 215 if result : 216 fields = result[0][1] 217 printername = (fields.get("pykotaPrinterName") or fields.get(self.info["printerrdn"]))[0] 218 result = self.doSearch("(&(objectClass=pykotaUserPQuota)(pykotaPrinterName=%s))" % printername, ["pykotaUserName"], base=self.info["userquotabase"]) 219 if result : 220 return [(pquotauserid, fields["pykotaUserName"][0]) for (pquotauserid, fields) in result] 221 222 def getPrinterGroups(self, printerid) : 223 """Returns the list of groups which uses a given printer.""" 224 # first get the printer's name from the id 225 result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName", self.info["printerrdn"]], base=printerid, scope=ldap.SCOPE_BASE) 226 if result : 227 fields = result[0][1] 228 printername = (fields.get("pykotaPrinterName") or fields.get(self.info["printerrdn"]))[0] 229 result = self.doSearch("(&(objectClass=pykotaGroupPQuota)(pykotaPrinterName=%s))" % printername, ["pykotaGroupName"], base=self.info["groupquotabase"]) 230 if result : 231 return [(pquotagroupid, fields["pykotaGroupName"][0]) for (pquotagroupid, fields) in result] 232 233 def getGroupMembersNames(self, groupname) : 234 """Returns the list of user's names which are member of this group.""" 235 result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), [self.info["groupmembers"]]) 236 if result : 237 fields = result[0][1] 238 return fields.get(self.info["groupmembers"]) 239 240 def getUserGroupsNames(self, userid) : 241 """Returns the list of groups' names the user is a member of.""" 242 username = self.getUserName(userid) 243 if username : 244 result = self.doSearch("(&(objectClass=pykotaGroup)(%s=%s))" % (self.info["groupmembers"], username), [self.info["grouprdn"]], base=self.info["groupbase"]) 245 if result : 246 return [v[self.info["grouprdn"]][0] for (k, v) in result] 247 return [] 355 """Returns the list of all printers for which name matches a certain pattern.""" 356 printers = [] 357 # see comment at the same place in pgstorage.py 358 result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName", "pykotaPricePerPage", "pykotaPricePerJob"], base=self.info["printerbase"]) 359 if result : 360 for (printerid, fields) in result : 361 printername = fields["pykotaPrinterName"][0] 362 if self.tool.matchString(printername, [ printerpattern ]) : 363 printer = StoragePrinter(self, printername) 364 printer.ident = printerid 365 printer.PricePerJob = float(fields.get("pykotaPricePerJob")[0] or 0.0) 366 printer.PricePerPage = float(fields.get("pykotaPricePerPage")[0] or 0.0) 367 printer.LastJob = self.getPrinterLastJob(printer) 368 printer.Exists = 1 369 printers.append(printer) 370 return printers 371 372 def getPrinterUsersAndQuotas(self, printer, names=None) : 373 """Returns the list of users who uses a given printer, along with their quotas.""" 374 usersandquotas = [] 375 result = self.doSearch("(&(objectClass=pykotaUserPQuota)(pykotaPrinterName=%s))" % printer.Name, ["pykotaUserName", "pykotaPageCounter", "pykotaLifePageCounter", "pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit"], base=self.info["userquotabase"]) 376 if result : 377 for (userquotaid, fields) in result : 378 user = self.getUser(fields["pykotaUserName"][0]) 379 if (names is None) or self.tool.matchString(user.Name, names) : 380 userpquota = StorageUserPQuota(self, user, printer) 381 userpquota.ident = userquotaid 382 userpquota.PageCounter = int(fields.get("pykotaPageCounter")[0] or 0) 383 userpquota.LifePageCounter = int(fields.get("pykotaLifePageCounter")[0] or 0) 384 userpquota.SoftLimit = fields.get("pykotaSoftLimit") 385 if userpquota.SoftLimit is not None : 386 if userpquota.SoftLimit[0].upper() == "NONE" : 387 userpquota.SoftLimit = None 388 else : 389 userpquota.SoftLimit = int(userpquota.SoftLimit[0]) 390 userpquota.HardLimit = fields.get("pykotaHardLimit") 391 if userpquota.HardLimit is not None : 392 if userpquota.HardLimit[0].upper() == "NONE" : 393 userpquota.HardLimit = None 394 elif userpquota.HardLimit is not None : 395 userpquota.HardLimit = int(userpquota.HardLimit[0]) 396 userpquota.DateLimit = fields.get("pykotaDateLimit") 397 if userpquota.DateLimit is not None : 398 if userpquota.DateLimit[0].upper() == "NONE" : 399 userpquota.DateLimit = None 400 else : 401 userpquota.DateLimit = userpquota.DateLimit[0] 402 userpquota.Exists = 1 403 usersandquotas.append((user, userpquota)) 404 return usersandquotas 405 406 def getPrinterGroupsAndQuotas(self, printer, names=None) : 407 """Returns the list of groups which uses a given printer, along with their quotas.""" 408 groupsandquotas = [] 409 result = self.doSearch("(&(objectClass=pykotaGroupPQuota)(pykotaPrinterName=%s))" % printer.Name, ["pykotaGroupName"], base=self.info["groupquotabase"]) 410 if result : 411 for (groupquotaid, fields) in result : 412 group = self.getGroup(fields.get("pykotaGroupName")[0]) 413 if (names is None) or self.tool.matchString(user.Name, names) : 414 grouppquota = self.getGroupPQuota(group, printer) 415 groupsandquotas.append((group, grouppquota)) 416 return groupsandquotas 248 417 249 418 def addPrinter(self, printername) : 250 """Adds a printer to the quota storage, returns it s id."""419 """Adds a printer to the quota storage, returns it.""" 251 420 fields = { self.info["printerrdn"] : printername, 252 421 "objectClass" : ["pykotaObject", "pykotaPrinter"], 422 "cn" : printername, 253 423 "pykotaPrinterName" : printername, 254 424 "pykotaPricePerPage" : "0.0", … … 256 426 } 257 427 dn = "%s=%s,%s" % (self.info["printerrdn"], printername, self.info["printerbase"]) 258 returnself.doAdd(dn, fields)259 260 def addUser(self, username) :261 """Adds a user to the quota storage, returns its id."""262 fields = { self.info["userrdn"] : username,263 "objectClass" : ["pykotaObject", "pykotaAccount", "pykotaAccountBalance"],264 " pykotaUserName" : username,265 " pykotaLimitBy" : "quota",266 "pykota Balance" : "0.0",267 "pykotaLi feTimePaid" : "0.0",428 self.doAdd(dn, fields) 429 return self.getPrinter(printername) 430 431 def addUser(self, user) : 432 """Adds a user to the quota storage, returns it.""" 433 fields = { self.info["userrdn"] : user.Name, 434 "objectClass" : ["pykotaObject", "pykotaAccount"], 435 "cn" : user.Name, 436 "pykotaUserName" : user.Name, 437 "pykotaLimitBY" : (user.LimitBy or "quota"), 268 438 } 269 dn = "%s=%s,%s" % (self.info["userrdn"], username, self.info["userbase"]) 270 return self.doAdd(dn, fields) 271 272 def addGroup(self, groupname) : 273 """Adds a group to the quota storage, returns its id.""" 274 fields = { self.info["grouprdn"] : groupname, 439 dn = "%s=%s,%s" % (self.info["userrdn"], user.Name, self.info["userbase"]) 440 self.doAdd(dn, fields) 441 fields = { 442 "objectClass" : ["pykotaObject", "pykotaAccountBalance"], 443 "cn" : user.Name, 444 "pykotaUserName" : user.Name, 445 "pykotaBalance" : str(user.AccountBalance or 0.0), 446 "pykotaLifeTimePaid" : str(user.LifeTimePaid or 0.0), 447 } 448 dn = "cn=%s,%s" % (user.Name, self.info["balancebase"]) 449 self.doAdd(dn, fields) 450 return self.getUser(user.Name) 451 452 def addGroup(self, group) : 453 """Adds a group to the quota storage, returns it.""" 454 fields = { self.info["grouprdn"] : group.Name, 275 455 "objectClass" : ["pykotaObject", "pykotaGroup"], 276 "pykotaGroupName" : groupname, 277 "pykotaLimitBy" : "quota", 456 "cn" : group.Name, 457 "pykotaGroupName" : group.Name, 458 "pykotaLimitBY" : (group.LimitBy or "quota"), 278 459 } 279 dn = "%s=%s,%s" % (self.info["grouprdn"], groupname, self.info["groupbase"]) 280 return self.doAdd(dn, fields) 281 282 def addUserPQuota(self, username, printerid) : 283 """Initializes a user print quota on a printer, adds the user to the quota storage if needed.""" 460 dn = "%s=%s,%s" % (self.info["grouprdn"], group.Name, self.info["groupbase"]) 461 self.doAdd(dn, fields) 462 return self.getGroup(group.Name) 463 464 def addUserToGroup(self, user, group) : 465 """Adds an user to a group.""" 466 if user.Name not in [u.Name for u in group.Members] : 467 result = self.doSearch("objectClass=pykotaGroup", None, base=group.ident, scope=ldap.SCOPE_BASE) 468 if result : 469 fields = result[0][1] 470 fields[self.info["groupmembers"]].append(user.Name) 471 self.doModify(group.ident, fields) 472 group.Members.append(user) 473 474 def addUserPQuota(self, user, printer) : 475 """Initializes a user print quota on a printer.""" 284 476 uuid = self.genUUID() 285 fields = { "objectClass" : ["pykotaObject", "pykotaUserPQuota"], 286 "cn" : uuid, 287 "pykotaUserName" : username, 288 "pykotaPrinterName" : self.getPrinterName(printerid), 477 fields = { "cn" : uuid, 478 "objectClass" : ["pykotaObject", "pykotaUserPQuota"], 479 "pykotaUserName" : user.Name, 480 "pykotaPrinterName" : printer.Name, 481 "pykotaDateLimit" : "None", 289 482 "pykotaPageCounter" : "0", 290 483 "pykotaLifePageCounter" : "0", 291 "pykotaSoftLimit" : "0",292 "pykotaHardLimit" : "0",293 "pykotaDateLimit" : "None",294 484 } 295 485 dn = "cn=%s,%s" % (uuid, self.info["userquotabase"]) 296 486 self.doAdd(dn, fields) 297 return (dn, printerid)298 299 def addGroupPQuota(self, group name, printerid) :300 """Initializes a group print quota on a printer , adds the group to the quota storage if needed."""487 return self.getUserPQuota(user, printer) 488 489 def addGroupPQuota(self, group, printer) : 490 """Initializes a group print quota on a printer.""" 301 491 uuid = self.genUUID() 302 fields = { "objectClass" : ["pykotaObject", "pykotaGroupPQuota"], 303 "cn" : uuid, 304 "pykotaGroupName" : groupname, 305 "pykotaPrinterName" : self.getPrinterName(printerid), 306 "pykotaSoftLimit" : "0", 307 "pykotaHardLimit" : "0", 492 fields = { "cn" : uuid, 493 "objectClass" : ["pykotaObject", "pykotaGroupPQuota"], 494 "pykotaGroupName" : group.Name, 495 "pykotaPrinterName" : printer.Name, 308 496 "pykotaDateLimit" : "None", 309 497 } 310 498 dn = "cn=%s,%s" % (uuid, self.info["groupquotabase"]) 311 499 self.doAdd(dn, fields) 312 return (dn, printerid) 313 314 def increaseUserBalance(self, userquotaid, amount) : 315 """Increases (or decreases) an user's account balance by a given amount.""" 316 balance = self.getUserBalance(userquotaid) 317 if balance : 318 (newbal, newpaid) = [(float(v) + float(amount)) for v in balance] 319 result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName"], base=userquotaid, scope=ldap.SCOPE_BASE) 320 if result : 321 username = result[0][1]["pykotaUserName"][0] 322 if username : 323 result = self.doSearch("(&(objectClass=pykotaAccountBalance)(pykotaUserName=%s))" % username , [ "pykotaBalance", "pykotaLifeTimePaid"]) 324 fields = { 325 "pykotaBalance" : str(newbal), 326 "pykotaLifeTimePaid" : str(newpaid), 327 } 328 return self.doModify(result[0][0], fields) 329 330 def getUserBalance(self, userquotaid) : 331 """Returns the current account balance for a given user quota identifier.""" 332 # first get the user's name from the user quota id 333 result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName"], base=userquotaid, scope=ldap.SCOPE_BASE) 334 if result : 335 username = result[0][1]["pykotaUserName"][0] 336 result = self.doSearch("(&(objectClass=pykotaAccountBalance)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaBalance", "pykotaLifeTimePaid"]) 337 if result : 338 fields = result[0][1] 339 return (float(fields["pykotaBalance"][0]), float(fields["pykotaLifeTimePaid"][0])) 340 341 def getUserBalanceFromUserId(self, userid) : 342 """Returns the current account balance for a given user id.""" 343 # first get the user's name from the user id 344 result = self.doSearch("objectClass=pykotaAccount", ["pykotaUserName", self.info["userrdn"]], base=userid, scope=ldap.SCOPE_BASE) 345 if result : 346 fields = result[0][1] 347 username = (fields.get("pykotaUserName") or fields.get(self.info["userrdn"]))[0] 348 result = self.doSearch("(&(objectClass=pykotaAccountBalance)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaBalance", "pykotaLifeTimePaid"]) 349 if result : 350 fields = result[0][1] 351 return (float(fields["pykotaBalance"][0]), float(fields["pykotaLifeTimePaid"][0])) 352 353 def getGroupBalance(self, groupquotaid) : 354 """Returns the current account balance for a given group, as the sum of each of its users' account balance.""" 355 # first get the group's name from the group quota id 356 result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName"], base=groupquotaid, scope=ldap.SCOPE_BASE) 357 if result : 358 groupname = result[0][1]["pykotaGroupName"][0] 359 members = self.getGroupMembersNames(groupname) or [] 360 balance = lifetimepaid = 0.0 361 for member in members : 362 userid = self.getUserId(member) 363 if userid : 364 userbal = self.getUserBalanceFromUserId(userid) 365 if userbal : 366 (bal, paid) = userbal 367 balance += bal 368 lifetimepaid += paid 369 return (balance, lifetimepaid) 370 371 def getUserLimitBy(self, userquotaid) : 372 """Returns the way in which user printing is limited.""" 373 result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName"], base=userquotaid, scope=ldap.SCOPE_BASE) 374 if result : 375 username = result[0][1]["pykotaUserName"][0] 376 result = self.doSearch("(&(objectClass=pykotaAccount)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaLimitBy"]) 377 if result : 378 return result[0][1]["pykotaLimitBy"][0] 379 380 def getGroupLimitBy(self, groupquotaid) : 381 """Returns the way in which group printing is limited.""" 382 # first get the group's name from the group quota id 383 result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName"], base=groupquotaid, scope=ldap.SCOPE_BASE) 384 if result : 385 groupname = result[0][1]["pykotaGroupName"][0] 386 result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), ["pykotaLimitBy"]) 387 if result : 388 return result[0][1]["pykotaLimitBy"][0] 389 390 def setUserBalance(self, userquotaid, balance) : 391 """Sets the account balance for a given user to a fixed value.""" 392 oldbalance = self.getUserBalance(userquotaid) 393 if oldbalance : 394 (oldbal, oldpaid) = oldbalance 395 difference = balance - oldbal 396 return self.increaseUserBalance(userquotaid, difference) 397 398 def limitUserBy(self, userquotaid, limitby) : 399 """Limits a given user based either on print quota or on account balance.""" 400 result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName"], base=userquotaid, scope=ldap.SCOPE_BASE) 401 if result : 402 username = result[0][1]["pykotaUserName"][0] 403 fields = { 404 "pykotaLimitBy" : limitby, 405 } 406 self.doModify(self.getUserId(username), fields) 407 408 def limitGroupBy(self, groupquotaid, limitby) : 409 """Limits a given group based either on print quota or on sum of its users' account balances.""" 410 result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName"], base=groupquotaid, scope=ldap.SCOPE_BASE) 411 if result : 412 groupname = result[0][1]["pykotaGroupName"][0] 413 fields = { 414 "pykotaLimitBy" : limitby, 415 } 416 self.doModify(self.getGroupId(groupname), fields) 417 418 def setUserPQuota(self, userquotaid, printerid, softlimit, hardlimit) : 419 """Sets soft and hard limits for a user quota on a specific printer given (userid, printerid).""" 420 fields = { 421 "pykotaSoftLimit" : str(softlimit), 422 "pykotaHardLimit" : str(hardlimit), 423 "pykotaDateLimit" : "None", 424 } 425 return self.doModify(userquotaid, fields) 426 427 def setGroupPQuota(self, groupquotaid, printerid, softlimit, hardlimit) : 428 """Sets soft and hard limits for a group quota on a specific printer given (groupid, printerid).""" 429 fields = { 430 "pykotaSoftLimit" : str(softlimit), 431 "pykotaHardLimit" : str(hardlimit), 432 "pykotaDateLimit" : "None", 433 } 434 return self.doModify(groupquotaid, fields) 435 436 def resetUserPQuota(self, userquotaid, printerid) : 437 """Resets the page counter to zero for a user on a printer. Life time page counter is kept unchanged.""" 438 fields = { 439 "pykotaPageCounter" : "0", 440 "pykotaDateLimit" : "None", 441 } 442 return self.doModify(userquotaid, fields) 443 444 def resetGroupPQuota(self, groupquotaid, printerid) : 445 """Resets the page counter to zero for a group on a printer. Life time page counter is kept unchanged.""" 446 fields = { 447 "pykotaPageCounter" : "0", 448 "pykotaDateLimit" : "None", 449 } 450 return self.doModify(groupquotaid, fields) 451 452 def updateUserPQuota(self, userquotaid, printerid, pagecount) : 453 """Updates the used user Quota information given (userid, printerid) and a job size in pages.""" 454 jobprice = self.computePrinterJobPrice(printerid, pagecount) 455 result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaPageCounter", "pykotaLifePageCounter"], base=userquotaid, scope=ldap.SCOPE_BASE) 456 if result : 457 oldfields = result[0][1] 458 fields = { 459 "pykotaPageCounter" : str(pagecount + int(oldfields["pykotaPageCounter"][0])), 460 "pykotaLifePageCounter" : str(pagecount + int(oldfields["pykotaLifePageCounter"][0])), 461 } 462 return self.doModify(userquotaid, fields) 463 464 def getUserPQuota(self, userquotaid, printerid) : 465 """Returns the Print Quota information for a given (userquotaid, printerid).""" 466 # first get the user's name from the id 467 result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName", "pykotaPageCounter", "pykotaLifePageCounter", "pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit"], base=userquotaid, scope=ldap.SCOPE_BASE) 468 if result : 469 fields = result[0][1] 470 datelimit = fields["pykotaDateLimit"][0].strip() 471 if (not datelimit) or (datelimit.upper() == "NONE") : 472 datelimit = None 473 return { "lifepagecounter" : int(fields["pykotaLifePageCounter"][0]), 474 "pagecounter" : int(fields["pykotaPageCounter"][0]), 475 "softlimit" : int(fields["pykotaSoftLimit"][0]), 476 "hardlimit" : int(fields["pykotaHardLimit"][0]), 477 "datelimit" : datelimit 478 } 479 480 def getGroupPQuota(self, grouppquotaid, printerid) : 481 """Returns the Print Quota information for a given (grouppquotaid, printerid).""" 482 result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName", "pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit"], base=grouppquotaid, scope=ldap.SCOPE_BASE) 483 if result : 484 fields = result[0][1] 485 groupname = fields["pykotaGroupName"][0] 486 datelimit = fields["pykotaDateLimit"][0].strip() 487 if (not datelimit) or (datelimit.upper() == "NONE") : 488 datelimit = None 489 quota = { 490 "softlimit" : int(fields["pykotaSoftLimit"][0]), 491 "hardlimit" : int(fields["pykotaHardLimit"][0]), 492 "datelimit" : datelimit 493 } 494 members = self.getGroupMembersNames(groupname) or [] 495 pagecounter = lifepagecounter = 0 496 printerusers = self.getPrinterUsers(printerid) 497 if printerusers : 498 for (userid, username) in printerusers : 499 if username in members : 500 userpquota = self.getUserPQuota(userid, printerid) 501 if userpquota : 502 pagecounter += userpquota["pagecounter"] 503 lifepagecounter += userpquota["lifepagecounter"] 504 quota.update({"pagecounter": pagecounter, "lifepagecounter": lifepagecounter}) 505 return quota 506 507 def setUserDateLimit(self, userquotaid, printerid, datelimit) : 508 """Sets the limit date for a soft limit to become an hard one given (userid, printerid).""" 500 return self.getGroupPQuota(group, printer) 501 502 def writePrinterPrices(self, printer) : 503 """Write the printer's prices back into the storage.""" 504 fields = { 505 "pykotaPricePerPage" : str(printer.PricePerPage), 506 "pykotaPricePerJob" : str(printer.PricePerJob), 507 } 508 self.doModify(printer.ident, fields) 509 510 def writeUserLimitBy(self, user, limitby) : 511 """Sets the user's limiting factor.""" 512 fields = { 513 "pykotaLimitBy" : limitby, 514 } 515 self.doModify(user.ident, fields) 516 517 def writeGroupLimitBy(self, group, limitby) : 518 """Sets the group's limiting factor.""" 519 fields = { 520 "pykotaLimitBy" : limitby, 521 } 522 self.doModify(group.ident, fields) 523 524 def writeUserPQuotaDateLimit(self, userpquota, datelimit) : 525 """Sets the date limit permanently for a user print quota.""" 509 526 fields = { 510 527 "pykotaDateLimit" : "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second), 511 528 } 512 return self.doModify(user quotaid, fields)513 514 def setGroupDateLimit(self, groupquotaid, printerid, datelimit) :515 """Sets the limit date for a soft limit to become an hard one given (groupid, printerid)."""529 return self.doModify(userpquota.ident, fields) 530 531 def writeGroupPQuotaDateLimit(self, grouppquota, datelimit) : 532 """Sets the date limit permanently for a group print quota.""" 516 533 fields = { 517 534 "pykotaDateLimit" : "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second), 518 535 } 519 return self.doModify(groupquotaid, fields) 520 521 def addJobToHistory(self, jobid, userid, printerid, pagecounter, action, jobsize=None) : 522 """Adds a job to the history: (jobid, userid, printerid, last page counter taken from requester).""" 536 return self.doModify(grouppquota.ident, fields) 537 538 def writeUserPQuotaPagesCounters(self, userpquota, newpagecounter, newlifepagecounter) : 539 """Sets the new page counters permanently for a user print quota.""" 540 fields = { 541 "pykotaPageCounter" : str(newpagecounter), 542 "pykotaLifePageCounter" : str(newlifepagecounter), 543 } 544 return self.doModify(userpquota.ident, fields) 545 546 def writeUserAccountBalance(self, user, newbalance, newlifetimepaid=None) : 547 """Sets the new account balance and eventually new lifetime paid.""" 548 fields = { 549 "pykotaBalance" : str(newbalance), 550 } 551 if newlifetimepaid is not None : 552 fields.update({ "pykotaLifeTimePaid" : str(newlifetimepaid) }) 553 return self.doModify(user.idbalance, fields) 554 555 def writeLastJobSize(self, lastjob, jobsize) : 556 """Sets the last job's size permanently.""" 557 fields = { 558 "pykotaJobSize" : str(jobsize), 559 } 560 self.doModify(lastjob.ident, fields) 561 562 def writeJobNew(self, printer, user, jobid, pagecounter, action, jobsize=None) : 563 """Adds a job in a printer's history.""" 523 564 uuid = self.genUUID() 524 printername = self.getPrinterName(printerid)525 565 fields = { 526 566 "objectClass" : ["pykotaObject", "pykotaJob"], 527 567 "cn" : uuid, 528 "pykotaUserName" : self.getUserName(userid),529 "pykotaPrinterName" : printer name,568 "pykotaUserName" : user.Name, 569 "pykotaPrinterName" : printer.Name, 530 570 "pykotaJobId" : jobid, 531 571 "pykotaPrinterPageCounter" : str(pagecounter), … … 536 576 dn = "cn=%s,%s" % (uuid, self.info["jobbase"]) 537 577 self.doAdd(dn, fields) 538 result = self.doSearch("(&(objectClass=pykotaLastJob)(pykotaPrinterName=%s))" % printername, None, base=self.info["lastjobbase"]) 539 if result : 540 lastjdn = result[0][0] 578 if printer.LastJob.Exists : 541 579 fields = { 542 580 "pykotaLastJobIdent" : uuid, 543 581 } 544 self.doModify( lastjdn, fields)582 self.doModify(printer.LastJob.lastjobident, fields) 545 583 else : 546 584 lastjuuid = self.genUUID() … … 549 587 "objectClass" : ["pykotaObject", "pykotaLastJob"], 550 588 "cn" : lastjuuid, 551 "pykotaPrinterName" : printer name,589 "pykotaPrinterName" : printer.Name, 552 590 "pykotaLastJobIdent" : uuid, 553 591 } 554 592 self.doAdd(lastjdn, fields) 555 556 def updateJobSizeInHistory(self, historyid, jobsize) : 557 """Updates a job size in the history given the history line's id.""" 558 result = self.doSearch("(&(objectClass=pykotaJob)(cn=%s))" % historyid, ["cn"], base=self.info["jobbase"]) 559 if result : 560 fields = { 561 "pykotaJobSize" : str(jobsize), 562 } 563 self.doModify(result[0][0], fields) 564 565 def getPrinterPageCounter(self, printerid) : 566 """Returns the last page counter value for a printer given its id, also returns last username, last jobid and history line id.""" 567 result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName", self.info["printerrdn"]], base=printerid, scope=ldap.SCOPE_BASE) 593 594 def writeUserPQuotaLimits(self, userpquota, softlimit, hardlimit) : 595 """Sets soft and hard limits for a user quota.""" 596 fields = { 597 "pykotaSoftLimit" : str(softlimit), 598 "pykotaHardLimit" : str(hardlimit), 599 } 600 self.doModify(userpquota.ident, fields) 601 602 def writeGroupPQuotaLimits(self, grouppquota, softlimit, hardlimit) : 603 """Sets soft and hard limits for a group quota on a specific printer given (groupid, printerid).""" 604 fields = { 605 "pykotaSoftLimit" : str(softlimit), 606 "pykotaHardLimit" : str(hardlimit), 607 } 608 self.doModify(grouppquota.ident, fields) 609 610 def deleteUser(self, user) : 611 """Completely deletes an user from the Quota Storage.""" 612 # TODO : What should we do if we delete the last person who used a given printer ? 613 # TODO : we can't reassign the last job to the previous one, because next user would be 614 # TODO : incorrectly charged (overcharged). 615 result = self.doSearch("(&(objectClass=pykotaLastJob)(pykotaUserName=%s))" % user.Name, base=self.info["lastjobbase"]) 616 for (ident, fields) in result : 617 self.doDelete(ident) 618 result = self.doSearch("(&(objectClass=pykotaJob)(pykotaUserName=%s))" % user.Name, base=self.info["jobbase"]) 619 for (ident, fields) in result : 620 self.doDelete(ident) 621 result = self.doSearch("(&(objectClass=pykotaUserPQuota)(pykotaUserName=%s))" % user.Name, ["pykotaUserName"], base=self.info["userquotabase"]) 622 for (ident, fields) in result : 623 self.doDelete(ident) 624 result = self.doSearch("objectClass=pykotaAccount", None, base=user.ident, scope=ldap.SCOPE_BASE) 568 625 if result : 569 626 fields = result[0][1] 570 printername = (fields.get("pykotaPrinterName") or fields.get(self.info["printerrdn"]))[0] 571 result = self.doSearch("(&(objectClass=pykotaLastjob)(|(pykotaPrinterName=%s)(%s=%s)))" % (printername, self.info["printerrdn"], printername), ["pykotaLastJobIdent"], base=self.info["lastjobbase"]) 572 if result : 573 lastjobident = result[0][1]["pykotaLastJobIdent"][0] 574 result = self.doSearch("(&(objectClass=pykotaJob)(cn=%s))" % lastjobident, ["pykotaUserName", "pykotaPrinterName", "pykotaJobId", "pykotaPrinterPageCounter", "pykotaJobSize", "pykotaAction", "createTimestamp"], base=self.info["jobbase"]) 575 if result : 576 fields = result[0][1] 577 return { "id": lastjobident, 578 "jobid" : fields.get("pykotaJobId")[0], 579 "userid" : self.getUserId(fields.get("pykotaUserName")[0]), 580 "username" : fields.get("pykotaUserName")[0], 581 "pagecounter" : int(fields.get("pykotaPrinterPageCounter")[0]), 582 "jobsize" : int(fields.get("pykotaJobSize")[0]), 583 } 584 585 def addUserToGroup(self, userid, groupid) : 586 """Adds an user to a group.""" 587 raise PyKotaStorageError, "Not implemented !" 588 589 def deleteUser(self, userid) : 590 """Completely deletes an user from the Quota Storage.""" 591 raise PyKotaStorageError, "Not implemented !" 592 593 def deleteGroup(self, groupid) : 594 """Completely deletes an user from the Quota Storage.""" 595 raise PyKotaStorageError, "Not implemented !" 596 597 def computePrinterJobPrice(self, printerid, jobsize) : 598 """Returns the price for a job on a given printer.""" 599 # TODO : create a base class with things like this 600 prices = self.getPrinterPrices(printerid) 601 if prices is None : 602 perpage = perjob = 0.0 603 else : 604 (perpage, perjob) = prices 605 return perjob + (perpage * jobsize) 627 for k in fields.keys() : 628 if k.startswith("pykota") : 629 del fields[k] 630 elif k.lower() == "objectclass" : 631 todelete = [] 632 for i in range(len(fields[k])) : 633 if fields[k][i].startswith("pykota") : 634 todelete.append(i) 635 todelete.sort() 636 todelete.reverse() 637 for i in todelete : 638 del fields[k][i] 639 if fields.get("objectclass") : 640 self.doModify(user.ident, fields, ignoreold=0) 641 else : 642 self.doDelete(user.ident) 643 result = self.doSearch("(&(objectClass=pykotaAccountBalance)(pykotaUserName=%s))" % user.Name, ["pykotaUserName"], base=self.info["balancebase"]) 644 for (ident, fields) in result : 645 self.doDelete(ident) 646 647 def deleteGroup(self, group) : 648 """Completely deletes a group from the Quota Storage.""" 649 result = self.doSearch("(&(objectClass=pykotaGroupPQuota)(pykotaGroupName=%s))" % group.Name, ["pykotaGroupName"], base=self.info["groupquotabase"]) 650 for (ident, fields) in result : 651 self.doDelete(ident) 652 result = self.doSearch("objectClass=pykotaGroup", None, base=group.ident, scope=ldap.SCOPE_BASE) 653 if result : 654 fields = result[0][1] 655 for k in fields.keys() : 656 if k.startswith("pykota") : 657 del fields[k] 658 elif k.lower() == "objectclass" : 659 todelete = [] 660 for i in range(len(fields[k])) : 661 if fields[k][i].startswith("pykota") : 662 todelete.append(i) 663 todelete.sort() 664 todelete.reverse() 665 for i in todelete : 666 del fields[k][i] 667 if fields.get("objectclass") : 668 self.doModify(group.ident, fields, ignoreold=0) 669 else : 670 self.doDelete(group.ident) 671 -
pykota/trunk/pykota/storages/pgstorage.py
r1024 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.3 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.2 2003/06/12 21:09:57 jalet 24 27 # wrongly placed code. … … 34 37 # 35 38 36 import fnmatch37 38 39 from pykota.storage import PyKotaStorageError 40 from pykota.storage import StorageObject,StorageUser,StorageGroup,StoragePrinter,StorageLastJob,StorageUserPQuota,StorageGroupPQuota 39 41 40 42 try : … … 74 76 self.tool.logger.log_message("Database closed.", "debug") 75 77 76 def doQuery(self, query) : 77 """Does a query.""" 78 if type(query) in (type([]), type(())) : 79 query = ";".join(query) 78 def beginTransaction(self) : 79 """Starts a transaction.""" 80 self.database.query("BEGIN;") 81 if self.debug : 82 self.tool.logger.log_message("Transaction begins...", "debug") 83 84 def commitTransaction(self) : 85 """Commits a transaction.""" 86 self.database.query("COMMIT;") 87 if self.debug : 88 self.tool.logger.log_message("Transaction committed.", "debug") 89 90 def rollbackTransaction(self) : 91 """Rollbacks a transaction.""" 92 self.database.query("ROLLBACK;") 93 if self.debug : 94 self.tool.logger.log_message("Transaction aborted.", "debug") 95 96 def doSearch(self, query) : 97 """Does a search query.""" 80 98 query = query.strip() 81 99 if not query.endswith(';') : 82 100 query += ';' 83 self.database.query("BEGIN;")84 if self.debug :85 self.tool.logger.log_message("Transaction began.", "debug")86 101 try : 87 102 if self.debug : … … 89 104 result = self.database.query(query) 90 105 except pg.error, msg : 91 self.database.query("ROLLBACK;")92 if self.debug :93 self.tool.logger.log_message("Transaction aborted.", "debug")94 106 raise PyKotaStorageError, msg 95 107 else : 96 self.database.query("COMMIT;") 108 if (result is not None) and (result.ntuples() > 0) : 109 return result.dictresult() 110 111 def doModify(self, query) : 112 """Does a (possibly multiple) modify query.""" 113 query = query.strip() 114 if not query.endswith(';') : 115 query += ';' 116 try : 97 117 if self.debug : 98 self.tool.logger.log_message("Transaction committed.", "debug") 99 return result 100 118 self.tool.logger.log_message("QUERY : %s" % query, "debug") 119 result = self.database.query(query) 120 except pg.error, msg : 121 raise PyKotaStorageError, msg 122 101 123 def doQuote(self, field) : 102 124 """Quotes a field for use as a string in SQL queries.""" … … 109 131 return pg._quote(field, typ) 110 132 111 def doParseResult(self, result) : 112 """Returns the result as a list of Python mappings.""" 113 if (result is not None) and (result.ntuples() > 0) : 114 return result.dictresult() 115 133 def getUser(self, username) : 134 """Extracts user information given its name.""" 135 user = StorageUser(self, username) 136 result = self.doSearch("SELECT * FROM users WHERE username=%s LIMIT 1" % self.doQuote(username)) 137 if result : 138 fields = result[0] 139 user.ident = fields.get("id") 140 user.LimitBy = fields.get("limitby") 141 user.AccountBalance = fields.get("balance") 142 user.LifeTimePaid = fields.get("lifetimepaid") 143 user.Exists = 1 144 return user 145 146 def getGroup(self, groupname) : 147 """Extracts group information given its name.""" 148 group = StorageGroup(self, groupname) 149 result = self.doSearch("SELECT * FROM groups WHERE groupname=%s LIMIT 1" % self.doQuote(groupname)) 150 if result : 151 fields = result[0] 152 group.ident = fields.get("id") 153 group.LimitBy = fields.get("limitby") 154 result = self.doSearch("SELECT SUM(balance) AS balance, SUM(lifetimepaid) AS lifetimepaid FROM users WHERE id IN (SELECT userid FROM groupsmembers WHERE groupid=%s)" % self.doQuote(group.ident)) 155 if result : 156 fields = result[0] 157 group.AccountBalance = fields.get("balance") 158 group.LifeTimePaid = fields.get("lifetimepaid") 159 group.Exists = 1 160 return group 161 162 def getPrinter(self, printername) : 163 """Extracts printer information given its name.""" 164 printer = StoragePrinter(self, printername) 165 result = self.doSearch("SELECT * FROM printers WHERE printername=%s LIMIT 1" % self.doQuote(printername)) 166 if result : 167 fields = result[0] 168 printer.ident = fields.get("id") 169 printer.PricePerJob = fields.get("priceperjob") 170 printer.PricePerPage = fields.get("priceperpage") 171 printer.LastJob = self.getPrinterLastJob(printer) 172 printer.Exists = 1 173 return printer 174 175 def getUserGroups(self, user) : 176 """Returns the user's groups list.""" 177 groups = [] 178 result = self.doSearch("SELECT groupname FROM groupsmembers JOIN groups ON groupsmembers.groupid=groups.id WHERE userid=%s" % self.doQuote(user.ident)) 179 if result : 180 for record in result : 181 groups.append(self.getGroup(record.get("groupname"))) 182 return groups 183 184 def getGroupMembers(self, group) : 185 """Returns the group's members list.""" 186 groupmembers = [] 187 result = self.doSearch("SELECT * FROM groupsmembers JOIN users ON groupsmembers.userid=users.id WHERE groupid=%s" % self.doQuote(group.ident)) 188 if result : 189 for record in result : 190 user = StorageUser(self, record.get("username")) 191 user.ident = record.get("userid") 192 user.LimitBy = record.get("limitby") 193 user.AccountBalance = record.get("balance") 194 user.LifeTimePaid = record.get("lifetimepaid") 195 user.Exists = 1 196 groupmembers.append(user) 197 return groupmembers 198 199 def getUserPQuota(self, user, printer) : 200 """Extracts a user print quota.""" 201 userpquota = StorageUserPQuota(self, user, printer) 202 if user.Exists : 203 result = self.doSearch("SELECT id, lifepagecounter, pagecounter, softlimit, hardlimit, datelimit FROM userpquota WHERE userid=%s AND printerid=%s" % (self.doQuote(user.ident), self.doQuote(printer.ident))) 204 if result : 205 fields = result[0] 206 userpquota.ident = fields.get("id") 207 userpquota.PageCounter = fields.get("pagecounter") 208 userpquota.LifePageCounter = fields.get("lifepagecounter") 209 userpquota.SoftLimit = fields.get("softlimit") 210 userpquota.HardLimit = fields.get("hardlimit") 211 userpquota.DateLimit = fields.get("datelimit") 212 userpquota.Exists = 1 213 return userpquota 214 215 def getGroupPQuota(self, group, printer) : 216 """Extracts a group print quota.""" 217 grouppquota = StorageGroupPQuota(self, group, printer) 218 if group.Exists : 219 result = self.doSearch("SELECT id, softlimit, hardlimit, datelimit FROM grouppquota WHERE groupid=%s AND printerid=%s" % (self.doQuote(group.ident), self.doQuote(printer.ident))) 220 if result : 221 fields = result[0] 222 grouppquota.ident = fields.get("id") 223 grouppquota.SoftLimit = fields.get("softlimit") 224 grouppquota.HardLimit = fields.get("hardlimit") 225 grouppquota.DateLimit = fields.get("datelimit") 226 result = self.doSearch("SELECT SUM(lifepagecounter) AS lifepagecounter, SUM(pagecounter) AS pagecounter FROM userpquota WHERE printerid=%s AND userid IN (SELECT userid FROM groupsmembers WHERE groupid=%s)" % (self.doQuote(printer.ident), self.doQuote(group.ident))) 227 if result : 228 fields = result[0] 229 grouppquota.PageCounter = fields.get("pagecounter") 230 grouppquota.LifePageCounter = fields.get("lifepagecounter") 231 grouppquota.Exists = 1 232 return grouppquota 233 234 def getPrinterLastJob(self, printer) : 235 """Extracts a printer's last job information.""" 236 lastjob = StorageLastJob(self, printer) 237 result = self.doSearch("SELECT jobhistory.id, jobid, userid, username, pagecounter, jobsize, jobdate FROM jobhistory, users WHERE printerid=%s AND userid=users.id ORDER BY jobdate DESC LIMIT 1" % self.doQuote(printer.ident)) 238 if result : 239 fields = result[0] 240 lastjob.ident = fields.get("id") 241 lastjob.JobId = fields.get("jobid") 242 lastjob.User = self.getUser(fields.get("username")) 243 lastjob.PrinterPageCounter = fields.get("pagecounter") 244 lastjob.JobSize = fields.get("jobsize") 245 lastjob.JobAction = fields.get("action") 246 lastjob.JobDate = fields.get("jobdate") 247 lastjob.Exists = 1 248 return lastjob 249 116 250 def getMatchingPrinters(self, printerpattern) : 117 """Returns the list of all printers as tuples (id, name) for printer names which matcha certain pattern."""118 printers list= []251 """Returns the list of all printers for which name matches a certain pattern.""" 252 printers = [] 119 253 # We 'could' do a SELECT printername FROM printers WHERE printername LIKE ... 120 254 # but we don't because other storages semantics may be different, so every 121 255 # storage should use fnmatch to match patterns and be storage agnostic 122 result = self.doQuery("SELECT id, printername FROM printers") 123 result = self.doParseResult(result) 124 if result is not None : 125 for printer in result : 126 if fnmatch.fnmatchcase(printer["printername"], printerpattern) : 127 printerslist.append((printer["id"], printer["printername"])) 128 return printerslist 129 130 def getPrinterId(self, printername) : 131 """Returns a printerid given a printername.""" 132 result = self.doQuery("SELECT id FROM printers WHERE printername=%s" % self.doQuote(printername)) 133 try : 134 return self.doParseResult(result)[0]["id"] 135 except TypeError : # Not found 136 return 137 138 def getPrinterPrices(self, printerid) : 139 """Returns a printer prices per page and per job given a printerid.""" 140 result = self.doQuery("SELECT priceperpage, priceperjob FROM printers WHERE id=%s" % self.doQuote(printerid)) 141 try : 142 printerprices = self.doParseResult(result)[0] 143 return (printerprices["priceperpage"], printerprices["priceperjob"]) 144 except TypeError : # Not found 145 return 146 147 def setPrinterPrices(self, printerid, perpage, perjob) : 148 """Sets prices per job and per page for a given printer.""" 149 self.doQuery("UPDATE printers SET priceperpage=%s, priceperjob=%s WHERE id=%s" % (self.doQuote(perpage), self.doQuote(perjob), self.doQuote(printerid))) 150 151 def getUserId(self, username) : 152 """Returns a userid given a username.""" 153 result = self.doQuery("SELECT id FROM users WHERE username=%s" % self.doQuote(username)) 154 try : 155 return self.doParseResult(result)[0]["id"] 156 except TypeError : # Not found 157 return 158 159 def getGroupId(self, groupname) : 160 """Returns a groupid given a grupname.""" 161 result = self.doQuery("SELECT id FROM groups WHERE groupname=%s" % self.doQuote(groupname)) 162 try : 163 return self.doParseResult(result)[0]["id"] 164 except TypeError : # Not found 165 return 166 167 def getJobHistoryId(self, jobid, userid, printerid) : 168 """Returns the history line's id given a (jobid, userid, printerid).""" 169 result = self.doQuery("SELECT id FROM jobhistory WHERE jobid=%s AND userid=%s AND printerid=%s" % (self.doQuote(jobid), self.doQuote(userid), self.doQuote(printerid))) 170 try : 171 return self.doParseResult(result)[0]["id"] 172 except TypeError : # Not found 173 return 174 175 def getPrinterUsers(self, printerid) : 176 """Returns the list of userids and usernames which uses a given printer.""" 177 result = self.doQuery("SELECT DISTINCT id, username FROM users WHERE id IN (SELECT userid FROM userpquota WHERE printerid=%s) ORDER BY username" % self.doQuote(printerid)) 178 result = self.doParseResult(result) 179 if result is None : 180 return [] 181 else : 182 return [(record["id"], record["username"]) for record in result] 183 184 def getPrinterGroups(self, printerid) : 185 """Returns the list of groups which uses a given printer.""" 186 result = self.doQuery("SELECT DISTINCT id, groupname FROM groups WHERE id IN (SELECT groupid FROM grouppquota WHERE printerid=%s)" % self.doQuote(printerid)) 187 result = self.doParseResult(result) 188 if result is None : 189 return [] 190 else : 191 return [(record["id"], record["groupname"]) for record in result] 192 193 def getGroupMembersNames(self, groupname) : 194 """Returns the list of user's names which are member of this group.""" 195 groupid = self.getGroupId(groupname) 196 if groupid is None : 197 return [] 198 else : 199 result = self.doQuery("SELECT DISTINCT username FROM users WHERE id IN (SELECT userid FROM groupsmembers WHERE groupid=%s)" % self.doQuote(groupid)) 200 return [record["username"] for record in (self.doParseResult(result) or [])] 201 202 def getUserGroupsNames(self, userid) : 203 """Returns the list of groups' names the user is a member of.""" 204 result = self.doQuery("SELECT DISTINCT groupname FROM groups WHERE id IN (SELECT groupid FROM groupsmembers WHERE userid=%s)" % self.doQuote(userid)) 205 return [record["groupname"] for record in (self.doParseResult(result) or [])] 256 result = self.doSearch("SELECT * FROM printers") 257 if result : 258 for record in result : 259 if self.tool.matchString(record["printername"], [ printerpattern ]) : 260 printer = StoragePrinter(self, record["printername"]) 261 printer.ident = record.get("id") 262 printer.PricePerJob = record.get("priceperjob") 263 printer.PricePerPage = record.get("priceperpage") 264 printer.LastJob = self.getPrinterLastJob(printer) 265 printer.Exists = 1 266 printers.append(printer) 267 return printers 268 269 def getPrinterUsersAndQuotas(self, printer, names=None) : 270 """Returns the list of users who uses a given printer, along with their quotas.""" 271 usersandquotas = [] 272 result = self.doSearch("SELECT users.id as uid,username,balance,lifetimepaid,limitby,userpquota.id,lifepagecounter,pagecounter,softlimit,hardlimit,datelimit FROM users JOIN userpquota ON users.id=userpquota.userid AND printerid=%s" % self.doQuote(printer.ident)) 273 if result : 274 for record in result : 275 user = StorageUser(self, record.get("username")) 276 if (names is None) or self.tool.matchString(user.Name, names) : 277 user.ident = record.get("uid") 278 user.LimitBy = record.get("limitby") 279 user.AccountBalance = record.get("balance") 280 user.LifeTimePaid = record.get("lifetimepaid") 281 user.Exists = 1 282 userpquota = StorageUserPQuota(self, user, printer) 283 userpquota.ident = record.get("id") 284 userpquota.PageCounter = record.get("pagecounter") 285 userpquota.LifePageCounter = record.get("lifepagecounter") 286 userpquota.SoftLimit = record.get("softlimit") 287 userpquota.HardLimit = record.get("hardlimit") 288 userpquota.DateLimit = record.get("datelimit") 289 userpquota.Exists = 1 290 usersandquotas.append((user, userpquota)) 291 return usersandquotas 292 293 def getPrinterGroupsAndQuotas(self, printer, names=None) : 294 """Returns the list of groups which uses a given printer, along with their quotas.""" 295 groupsandquotas = [] 296 result = self.doSearch("SELECT groupname FROM groups JOIN grouppquota ON groups.id=grouppquota.groupid AND printerid=%s" % self.doQuote(printer.ident)) 297 if result : 298 for record in result : 299 group = self.getGroup(record.get("groupname")) 300 if (names is None) or self.tool.matchString(group.Name, names) : 301 grouppquota = self.getGroupPQuota(group, printer) 302 groupsandquotas.append((group, grouppquota)) 303 return groupsandquotas 206 304 207 305 def addPrinter(self, printername) : 208 """Adds a printer to the quota storage, returns it s id."""209 self.do Query("INSERT INTO printers (printername) VALUES (%s)" % self.doQuote(printername))210 return self.getPrinter Id(printername)211 212 def addUser(self, user name) :306 """Adds a printer to the quota storage, returns it.""" 307 self.doModify("INSERT INTO printers (printername) VALUES (%s)" % self.doQuote(printername)) 308 return self.getPrinter(printername) 309 310 def addUser(self, user) : 213 311 """Adds a user to the quota storage, returns its id.""" 214 self.do Query("INSERT INTO users (username) VALUES (%s)" % self.doQuote(username))215 return self.getUser Id(username)216 217 def addGroup(self, group name) :312 self.doModify("INSERT INTO users (username, limitby, balance, lifetimepaid) VALUES (%s, %s, %s, %s)" % (self.doQuote(user.Name), self.doQuote(user.LimitBy), self.doQuote(user.AccountBalance), self.doQuote(user.LifeTimePaid))) 313 return self.getUser(user.Name) 314 315 def addGroup(self, group) : 218 316 """Adds a group to the quota storage, returns its id.""" 219 self.doQuery("INSERT INTO groups (groupname) VALUES (%s)" % self.doQuote(groupname)) 220 return self.getGroupId(groupname) 221 222 def addUserPQuota(self, username, printerid) : 223 """Initializes a user print quota on a printer, adds the user to the quota storage if needed.""" 224 userid = self.getUserId(username) 225 if userid is None : 226 userid = self.addUser(username) 227 uqexists = (self.getUserPQuota(userid, printerid) is not None) 228 if not uqexists : 229 self.doQuery("INSERT INTO userpquota (userid, printerid) VALUES (%s, %s)" % (self.doQuote(userid), self.doQuote(printerid))) 230 return (userid, printerid) 231 232 def addGroupPQuota(self, groupname, printerid) : 233 """Initializes a group print quota on a printer, adds the group to the quota storage if needed.""" 234 groupid = self.getGroupId(groupname) 235 if groupid is None : 236 groupid = self.addGroup(groupname) 237 gqexists = (self.getGroupPQuota(groupid, printerid) is not None) 238 if not gqexists : 239 self.doQuery("INSERT INTO grouppquota (groupid, printerid) VALUES (%s, %s)" % (self.doQuote(groupid), self.doQuote(printerid))) 240 return (groupid, printerid) 241 242 def increaseUserBalance(self, userid, amount) : 243 """Increases (or decreases) an user's account balance by a given amount.""" 244 self.doQuery("UPDATE users SET balance=balance+(%s), lifetimepaid=lifetimepaid+(%s) WHERE id=%s" % (self.doQuote(amount), self.doQuote(amount), self.doQuote(userid))) 245 246 def getUserBalance(self, userid) : 247 """Returns the current account balance for a given user.""" 248 result = self.doQuery("SELECT balance, lifetimepaid FROM users WHERE id=%s" % self.doQuote(userid)) 249 try : 250 result = self.doParseResult(result)[0] 251 except TypeError : # Not found 252 return 253 else : 254 return (result["balance"], result["lifetimepaid"]) 255 256 def getGroupBalance(self, groupid) : 257 """Returns the current account balance for a given group, as the sum of each of its users' account balance.""" 258 result = self.doQuery("SELECT SUM(balance) AS balance, SUM(lifetimepaid) AS lifetimepaid FROM users WHERE id in (SELECT userid FROM groupsmembers WHERE groupid=%s)" % self.doQuote(groupid)) 259 try : 260 result = self.doParseResult(result)[0] 261 except TypeError : # Not found 262 return 263 else : 264 return (result["balance"], result["lifetimepaid"]) 265 266 def getUserLimitBy(self, userid) : 267 """Returns the way in which user printing is limited.""" 268 result = self.doQuery("SELECT limitby FROM users WHERE id=%s" % self.doQuote(userid)) 269 try : 270 return self.doParseResult(result)[0]["limitby"] 271 except TypeError : # Not found 272 return 273 274 def getGroupLimitBy(self, groupid) : 275 """Returns the way in which group printing is limited.""" 276 result = self.doQuery("SELECT limitby FROM groups WHERE id=%s" % self.doQuote(groupid)) 277 try : 278 return self.doParseResult(result)[0]["limitby"] 279 except TypeError : # Not found 280 return 281 282 def setUserBalance(self, userid, balance) : 283 """Sets the account balance for a given user to a fixed value.""" 284 (current, lifetimepaid) = self.getUserBalance(userid) 285 difference = balance - current 286 self.increaseUserBalance(userid, difference) 287 288 def limitUserBy(self, userid, limitby) : 289 """Limits a given user based either on print quota or on account balance.""" 290 self.doQuery("UPDATE users SET limitby=%s WHERE id=%s" % (self.doQuote(limitby), self.doQuote(userid))) 291 292 def limitGroupBy(self, groupid, limitby) : 293 """Limits a given group based either on print quota or on sum of its users' account balances.""" 294 self.doQuery("UPDATE groups SET limitby=%s WHERE id=%s" % (self.doQuote(limitby), self.doQuote(groupid))) 295 296 def setUserPQuota(self, userid, printerid, softlimit, hardlimit) : 297 """Sets soft and hard limits for a user quota on a specific printer given (userid, printerid).""" 298 self.doQuery("UPDATE userpquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE userid=%s AND printerid=%s" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(userid), self.doQuote(printerid))) 299 300 def setGroupPQuota(self, groupid, printerid, softlimit, hardlimit) : 301 """Sets soft and hard limits for a group quota on a specific printer given (groupid, printerid).""" 302 self.doQuery("UPDATE grouppquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE groupid=%s AND printerid=%s" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(groupid), self.doQuote(printerid))) 303 304 def resetUserPQuota(self, userid, printerid) : 305 """Resets the page counter to zero for a user on a printer. Life time page counter is kept unchanged.""" 306 self.doQuery("UPDATE userpquota SET pagecounter=0, datelimit=NULL WHERE userid=%s AND printerid=%s" % (self.doQuote(userid), self.doQuote(printerid))) 307 308 def resetGroupPQuota(self, groupid, printerid) : 309 """Resets the page counter to zero for a group on a printer. Life time page counter is kept unchanged.""" 310 self.doQuery("UPDATE grouppquota SET pagecounter=0, datelimit=NULL WHERE groupid=%s AND printerid=%s" % (self.doQuote(groupid), self.doQuote(printerid))) 311 312 def updateUserPQuota(self, userid, printerid, pagecount) : 313 """Updates the used user Quota information given (userid, printerid) and a job size in pages.""" 314 jobprice = self.computePrinterJobPrice(printerid, pagecount) 315 queries = [] 316 queries.append("UPDATE userpquota SET lifepagecounter=lifepagecounter+(%s), pagecounter=pagecounter+(%s) WHERE userid=%s AND printerid=%s" % (self.doQuote(pagecount), self.doQuote(pagecount), self.doQuote(userid), self.doQuote(printerid))) 317 queries.append("UPDATE users SET balance=balance-(%s) WHERE id=%s" % (self.doQuote(jobprice), self.doQuote(userid))) 318 self.doQuery(queries) 319 320 def getUserPQuota(self, userid, printerid) : 321 """Returns the Print Quota information for a given (userid, printerid).""" 322 result = self.doQuery("SELECT lifepagecounter, pagecounter, softlimit, hardlimit, datelimit FROM userpquota WHERE userid=%s AND printerid=%s" % (self.doQuote(userid), self.doQuote(printerid))) 323 try : 324 return self.doParseResult(result)[0] 325 except TypeError : # Not found 326 return 327 328 def getGroupPQuota(self, groupid, printerid) : 329 """Returns the Print Quota information for a given (groupid, printerid).""" 330 result = self.doQuery("SELECT softlimit, hardlimit, datelimit FROM grouppquota WHERE groupid=%s AND printerid=%s" % (self.doQuote(groupid), self.doQuote(printerid))) 331 try : 332 grouppquota = self.doParseResult(result)[0] 333 except TypeError : 334 return 335 else : 336 result = self.doQuery("SELECT SUM(lifepagecounter) as lifepagecounter, SUM(pagecounter) as pagecounter FROM userpquota WHERE printerid=%s AND userid in (SELECT userid FROM groupsmembers WHERE groupid=%s)" % (self.doQuote(printerid), self.doQuote(groupid))) 337 try : 338 result = self.doParseResult(result)[0] 339 except TypeError : # Not found 340 return 341 else : 342 grouppquota.update({"lifepagecounter": result["lifepagecounter"], "pagecounter": result["pagecounter"]}) 343 return grouppquota 344 345 def setUserDateLimit(self, userid, printerid, datelimit) : 346 """Sets the limit date for a soft limit to become an hard one given (userid, printerid).""" 347 self.doQuery("UPDATE userpquota SET datelimit=%s::TIMESTAMP WHERE userid=%s AND printerid=%s" % (self.doQuote("%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second)), self.doQuote(userid), self.doQuote(printerid))) 348 349 def setGroupDateLimit(self, groupid, printerid, datelimit) : 350 """Sets the limit date for a soft limit to become an hard one given (groupid, printerid).""" 351 self.doQuery("UPDATE grouppquota SET datelimit=%s::TIMESTAMP WHERE groupid=%s AND printerid=%s" % (self.doQuote("%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second)), self.doQuote(groupid), self.doQuote(printerid))) 352 353 def addJobToHistory(self, jobid, userid, printerid, pagecounter, action, jobsize=None) : 354 """Adds a job to the history: (jobid, userid, printerid, last page counter taken from requester).""" 355 self.doQuery("INSERT INTO jobhistory (jobid, userid, printerid, pagecounter, action, jobsize) VALUES (%s, %s, %s, %s, %s, %s)" % (self.doQuote(jobid), self.doQuote(userid), self.doQuote(printerid), self.doQuote(pagecounter), self.doQuote(action), self.doQuote(jobsize))) 356 return self.getJobHistoryId(jobid, userid, printerid) # in case jobid is not sufficient 357 358 def updateJobSizeInHistory(self, historyid, jobsize) : 359 """Updates a job size in the history given the history line's id.""" 360 self.doQuery("UPDATE jobhistory SET jobsize=%s WHERE id=%s" % (self.doQuote(jobsize), self.doQuote(historyid))) 361 362 def getPrinterPageCounter(self, printerid) : 363 """Returns the last page counter value for a printer given its id, also returns last username, last jobid and history line id.""" 364 result = self.doQuery("SELECT jobhistory.id, jobid, userid, username, pagecounter, jobsize FROM jobhistory, users WHERE printerid=%s AND userid=users.id ORDER BY jobdate DESC LIMIT 1" % self.doQuote(printerid)) 365 try : 366 return self.doParseResult(result)[0] 367 except TypeError : # Not found 368 return 369 370 def addUserToGroup(self, userid, groupid) : 317 self.doModify("INSERT INTO groups (groupname, limitby) VALUES (%s, %s)" % (self.doQuote(group.Name), self.doQuote(group.LimitBy))) 318 return self.getGroup(group.Name) 319 320 def addUserToGroup(self, user, group) : 371 321 """Adds an user to a group.""" 372 result = self.do Query("SELECT COUNT(*) AS mexists FROM groupsmembers WHERE groupid=%s AND userid=%s" % (self.doQuote(groupid), self.doQuote(userid)))322 result = self.doModify("SELECT COUNT(*) AS mexists FROM groupsmembers WHERE groupid=%s AND userid=%s" % (self.doQuote(group.ident), self.doQuote(user.ident))) 373 323 try : 374 324 mexists = self.doParseResult(result)[0]["mexists"] … … 376 326 mexists = 0 377 327 if not mexists : 378 self.doQuery("INSERT INTO groupsmembers (groupid, userid) VALUES (%s, %s)" % (self.doQuote(groupid), self.doQuote(userid))) 379 380 def deleteUser(self, userid) : 328 self.doModify("INSERT INTO groupsmembers (groupid, userid) VALUES (%s, %s)" % (self.doQuote(group.ident), self.doQuote(user.ident))) 329 330 def addUserPQuota(self, user, printer) : 331 """Initializes a user print quota on a printer.""" 332 self.doModify("INSERT INTO userpquota (userid, printerid) VALUES (%s, %s)" % (self.doQuote(user.ident), self.doQuote(printer.ident))) 333 return self.getUserPQuota(user, printer) 334 335 def addGroupPQuota(self, group, printer) : 336 """Initializes a group print quota on a printer.""" 337 self.doModify("INSERT INTO grouppquota (groupid, printerid) VALUES (%s, %s)" % (self.doQuote(group.ident), self.doQuote(printer.ident))) 338 return self.getGroupPQuota(group, printer) 339 340 def writePrinterPrices(self, printer) : 341 """Write the printer's prices back into the storage.""" 342 self.doModify("UPDATE printers SET priceperpage=%s, priceperjob=%s WHERE printerid=%s" % (self.doQuote(printer.PricePerPage), self.doQuote(printer.PricePerJob), self.doQuote(printer.ident))) 343 344 def writeUserLimitBy(self, user, limitby) : 345 """Sets the user's limiting factor.""" 346 self.doModify("UPDATE users SET limitby=%s WHERE id=%s" % (self.doQuote(limitby), self.doQuote(user.ident))) 347 348 def writeGroupLimitBy(self, group, limitby) : 349 """Sets the group's limiting factor.""" 350 self.doModify("UPDATE groups SET limitby=%s WHERE id=%s" % (self.doQuote(limitby), self.doQuote(group.ident))) 351 352 def writeUserPQuotaDateLimit(self, userpquota, datelimit) : 353 """Sets the date limit permanently for a user print quota.""" 354 self.doModify("UPDATE userpquota SET datelimit::TIMESTAMP=%s WHERE id=%s" % (self.doQuote(datelimit), self.doQuote(userpquota.ident))) 355 356 def writeGroupPQuotaDateLimit(self, grouppquota, datelimit) : 357 """Sets the date limit permanently for a group print quota.""" 358 self.doModify("UPDATE grouppquota SET datelimit::TIMESTAMP=%s WHERE id=%s" % (self.doQuote(datelimit), self.doQuote(grouppquota.ident))) 359 360 def writeUserPQuotaPagesCounters(self, userpquota, newpagecounter, newlifepagecounter) : 361 """Sets the new page counters permanently for a user print quota.""" 362 self.doModify("UPDATE userpquota SET pagecounter=%s,lifepagecounter=%s WHERE id=%s" % (self.doQuote(newpagecounter), self.doQuote(newlifepagecounter), self.doQuote(userpquota.ident))) 363 364 def writeUserAccountBalance(self, user, newbalance, newlifetimepaid=None) : 365 """Sets the new account balance and eventually new lifetime paid.""" 366 if newlifetimepaid is not None : 367 self.doModify("UPDATE users SET balance=%s, lifetimepaid=%s WHERE id=%s" % (self.doQuote(newbalance), self.doQuote(newlifetimepaid), self.doQuote(user.ident))) 368 else : 369 self.doModify("UPDATE users SET balance=%s WHERE id=%s" % (self.doQuote(newbalance), self.doQuote(user.ident))) 370 371 def writeLastJobSize(self, lastjob, jobsize) : 372 """Sets the last job's size permanently.""" 373 self.doModify("UPDATE jobhistory SET jobsize=%s WHERE id=%s" % (self.doQuote(jobsize), self.doQuote(lastjob.ident))) 374 375 def writeJobNew(self, printer, user, jobid, pagecounter, action, jobsize=None) : 376 """Adds a job in a printer's history.""" 377 if jobsize is not None : 378 self.doModify("INSERT INTO jobhistory (userid, printerid, jobid, pagecounter, action, jobsize) VALUES (%s, %s, %s, %s, %s, %s)" % (self.doQuote(user.ident), self.doQuote(printer.ident), self.doQuote(jobid), self.doQuote(pagecounter), self.doQuote(action), self.doQuote(jobsize))) 379 else : 380 self.doModify("INSERT INTO jobhistory (userid, printerid, jobid, pagecounter, action) VALUES (%s, %s, %s, %s, %s)" % (self.doQuote(user.ident), self.doQuote(printer.ident), self.doQuote(jobid), self.doQuote(pagecounter), self.doQuote(action))) 381 382 def writeUserPQuotaLimits(self, userpquota, softlimit, hardlimit) : 383 """Sets soft and hard limits for a user quota.""" 384 self.doModify("UPDATE userpquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE id=%s" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(userpquota.ident))) 385 386 def writeGroupPQuotaLimits(self, grouppquota, softlimit, hardlimit) : 387 """Sets soft and hard limits for a group quota on a specific printer given (groupid, printerid).""" 388 self.doModify("UPDATE grouppquota SET softlimit=%s, hardlimit=%s, datelimit=NULL WHERE id=%s" % (self.doQuote(softlimit), self.doQuote(hardlimit), self.doQuote(grouppquota.ident))) 389 390 def deleteUser(self, user) : 381 391 """Completely deletes an user from the Quota Storage.""" 382 queries = []383 queries.append("DELETE FROM groupsmembers WHERE userid=%s" % self.doQuote(userid))384 queries.append("DELETE FROM jobhistory WHERE userid=%s" % self.doQuote(userid))385 queries.append("DELETE FROM userpquota WHERE userid=%s" % self.doQuote(userid))386 queries.append("DELETE FROM users WHERE id=%s" % self.doQuote(userid))387 392 # TODO : What should we do if we delete the last person who used a given printer ? 388 self.doQuery(queries) 389 390 def deleteGroup(self, groupid) : 391 """Completely deletes an user from the Quota Storage.""" 392 queries = [] 393 queries.append("DELETE FROM groupsmembers WHERE groupid=%s" % self.doQuote(groupid)) 394 queries.append("DELETE FROM grouppquota WHERE groupid=%s" % self.doQuote(groupid)) 395 queries.append("DELETE FROM groups WHERE id=%s" % self.doQuote(groupid)) 396 self.doQuery(queries) 397 398 def computePrinterJobPrice(self, printerid, jobsize) : 399 """Returns the price for a job on a given printer.""" 400 # TODO : create a base class with things like this 401 prices = self.getPrinterPrices(printerid) 402 if prices is None : 403 perpage = perjob = 0.0 404 else : 405 (perpage, perjob) = prices 406 return perjob + (perpage * jobsize) 407 393 # TODO : we can't reassign the last job to the previous one, because next user would be 394 # TODO : incorrectly charged (overcharged). 395 for q in [ 396 "DELETE FROM groupsmembers WHERE userid=%s" % self.doQuote(user.ident), 397 "DELETE FROM jobhistory WHERE userid=%s" % self.doQuote(user.ident), 398 "DELETE FROM userpquota WHERE userid=%s" % self.doQuote(user.ident), 399 "DELETE FROM users WHERE id=%s" % self.doQuote(user.ident), 400 ] : 401 self.doModify(q) 402 403 def deleteGroup(self, group) : 404 """Completely deletes a group from the Quota Storage.""" 405 for q in [ 406 "DELETE FROM groupsmembers WHERE groupid=%s" % self.doQuote(group.ident), 407 "DELETE FROM grouppquota WHERE groupid=%s" % self.doQuote(group.ident), 408 "DELETE FROM groups WHERE id=%s" % self.doQuote(group.ident), 409 ] : 410 self.doModify(q) 411 -
pykota/trunk/pykota/tool.py
r1021 r1041 21 21 # 22 22 # $Log$ 23 # Revision 1.41 2003/06/25 14:10:01 jalet 24 # Hey, it may work (edpykota --reset excepted) ! 25 # 23 26 # Revision 1.40 2003/06/10 16:37:54 jalet 24 27 # Deletion of the second user which is not needed anymore. … … 305 308 touser = "%s@%s" % (touser, self.smtpserver) 306 309 server = smtplib.SMTP(self.smtpserver) 307 server.sendmail(adminmail, [touser], fullmessage) 310 try : 311 server.sendmail(adminmail, [touser], fullmessage) 312 except smtplib.SMTPRecipientsRefused, answer : 313 for (k, v) in answer.recipients.items() : 314 self.logger.log_message(_("Impossible to send mail to %s, error %s : %s") % (k, v[0], v[1]), "error") 308 315 server.quit() 309 316 … … 317 324 self.sendMessage(adminmail, adminmail, "Subject: %s\n\n%s" % (subject, message)) 318 325 319 def checkGroupPQuota(self, group name, printername) :326 def checkGroupPQuota(self, grouppquota) : 320 327 """Checks the group quota on a printer and deny or accept the job.""" 321 printerid = self.storage.getPrinterId(printername) 322 policy = self.config.getPrinterPolicy(printername) 323 groupid = self.storage.getGroupId(groupname) 324 limitby = self.storage.getGroupLimitBy(groupid) 325 if limitby == "balance" : 326 balance = self.storage.getGroupBalance(groupid) 327 if balance is None : 328 group = grouppquota.Group 329 printer = grouppquota.Printer 330 if group.LimitBy.lower() == "balance" : 331 # TODO : there's no warning (no account balance soft limit) 332 if float(group.AccountBalance) <= 0.0 : 333 action = "DENY" 334 else : 335 action = "ALLOW" 336 else : 337 if grouppquota.SoftLimit is not None : 338 softlimit = int(grouppquota.SoftLimit) 339 if grouppquota.PageCounter < softlimit : 340 action = "ALLOW" 341 else : 342 if grouppquota.HardLimit is None : 343 # only a soft limit, this is equivalent to having only a hard limit 344 action = "DENY" 345 else : 346 hardlimit = int(grouppquota.HardLimit) 347 if softlimit <= grouppquota.PageCounter < hardlimit : 348 now = DateTime.now() 349 if grouppquota.DateLimit is not None : 350 datelimit = DateTime.ISO.ParseDateTime(grouppquota.DateLimit) 351 else : 352 datelimit = now + self.config.getGraceDelay(printer.Name) 353 grouppquota.setDateLimit(datelimit) 354 if now < datelimit : 355 action = "WARN" 356 else : 357 action = "DENY" 358 else : 359 action = "DENY" 360 else : 361 if grouppquota.HardLimit is not None : 362 # no soft limit, only a hard one. 363 hardlimit = int(grouppquota.HardLimit) 364 if grouppquota.PageCounter < hardlimit : 365 action = "ALLOW" 366 else : 367 action = "DENY" 368 else : 369 # Both are unset, no quota, i.e. accounting only 370 action = "ALLOW" 371 return action 372 373 def checkUserPQuota(self, userpquota) : 374 """Checks the user quota on a printer and deny or accept the job.""" 375 user = userpquota.User 376 printer = userpquota.Printer 377 378 # first we check any group the user is a member of 379 for group in self.storage.getUserGroups(user) : 380 grouppquota = self.storage.getGroupPQuota(group, printer) 381 if grouppquota.Exists : 382 action = self.checkGroupPQuota(grouppquota) 383 if action == "DENY" : 384 return action 385 386 # then we check the user's own quota 387 policy = self.config.getPrinterPolicy(printer.Name) 388 if user.LimitBy.lower() == "balance" : 389 if user.AccountBalance is None : 328 390 if policy == "ALLOW" : 329 391 action = "POLICY_ALLOW" 330 392 else : 331 393 action = "POLICY_DENY" 332 self.logger.log_message(_("Unable to find group %s's account balance, applying default policy (%s) for printer %s") % (groupname, action, printername))394 self.logger.log_message(_("Unable to find user %s's account balance, applying default policy (%s) for printer %s") % (user.Name, action, printer.Name)) 333 395 else : 334 396 # TODO : there's no warning (no account balance soft limit) 335 (balance, lifetimepaid) = balance 336 if balance <= 0.0 : 397 if float(user.AccountBalance or 0.0) <= 0.0 : 337 398 action = "DENY" 338 399 else : 339 400 action = "ALLOW" 340 401 else : 341 quota = self.storage.getGroupPQuota(groupid, printerid) 342 if quota is None : 343 # Unknown group or printer or combination 402 if not userpquota.Exists : 403 # Unknown userquota 344 404 if policy == "ALLOW" : 345 405 action = "POLICY_ALLOW" 346 406 else : 347 407 action = "POLICY_DENY" 348 self.logger.log_message(_("Unable to match group %s on printer %s, applying default policy (%s)") % (groupname, printername, action))408 self.logger.log_message(_("Unable to match user %s on printer %s, applying default policy (%s)") % (user.Name, printer.Name, action)) 349 409 else : 350 pagecounter = quota["pagecounter"] 351 softlimit = quota["softlimit"] 352 hardlimit = quota["hardlimit"] 353 datelimit = quota["datelimit"] 354 if softlimit is not None : 410 pagecounter = int(userpquota.PageCounter or 0) 411 if userpquota.SoftLimit is not None : 412 softlimit = int(userpquota.SoftLimit) 355 413 if pagecounter < softlimit : 356 414 action = "ALLOW" 357 415 else : 358 if hardlimit is None :416 if userpquota.HardLimit is None : 359 417 # only a soft limit, this is equivalent to having only a hard limit 360 418 action = "DENY" 361 419 else : 420 hardlimit = int(userpquota.HardLimit) 362 421 if softlimit <= pagecounter < hardlimit : 363 422 now = DateTime.now() 364 if datelimit is not None :365 datelimit = DateTime.ISO.ParseDateTime( datelimit)423 if userpquota.DateLimit is not None : 424 datelimit = DateTime.ISO.ParseDateTime(userpquota.DateLimit) 366 425 else : 367 datelimit = now + self.config.getGraceDelay(printer name)368 self.storage.setGroupDateLimit(groupid, printerid,datelimit)426 datelimit = now + self.config.getGraceDelay(printer.Name) 427 userpquota.setDateLimit(datelimit) 369 428 if now < datelimit : 370 429 action = "WARN" … … 374 433 action = "DENY" 375 434 else : 376 if hardlimit is not None :435 if userpquota.HardLimit is not None : 377 436 # no soft limit, only a hard one. 437 hardlimit = int(userpquota.HardLimit) 378 438 if pagecounter < hardlimit : 379 439 action = "ALLOW" … … 385 445 return action 386 446 387 def checkUserPQuota(self, username, printername) : 388 """Checks the user quota on a printer and deny or accept the job.""" 389 # first we check any group the user is a member of 390 userid = self.storage.getUserId(username) 391 for groupname in self.storage.getUserGroupsNames(userid) : 392 action = self.checkGroupPQuota(groupname, printername) 393 if action in ("DENY", "POLICY_DENY") : 394 return action 395 396 # then we check the user's own quota 397 printerid = self.storage.getPrinterId(printername) 398 policy = self.config.getPrinterPolicy(printername) 399 limitby = self.storage.getUserLimitBy(userid) 400 if limitby == "balance" : 401 balance = self.storage.getUserBalance(userid) 402 if balance is None : 403 if policy == "ALLOW" : 404 action = "POLICY_ALLOW" 405 else : 406 action = "POLICY_DENY" 407 self.logger.log_message(_("Unable to find user %s's account balance, applying default policy (%s) for printer %s") % (username, action, printername)) 408 else : 409 # TODO : there's no warning (no account balance soft limit) 410 (balance, lifetimepaid) = balance 411 if balance <= 0.0 : 412 action = "DENY" 413 else : 414 action = "ALLOW" 415 else : 416 quota = self.storage.getUserPQuota(userid, printerid) 417 if quota is None : 418 # Unknown user or printer or combination 419 if policy == "ALLOW" : 420 action = "POLICY_ALLOW" 421 else : 422 action = "POLICY_DENY" 423 self.logger.log_message(_("Unable to match user %s on printer %s, applying default policy (%s)") % (username, printername, action)) 424 else : 425 pagecounter = quota["pagecounter"] 426 softlimit = quota["softlimit"] 427 hardlimit = quota["hardlimit"] 428 datelimit = quota["datelimit"] 429 if softlimit is not None : 430 if pagecounter < softlimit : 431 action = "ALLOW" 432 else : 433 if hardlimit is None : 434 # only a soft limit, this is equivalent to having only a hard limit 435 action = "DENY" 436 else : 437 if softlimit <= pagecounter < hardlimit : 438 now = DateTime.now() 439 if datelimit is not None : 440 datelimit = DateTime.ISO.ParseDateTime(datelimit) 441 else : 442 datelimit = now + self.config.getGraceDelay(printername) 443 self.storage.setUserDateLimit(userid, printerid, datelimit) 444 if now < datelimit : 445 action = "WARN" 446 else : 447 action = "DENY" 448 else : 449 action = "DENY" 450 else : 451 if hardlimit is not None : 452 # no soft limit, only a hard one. 453 if pagecounter < hardlimit : 454 action = "ALLOW" 455 else : 456 action = "DENY" 457 else : 458 # Both are unset, no quota, i.e. accounting only 459 action = "ALLOW" 460 return action 461 462 def warnGroupPQuota(self, groupname, printername) : 447 def warnGroupPQuota(self, grouppquota) : 463 448 """Checks a group quota and send messages if quota is exceeded on current printer.""" 464 admin = self.config.getAdmin(printername) 465 adminmail = self.config.getAdminMail(printername) 466 mailto = self.config.getMailTo(printername) 467 action = self.checkGroupPQuota(groupname, printername) 468 groupmembers = self.storage.getGroupMembersNames(groupname) 449 group = grouppquota.Group 450 printer = grouppquota.Printer 451 admin = self.config.getAdmin(printer.Name) 452 adminmail = self.config.getAdminMail(printer.Name) 453 mailto = self.config.getMailTo(printer.Name) 454 action = self.checkGroupPQuota(grouppquota, printer) 469 455 if action.startswith("POLICY_") : 470 456 action = action[7:] 471 457 if action == "DENY" : 472 adminmessage = _("Print Quota exceeded for group %s on printer %s") % (group name, printername)458 adminmessage = _("Print Quota exceeded for group %s on printer %s") % (group.Name, printer.Name) 473 459 self.logger.log_message(adminmessage) 474 460 if mailto in [ "BOTH", "ADMIN" ] : 475 461 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 476 for user name in groupmembers:462 for user in self.storage.getGroupMembers(group) : 477 463 if mailto in [ "BOTH", "USER" ] : 478 self.sendMessageToUser(admin, adminmail, user name, _("Print Quota Exceeded"), _("You are not allowed to print anymore because\nyour group Print Quota is exceeded on printer %s.") % printername)464 self.sendMessageToUser(admin, adminmail, user.Name, _("Print Quota Exceeded"), _("You are not allowed to print anymore because\nyour group Print Quota is exceeded on printer %s.") % printer.Name) 479 465 elif action == "WARN" : 480 adminmessage = _("Print Quota soft limit exceeded for group %s on printer %s") % (group name, printername)466 adminmessage = _("Print Quota soft limit exceeded for group %s on printer %s") % (group.Name, printer.Name) 481 467 self.logger.log_message(adminmessage) 482 468 if mailto in [ "BOTH", "ADMIN" ] : 483 469 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 484 for user name in groupmembers:470 for user in self.storage.getGroupMembers(group) : 485 471 if mailto in [ "BOTH", "USER" ] : 486 self.sendMessageToUser(admin, adminmail, user name, _("Print Quota Exceeded"), _("You will soon be forbidden to print anymore because\nyour group Print Quota is almost reached on printer %s.") % printername)472 self.sendMessageToUser(admin, adminmail, user.Name, _("Print Quota Exceeded"), _("You will soon be forbidden to print anymore because\nyour group Print Quota is almost reached on printer %s.") % printer.Name) 487 473 return action 488 474 489 def warnUserPQuota(self, user name, printername) :475 def warnUserPQuota(self, userpquota) : 490 476 """Checks a user quota and send him a message if quota is exceeded on current printer.""" 491 admin = self.config.getAdmin(printername) 492 adminmail = self.config.getAdminMail(printername) 493 mailto = self.config.getMailTo(printername) 494 action = self.checkUserPQuota(username, printername) 477 user = userpquota.User 478 printer = userpquota.Printer 479 admin = self.config.getAdmin(printer.Name) 480 adminmail = self.config.getAdminMail(printer.Name) 481 mailto = self.config.getMailTo(printer.Name) 482 action = self.checkUserPQuota(userpquota) 495 483 if action.startswith("POLICY_") : 496 484 action = action[7:] 497 485 if action == "DENY" : 498 adminmessage = _("Print Quota exceeded for user %s on printer %s") % (user name, printername)486 adminmessage = _("Print Quota exceeded for user %s on printer %s") % (user.Name, printer.Name) 499 487 self.logger.log_message(adminmessage) 500 488 if mailto in [ "BOTH", "USER" ] : 501 self.sendMessageToUser(admin, adminmail, user name, _("Print Quota Exceeded"), _("You are not allowed to print anymore because\nyour Print Quota is exceeded on printer %s.") % printername)489 self.sendMessageToUser(admin, adminmail, user.Name, _("Print Quota Exceeded"), _("You are not allowed to print anymore because\nyour Print Quota is exceeded on printer %s.") % printer.Name) 502 490 if mailto in [ "BOTH", "ADMIN" ] : 503 491 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage) 504 492 elif action == "WARN" : 505 adminmessage = _("Print Quota soft limit exceeded for user %s on printer %s") % (user name, printername)493 adminmessage = _("Print Quota soft limit exceeded for user %s on printer %s") % (user.Name, printer.Name) 506 494 self.logger.log_message(adminmessage) 507 495 if mailto in [ "BOTH", "USER" ] : 508 self.sendMessageToUser(admin, adminmail, user name, _("Print Quota Exceeded"), _("You will soon be forbidden to print anymore because\nyour Print Quota is almost reached on printer %s.") % printername)496 self.sendMessageToUser(admin, adminmail, user.Name, _("Print Quota Exceeded"), _("You will soon be forbidden to print anymore because\nyour Print Quota is almost reached on printer %s.") % printer.Name) 509 497 if mailto in [ "BOTH", "ADMIN" ] : 510 498 self.sendMessageToAdmin(adminmail, _("Print Quota"), adminmessage)