Printtracker.py

From Nuclear Physics Group Documentation Pages
Revision as of 01:31, 23 November 2010 by Aduston (talk | contribs)
Jump to navigationJump to search
#!/usr/bin/env python
# A script for gathering printer usage information on Cups print servers.

# Copyright (C) 2010 Adam Duston

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


import sys, os, subprocess
from datetime import date, timedelta

# Log file paths
CUPSLOGPATH = "/var/log/cups/page_log"
USAGELOGPATH = "/var/log/printtracker/weekly_usage" 
REPORTPATH = "/var/log/printtracker/monthly_report"

# Where reports should be sent
REPORTTO = "npg-admins@einstein.unh.edu"
CC = "aduston@physics.unh.edu"

def get_users():
    """
        Return a list of usernames from ldap using getent.
    """
    return [line.split(':')[0] for line in subprocess.Popen("getent passwd",
            stdout=subprocess.PIPE, shell=True).stdout.readlines()]

def calc_totals(logpath, index):
    """
        Sum up the total number of pages printed per user from the given log.
        The index argument determines the column (space delimited) in the log
        that contains the values to sum. Returns username and page totals as 
        a list of tuples.
    """    
    # Start an empty list to store output
    list = [] 

    # Sum up the given column index in the log file for each user 
    for user in get_users():
        sum = 0
        for line in open(logpath):
            if user in line:
                sum += int(line.split()[index])
        # Only add a user to the output if they've printed something.
        if sum > 0:
           list.append((user, sum)) 

    return list 

def weekly_totals():
    """
        Append page totals to this month's running total file.
        Logs are rotated weekly, so this needs to run once a week. 
    """
    # Open the output file in append mode.
    outfile = open(USAGELOGPATH, "a")
    # Write usernames and total pages printed one per line in the output file
    outfile.writelines(["%s %i\n" % (x[0], x[1]) for x in 
                        calc_totals(CUPSLOGPATH, 6)]) 

def monthly_report():
    """
        Generate a monthly print usage report and e-mail it, clean out weekly log
    """
    # Since cron.monthly runs on the first day of the month we need to find
    # yesterday's date in order to label the report with the correct month
    yesterday = date.today() - timedelta(days=1) 

    HEADER = "Printer usage report for %s:" % yesterday.strftime("%B %Y")
    
    # Print the report to a file
    report = open(REPORTPATH, "w")
    report.writelines(HEADER + '\n\n')
    report.writelines(["%s: %i\n" % (x[0], x[1]) for x in
                       calc_totals(USAGELOGPATH, 1)]) 

    # Format the command to e-mail the usage report
    command = "mail -s \"Printtracker Monthly Report\" -c " + CC + " " + \
              REPORTTO + " < " + REPORTPATH
    
    # Send the report
    subprocess.Popen(command, shell=True) 

    # Clean old values from the weekly log
    open(USAGELOGPATH, "w").write("")  

def usage():
    """
        Print usage information
    """
    print "Usage: printtracker.py [options]"
    print "Options:"
    print "-m, --monthly"
    print "    Generate a monthly print usage report and send it via e-mail to the  administrator."
    print "-w, --weekly"
    print "    Generate weekly per-user print totals and append to the monthly usage log."

def main():
    try:
        arg = sys.argv[1]
        if arg == "-w" or arg == "--weekly":
            weekly_totals()
        elif arg == "-m" or arg == "--monthly":
            monthly_report()
        else:
            usage()
    except:
        usage() 
        sys.exit(1)
        
if __name__ == "__main__":
    main()