root / pykota / trunk / bin / pkturnkey @ 2435

Revision 2435, 13.9 kB (checked in by jerome, 19 years ago)

Added the --gidmin, --gidmax, --dousers, --dogroups command line switches
to pkturnkey.
Added group management to pkturnkey.
Severity : testers more than welcome :-)

  • 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]
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       
96class PKTurnKey(Tool) :
97    """A class for an initialization tool."""
98    def listPrinters(self) :
99        """Returns a list of tuples (queuename, deviceuri) for all existing print queues."""
100        self.printInfo("Extracting all print queues.")
101        result = os.popen("lpstat -v", "r")
102        lines = result.readlines()
103        result.close()
104        printers = []
105        for line in lines :
106            (begin, end) = line.split(':', 1)
107            deviceuri = end.strip()
108            queuename = begin.split()[-1]
109            printers.append((queuename, deviceuri))
110        return printers   
111       
112    def listUsers(self, uidmin, uidmax) :   
113        """Returns a list of users whose uids are between uidmin and uidmax."""
114        self.printInfo("Extracting all users whose uid is between %s and %s." % (uidmin, uidmax))
115        return [(entry[0], entry[3]) for entry in pwd.getpwall() if uidmin <= entry[2] <= uidmax]
116       
117    def listGroups(self, gidmin, gidmax, users) :
118        """Returns a list of groups whose gids are between gidmin and gidmax."""
119        self.printInfo("Extracting all groups whose gid is between %s and %s." % (gidmin, gidmax))
120        groups = [(entry[0], entry[2], entry[3]) for entry in grp.getgrall() if gidmin <= entry[2] <= gidmax]
121        gidusers = {}
122        usersgid = {}
123        for u in users :
124            gidusers.setdefault(u[1], []).append(u[0])
125            usersgid.setdefault(u[0], []).append(u[1]) 
126           
127        membership = {}   
128        for g in range(len(groups)) :
129            (gname, gid, members) = groups[g]
130            newmembers = {}
131            for m in members :
132                newmembers[m] = m
133            try :
134                usernames = gidusers[gid]
135            except KeyError :   
136                pass
137            else :   
138                for username in usernames :
139                    if not newmembers.has_key(username) :
140                        newmembers[username] = username
141            for member in newmembers.keys() :           
142                if not usersgid.has_key(member) :
143                    del newmembers[member]
144            membership[gname] = newmembers.keys()
145        return membership
146       
147    def runCommand(self, command, dryrun) :   
148        """Launches an external command."""
149        self.printInfo("%s" % command)
150        if not dryrun :   
151            os.system(command)
152           
153    def createPrinters(self, printers, dryrun=0) :   
154        """Creates all printers in PyKota's database."""
155        if printers :
156            needswarning = [p[0] for p in printers if p[1].find("cupspykota") == -1]
157            command = "pkprinters --add %s" % " ".join(['"%s"' % p[0] for p in printers])
158            self.runCommand(command, dryrun)
159            for p in needswarning :
160                self.printInfo(_("Printer %s is not managed by PyKota yet. Please modify printers.conf and restart CUPS.") % p, "warn")
161       
162    def createUsers(self, users, dryrun=0) :
163        """Creates all users in PyKota's database."""
164        if users :
165            command = "edpykota --add --noquota %s" % " ".join(['"%s"' % u for u in users])
166            self.runCommand(command, dryrun)
167           
168    def createGroups(self, groups, dryrun=0) :
169        """Creates all groups in PyKota's database."""
170        if groups :
171            commands = ["edpykota --groups --add --noquota %s" % " ".join(['"%s"' % g for g in groups.keys()])]
172            revmembership = {}
173            for (groupname, usernames) in groups.items() :
174                for username in usernames :
175                    revmembership.setdefault(username, []).append(groupname)
176            for (username, groupnames) in revmembership.items() :       
177                commands.append('edpykota --ingroups %s "%s"' % (",".join(['"%s"' % g for g in groupnames]), username))
178            for command in commands :
179                self.runCommand(command, dryrun)
180       
181    def main(self, names, options) :
182        """Intializes PyKota's database."""
183        if not self.config.isAdmin :
184            raise PyKotaToolError, "%s : %s" % (pwd.getpwuid(os.geteuid())[0], _("You're not allowed to use this command."))
185           
186        # TODO : names not used for now   
187        if not names :
188            names = ["*"]
189           
190        self.printInfo(_("Please be patient..."))
191        dryrun = not options["force"]
192        if dryrun :
193            self.printInfo(_("Don't worry, the database WILL NOT BE MODIFIED."))
194        else :   
195            self.printInfo(_("Please WORRY NOW, the database WILL BE MODIFIED."))
196           
197        if options["dousers"] :   
198            if not options["uidmin"] :   
199                self.printInfo(_("System users will have a print account as well !"), "warn")
200                uidmin = 0
201            else :   
202                try :
203                    uidmin = int(options["uidmin"])
204                except :   
205                    try :
206                        uidmin = pwd.getpwnam(options["uidmin"])[2]
207                    except KeyError, msg :   
208                        raise PyKotaToolError, _("Unknown username %s : %s") % (options["uidmin"], msg)
209                       
210            if not options["uidmax"] :   
211                uidmax = sys.maxint
212            else :   
213                try :
214                    uidmax = int(options["uidmax"])
215                except :   
216                    try :
217                        uidmax = pwd.getpwnam(options["uidmax"])[2]
218                    except KeyError, msg :   
219                        raise PyKotaToolError, _("Unknown username %s : %s") % (options["uidmax"], msg)
220           
221            if uidmin > uidmax :           
222                (uidmin, uidmax) = (uidmax, uidmin)
223            users = self.listUsers(uidmin, uidmax)
224        else :   
225            users = []
226           
227        if options["dogroups"] :   
228            if not options["gidmin"] :   
229                self.printInfo(_("System groups will have a print account as well !"), "warn")
230                gidmin = 0
231            else :   
232                try :
233                    gidmin = int(options["gidmin"])
234                except :   
235                    try :
236                        gidmin = grp.getgrnam(options["gidmin"])[2]
237                    except KeyError, msg :   
238                        raise PyKotaToolError, _("Unknown groupname %s : %s") % (options["gidmin"], msg)
239                       
240            if not options["gidmax"] :   
241                gidmax = sys.maxint
242            else :   
243                try :
244                    gidmax = int(options["gidmax"])
245                except :   
246                    try :
247                        gidmax = grp.getgrnam(options["gidmax"])[2]
248                    except KeyError, msg :   
249                        raise PyKotaToolError, _("Unknown groupname %s : %s") % (options["gidmax"], msg)
250           
251            if gidmin > gidmax :           
252                (gidmin, gidmax) = (gidmax, gidmin)
253            groups = self.listGroups(gidmin, gidmax, users)
254            if not options["emptygroups"] :
255                for (groupname, members) in groups.items() :
256                    if not members :
257                        del groups[groupname]
258        else :   
259            groups = []
260           
261        printers = self.listPrinters()                   
262        if printers :
263            self.createPrinters(printers, dryrun)
264            self.createUsers([entry[0] for entry in users], dryrun)
265            self.createGroups(groups, dryrun)
266       
267        if dryrun :
268            self.printInfo(_("Simulation terminated."))
269        else :   
270            self.printInfo(_("Database initialized !"))
271                   
272                     
273if __name__ == "__main__" : 
274    retcode = 0
275    try :
276        short_options = "hvdDefu:U:g:G:"
277        long_options = ["help", "version", "dousers", "dogroups", \
278                        "emptygroups", "force", "uidmin=", "uidmax=", \
279                        "gidmin=", "gidmax="]
280       
281        # Initializes the command line tool
282        manager = PKTurnKey(doc=__doc__)
283        manager.deferredInit()
284       
285        # parse and checks the command line
286        (options, args) = manager.parseCommandline(sys.argv[1:], \
287                                                   short_options, \
288                                                   long_options, \
289                                                   allownothing=1)
290       
291        # sets long options
292        options["help"] = options["h"] or options["help"]
293        options["version"] = options["v"] or options["version"]
294        options["dousers"] = options["d"] or options["dousers"]
295        options["dogroups"] = options["D"] or options["dogroups"]
296        options["emptygroups"] = options["e"] or options["emptygroups"]
297        options["force"] = options["f"] or options["force"]
298        options["uidmin"] = options["u"] or options["uidmin"]
299        options["uidmax"] = options["U"] or options["uidmax"]
300        options["gidmin"] = options["g"] or options["gidmin"]
301        options["gidmax"] = options["G"] or options["gidmax"]
302       
303        if options["uidmin"] or options["uidmax"] :
304            if not options["dousers"] :
305                manager.printInfo(_("The --uidmin or --uidmax command line option implies --dousers as well."), "warn")
306            options["dousers"] = 1   
307           
308        if options["gidmin"] or options["gidmax"] :
309            if not options["dogroups"] :
310                manager.printInfo(_("The --gidmin or --gidmax command line option implies --dogroups as well."), "warn")
311            options["dogroups"] = 1
312       
313        if options["dogroups"] :
314            if not options["dousers"] :
315                manager.printInfo(_("The --dogroups command line option implies --dousers as well."), "warn")
316            options["dousers"] = 1   
317           
318        if options["help"] :
319            manager.display_usage_and_quit()
320        elif options["version"] :
321            manager.display_version_and_quit()
322        else :
323            retcode = manager.main(args, options)
324    except KeyboardInterrupt :       
325        sys.stderr.write("\nInterrupted with Ctrl+C !\n")
326    except SystemExit :       
327        pass
328    except :
329        try :
330            manager.crashed("pkturnkey failed")
331        except :   
332            crashed("pkturnkey failed")
333        retcode = -1
334
335    try :
336        manager.storage.close()
337    except (TypeError, NameError, AttributeError) :   
338        pass
339       
340    sys.exit(retcode)   
Note: See TracBrowser for help on using the browser.