Changeset 3413 for pykota/trunk/bin/pkturnkey
- Timestamp:
- 09/27/08 22:02:37 (16 years ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
pykota/trunk/bin/pkturnkey
r3411 r3413 9 9 # the Free Software Foundation, either version 3 of the License, or 10 10 # (at your option) any later version. 11 # 11 # 12 12 # This program is distributed in the hope that it will be useful, 13 13 # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 15 # GNU General Public License for more details. 16 # 16 # 17 17 # You should have received a copy of the GNU General Public License 18 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. … … 51 51 -v | --version Prints pkturnkey version number then exits. 52 52 -h | --help Prints this message then exits. 53 53 54 54 -c | --doconf Give hints about what to put into pykota.conf 55 55 56 56 -d | --dousers Manages users accounts as well. 57 57 58 58 -D | --dogroups Manages users groups as well. 59 59 Implies -d | --dousers. 60 60 61 61 -e | --emptygroups Includes empty groups. 62 62 63 63 -f | --force Modifies the database instead of printing what 64 64 it would do. 65 65 66 66 -u | --uidmin uid Only adds users whose uid is greater than or equal to 67 67 uid. You can pass an username there as well, and its … … 69 69 If not set, 0 will be used automatically. 70 70 Implies -d | --dousers. 71 71 72 72 -U | --uidmax uid Only adds users whose uid is lesser than or equal to 73 73 uid. You can pass an username there as well, and its … … 81 81 If not set, 0 will be used automatically. 82 82 Implies -D | --dogroups. 83 83 84 84 -G | --gidmax gid Only adds groups whose gid is lesser than or equal to 85 85 gid. You can pass a groupname there as well, and its … … 88 88 Implies -D | --dogroups. 89 89 90 examples : 90 examples : 91 91 92 92 $ pkturnkey --dousers --uidmin jerome … … 95 95 printers and print accounts for all users whose uid is greater than 96 96 or equal to jerome's one. Won't manage any users group. 97 97 98 98 To REALLY initialize the database instead of simulating it, please 99 99 use the -f | --force command line switch. 100 100 101 101 You can limit the initialization to only a subset of the existing 102 102 printers, by passing their names at the end of the command line. 103 103 """) 104 104 105 105 class PKTurnKey(Tool) : 106 106 """A class for an initialization tool.""" … … 118 118 if self.matchString(queuename, namestomatch) : 119 119 printers.append((queuename, deviceuri)) 120 else : 120 else : 121 121 self.printInfo("Print queue %s skipped." % queuename) 122 return printers 123 124 def listUsers(self, uidmin, uidmax) : 122 return printers 123 124 def listUsers(self, uidmin, uidmax) : 125 125 """Returns a list of users whose uids are between uidmin and uidmax.""" 126 126 self.printInfo("Extracting all users whose uid is between %s and %s." % (uidmin, uidmax)) 127 127 return [(entry[0], entry[3]) for entry in pwd.getpwall() if uidmin <= entry[2] <= uidmax] 128 128 129 129 def listGroups(self, gidmin, gidmax, users) : 130 130 """Returns a list of groups whose gids are between gidmin and gidmax.""" … … 135 135 for u in users : 136 136 gidusers.setdefault(u[1], []).append(u[0]) 137 usersgid.setdefault(u[0], []).append(u[1]) 138 139 membership = {} 137 usersgid.setdefault(u[0], []).append(u[1]) 138 139 membership = {} 140 140 for g in range(len(groups)) : 141 141 (gname, gid, members) = groups[g] … … 145 145 try : 146 146 usernames = gidusers[gid] 147 except KeyError : 147 except KeyError : 148 148 pass 149 else : 149 else : 150 150 for username in usernames : 151 151 if not newmembers.has_key(username) : 152 152 newmembers[username] = username 153 for member in newmembers.keys() : 153 for member in newmembers.keys() : 154 154 if not usersgid.has_key(member) : 155 155 del newmembers[member] 156 156 membership[gname] = newmembers.keys() 157 157 return membership 158 159 def runCommand(self, command, dryrun) : 158 159 def runCommand(self, command, dryrun) : 160 160 """Launches an external command.""" 161 161 self.printInfo("%s" % command) 162 if not dryrun : 162 if not dryrun : 163 163 os.system(command) 164 165 def createPrinters(self, printers, dryrun=0) : 164 165 def createPrinters(self, printers, dryrun=0) : 166 166 """Creates all printers in PyKota's database.""" 167 167 if printers : … … 171 171 args.close() 172 172 self.runCommand("pkprinters --arguments /tmp/pkprinters.args", dryrun) 173 173 174 174 def createUsers(self, users, printers, dryrun=0) : 175 175 """Creates all users in PyKota's database.""" … … 180 180 args.close() 181 181 self.runCommand("pkusers --arguments /tmp/pkusers.users.args", dryrun) 182 182 183 183 printersnames = [p[0] for p in printers] 184 184 args = open("/tmp/edpykota.users.args", "w") … … 188 188 args.close() 189 189 self.runCommand("edpykota --arguments /tmp/edpykota.users.args", dryrun) 190 190 191 191 def createGroups(self, groups, printers, dryrun=0) : 192 192 """Creates all groups in PyKota's database.""" … … 197 197 args.close() 198 198 self.runCommand("pkusers --arguments /tmp/pkusers.groups.args", dryrun) 199 199 200 200 printersnames = [p[0] for p in printers] 201 201 args = open("/tmp/edpykota.groups.args", "w") … … 205 205 args.close() 206 206 self.runCommand("edpykota --arguments /tmp/edpykota.groups.args", dryrun) 207 207 208 208 revmembership = {} 209 209 for (groupname, usernames) in groups.items() : 210 210 for username in usernames : 211 211 revmembership.setdefault(username, []).append(groupname) 212 commands = [] 213 for (username, groupnames) in revmembership.items() : 212 commands = [] 213 for (username, groupnames) in revmembership.items() : 214 214 commands.append('pkusers --ingroups %s "%s"' \ 215 215 % (",".join(['"%s"' % g for g in groupnames]), username)) 216 216 for command in commands : 217 217 self.runCommand(command, dryrun) 218 218 219 219 def supportsSNMP(self, hostname, community) : 220 220 """Returns 1 if the printer accepts SNMP queries, else 0.""" … … 222 222 try : 223 223 from pysnmp.entity.rfc3413.oneliner import cmdgen 224 except ImportError : 224 except ImportError : 225 225 hasV4 = False 226 226 try : … … 228 228 from pysnmp.mapping.udp.role import Manager 229 229 from pysnmp.proto.api import alpha 230 except ImportError : 230 except ImportError : 231 231 logerr("pysnmp doesn't seem to be installed. SNMP checks will be ignored !\n") 232 232 return 0 233 else : 233 else : 234 234 hasV4 = True 235 236 if hasV4 : 235 236 if hasV4 : 237 237 def retrieveSNMPValues(hostname, community) : 238 238 """Retrieves a printer's internal page counter and status via SNMP.""" … … 241 241 cmdgen.UdpTransportTarget((hostname, 161)), \ 242 242 tuple([int(i) for i in pageCounterOID.split('.')])) 243 if errorIndication : 243 if errorIndication : 244 244 raise "No SNMP !" 245 elif errorStatus : 245 elif errorStatus : 246 246 raise "No SNMP !" 247 else : 247 else : 248 248 self.SNMPOK = True 249 249 else : 250 def retrieveSNMPValues(hostname, community) : 250 def retrieveSNMPValues(hostname, community) : 251 251 """Retrieves a printer's internal page counter and status via SNMP.""" 252 252 ver = alpha.protoVersions[alpha.protoVersionId1] … … 260 260 (hostname, 161), \ 261 261 (handleAnswer, req)) 262 except : 262 except : 263 263 raise "No SNMP !" 264 264 tsp.close() 265 265 266 266 def handleAnswer(wholemsg, notusedhere, req): 267 267 """Decodes and handles the SNMP answer.""" … … 270 270 try : 271 271 rsp.berDecode(wholemsg) 272 except TypeMismatchError, msg : 272 except TypeMismatchError, msg : 273 273 raise "No SNMP !" 274 274 else : … … 281 281 for varBind in rsp.apiAlphaGetPdu().apiAlphaGetVarBindList(): 282 282 self.values.append(varBind.apiAlphaGetOidVal()[1].rawAsn1Value) 283 try : 283 try : 284 284 pagecounter = self.values[0] 285 285 except : 286 286 raise "No SNMP !" 287 else : 287 else : 288 288 self.SNMPOK = 1 289 289 return 1 290 290 291 291 self.SNMPOK = 0 292 292 try : 293 293 retrieveSNMPValues(hostname, community) 294 except : 294 except : 295 295 self.SNMPOK = 0 296 296 return self.SNMPOK 297 297 298 298 def supportsPJL(self, hostname, port) : 299 299 """Returns 1 if the printer accepts PJL queries over TCP, else 0.""" 300 300 def alarmHandler(signum, frame) : 301 301 raise "Timeout !" 302 302 303 303 pjlsupport = 0 304 304 signal.signal(signal.SIGALRM, alarmHandler) … … 311 311 if not answer.startswith("@PJL") : 312 312 raise "No PJL !" 313 except : 313 except : 314 314 pass 315 else : 315 else : 316 316 pjlsupport = 1 317 317 s.close() … … 319 319 signal.signal(signal.SIGALRM, signal.SIG_IGN) 320 320 return pjlsupport 321 322 def hintConfig(self, printers) : 321 322 def hintConfig(self, printers) : 323 323 """Gives some hints about what to put into pykota.conf""" 324 324 if not printers : 325 325 return 326 sys.stderr.flush() # ensure outputs don't mix 327 print 326 sys.stderr.flush() # ensure outputs don't mix 327 print 328 328 print "--- CUT ---" 329 329 print "# Here are some lines that we suggest you add at the end" … … 338 338 try : 339 339 uri = uri.split("cupspykota:", 2)[-1] 340 except (ValueError, IndexError) : 340 except (ValueError, IndexError) : 341 341 pass 342 else : 342 else : 343 343 while uri and uri.startswith("/") : 344 344 uri = uri[1:] 345 345 try : 346 (backend, destination) = uri.split(":", 1) 346 (backend, destination) = uri.split(":", 1) 347 347 if backend not in ("ipp", "http", "https", "lpd", "socket") : 348 348 raise ValueError 349 except ValueError : 349 except ValueError : 350 350 pass 351 else : 351 else : 352 352 while destination.startswith("/") : 353 353 destination = destination[1:] 354 checkauth = destination.split("@", 1) 354 checkauth = destination.split("@", 1) 355 355 if len(checkauth) == 2 : 356 356 destination = checkauth[1] … … 362 362 except ValueError : 363 363 port = 9100 364 else : 364 else : 365 365 (hostname, port) = parts[0], 9100 366 366 367 367 if self.supportsSNMP(hostname, "public") : 368 368 accounter = "hardware(snmp)" … … 371 371 elif self.supportsPJL(hostname, 9101) : 372 372 accounter = "hardware(pjl:9101)" 373 elif self.supportsPJL(hostname, port) : 373 elif self.supportsPJL(hostname, port) : 374 374 accounter = "hardware(pjl:%s)" % port 375 376 print "preaccounter : software()" 375 376 print "preaccounter : software()" 377 377 print "accounter : %s" % accounter 378 378 print 379 379 print "--- CUT ---" 380 380 381 381 def main(self, names, options) : 382 382 """Intializes PyKota's database.""" 383 383 self.adminOnly() 384 384 385 385 if not names : 386 386 names = ["*"] 387 387 388 388 self.printInfo(_("Please be patient...")) 389 389 dryrun = not options["force"] 390 390 if dryrun : 391 391 self.printInfo(_("Don't worry, the database WILL NOT BE MODIFIED.")) 392 else : 392 else : 393 393 self.printInfo(_("Please WORRY NOW, the database WILL BE MODIFIED.")) 394 395 if options["dousers"] : 396 if not options["uidmin"] : 394 395 if options["dousers"] : 396 if not options["uidmin"] : 397 397 self.printInfo(_("System users will have a print account as well !"), "warn") 398 398 uidmin = 0 399 else : 399 else : 400 400 try : 401 401 uidmin = int(options["uidmin"]) 402 except : 402 except : 403 403 try : 404 404 uidmin = pwd.getpwnam(options["uidmin"])[2] 405 except KeyError, msg : 405 except KeyError, msg : 406 406 raise PyKotaCommandLineError, _("Unknown username %s : %s") \ 407 407 % (options["uidmin"], msg) 408 409 if not options["uidmax"] : 408 409 if not options["uidmax"] : 410 410 uidmax = sys.maxint 411 else : 411 else : 412 412 try : 413 413 uidmax = int(options["uidmax"]) 414 except : 414 except : 415 415 try : 416 416 uidmax = pwd.getpwnam(options["uidmax"])[2] 417 except KeyError, msg : 417 except KeyError, msg : 418 418 raise PyKotaCommandLineError, _("Unknown username %s : %s") \ 419 419 % (options["uidmax"], msg) 420 421 if uidmin > uidmax : 420 421 if uidmin > uidmax : 422 422 (uidmin, uidmax) = (uidmax, uidmin) 423 423 users = self.listUsers(uidmin, uidmax) 424 else : 424 else : 425 425 users = [] 426 427 if options["dogroups"] : 428 if not options["gidmin"] : 426 427 if options["dogroups"] : 428 if not options["gidmin"] : 429 429 self.printInfo(_("System groups will have a print account as well !"), "warn") 430 430 gidmin = 0 431 else : 431 else : 432 432 try : 433 433 gidmin = int(options["gidmin"]) 434 except : 434 except : 435 435 try : 436 436 gidmin = grp.getgrnam(options["gidmin"])[2] 437 except KeyError, msg : 437 except KeyError, msg : 438 438 raise PyKotaCommandLineError, _("Unknown groupname %s : %s") \ 439 439 % (options["gidmin"], msg) 440 441 if not options["gidmax"] : 440 441 if not options["gidmax"] : 442 442 gidmax = sys.maxint 443 else : 443 else : 444 444 try : 445 445 gidmax = int(options["gidmax"]) 446 except : 446 except : 447 447 try : 448 448 gidmax = grp.getgrnam(options["gidmax"])[2] 449 except KeyError, msg : 449 except KeyError, msg : 450 450 raise PyKotaCommandLineError, _("Unknown groupname %s : %s") \ 451 451 % (options["gidmax"], msg) 452 453 if gidmin > gidmax : 452 453 if gidmin > gidmax : 454 454 (gidmin, gidmax) = (gidmax, gidmin) 455 455 groups = self.listGroups(gidmin, gidmax, users) … … 458 458 if not members : 459 459 del groups[groupname] 460 else : 460 else : 461 461 groups = [] 462 462 463 463 printers = self.listPrinters(names) 464 464 if printers : … … 466 466 self.createUsers([entry[0] for entry in users], printers, dryrun) 467 467 self.createGroups(groups, printers, dryrun) 468 468 469 469 if dryrun : 470 470 self.printInfo(_("Simulation terminated.")) 471 else : 471 else : 472 472 self.printInfo(_("Database initialized !")) 473 474 if options["doconf"] : 473 474 if options["doconf"] : 475 475 self.hintConfig(printers) 476 477 478 if __name__ == "__main__" : 476 477 478 if __name__ == "__main__" : 479 479 retcode = 0 480 480 try : … … 483 483 "emptygroups", "force", "uidmin=", "uidmax=", \ 484 484 "gidmin=", "gidmax=", "doconf"] 485 485 486 486 # Initializes the command line tool 487 487 manager = PKTurnKey(doc=__doc__) 488 488 manager.deferredInit() 489 489 490 490 # parse and checks the command line 491 491 (options, args) = manager.parseCommandline(sys.argv[1:], \ … … 493 493 long_options, \ 494 494 allownothing=1) 495 495 496 496 # sets long options 497 497 options["help"] = options["h"] or options["help"] … … 506 506 options["gidmax"] = options["G"] or options["gidmax"] 507 507 options["doconf"] = options["c"] or options["doconf"] 508 508 509 509 if options["uidmin"] or options["uidmax"] : 510 510 if not options["dousers"] : 511 511 manager.printInfo(_("The --uidmin or --uidmax command line option implies --dousers as well."), "warn") 512 options["dousers"] = 1 513 512 options["dousers"] = 1 513 514 514 if options["gidmin"] or options["gidmax"] : 515 515 if not options["dogroups"] : 516 516 manager.printInfo(_("The --gidmin or --gidmax command line option implies --dogroups as well."), "warn") 517 517 options["dogroups"] = 1 518 518 519 519 if options["dogroups"] : 520 520 if not options["dousers"] : 521 521 manager.printInfo(_("The --dogroups command line option implies --dousers as well."), "warn") 522 options["dousers"] = 1 523 522 options["dousers"] = 1 523 524 524 if options["help"] : 525 525 manager.display_usage_and_quit() … … 528 528 else : 529 529 retcode = manager.main(args, options) 530 except KeyboardInterrupt : 530 except KeyboardInterrupt : 531 531 logerr("\nInterrupted with Ctrl+C !\n") 532 532 retcode = -3 533 except PyKotaCommandLineError, msg : 533 except PyKotaCommandLineError, msg : 534 534 logerr("%s : %s\n" % (sys.argv[0], msg)) 535 535 retcode = -2 536 except SystemExit : 536 except SystemExit : 537 537 pass 538 538 except : 539 539 try : 540 540 manager.crashed("pkturnkey failed") 541 except : 541 except : 542 542 crashed("pkturnkey failed") 543 543 retcode = -1 … … 545 545 try : 546 546 manager.storage.close() 547 except (TypeError, NameError, AttributeError) : 547 except (TypeError, NameError, AttributeError) : 548 548 pass 549 550 sys.exit(retcode) 549 550 sys.exit(retcode)