#####
##### This file is part of Mail-in-a-Box-LDAP which is released under the
##### terms of the GNU Affero General Public License as published by the
##### Free Software Foundation, either version 3 of the License, or (at
##### your option) any later version. See file LICENSE or go to
##### https://github.com/downtownallday/mailinabox-ldap for full license
##### details.
#####


#
# This is a status_checks management hook for the logwatch setup mod.
#
# It adds logwatch output to status checks. In most circumstances it
# will cause a "status checks change notice" email to be sent every
# day when daily_tasks.sh runs status checks around 3 am.
#
# The hook is enabled by placing the file in directory
# LOCAL_MODS_DIR/managment_hooks_d.
#

import os, time
import logging
from utils import shell

log = logging.getLogger(__name__)

def do_hook(hook_name, hook_data, mods_env):
    if hook_name != 'status_checks':
        # we only care about hooking status_checks
        log.debug('hook - ignoring hook %s', hook_name)
        return False
    
    if hook_data['op'] != 'output_changes_end':
        # we only want to append for --show-changes
        log.debug('hook - ignoring hook op %s:%s', hook_name, hook_data['op'])
        return False

    output = hook_data['output']
    
    if not os.path.exists("/usr/sbin/logwatch"):
        output.print_error("logwatch is not installed")
        return True

    # determine scope and period of the logwatch log file scan
    since_mtime = hook_data['since'] if 'since' in hook_data else 0
    if since_mtime <= 0:
        since = 'since 24 hours ago for that hour'
        since_desc = 'since 24 hours ago'
    else:
        local_str = time.strftime(
            "%Y-%m-%d %H:%M:%S",
            time.localtime(since_mtime)
        )
        # "for that second" can cause logwatch to hang and peg cpu at 100%
        # since = 'since %s for that second' % local_str
        since = 'since %s for that minute' % local_str
        since_desc = 'since %s' % local_str

    # run logwatch
    report = shell(
        'check_output',
        [
            '/usr/sbin/logwatch',
            '--range', since,
            '--output', 'stdout',
            '--format', 'text',
            '--service', 'all',
            '--service', '-zz-disk_space',
            '--service', '-zz-network',
            '--service', '-zz-sys',
        ],
        capture_stderr=True,
        trap=False
    )

    # defer outputting the heading text because if there is no
    # logwatch output we care about, we don't want any output at all
    # (which could avoid a status check email)
    heading_done = False    
    def try_output_heading():
        nonlocal heading_done
        if heading_done: return
        output.add_heading('System Log Watch (%s)' % since_desc);
        heading_done=True

    in_summary = False  # true if we're currently processing the logwatch summary text, which is the text output by logwatch that is surrounded by lines containing hashes. we ignore the summary text
    blank_line_count = 1 # keep track of the count of adjacent blank lines
    output_info = False # true if we've called output.print_info at least once
    
    for line in report.split('\n'):
        line = line.strip();
        if line == '':
            blank_line_count += 1
            if blank_line_count == 1 and output_info:
                output.print_line('')
        
        elif line.startswith('##'):
            in_summary = '## Logwatch' in line
                
        elif line.startswith('--'):
            if ' Begin --' in line:
                start = line.find(' ')
                end = line.rfind(' Begin --')
                try_output_heading()
                output.print_info("%s" % line[start+1:end])
                output_info = True
                blank_line_count = 0
                
        else:
            if not in_summary:
                try_output_heading()
                output.print_line(line)
                blank_line_count = 0
    
    return True