#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# (c) Copyright 2003-2015 HP Development Company, L.P.
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
#
# Author: Amarnath Chitumalla
#
from __future__ import print_function
__version__ = '1.0'
__title__ = 'HPLIP logs capture Utility'
__mod__ = 'hp-logcapture'
__doc__ = """Captures the HPLIP log files."""

import os
import sys
import getopt
import glob
import datetime

from base.g import *
from base import utils,tui,module, os_utils
from base.sixext import to_string_utf8
from subprocess import Popen, PIPE
from installer.core_install import *

CUPS_FILE='/etc/cups/cupsd.conf'
CUPS_BACKUP_FILE='/etc/cups/cupsd.conf_orginal'
LOG_FOLDER_PATH='./'
LOG_FOLDER_NAME='hplip_troubleshoot_logs'
LOG_FILES=LOG_FOLDER_PATH + LOG_FOLDER_NAME
TMP_DIR = "/var/spool/cups/tmp"
USER_NAME =""
USERS={}
################ is_journal() function ##############
#Capture logs from system journal for Fedora 21 onwards

def is_journal():
    core =  CoreInstall(MODE_INSTALLER, INTERACTIVE_MODE)
    core.get_distro()
    distro_name = core.distro_name
    distro_ver = core.distro_version
    if distro_name == "fedora" and distro_ver >=" 21" :
        journal = True
    else:
        journal = False
    return journal

############ enable_log() function ############
#This function changes CUPS conf log level to debug and restarts CUPS service.

def enable_log():
    result = False
    cmd='cp -f %s %s'%(CUPS_FILE,CUPS_BACKUP_FILE)
    log.debug("Backup CUPS conf file. cmd =%s"%cmd)
    sts,out=utils.run(cmd)
    if sts != 0:
        log.error("Failed to take back cups file=%s"%CUPS_FILE)

    #check if cups is log level enabled or disable
    cmd="grep 'LogLevel warn' %s"%CUPS_FILE
    log.debug ("cmd= %s"%cmd)
    sts,out=utils.run(cmd)
    if sts == 0:
        cmd = "sed -i 's/LogLevel.*warn/LogLevel debug\rhpLogLevel 15/' %s "%CUPS_FILE
        log.debug("Changing 'Log level' to debug. cmd=%s"%cmd)
        sts= os.system(cmd)
        if sts != 0:
           log.error("Failed to update Loglevel to Debug in cups=%s"%CUPS_FILE)

        cmd=None
        if utils.which('service'):
           cmd = os.path.join(utils.which('service'), 'service')+" cups restart"
        elif utils.which('systemctl'):
           cmd = os.path.join(utils.which('systemctl'), 'systemctl')+" restart %s.service"%service_name
        elif os.path.exists('/etc/init.d/cups'):
           cmd = "/etc/init.d/cups restart"
        else:
           log.error("service command not found.. Please restart cups manually..")

        if cmd:
           log.debug("CUPS restart cmd = %s"%cmd)
           sts,out = utils.run(cmd)
           if sts == 0:
               result = True

    return result

############ restore_loglevels() function ############
#This function restores CUPS conf file to previous value and restarts CUPS service.

def restore_loglevels():
    result = False
    cmd='cp -f %s %s'%(CUPS_BACKUP_FILE,CUPS_FILE)
    log.debug("Restoring CUPS conf file. cmd=%s"%cmd)
    sts, out = utils.run(cmd)
    if sts == 0:
       cmd='rm -f %s'%CUPS_BACKUP_FILE
       log.debug("Removing Temporary file.. cmd=%s"%cmd)
       sts,out = utils.run(cmd)
       if sts != 0:
            log.warn("Failed to remove the Temporary backup file=%s"%CUPS_BACKUP_FILE)
    else:
       log.error("Failed to restore cups config file = %s"%CUPS_FILE)
    log.debug("Restarting CUPS service")

    cmd=None
    if utils.which('service'):
       cmd = os.path.join(utils.which('service'), 'service')+" cups restart"
    elif utils.which('systemctl'):
       cmd = os.path.join(utils.which('systemctl'), 'systemctl')+" restart %s.service"%service_name
    elif os.path.exists('/etc/init.d/cups'):
       cmd = "/etc/init.d/cups restart"
    else:
       log.error("service command not found.. Please restart cups manually..")

    if cmd:
        log.debug("CUPS restart cmd = %s"%cmd)
        sts,out = utils.run(cmd)
        if sts == 0:
           result = True

    return result

