root / pykota / trunk / pykota / storages / ldapstorage.py @ 1031

Revision 1031, 28.6 kB (checked in by jalet, 21 years ago)

More work on LDAP

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1# PyKota
2#
3# PyKota : Print Quotas for CUPS and LPRng
4#
5# (c) 2003 Jerome Alet <alet@librelogiciel.com>
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
19#
20# $Id$
21#
22# $Log$
23# Revision 1.9  2003/06/16 11:59:09  jalet
24# More work on LDAP
25#
26# Revision 1.8  2003/06/15 22:26:52  jalet
27# More work on LDAP
28#
29# Revision 1.7  2003/06/14 22:44:21  jalet
30# More work on LDAP storage backend.
31#
32# Revision 1.6  2003/06/13 19:07:57  jalet
33# Two big bugs fixed, time to release something ;-)
34#
35# Revision 1.5  2003/06/10 16:37:54  jalet
36# Deletion of the second user which is not needed anymore.
37# Added a debug configuration field in /etc/pykota.conf
38# All queries can now be sent to the logger in debug mode, this will
39# greatly help improve performance when time for this will come.
40#
41# Revision 1.4  2003/06/10 10:45:32  jalet
42# Not implemented methods now raise an exception when called.
43#
44# Revision 1.3  2003/06/06 20:49:15  jalet
45# Very latest schema. UNTESTED.
46#
47# Revision 1.2  2003/06/06 14:21:08  jalet
48# New LDAP schema.
49# Small bug fixes.
50#
51# Revision 1.1  2003/06/05 11:19:13  jalet
52# More good work on LDAP storage.
53#
54#
55#
56
57#
58# My IANA assigned number, for
59# "Conseil Internet & Logiciels Libres, J�me Alet"
60# is 16868. Use this as a base to create the LDAP schema.
61#
62
63import time
64import md5
65import fnmatch
66
67from pykota.storage import PyKotaStorageError
68
69try :
70    import ldap
71    from ldap import modlist
72except ImportError :   
73    import sys
74    # TODO : to translate or not to translate ?
75    raise PyKotaStorageError, "This python version (%s) doesn't seem to have the python-ldap module installed correctly." % sys.version.split()[0]
76   
77class Storage :
78    def __init__(self, pykotatool, host, dbname, user, passwd) :
79        """Opens the LDAP connection."""
80        # raise PyKotaStorageError, "Sorry, the LDAP backend for PyKota is not yet implemented !"
81        self.closed = 1
82        self.tool = pykotatool
83        self.debug = pykotatool.config.getDebug()
84        self.info = pykotatool.config.getLDAPInfo()
85        try :
86            self.database = ldap.initialize(host) 
87            self.database.simple_bind_s(user, passwd)
88            self.basedn = dbname
89        except ldap.SERVER_DOWN :   
90            raise PyKotaStorageError, "LDAP backend for PyKota seems to be down !" # TODO : translate
91        except ldap.LDAPError :   
92            raise PyKotaStorageError, "Unable to connect to LDAP server %s as %s." % (host, user) # TODO : translate
93        else :   
94            self.closed = 0
95            if self.debug :
96                self.tool.logger.log_message("Database opened (host=%s, dbname=%s, user=%s)" % (host, dbname, user), "debug")
97           
98    def __del__(self) :       
99        """Closes the database connection."""
100        if not self.closed :
101            del self.database
102            self.closed = 1
103            if self.debug :
104                self.tool.logger.log_message("Database closed.", "debug")
105       
106    def genUUID(self) :   
107        """Generates an unique identifier.
108       
109           TODO : this one is not unique accross several print servers, but should be sufficient for testing.
110        """
111        return md5.md5("%s" % time.time()).hexdigest()
112       
113    def doSearch(self, key, fields=None, base="", scope=ldap.SCOPE_SUBTREE) :
114        """Does an LDAP search query."""
115        try :
116            base = base or self.basedn
117            if self.debug :
118                self.tool.logger.log_message("QUERY : BaseDN : %s, Scope : %s, Filter : %s, Attributes : %s" % (base, scope, key, fields), "debug")
119            result = self.database.search_s(base or self.basedn, scope, key, fields)
120        except ldap.LDAPError :   
121            raise PyKotaStorageError, _("Search for %s(%s) from %s(scope=%s) returned no answer.") % (key, fields, base, scope)
122        else :     
123            if self.debug :
124                self.tool.logger.log_message("QUERY : Result : %s" % result, "debug")
125            return result
126           
127    def doAdd(self, dn, fields) :
128        """Adds an entry in the LDAP directory."""
129        try :
130            if self.debug :
131                self.tool.logger.log_message("QUERY : ADD(%s, %s)" % (dn, str(fields)), "debug")
132            self.database.add_s(dn, modlist.addModlist(fields))
133        except ldap.LDAPError :
134            raise PyKotaStorageError, _("Problem adding LDAP entry (%s, %s)") % (dn, str(fields))
135        else :
136            return dn
137           
138    def doModify(self, dn, fields) :
139        """Modifies an entry in the LDAP directory."""
140        try :
141            oldentry = self.doSearch("objectClass=*", base=dn, scope=ldap.SCOPE_BASE)
142            if self.debug :
143                self.tool.logger.log_message("QUERY : Modify(%s, %s ==> %s)" % (dn, oldentry[0][1], fields), "debug")
144            self.database.modify_s(dn, modlist.modifyModlist(oldentry[0][1], fields, ignore_oldexistent=1))
145        except ldap.LDAPError :
146            raise PyKotaStorageError, _("Problem modifying LDAP entry (%s, %s)") % (dn, fields)
147        else :
148            return dn
149       
150    def getMatchingPrinters(self, printerpattern) :
151        """Returns the list of all printers as tuples (id, name) for printer names which match a certain pattern."""
152        result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName"], base=self.info["printerbase"])
153        if result :
154            return [(printerid, printer["pykotaPrinterName"][0]) for (printerid, printer) in result if fnmatch.fnmatchcase(printer["pykotaPrinterName"][0], printerpattern)]
155           
156    def getPrinterId(self, printername) :       
157        """Returns a printerid given a printername."""
158        result = self.doSearch("(&(objectClass=pykotaPrinter)(|(pykotaPrinterName=%s)(%s=%s)))" % (printername, self.info["printerrdn"], printername), ["pykotaPrinterName"], base=self.info["printerbase"])
159        if result :
160            return result[0][0]
161           
162    def getPrinterName(self, printerid) :       
163        """Returns a printerid given a printer id."""
164        result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName"], base=printerid, scope=ldap.SCOPE_BASE)
165        if result :
166            return result[0][1]["pykotaPrinterName"][0]
167           
168    def getPrinterPrices(self, printerid) :       
169        """Returns a printer prices per page and per job given a printerid."""
170        result = self.doSearch("(|(pykotaPrinterName=*)(%s=*))" % self.info["printerrdn"], ["pykotaPricePerPage", "pykotaPricePerJob"], base=printerid, scope=ldap.SCOPE_BASE)
171        if result :
172            return (float(result[0][1]["pykotaPricePerPage"][0]), float(result[0][1]["pykotaPricePerJob"][0]))
173           
174    def setPrinterPrices(self, printerid, perpage, perjob) :
175        """Sets prices per job and per page for a given printer."""
176        fields = { 
177                   "pykotaPricePerPage" : str(perpage),
178                   "pykotaPricePerJob" : str(perjob),
179                 } 
180        return self.doModify(printerid, fields)
181   
182    def getUserId(self, username) :
183        """Returns a userid given a username."""
184        result = self.doSearch("(&(objectClass=pykotaAccount)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), [self.info["userrdn"]], base=self.info["userbase"])
185        if result :
186            return result[0][0]
187           
188    def getUserName(self, userid) :
189        """Returns a username given a userid."""
190        result = self.doSearch("objectClass=pykotaAccount", ["pykotaUserName"], base=userid, scope=ldap.SCOPE_BASE)
191        if result :
192            return result[0][1]["pykotaUserName"][0]
193           
194    def getGroupId(self, groupname) :
195        """Returns a groupid given a grupname."""
196        result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), [self.info["grouprdn"]], base=self.info["groupbase"])
197        if result is not None :
198            (groupid, dummy) = result[0]
199            return groupid
200           
201    def getJobHistoryId(self, jobid, userid, printerid) :       
202        """Returns the history line's id given a (jobid, userid, printerid).
203       
204           TODO : delete because shouldn't be needed by the LDAP backend
205        """
206        raise PyKotaStorageError, "Not implemented !"
207           
208    def getPrinterUsers(self, printerid) :       
209        """Returns the list of userids and usernames which uses a given printer."""
210        # first get the printer's name from the id
211        result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName", self.info["printerrdn"]], base=printerid, scope=ldap.SCOPE_BASE)
212        if result :
213            fields = result[0][1]
214            printername = (fields.get("pykotaPrinterName") or fields.get(self.info["printerrdn"]))[0]
215            result = self.doSearch("(&(objectClass=pykotaUserPQuota)(pykotaPrinterName=%s))" % printername, ["pykotaUserName"], base=self.info["userquotabase"]) 
216            if result :
217                return [(pquotauserid, fields["pykotaUserName"][0]) for (pquotauserid, fields) in result]
218       
219    def getPrinterGroups(self, printerid) :       
220        """Returns the list of groups which uses a given printer."""
221        # first get the printer's name from the id
222        result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName", self.info["printerrdn"]], base=printerid, scope=ldap.SCOPE_BASE)
223        if result :
224            fields = result[0][1]
225            printername = (fields.get("pykotaPrinterName") or fields.get(self.info["printerrdn"]))[0]
226            result = self.doSearch("(&(objectClass=pykotaGroupPQuota)(pykotaPrinterName=%s))" % printername, ["pykotaGroupName"], base=self.info["groupquotabase"]) 
227            if result :
228                return [(pquotagroupid, fields["pykotaGroupName"][0]) for (pquotagroupid, fields) in result]
229       
230    def getGroupMembersNames(self, groupname) :       
231        """Returns the list of user's names which are member of this group."""
232        result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), [self.info["groupmembers"]])
233        if result :
234            fields = result[0][1]
235            return fields.get(self.info["groupmembers"])
236       
237    def getUserGroupsNames(self, userid) :       
238        """Returns the list of groups' names the user is a member of."""
239        username = self.getUserName(userid)
240        if username :
241            result = self.doSearch("(&(objectClass=pykotaGroup)(%s=%s))" % (self.info["groupmembers"], username), [self.info["grouprdn"]], base=self.info["groupbase"])
242            if result :
243                return [v[self.info["grouprdn"]][0] for (k, v) in result]
244       
245    def addPrinter(self, printername) :       
246        """Adds a printer to the quota storage, returns its id."""
247        fields = { self.info["printerrdn"] : printername,
248                   "objectClass" : ["pykotaObject", "pykotaPrinter"],
249                   "pykotaPrinterName" : printername,
250                   "pykotaPricePerPage" : "0.0",
251                   "pykotaPricePerJob" : "0.0",
252                 } 
253        dn = "%s=%s,%s" % (self.info["printerrdn"], printername, self.info["printerbase"])
254        return self.doAdd(dn, fields)
255       
256    def addUser(self, username) :       
257        """Adds a user to the quota storage, returns its id."""
258        fields = { self.info["userrdn"] : username,
259                   "objectClass" : ["pykotaObject", "pykotaAccount", "pykotaAccountBalance"],
260                   "pykotaUserName" : username,
261                   "pykotaLimitBy" : "quota",
262                   "pykotaBalance" : "0.0",
263                   "pykotaLifeTimePaid" : "0.0",
264                 } 
265        dn = "%s=%s,%s" % (self.info["userrdn"], username, self.info["userbase"])
266        return self.doAdd(dn, fields)
267       
268    def addGroup(self, groupname) :       
269        """Adds a group to the quota storage, returns its id."""
270        fields = { self.info["grouprdn"] : groupname,
271                   "objectClass" : ["pykotaObject", "pykotaGroup"],
272                   "pykotaGroupName" : groupname,
273                   "pykotaLimitBy" : "quota",
274                 } 
275        dn = "%s=%s,%s" % (self.info["grouprdn"], groupname, self.info["groupbase"])
276        return self.doAdd(dn, fields)
277       
278    def addUserPQuota(self, username, printerid) :
279        """Initializes a user print quota on a printer, adds the user to the quota storage if needed."""
280        uuid = self.genUUID()
281        fields = { "objectClass" : ["pykotaObject", "pykotaUserPQuota"],
282                   "cn" : uuid,
283                   "pykotaUserName" : username,
284                   "pykotaPrinterName" : self.getPrinterName(printerid), 
285                   "pykotaPageCounter" : "0",
286                   "pykotaLifePageCounter" : "0",
287                   "pykotaSoftLimit" : "0",
288                   "pykotaHardLimit" : "0",
289                   "pykotaDateLimit" : "None",
290                 } 
291        dn = "cn=%s,%s" % (uuid, self.info["userquotabase"])
292        self.doAdd(dn, fields)
293        return (dn, printerid)
294       
295    def addGroupPQuota(self, groupname, printerid) :
296        """Initializes a group print quota on a printer, adds the group to the quota storage if needed."""
297        uuid = self.genUUID()
298        fields = { "objectClass" : ["pykotaObject", "pykotaGroupPQuota"],
299                   "cn" : uuid,
300                   "pykotaGroupName" : groupname,
301                   "pykotaPrinterName" : self.getPrinterName(printerid), 
302                   "pykotaSoftLimit" : "0",
303                   "pykotaHardLimit" : "0",
304                   "pykotaDateLimit" : "None",
305                 } 
306        dn = "cn=%s,%s" % (uuid, self.info["groupquotabase"])
307        self.doAdd(dn, fields)
308        return (dn, printerid)
309       
310    def increaseUserBalance(self, userquotaid, amount) :   
311        """Increases (or decreases) an user's account balance by a given amount."""
312        balance = self.getUserBalance(userquotaid)
313        if balance :
314            (newbal, newpaid) = [(float(v) + float(amount)) for v in balance]
315            result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName"], base=userquotaid, scope=ldap.SCOPE_BASE)
316            if result :
317                username = result[0][1]["pykotaUserName"][0]
318                if username :
319                    result = self.doSearch("(&(objectClass=pykotaAccountBalance)(pykotaUserName=%s))" % username , [ "pykotaBalance", "pykotaLifeTimePaid"])
320                    fields = {
321                               "pykotaBalance" : str(newbal),
322                               "pykotaLifeTimePaid" : str(newpaid),
323                             }
324                    return self.doModify(result[0][0], fields)         
325       
326    def getUserBalance(self, userquotaid) :   
327        """Returns the current account balance for a given user quota identifier."""
328        # first get the user's name from the user quota id
329        result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName"], base=userquotaid, scope=ldap.SCOPE_BASE)
330        if result :
331            username = result[0][1]["pykotaUserName"][0]
332            result = self.doSearch("(&(objectClass=pykotaAccountBalance)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaBalance", "pykotaLifeTimePaid"])
333            if result :
334                fields = result[0][1]
335                return (float(fields["pykotaBalance"][0]), float(fields["pykotaLifeTimePaid"][0]))
336       
337    def getUserBalanceFromUserId(self, userid) :   
338        """Returns the current account balance for a given user id."""
339        # first get the user's name from the user id
340        result = self.doSearch("objectClass=pykotaAccount", ["pykotaUserName", self.info["userrdn"]], base=userid, scope=ldap.SCOPE_BASE)
341        if result :
342            fields = result[0][1]
343            username = (fields.get("pykotaUserName") or fields.get(self.info["userrdn"]))[0]
344            result = self.doSearch("(&(objectClass=pykotaAccountBalance)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaBalance", "pykotaLifeTimePaid"])
345            if result :
346                fields = result[0][1]
347                return (float(fields["pykotaBalance"][0]), float(fields["pykotaLifeTimePaid"][0]))
348       
349    def getGroupBalance(self, groupquotaid) :   
350        """Returns the current account balance for a given group, as the sum of each of its users' account balance."""
351        # first get the group's name from the group quota id
352        result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName"], base=groupquotaid, scope=ldap.SCOPE_BASE)
353        if result :
354            groupname = result[0][1]["pykotaGroupName"][0]
355            members = self.getGroupMembersNames(groupname)
356            balance = lifetimepaid = 0.0
357            for member in members :
358                userid = self.getUserId(member)
359                if userid :
360                    userbal = self.getUserBalanceFromUserId(userid)
361                    if userbal :
362                        (bal, paid) = userbal
363                        balance += bal
364                        lifetimepaid += paid
365            return (balance, lifetimepaid)           
366       
367    def getUserLimitBy(self, userquotaid) :   
368        """Returns the way in which user printing is limited."""
369        result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName"], base=userquotaid, scope=ldap.SCOPE_BASE)
370        if result :
371            username = result[0][1]["pykotaUserName"][0]
372            result = self.doSearch("(&(objectClass=pykotaAccount)(|(pykotaUserName=%s)(%s=%s)))" % (username, self.info["userrdn"], username), ["pykotaLimitBy"])
373            if result :
374                return result[0][1]["pykotaLimitBy"][0]
375       
376    def getGroupLimitBy(self, groupquotaid) :   
377        """Returns the way in which group printing is limited."""
378        # first get the group's name from the group quota id
379        result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName"], base=groupquotaid, scope=ldap.SCOPE_BASE)
380        if result :
381            groupname = result[0][1]["pykotaGroupName"][0]
382            result = self.doSearch("(&(objectClass=pykotaGroup)(|(pykotaGroupName=%s)(%s=%s)))" % (groupname, self.info["grouprdn"], groupname), ["pykotaLimitBy"])
383            if result :
384                return result[0][1]["pykotaLimitBy"][0]
385       
386    def setUserBalance(self, userquotaid, balance) :   
387        """Sets the account balance for a given user to a fixed value."""
388        oldbalance = self.getUserBalance(userquotaid)
389        if oldbalance :
390            (oldbal, oldpaid) = oldbalance
391            difference = balance - oldbal
392            return self.increaseUserBalance(userquotaid, difference)
393       
394    def limitUserBy(self, userquotaid, limitby) :   
395        """Limits a given user based either on print quota or on account balance."""
396        result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName"], base=userquotaid, scope=ldap.SCOPE_BASE)
397        if result :
398            username = result[0][1]["pykotaUserName"][0]
399            fields = {
400                       "pykotaLimitBy" : limitby,
401                     }
402            self.doModify(self.getUserId(username), fields)
403       
404    def limitGroupBy(self, groupquotaid, limitby) :   
405        """Limits a given group based either on print quota or on sum of its users' account balances."""
406        result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName"], base=groupquotaid, scope=ldap.SCOPE_BASE)
407        if result :
408            groupname = result[0][1]["pykotaGroupName"][0]
409            fields = {
410                       "pykotaLimitBy" : limitby,
411                     }
412            self.doModify(self.getGroupId(groupname), fields)
413       
414    def setUserPQuota(self, userquotaid, printerid, softlimit, hardlimit) :
415        """Sets soft and hard limits for a user quota on a specific printer given (userid, printerid)."""
416        fields = { 
417                   "pykotaSoftLimit" : str(softlimit),
418                   "pykotaHardLimit" : str(hardlimit),
419                 } 
420        return self.doModify(userquotaid, fields)
421       
422    def setGroupPQuota(self, groupquotaid, printerid, softlimit, hardlimit) :
423        """Sets soft and hard limits for a group quota on a specific printer given (groupid, printerid)."""
424        fields = { 
425                   "pykotaSoftLimit" : str(softlimit),
426                   "pykotaHardLimit" : str(hardlimit),
427                 } 
428        return self.doModify(groupquotaid, fields)
429       
430    def resetUserPQuota(self, userquotaid, printerid) :   
431        """Resets the page counter to zero for a user on a printer. Life time page counter is kept unchanged."""
432        fields = {
433                   "pykotaPageCounter" : "0",
434                   "pykotaDateLimit" : "None",
435                 }
436        return self.doModify(userquotaid, fields)     
437       
438    def resetGroupPQuota(self, groupquotaid, printerid) :   
439        """Resets the page counter to zero for a group on a printer. Life time page counter is kept unchanged."""
440        fields = {
441                   "pykotaPageCounter" : "0",
442                   "pykotaDateLimit" : "None",
443                 }
444        return self.doModify(groupquotaid, fields)     
445       
446    def updateUserPQuota(self, userquotaid, printerid, pagecount) :
447        """Updates the used user Quota information given (userid, printerid) and a job size in pages."""
448        jobprice = self.computePrinterJobPrice(printerid, pagecount)
449        result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaPageCounter", "pykotaLifePageCounter"], base=userquotaid, scope=ldap.SCOPE_BASE)
450        if result :
451            oldfields = result[0][1]
452            fields = {
453                       "pykotaPageCounter" : str(pagecount + int(oldfields["pykotaPageCounter"][0])),
454                       "pykotaLifePageCounter" : str(pagecount + int(oldfields["pykotaLifePageCounter"][0])),
455                     } 
456            return self.doModify(userquotaid, fields)         
457       
458    def getUserPQuota(self, userquotaid, printerid) :
459        """Returns the Print Quota information for a given (userquotaid, printerid)."""
460        # first get the user's name from the id
461        result = self.doSearch("objectClass=pykotaUserPQuota", ["pykotaUserName", "pykotaPageCounter", "pykotaLifePageCounter", "pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit"], base=userquotaid, scope=ldap.SCOPE_BASE)
462        if result :
463            fields = result[0][1]
464            datelimit = fields["pykotaDateLimit"][0].strip()
465            if (not datelimit) or (datelimit.upper() == "NONE") : 
466                datelimit = None
467            return { "lifepagecounter" : int(fields["pykotaLifePageCounter"][0]), 
468                     "pagecounter" : int(fields["pykotaPageCounter"][0]),
469                     "softlimit" : int(fields["pykotaSoftLimit"][0]),
470                     "hardlimit" : int(fields["pykotaHardLimit"][0]),
471                     "datelimit" : datelimit
472                   }
473       
474    def getGroupPQuota(self, grouppquotaid, printerid) :
475        """Returns the Print Quota information for a given (grouppquotaid, printerid)."""
476        result = self.doSearch("objectClass=pykotaGroupPQuota", ["pykotaGroupName", "pykotaSoftLimit", "pykotaHardLimit", "pykotaDateLimit"], base=grouppquotaid, scope=ldap.SCOPE_BASE)
477        if result :
478            fields = result[0][1]
479            groupname = fields["pykotaGroupName"][0]
480            datelimit = fields["pykotaDateLimit"][0].strip()
481            if (not datelimit) or (datelimit.upper() == "NONE") : 
482                datelimit = None
483            quota = {
484                      "softlimit" : int(fields["pykotaSoftLimit"][0]),
485                      "hardlimit" : int(fields["pykotaHardLimit"][0]),
486                      "datelimit" : datelimit
487                    }
488            members = self.getGroupMembersNames(groupname)
489            pagecounter = lifepagecounter = 0
490            printerusers = self.getPrinterUsers(printerid)
491            if printerusers :
492                for (userid, username) in printerusers :
493                    if username in members :
494                        userpquota = self.getUserPQuota(userid, printerid)
495                        if userpquota :
496                            pagecounter += userpquota["pagecounter"]
497                            lifepagecounter += userpquota["lifepagecounter"]
498            quota.update({"pagecounter": pagecounter, "lifepagecounter": lifepagecounter})               
499            return quota
500       
501    def setUserDateLimit(self, userquotaid, printerid, datelimit) :
502        """Sets the limit date for a soft limit to become an hard one given (userid, printerid)."""
503        fields = {
504                   "pykotaDateLimit" : "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second),
505                 }
506        return self.doModify(userquotaid, fields)
507       
508    def setGroupDateLimit(self, groupquotaid, printerid, datelimit) :
509        """Sets the limit date for a soft limit to become an hard one given (groupid, printerid)."""
510        fields = {
511                   "pykotaDateLimit" : "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second),
512                 }
513        return self.doModify(groupquotaid, fields)
514       
515    def addJobToHistory(self, jobid, userid, printerid, pagecounter, action) :
516        """Adds a job to the history: (jobid, userid, printerid, last page counter taken from requester)."""
517        raise PyKotaStorageError, "Not implemented !"
518   
519    def updateJobSizeInHistory(self, historyid, jobsize) :
520        """Updates a job size in the history given the history line's id."""
521        raise PyKotaStorageError, "Not implemented !"
522   
523    def getPrinterPageCounter(self, printerid) :
524        """Returns the last page counter value for a printer given its id, also returns last username, last jobid and history line id."""
525        result = self.doSearch("objectClass=pykotaPrinter", ["pykotaPrinterName", self.info["printerrdn"]], base=printerid, scope=ldap.SCOPE_BASE)
526        if result :
527            fields = result[0][1]
528            printername = (fields.get("pykotaPrinterName") or fields.get(self.info["printerrdn"]))[0]
529            result = self.doSearch("(&(objectClass=pykotaLastjob)(|(pykotaPrinterName=%s)(%s=%s)))" % (printername, self.info["printerrdn"], printername), ["pykotaLastJobIdent"], base=self.info["lastjobbase"])
530            if result :
531                lastjobident = result[0][1]["pykotaLastJobIdent"][0]
532                result = self.doSearch("(&(objectClass=pykotaJob)(cn=%s))" % lastjobident, ["pykotaUserName", "pykotaPrinterName", "pykotaJobId", "pykotaPrinterPageCounter", "pykotaJobSize", "pykotaAction", "createTimestamp"], base=self.info["jobbase"])
533                if result :
534                    fields = result[0][1]
535                    return { "id": lastjobident, 
536                             "jobid" : fields.get("pykotaJobId")[0],
537                             "userid" : self.getUserId(fields.get("pykotaUserName")[0]),
538                             "username" : fields.get("pykotaUserName")[0], 
539                             "pagecounter" : int(fields.get("pykotaPrinterPageCounter")[0]),
540                           }
541       
542    def addUserToGroup(self, userid, groupid) :   
543        """Adds an user to a group."""
544        raise PyKotaStorageError, "Not implemented !"
545       
546    def deleteUser(self, userid) :   
547        """Completely deletes an user from the Quota Storage."""
548        raise PyKotaStorageError, "Not implemented !"
549       
550    def deleteGroup(self, groupid) :   
551        """Completely deletes an user from the Quota Storage."""
552        raise PyKotaStorageError, "Not implemented !"
553       
554    def computePrinterJobPrice(self, printerid, jobsize) :   
555        """Returns the price for a job on a given printer."""
556        # TODO : create a base class with things like this
557        prices = self.getPrinterPrices(printerid)
558        if prices is None :
559            perpage = perjob = 0.0
560        else :   
561            (perpage, perjob) = prices
562        return perjob + (perpage * jobsize)
Note: See TracBrowser for help on using the browser.