root / pykota / trunk / bin / pkturnkey @ 2466

Revision 2466, 14.6 kB (checked in by jerome, 19 years ago)

Much more powerful pkturnkey

  • 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 Turn Key tool
5#
6# PyKota - Print Quotas for CUPS and LPRng
7#
8# (c) 2003, 2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22#
23# $Id$
24#
25#
26
27import sys
28import os
29import pwd
30import grp
31
32from pykota.tool import Tool, PyKotaToolError, crashed, N_
33
34__doc__ = N_("""pkturnkey v%(__version__)s (c) %(__years__)s %(__author__)s
35
36A turn key tool for PyKota. When launched, this command will initialize
37PyKota's database with all existing print queues and some or all users.
38For now, no prices or limits are set, so printing is fully accounted
39for, but not limited.
40
41command line usage :
42
43  pkturnkey [options] [printqueues names]
44
45options :
46
47  -v | --version       Prints pkturnkey version number then exits.
48  -h | --help          Prints this message then exits.
49 
50  -d | --dousers       Manages users accounts as well.
51 
52  -D | --dogroups      Manages users groups as well.
53                       Implies -d | --dousers.
54 
55  -e | --emptygroups   Includes empty groups.
56 
57  -f | --force         Modifies the database instead of printing what
58                       it would do.
59                       
60  -u | --uidmin uid    Only adds users whose uid is greater than or equal to
61                       uid. You can pass an username there as well, and its
62                       uid will be used automatically.
63                       If not set, 0 will be used automatically.
64                       Implies -d | --dousers.
65                       
66  -U | --uidmax uid    Only adds users whose uid is lesser than or equal to
67                       uid. You can pass an username there as well, and its
68                       uid will be used automatically.
69                       If not set, a large value will be used automatically.
70                       Implies -d | --dousers.
71
72  -g | --gidmin gid    Only adds groups whose gid is greater than or equal to
73                       gid. You can pass a groupname there as well, and its
74                       gid will be used automatically.
75                       If not set, 0 will be used automatically.
76                       Implies -D | --dogroups.
77                       
78  -G | --gidmax gid    Only adds groups whose gid is lesser than or equal to
79                       gid. You can pass a groupname there as well, and its
80                       gid will be used automatically.
81                       If not set, a large value will be used automatically.
82                       Implies -D | --dogroups.
83
84examples :                             
85
86  $ pkturnkey --dousers --uidmin jerome
87
88  Will simulate the initialization of PyKota's database will all existing
89  printers and print accounts for all users whose uid is greater than
90  or equal to jerome's one. Won't manage any users group.
91 
92  To REALLY initialize the database instead of simulating it, please
93  use the -f | --force command line switch.
94 
95  You can limit the initialization to only a subset of the existing
96  printers, by passing their names at the end of the command line.
97""")
98       
99class PKTurnKey(Tool) :
100    """A class for an initialization tool."""
101    def listPrinters(self, namestomatch) :
102        """Returns a list of tuples (queuename, deviceuri) for all existing print queues."""
103        self.printInfo("Extracting all print queues.")
104        result = os.popen("lpstat -v", "r")
105        lines = result.readlines()
106        result.close()
107        printers = []
108        for line in lines :
109            (begin, end) = line.split(':', 1)
110            deviceuri = end.strip()
111            queuename = begin.split()[-1]
112            if self.matchString(queuename, namestomatch) :
113                printers.append((queuename, deviceuri))
114            else :   
115                self.printInfo("Print queue %s skipped." % queuename)
116        return printers   
117       
118    def listUsers(self, uidmin, uidmax) :   
119        """Returns a list of users whose uids are between uidmin and uidmax."""
120        self.printInfo("Extracting all users whose uid is between %s and %s." % (uidmin, uidmax))
121        return [(entry[0], entry[3]) for entry in pwd.getpwall() if uidmin <= entry[2] <= uidmax]
122       
123    def listGroups(self, gidmin, gidmax, users) :
124        """Returns a list of groups whose gids are between gidmin and gidmax."""
125        self.printInfo("Extracting all groups whose gid is between %s and %s." % (gidmin, gidmax))
126        groups = [(entry[0], entry[2], entry[3]) for entry in grp.getgrall() if gidmin <= entry[2] <= gidmax]
127        gidusers = {}
128        usersgid = {}
129        for u in users :
130            gidusers.setdefault(u[1], []).append(u[0])
131            usersgid.setdefault(u[0], []).append(u[1]) 
132           
133        membership = {}   
134        for g in range(len(groups)) :
135            (gname, gid, members) = groups[g]
136            newmembers = {}
137            for m in members :
138                newmembers[m] = m
139            try :
140                usernames = gidusers[gid]
141            except KeyError :   
142                pass
143            else :   
144                for username in usernames :
145                    if not newmembers.has_key(username) :
146                        newmembers[username] = username
147            for member in newmembers.keys() :           
148                if not usersgid.has_key(member) :
149                    del newmembers[member]
150            membership[gname] = newmembers.keys()
151        return membership
152       
153    def runCommand(self, command, dryrun) :   
154        """Launches an external command."""
155        self.printInfo("%s" % command)
156        if not dryrun :   
157            os.system(command)
158           
159    def createPrinters(self, printers, dryrun=0) :   
160        """Creates all printers in PyKota's database."""
161        if printers :
162            needswarning = [p[0] for p in printers if p[1].find("cupspykota") == -1]
163            command = "pkprinters --add %s" % " ".join(['"%s"' % p[0] for p in printers])
164            self.runCommand(command, dryrun)
165            for p in needswarning :
166                self.printInfo(_("Printer %s is not managed by PyKota yet. Please modify printers.conf and restart CUPS.") % p, "warn")
167       
168    def createUsers(self, users, printers, dryrun=0) :
169        """Creates all users in PyKota's database."""
170        if users :
171            printersnames = [p[0] for p in printers]
172            command = "edpykota --add --noquota --printer %s %s" % (",".join(['"%s"' % p for p in printersnames]), \
173                                                                    " ".join(['"%s"' % u for u in users]))
174            self.runCommand(command, dryrun)
175           
176    def createGroups(self, groups, printers, dryrun=0) :
177        """Creates all groups in PyKota's database."""
178        if groups :
179            printersnames = [p[0] for p in printers]
180            commands = ["edpykota --add --groups --noquota --printer %s %s" % (",".join(['"%s"' % p for p in printersnames]), \
181                                                                               " ".join(['"%s"' % g for g in groups.keys()]))]
182            revmembership = {}
183            for (groupname, usernames) in groups.items() :
184                for username in usernames :
185                    revmembership.setdefault(username, []).append(groupname)
186            for (username, groupnames) in revmembership.items() :       
187                commands.append('edpykota --ingroups %s "%s"' % (",".join(['"%s"' % g for g in groupnames]), username))
188            for command in commands :
189                self.runCommand(command, dryrun)
190       
191    def main(self, names, options) :
192        """Intializes PyKota's database."""
193        if not self.config.isAdmin :
194            raise PyKotaToolError, "%s : %s" % (pwd.getpwuid(os.geteuid())[0], _("You're not allowed to use this command."))
195           
196        if not names :
197            names = ["*"]
198           
199        self.printInfo(_("Please be patient..."))
200        dryrun = not options["force"]
201        if dryrun :
202            self.printInfo(_("Don't worry, the database WILL NOT BE MODIFIED."))
203        else :   
204            self.printInfo(_("Please WORRY NOW, the database WILL BE MODIFIED."))
205           
206        if options["dousers"] :   
207            if not options["uidmin"] :   
208                self.printInfo(_("System users will have a print account as well !"), "warn")
209                uidmin = 0
210            else :   
211                try :
212                    uidmin = int(options["uidmin"])
213                except :   
214                    try :
215                        uidmin = pwd.getpwnam(options["uidmin"])[2]
216                    except KeyError, msg :   
217                        raise PyKotaToolError, _("Unknown username %s : %s") % (options["uidmin"], msg)
218                       
219            if not options["uidmax"] :   
220                uidmax = sys.maxint
221            else :   
222                try :
223                    uidmax = int(options["uidmax"])
224                except :   
225                    try :
226                        uidmax = pwd.getpwnam(options["uidmax"])[2]
227                    except KeyError, msg :   
228                        raise PyKotaToolError, _("Unknown username %s : %s") % (options["uidmax"], msg)
229           
230            if uidmin > uidmax :           
231                (uidmin, uidmax) = (uidmax, uidmin)
232            users = self.listUsers(uidmin, uidmax)
233        else :   
234            users = []
235           
236        if options["dogroups"] :   
237            if not options["gidmin"] :   
238                self.printInfo(_("System groups will have a print account as well !"), "warn")
239                gidmin = 0
240            else :   
241                try :
242                    gidmin = int(options["gidmin"])
243                except :   
244                    try :
245                        gidmin = grp.getgrnam(options["gidmin"])[2]
246                    except KeyError, msg :   
247                        raise PyKotaToolError, _("Unknown groupname %s : %s") % (options["gidmin"], msg)
248                       
249            if not options["gidmax"] :   
250                gidmax = sys.maxint
251            else :   
252                try :
253                    gidmax = int(options["gidmax"])
254                except :   
255                    try :
256                        gidmax = grp.getgrnam(options["gidmax"])[2]
257                    except KeyError, msg :   
258                        raise PyKotaToolError, _("Unknown groupname %s : %s") % (options["gidmax"], msg)
259           
260            if gidmin > gidmax :           
261                (gidmin, gidmax) = (gidmax, gidmin)
262            groups = self.listGroups(gidmin, gidmax, users)
263            if not options["emptygroups"] :
264                for (groupname, members) in groups.items() :
265                    if not members :
266                        del groups[groupname]
267        else :   
268            groups = []
269           
270        printers = self.listPrinters(names)
271        if printers :
272            self.createPrinters(printers, dryrun)
273            self.createUsers([entry[0] for entry in users], printers, dryrun)
274            self.createGroups(groups, printers, dryrun)
275       
276        if dryrun :
277            self.printInfo(_("Simulation terminated."))
278        else :   
279            self.printInfo(_("Database initialized !"))
280                   
281                     
282if __name__ == "__main__" : 
283    retcode = 0
284    try :
285        short_options = "hvdDefu:U:g:G:"
286        long_options = ["help", "version", "dousers", "dogroups", \
287                        "emptygroups", "force", "uidmin=", "uidmax=", \
288                        "gidmin=", "gidmax="]
289       
290        # Initializes the command line tool
291        manager = PKTurnKey(doc=__doc__)
292        manager.deferredInit()
293       
294        # parse and checks the command line
295        (options, args) = manager.parseCommandline(sys.argv[1:], \
296                                                   short_options, \
297                                                   long_options, \
298                                                   allownothing=1)
299       
300        # sets long options
301        options["help"] = options["h"] or options["help"]
302        options["version"] = options["v"] or options["version"]
303        options["dousers"] = options["d"] or options["dousers"]
304        options["dogroups"] = options["D"] or options["dogroups"]
305        options["emptygroups"] = options["e"] or options["emptygroups"]
306        options["force"] = options["f"] or options["force"]
307        options["uidmin"] = options["u"] or options["uidmin"]
308        options["uidmax"] = options["U"] or options["uidmax"]
309        options["gidmin"] = options["g"] or options["gidmin"]
310        options["gidmax"] = options["G"] or options["gidmax"]
311       
312        if options["uidmin"] or options["uidmax"] :
313            if not options["dousers"] :
314                manager.printInfo(_("The --uidmin or --uidmax command line option implies --dousers as well."), "warn")
315            options["dousers"] = 1   
316           
317        if options["gidmin"] or options["gidmax"] :
318            if not options["dogroups"] :
319                manager.printInfo(_("The --gidmin or --gidmax command line option implies --dogroups as well."), "warn")
320            options["dogroups"] = 1
321       
322        if options["dogroups"] :
323            if not options["dousers"] :
324                manager.printInfo(_("The --dogroups command line option implies --dousers as well."), "warn")
325            options["dousers"] = 1   
326           
327        if options["help"] :
328            manager.display_usage_and_quit()
329        elif options["version"] :
330            manager.display_version_and_quit()
331        else :
332            retcode = manager.main(args, options)
333    except KeyboardInterrupt :       
334        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
335    except SystemExit :       
336        pass
337    except :
338        try :
339            manager.crashed("pkturnkey failed")
340        except :   
341            crashed("pkturnkey failed")
342        retcode = -1
343
344    try :
345        manager.storage.close()
346    except (TypeError, NameError, AttributeError) :   
347        pass
348       
349    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.