def usage(typ='text'):
    if typ == 'text':
        utils.log_title(__title__, __version__)

    utils.format_text(USAGE, typ, __title__, __mod__, __version__)
    sys.exit(0)


def backup_clearLog(strLog):
    if os.path.exists(strLog):
        iArch =1
        while os.path.exists("%s.%d"%(strLog, iArch)) or os.path.exists("%s.%d.gz"%(strLog, iArch)):
            iArch +=1
        sts,out = utils.run('cp %s %s.%d'%(strLog, strLog, iArch))
        if sts != 0:
            log.error("Failed to archive %s log file"%strLog)
        else:
            cmd = 'cat /dev/null > %s' % strLog
            sts = os_utils.execute(cmd)
            if sts != 0:
                log.warn("Failed to clear the %s log file"%strLog)
            if utils.which('gzip'):
                sts,out = utils.run ('gzip %s.%d'%(strLog, iArch))
                if sts != 0:
                    log.info("Existing %s log file copied to %s.%d"%(strLog, strLog, iArch))
                else:
                    log.info("Existing %s log file copied to %s.%d.gz"%(strLog, strLog, iArch))
            else:
                log.info("Existing %s log file copied to %s.%d"%(strLog, strLog, iArch))



USAGE = [(__doc__, "", "name", True),
         ("Usage: [su -c /sudo] %s [USER INFO] [OPTIONS]" % __mod__, "", "summary", True),
         ("e.g. su -c '%s'"%__mod__,"","summary",True),
         ("[USER INFO]", "", "heading", False),
         ("User name for which logs to be collected:", "--user=<username> ", "option", False),
         utils.USAGE_OPTIONS,
         utils.USAGE_HELP,
         utils.USAGE_LOGGING1, utils.USAGE_LOGGING2, utils.USAGE_LOGGING3,
        ]


######## Main #######
try:
    mod = module.Module(__mod__, __title__, __version__, __doc__, USAGE,
                    (INTERACTIVE_MODE,),run_as_root_ok=True, quiet=True)

    opts, device_uri, printer_name, mode, ui_toolkit, loc = \
               mod.parseStdOpts('hl:g:r', ['help', 'help-rest', 'help-man', 'help-desc', 'logging=', 'debug','user='],handle_device_printer=False)
except getopt.GetoptError as e:
    log.error(e.msg)
    usage()

if os.getenv("HPLIP_DEBUG"):
    log.set_level('debug')

for o, a in opts:
    if o in ('-h', '--help'):
        usage()

    elif o == '--help-rest':
        usage('rest')

    elif o == '--help-man':
        usage('man')

    elif o == '--help-desc':
        print(__doc__, end=' ')
        clean_exit(0,False)

    elif o in ('-l', '--logging'):
        log_level = a.lower().strip()
        if not log.set_level(log_level):
            usage()

    elif o in ('-g', '--debug'):
        log.set_level('debug')

    elif o == '--user':
        USER_NAME = a



if os.getuid() != 0:
    log.error("logCapture needs root permissions since cups service restart requires....")
    sys.exit()

if not USER_NAME:
    pout = Popen(["who"], stdout=PIPE)
    output = to_string_utf8(pout.communicate()[0])
    if output:
        USER_NAME = output.split(' ')[0]

    if not USER_NAME:
        log.error("Failed to get the user name. Try again by passing '--user' option")
        sys.exit(1)

if not os.path.exists(TMP_DIR):
    TMP_DIR = "/tmp"

cmd = "mkdir -p %s"%LOG_FILES
log.debug("Creating temporary logs folder =%s"%cmd)
sts, out = utils.run(cmd)
if sts != 0:
   log.error("Failed to create directory =%s. Exiting"%LOG_FILES)
   sys.exit(1)

sts,out = utils.run('chmod 755  %s'%LOG_FILES)
if sts != 0:
    log.error("Failed to change permissions for %s."%(LOG_FILES))


USERS[USER_NAME]="/home/"+USER_NAME+"/.hplip"

USERS['root']="/root/.hplip"
for u in USERS:
    sts, out = utils.run('mkdir -p %s/%s'%(LOG_FILES,u))
    if sts != 0:
       log.error("Failed to create directory =%s. Exiting"%LOG_FILES)
       sys.exit(1)

    sts,out = utils.run('chmod 755  %s/%s'%(LOG_FILES,u))
    if sts != 0:
        log.error("Failed to change permissions for %s/%s."%(LOG_FILES,u))


enable_log()

