root / pykota / trunk / pykota / storage.py @ 1062

Revision 1062, 11.5 kB (checked in by jalet, 21 years ago)

The previous bug fix was incomplete.

  • 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.17  2003/07/05 07:46:50  jalet
24# The previous bug fix was incomplete.
25#
26# Revision 1.16  2003/06/25 19:52:31  jalet
27# Should be ready for testing :-)
28#
29# Revision 1.15  2003/06/25 14:10:58  jalet
30# Exception raising for now.
31#
32# Revision 1.14  2003/06/25 14:10:01  jalet
33# Hey, it may work (edpykota --reset excepted) !
34#
35# Revision 1.13  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.12  2003/04/23 22:13:57  jalet
42# Preliminary support for LPRng added BUT STILL UNTESTED.
43#
44# Revision 1.11  2003/04/10 21:47:20  jalet
45# Job history added. Upgrade script neutralized for now !
46#
47# Revision 1.10  2003/03/29 13:45:27  jalet
48# GPL paragraphs were incorrectly (from memory) copied into the sources.
49# Two README files were added.
50# Upgrade script for PostgreSQL pre 1.01 schema was added.
51#
52# Revision 1.9  2003/02/17 22:55:01  jalet
53# More options can now be set per printer or globally :
54#
55#       admin
56#       adminmail
57#       gracedelay
58#       requester
59#
60# the printer option has priority when both are defined.
61#
62# Revision 1.8  2003/02/17 22:05:50  jalet
63# Storage backend now supports admin and user passwords (untested)
64#
65# Revision 1.7  2003/02/10 12:07:31  jalet
66# Now repykota should output the recorded total page number for each printer too.
67#
68# Revision 1.6  2003/02/09 13:05:43  jalet
69# Internationalization continues...
70#
71# Revision 1.5  2003/02/08 22:39:46  jalet
72# --reset command line option added
73#
74# Revision 1.4  2003/02/08 09:59:59  jalet
75# Added preliminary base class for all storages
76#
77# Revision 1.3  2003/02/05 22:10:29  jalet
78# Typos
79#
80# Revision 1.2  2003/02/05 22:02:22  jalet
81# __import__ statement didn't work as expected
82#
83# Revision 1.1  2003/02/05 21:28:17  jalet
84# Initial import into CVS
85#
86#
87#
88
89class PyKotaStorageError(Exception):
90    """An exception for Quota Storage related stuff."""
91    def __init__(self, message = ""):
92        self.message = message
93        Exception.__init__(self, message)
94    def __repr__(self):
95        return self.message
96    __str__ = __repr__
97       
98class StorageObject :
99    """Object present in the Quota Storage."""
100    def __init__(self, parent) :
101        "Initialize minimal data."""
102        self.parent = parent
103        self.ident = None
104        self.Exists = 0
105       
106class StorageUser(StorageObject) :       
107    """User class."""
108    def __init__(self, parent, name) :
109        StorageObject.__init__(self, parent)
110        self.Name = name
111        self.LimitBy = None
112        self.AccountBalance = None
113        self.LifeTimePaid = None
114       
115    def consumeAccountBalance(self, amount) :     
116        """Consumes an amount of money from the user's account balance."""
117        newbalance = float(self.AccountBalance or 0.0) - amount
118        self.parent.writeUserAccountBalance(self, newbalance)
119        self.AccountBalance = newbalance
120       
121    def setAccountBalance(self, balance, lifetimepaid) :   
122        """Sets the user's account balance in case he pays more money."""
123        self.parent.writeUserAccountBalance(self, balance, lifetimepaid)
124        self.AccountBalance = balance
125        self.LifeTimePaid = lifetimepaid
126       
127    def setLimitBy(self, limitby) :   
128        """Sets the user's limiting factor."""
129        try :
130            limitby = limitby.lower()
131        except AttributeError :   
132            limitby = "quota"
133        if limitby in ["quota", "balance"] :
134            self.parent.writeUserLimitBy(self, limitby)
135            self.LimitBy = limitby
136       
137    def delete(self) :   
138        """Deletes an user from the Quota Storage."""
139        self.parent.beginTransaction()
140        try :
141            self.parent.deleteUser(self)
142        except PyKotaStorageError, msg :   
143            self.parent.rollbackTransaction()
144            raise PyKotaStorageError, msg
145        else :   
146            self.parent.commitTransaction()
147       
148class StorageGroup(StorageObject) :       
149    """User class."""
150    def __init__(self, parent, name) :
151        StorageObject.__init__(self, parent)
152        self.Name = name
153        self.LimitBy = None
154        self.AccountBalance = None
155        self.LifeTimePaid = None
156       
157    def setLimitBy(self, limitby) :   
158        """Sets the user's limiting factor."""
159        try :
160            limitby = limitby.lower()
161        except AttributeError :   
162            limitby = "quota"
163        if limitby in ["quota", "balance"] :
164            self.parent.writeGroupLimitBy(self, limitby)
165            self.LimitBy = limitby
166       
167    def delete(self) :   
168        """Deletes a group from the Quota Storage."""
169        self.parent.beginTransaction()
170        try :
171            self.parent.deleteGroup(self)
172        except PyKotaStorageError, msg :   
173            self.parent.rollbackTransaction()
174            raise PyKotaStorageError, msg
175        else :   
176            self.parent.commitTransaction()
177       
178class StoragePrinter(StorageObject) :
179    """Printer class."""
180    def __init__(self, parent, name) :
181        StorageObject.__init__(self, parent)
182        self.Name = name
183        self.PricePerPage = None
184        self.PricePerJob = None
185        self.LastJob = None
186       
187    def addJobToHistory(self, jobid, user, pagecounter, action, jobsize=None) :   
188        """Adds a job to the printer's history."""
189        self.parent.writeJobNew(self, user, jobid, pagecounter, action, jobsize)
190        # TODO : update LastJob object ? Probably not needed.
191       
192    def setPrices(self, priceperpage = None, priceperjob = None) :   
193        """Sets the printer's prices."""
194        if priceperpage is None :
195            priceperpage = self.PricePerPage
196        else :   
197            self.PricePerPage = float(priceperpage)
198        if priceperjob is None :   
199            priceperjob = self.PricePerJob
200        else :   
201            self.PricePerJob = float(priceperjob)
202        self.parent.writePrinterPrices(self)
203       
204class StorageUserPQuota(StorageObject) :
205    """User Print Quota class."""
206    def __init__(self, parent, user, printer) :
207        StorageObject.__init__(self, parent)
208        self.User = user
209        self.Printer = printer
210        self.PageCounter = None
211        self.LifePageCounter = None
212        self.SoftLimit = None
213        self.HardLimit = None
214        self.DateLimit = None
215       
216    def setDateLimit(self, datelimit) :   
217        """Sets the date limit for this quota."""
218        date = "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second)
219        self.parent.writeUserPQuotaDateLimit(self, date)
220        self.DateLimit = date
221       
222    def setLimits(self, softlimit, hardlimit) :   
223        """Sets the soft and hard limit for this quota."""
224        self.parent.writeUserPQuotaLimits(self, softlimit, hardlimit)
225        self.SoftLimit = softlimit
226        self.HardLimit = hardlimit
227       
228    def reset(self) :   
229        """Resets page counter to 0."""
230        self.parent.writeUserPQuotaPagesCounters(self, 0, int(self.LifePageCounter or 0))
231        self.PageCounter = 0
232       
233    def increasePagesUsage(self, nbpages) :
234        """Increase the value of used pages and money."""
235        if nbpages :
236            jobprice = (float(self.Printer.PricePerPage or 0.0) * nbpages) + float(self.Printer.PricePerJob or 0.0)
237            newpagecounter = int(self.PageCounter or 0) + nbpages
238            newlifepagecounter = int(self.LifePageCounter or 0) + nbpages
239            self.parent.beginTransaction()
240            try :
241                if jobprice : # optimization : don't access the database if unneeded.
242                    self.User.consumeAccountBalance(jobprice)
243                self.parent.writeUserPQuotaPagesCounters(self, newpagecounter, newlifepagecounter)
244            except PyKotaStorageError, msg :   
245                self.parent.rollbackTransaction()
246                raise PyKotaStorageError, msg
247            else :   
248                self.parent.commitTransaction()
249                self.PageCounter = newpagecounter
250                self.LifePageCounter = newlifepagecounter
251       
252class StorageGroupPQuota(StorageObject) :
253    """Group Print Quota class."""
254    def __init__(self, parent, group, printer) :
255        StorageObject.__init__(self, parent)
256        self.Group = group
257        self.Printer = printer
258        self.PageCounter = None
259        self.LifePageCounter = None
260        self.SoftLimit = None
261        self.HardLimit = None
262        self.DateLimit = None
263       
264    def setDateLimit(self, datelimit) :   
265        """Sets the date limit for this quota."""
266        date = "%04i-%02i-%02i %02i:%02i:%02i" % (datelimit.year, datelimit.month, datelimit.day, datelimit.hour, datelimit.minute, datelimit.second)
267        self.parent.writeGroupPQuotaDateLimit(self, date)
268        self.DateLimit = date
269       
270    def setLimits(self, softlimit, hardlimit) :   
271        """Sets the soft and hard limit for this quota."""
272        self.parent.writeGroupPQuotaLimits(self, softlimit, hardlimit)
273        self.SoftLimit = softlimit
274        self.HardLimit = hardlimit
275       
276class StorageLastJob(StorageObject) :
277    """Printer's Last Job class."""
278    def __init__(self, parent, printer) :
279        StorageObject.__init__(self, parent)
280        self.Printer = printer
281        self.JobId = None
282        self.User = None
283        self.PrinterPageCounter = None
284        self.JobSize = None
285        self.JobAction = None
286        self.JobDate = None
287       
288    def setSize(self, jobsize) :
289        """Sets the last job's size."""
290        self.parent.writeLastJobSize(self, jobsize)
291        self.JobSize = jobsize
292   
293def openConnection(pykotatool) :
294    """Returns a connection handle to the appropriate Quota Storage Database."""
295    backendinfo = pykotatool.config.getStorageBackend()
296    backend = backendinfo["storagebackend"]
297    try :
298        if not backend.isalpha() :
299            # don't trust user input
300            raise ImportError
301        #   
302        # TODO : descending compatibility
303        #
304        if backend == "postgresql" :
305            backend = "pgstorage"       # TODO : delete, this is for descending compatibility only
306        exec "from pykota.storages import %s as storagebackend" % backend.lower()   
307    except ImportError :
308        raise PyKotaStorageError, _("Unsupported quota storage backend %s") % backend
309    else :   
310        host = backendinfo["storageserver"]
311        database = backendinfo["storagename"]
312        admin = backendinfo["storageadmin"]
313        adminpw = backendinfo["storageadminpw"]
314        return getattr(storagebackend, "Storage")(pykotatool, host, database, admin, adminpw)
Note: See TracBrowser for help on using the browser.