root / pykota / trunk / bin / dumpykota @ 2015

Revision 2015, 14.9 kB (checked in by jalet, 19 years ago)

Fixed the time zone field in page_log output to make PrintAnalyzer? happy

  • Property svn:eol-style set to native
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
Line 
1#! /usr/bin/env python
2# -*- coding: ISO-8859-15 -*-
3
4# PyKota Print Quota Data Dumper
5#
6# PyKota - Print Quotas for CUPS and LPRng
7#
8# (c) 2003-2004 Jerome Alet <alet@librelogiciel.com>
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22#
23# $Id$
24#
25# $Log$
26# Revision 1.20  2005/01/08 11:25:48  jalet
27# Fixed the time zone field in page_log output to make PrintAnalyzer happy
28#
29# Revision 1.19  2005/01/08 10:52:01  jalet
30# Now dumpykota can dump the history into CUPS' page_log format, allowing the
31# use of tools like PrintAnalyzer or phpPrintAnalyzer along with PyKota
32#
33# Revision 1.18  2005/01/07 12:40:53  jalet
34# Fixed field type's name in XML dumps.
35#
36# Revision 1.17  2004/12/21 15:50:00  jalet
37# The dumpykota command now supports extended filtering capabilities with
38# the PostgreSQL backend. LDAP doesn't yet support such possibilities.
39#
40# Revision 1.16  2004/12/21 14:45:31  jalet
41# Prepared dumpykota to accept the new --filter command line option. Some
42# additionnal work needs to be done in the backends though.
43#
44# Revision 1.15  2004/10/12 15:37:00  jalet
45# Now outputs the name of the offending user if a mere mortal tries to use
46# one of these commands !!!
47#
48# Revision 1.14  2004/10/11 22:53:05  jalet
49# Postponed string interpolation to help message's output method
50#
51# Revision 1.13  2004/10/11 12:49:06  jalet
52# Renders help translatable
53#
54# Revision 1.12  2004/10/07 21:14:28  jalet
55# Hopefully final fix for data encoding to and from the database
56#
57# Revision 1.11  2004/10/07 14:35:40  jalet
58# Now edpykota refuses to launch if the user is not a PyKota administrator.
59# dumpykota : now has the same error message than edpykota in this case.
60#
61# Revision 1.10  2004/10/06 10:05:47  jalet
62# Minor changes to allow any PyKota administrator to launch enhanced versions
63# of the commands, and not only the root user.
64#
65# Revision 1.9  2004/10/05 20:08:46  jalet
66# Misleading help message. Thx to Johannes Laemmermann.
67#
68# Revision 1.8  2004/10/05 09:59:19  jalet
69# Restore compatibility with Python 2.1
70#
71# Revision 1.7  2004/10/04 21:25:29  jalet
72# dumpykota can now output datas in the XML format
73#
74# Revision 1.6  2004/09/15 18:28:41  jalet
75# Updated help for dumpykota
76#
77# Revision 1.5  2004/09/15 07:38:05  jalet
78# Fix for uninitialized variable
79#
80# Revision 1.4  2004/09/15 07:26:19  jalet
81# Data dumps are now ordered by entry creation date if applicable.
82# Now dumpykota exits with a message when there's a broken pipe like
83# in dumpykota --data history | head -3
84#
85# Revision 1.3  2004/09/15 06:58:25  jalet
86# User groups membership and printer groups membership can now be dumped too
87#
88# Revision 1.2  2004/09/14 22:29:12  jalet
89# First version of dumpykota. Works fine but only with PostgreSQL backend
90# for now.
91#
92# Revision 1.1  2004/07/01 19:22:37  jalet
93# First draft of dumpykota
94#
95#
96#
97
98import sys
99import os
100import pwd
101from mx import DateTime
102
103try :
104    import jaxml
105except ImportError :   
106    sys.stderr.write("The jaxml Python module is not installed. XML output is disabled.\n")
107    sys.stderr.write("Download jaxml from http://www.librelogiciel.com/software/ or from your Debian archive of choice\n")
108    hasJAXML = 0
109else :   
110    hasJAXML = 1
111
112from pykota import version
113from pykota.tool import PyKotaTool, PyKotaToolError, crashed, N_
114from pykota.config import PyKotaConfigError
115from pykota.storage import PyKotaStorageError
116
117__doc__ = N_("""dumpykota v%s (c) 2003-2004 C@LL - Conseil Internet & Logiciels Libres
118
119Dumps PyKota database's content.
120
121command line usage :
122
123  dumpykota [options] [filterexpr]
124
125options :
126
127  -v | --version       Prints dumpykota's version number then exits.
128  -h | --help          Prints this message then exits.
129 
130  -d | --data type     Dumps 'type' datas. Allowed types are :
131                       
132                         - history : dumps the jobs history.
133                         - users : dumps users.
134                         - groups : dumps user groups.
135                         - printers : dump printers.
136                         - upquotas : dump user quotas.
137                         - gpquotas : dump user groups quotas.
138                         - payments : dumps user payments.
139                         - pmembers : dumps printer groups members.
140                         - umembers : dumps user groups members.
141                         
142                       NB : the -d | --data command line option   
143                       is MANDATORY.
144 
145  -f | --format fmt    Dumps datas in the 'fmt' format. When not specified,
146                       the format is to dump datas in the csv format (comma
147                       separated values). All data dumped is between double
148                       quotes. Allowed formats are :
149                       
150                         - csv : separate datas with commas
151                         - ssv : separate datas with semicolons
152                         - tsv : separate datas with tabs
153                         - xml : dump data as XML
154                         - cups : dump datas in CUPS' page_log format :
155                                  ONLY AVAILABLE WITH --data history
156                         
157  -o | --output fname  All datas will be dumped to the file instead of
158                       to the standard output. The special '-' filename
159                       is the default value and means stdout.
160                       WARNING : existing files are truncated !
161                       
162  Use the filter expressions to extract only parts of the
163  datas. Allowed filters are of the form :
164               
165         key=value
166                         
167  Allowed keys for now are : 
168                       
169         username       User's name
170         groupname      Users group's name
171         printername    Printer's name
172         pgroupname     Printers group's name
173         
174  Contrary to other PyKota management tools, wildcard characters are not
175  expanded, so you can't use them.
176 
177  NB : not all keys are allowed for each data type, so the result may be
178  empty if you use a key not available for a particular data type.
179 
180Examples :
181
182  $ dumpykota --data history --format csv >myfile.csv
183 
184  This dumps the history in a comma separated values file, for possible
185  use in a spreadsheet.
186 
187  $ dumpykota --data users --format xml -o users.xml
188 
189  Dumps all users datas to the users.xml file.
190 
191  $ dumpykota --data history printername=HP2100 username=jerome
192 
193  Dumps the job history for user jerome on printer HP2100 only.
194 
195This program is free software; you can redistribute it and/or modify
196it under the terms of the GNU General Public License as published by
197the Free Software Foundation; either version 2 of the License, or
198(at your option) any later version.
199
200This program is distributed in the hope that it will be useful,
201but WITHOUT ANY WARRANTY; without even the implied warranty of
202MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
203GNU General Public License for more details.
204
205You should have received a copy of the GNU General Public License
206along with this program; if not, write to the Free Software
207Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
208
209Please e-mail bugs to: %s""")
210       
211class DumPyKota(PyKotaTool) :       
212    """A class for dumpykota."""
213    def main(self, arguments, options) :
214        """Print Quota Data Dumper."""
215        if not self.config.isAdmin :
216            raise PyKotaToolError, "%s : %s" % (pwd.getpwuid(os.geteuid())[0], _("You're not allowed to use this command."))
217           
218        extractonly = {}
219        for filterexp in arguments :
220            if filterexp.strip() :
221                try :
222                    (filterkey, filtervalue) = [part.strip() for part in filterexp.split("=")]
223                    if filterkey not in [ "username",
224                                          "groupname",
225                                          "printername",
226                                          "pgroupname",
227                                        ] :
228                        raise ValueError               
229                except ValueError :   
230                    raise PyKotaToolError, _("Invalid value [%s] for --filter command line option, see help.") % filterexp
231                else :   
232                    extractonly.update({ filterkey : filtervalue })
233           
234        datatype = options["data"]
235        if datatype not in [ "history",
236                             "users",
237                             "groups",
238                             "printers",
239                             "upquotas",
240                             "gpquotas",
241                             "payments",
242                             "pmembers",
243                             "umembers",
244                           ] :
245            raise PyKotaToolError, _("Invalid modifier [%s] for --data command line option, see help.") % datatype
246                   
247        format = options["format"]
248        if (format not in [ "csv",
249                           "ssv",
250                           "tsv",
251                           "xml",
252                           "cups",
253                         ]) \
254              or ((format == "cups") and (datatype != "history")) :
255            raise PyKotaToolError, _("Invalid modifier [%s] for --format command line option, see help.") % format
256           
257        if (format == "xml") and not hasJAXML :
258            raise PyKotaToolError, _("XML output is disabled because the jaxml module is not available.")
259           
260        entries = getattr(self.storage, "extract%s" % datatype.title())(extractonly)   
261        if entries :
262            mustclose = 0   
263            if options["output"].strip() == "-" :   
264                self.outfile = sys.stdout
265            else :   
266                self.outfile = open(options["output"], "w")
267                mustclose = 1
268               
269            retcode = getattr(self, "dump%s" % format.title())(entries, datatype)
270           
271            if mustclose :
272                self.outfile.close()
273               
274            return retcode   
275        return 0
276       
277    def dumpWithSeparator(self, separator, entries) :   
278        """Dumps datas with a separator."""
279        for entry in entries :
280            line = separator.join([ '"%s"' % field for field in entry ])
281            try :
282                self.outfile.write("%s\n" % line)
283            except IOError, msg :   
284                sys.stderr.write("%s : %s\n" % (_("PyKota data dumper failed : I/O error"), msg))
285                return -1
286        return 0       
287       
288    def dumpCsv(self, entries, dummy) :   
289        """Dumps datas with a comma as the separator."""
290        return self.dumpWithSeparator(",", entries)
291                           
292    def dumpSsv(self, entries, dummy) :   
293        """Dumps datas with a comma as the separator."""
294        return self.dumpWithSeparator(";", entries)
295                           
296    def dumpTsv(self, entries, dummy) :   
297        """Dumps datas with a comma as the separator."""
298        return self.dumpWithSeparator("\t", entries)
299       
300    def dumpCups(self, entries, dummy) :   
301        """Dumps history datas as CUPS' page_log format."""
302        fieldnames = entries[0]
303        fields = {}
304        for i in range(len(fieldnames)) :
305            fields[fieldnames[i]] = i
306        sortindex = fields["jobdate"]   
307        entries = entries[1:]
308        entries.sort(lambda m,n : cmp(m[sortindex], n[sortindex]))
309        for entry in entries[1:] :   
310            printername = entry[fields["printername"]]
311            username = entry[fields["username"]]
312            jobid = entry[fields["jobid"]]
313            jobdate = DateTime.ISO.ParseDateTime(entry[fields["jobdate"]])
314            gmtoffset = jobdate.gmtoffset()
315            jobdate = "%s %+03i00" % (jobdate.strftime("%d/%b/%Y:%H:%M:%S"), gmtoffset.hour)
316            jobsize = entry[fields["jobsize"]]
317            copies = entry[fields["copies"]]
318            hostname = entry[fields["hostname"]]
319            self.outfile.write("%s %s %s [%s] %s %s - %s\n" % (printername, username, jobid, jobdate, jobsize, copies, hostname))
320       
321    def dumpXml(self, entries, datatype) :   
322        """Dumps datas as XML."""
323        x = jaxml.XML_document(encoding="UTF-8")
324        x.pykota(version=version.__version__, author=version.__author__)
325        x.dump(storage=self.config.getStorageBackend()["storagebackend"], type=datatype)
326        headers = entries[0]
327        for entry in entries[1:] :
328            x._push()
329            x.entry()
330            for i in range(len(entry)) :
331                value = str(entry[i])
332                typval = type(entry[i]).__name__
333                try :
334                    value = unicode(value, self.getCharset()).encode("UTF-8")
335                except UnicodeError :   
336                    pass
337                x.attribute(value, type=typval, name=headers[i])
338            x._pop()   
339        x._output(self.outfile)
340                           
341if __name__ == "__main__" : 
342    retcode = 0
343    try :
344        defaults = { \
345                     "format" : "csv", \
346                     "output" : "-", \
347                   }
348        short_options = "vhd:f:o:"
349        long_options = ["help", "version", "data=", "format=", "output="]
350       
351        # Initializes the command line tool
352        dumper = DumPyKota(doc=__doc__)
353       
354        # parse and checks the command line
355        (options, args) = dumper.parseCommandline(sys.argv[1:], short_options, long_options, allownothing=1)
356       
357        # sets long options
358        options["help"] = options["h"] or options["help"]
359        options["version"] = options["v"] or options["version"]
360        options["data"] = options["d"] or options["data"]
361        options["format"] = options["f"] or options["format"] or defaults["format"]
362        options["output"] = options["o"] or options["output"] or defaults["output"]
363       
364        if options["help"] :
365            dumper.display_usage_and_quit()
366        elif options["version"] :
367            dumper.display_version_and_quit()
368        elif options["data"] is None :   
369            raise PyKotaToolError, _("The -d | --data command line option is mandatory, see help.")
370        else :
371            retcode = dumper.main(args, options)
372    except SystemExit :       
373        pass
374    except :
375        try :
376            dumper.crashed("dumpykota failed")
377        except :   
378            crashed("dumpykota failed")
379        retcode = -1
380
381    try :
382        dumper.storage.close()
383    except (TypeError, NameError, AttributeError) :   
384        pass
385       
386    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.