#### Clearing previous logs.. ###########
if not is_journal():
    ok,user_input = tui.enter_choice("Archiving system logs (i.e. syslog, message, error_log). Press (y=yes*, n=no, q=quit):",['y', 'n','q'], 'y')
    if not ok or user_input == "q":
        restore_loglevels()
        log.warn("User exit")
        sys.exit(1)

    if ok and user_input == "y":
        backup_clearLog('/var/log/syslog')
        backup_clearLog('/var/log/messages')
        backup_clearLog('/var/log/cups/error_log')



######## Waiting for user to completed job #######
while 1:
    log_time = datetime.datetime.strftime(datetime.datetime.now(),'%Y-%m-%d %H:%M:%S')
    log.info(log.bold("\nPlease perform the tasks (Print, scan, fax) for which you need to collect the logs."))
    ok,user_input =tui.enter_choice("Are you done with tasks?. Press (y=yes*, q=quit):",['y','q'], 'y')
    if ok and user_input == "y":
        break;
    elif not ok or user_input == "q":
        restore_loglevels()
        log.warn("User exit")
        sys.exit(1)

######## Copying logs to Temporary log folder #######
sts,out = utils.run('hp-check')
if sts != 0:
    log.error("Failed to run hp-check command")

log.debug("Copying logs to Temporary folder =%s"%LOG_FILES)
if not is_journal():
    if os.path.exists('/var/log/syslog'):
        sts,out = utils.run ('cp -f /var/log/syslog %s/syslog.log'%LOG_FILES)
        if sts != 0:
           log.error("Failed to capture %s log file."%("/var/log/syslog"))

    if os.path.exists('/var/log/messages'):
        sts,out = utils.run('cp -f /var/log/messages %s/messages.log'%LOG_FILES)
        if sts != 0:
           log.error("Failed to capture %s log file."%("/var/log/messages"))

    if os.path.exists('/var/log/cups/error_log'):
        sts,out = utils.run('cp -f /var/log/cups/error_log %s/cups_error_log.log'%LOG_FILES)
        if sts != 0:
           log.error("Failed to capture %s log file."%("/var/log/cups/error_log"))
else:
    log.debug("Collecting cups logs from system journal")
    cmd = "journalctl -u cups.service -e --since '%s' " %log_time
    sts = os.system(cmd + "> %s/cups_error.log"%LOG_FILES)
    if sts != 0:
        log.error("Failed to capture logs from journal")


    log.debug("Collecting messages from system journal")
    cmd = "journalctl --since '%s' " %log_time
    sts = os.system(cmd + "> %s/messages.log"%LOG_FILES)
    if sts != 0:
        log.error("Failed to capture messages from journal")

for u in USERS:
    sts = os.system('cp -f %s/*.log  %s/%s 2>/devnull '%(USERS[u],LOG_FILES,u))

sts,out = utils.run('mv -f ./hp-check.log %s'%LOG_FILES)
if sts != 0:
    log.error("Failed to capture %s log files."%("./hp-check.log"))
cmd = 'chmod 666  %s/*.log' % LOG_FILES
sts = os_utils.execute(cmd)
if sts != 0:
    log.error("Failed to change permissions for %s."%(LOG_FILES))

######## Compressing log files #######
cmd = 'tar -zcf %s.tar.gz %s'%(LOG_FOLDER_NAME,LOG_FILES)
log.debug("Compressing logs. cmd =%s"%cmd)

sts_compress,out = utils.run(cmd)
if sts_compress != 0:
    log.error("Failed to compress %s folder."%(LOG_FILES))
else:
    log.debug("Changing Permissions of ./%s.tar.gz "%LOG_FOLDER_NAME)
    sts,out = utils.run('chmod 666 -R ./%s.tar.gz'%(LOG_FOLDER_NAME))
    if sts != 0:
        log.error("Failed to change permissions for %s.tar.gz."%(LOG_FILES))
    log.debug("Removing Temporary log files..")
    sts,out = utils.run('rm -rf %s'%LOG_FILES)
    if sts != 0:
        log.error("Failed to remove temporary files. Remove manually."%(LOG_FILES))

restore_loglevels()

log.info("")
log.info("")
if sts_compress == 0:
    log.info(log.bold("Logs are saved as %s/%s.tar.gz"%( os.getcwd(),LOG_FOLDER_NAME)))
    log.info(log.bold("Please create a bug @https://bugs.launchpad.net/hplip/+filebug and upload this log file."))
else:
    log.info(log.bold("Logs are saved as %s/%s"%(os.getcwd(),LOG_FOLDER_NAME)))
log.info("")
