#!/usr/local/bin/python3

import sys
import os
import shutil
import tarfile
import subprocess
import glob
import datetime
import re

TMP_DIR = "./msdx_tmp"

args = sys.argv
working_dir = ""
rhel_ver = ""

def extract_sd(sd_file):
    global working_dir
    if not [ os.path.exists(sd_file) ]:
        sys.exit("support dump file " + sd_file + "does not exists")
    
    if os.path.exists(TMP_DIR):
        shutil.rmtree(TMP_DIR)
    
    tar = tarfile.open(sd_file)
    tar.extractall(path=TMP_DIR)
    tar.close()
    
    dir_name = os.listdir(TMP_DIR)[0]
    print(dir_name)
    
    file_name = ""
    
    sd_meta = ['ls', '-l', TMP_DIR]
    res = subprocess.check_output(sd_meta).split()
    sd_time = res[7].decode('utf-8') + "-" + res[8].decode('utf-8') + "-" + res[9].decode('utf-8').replace(":", "")
    
    with open(TMP_DIR + "/" + dir_name + "/hostname") as f:
        s = f.read().rstrip()
        hostname = s
        print(hostname)
 
    working_dir = hostname + "-" + sd_time
    os.rename(TMP_DIR + "/" + dir_name, working_dir)
    shutil.rmtree(TMP_DIR)


def check_os():
    global rhel_ver, working_dir
    f = open(working_dir + "/system_info/lsb_release_a", "r")
    lines = f.readlines()
    for line in lines:
        if line.find('Description:') != -1:
            items = re.split("\t", line.rstrip())
            msdx_print("OS : " + items[1])
        elif line.find('Release:') != -1:
            items = re.split("\t", line.rstrip())
            rhel_ver = items[1]

def check_logs():
    global working_dir
    format_A = '%Y-%m-%d %H:%M:%S,%f'
    format_B = '%Y-%m-%dT%H:%M:%S,%f'
    logs =       {"mfs":"mapr-logs/mfs.log-3*", "warden":"mapr-logs/warden.log*",
                  "cldb":"mapr-logs/cldb.log*", "nfs":"mapr-logs/nfsserver.log*",
                  "apiserver":"mapr-logs/apiserver/apiserver*", "adminui":"mapr-logs/adminuiapp*",
                  "nodemanager":"hadoop-2.7.0-logs/yarn-mapr-nodemanager*.log*","resourcemanager":"hadoop-2.7.0-logs/yarn-mapr-resourcemanager*.log*",
                  "hivemeta":"hive-2.1/mapr/mapr-metastore-*", "hs2":"hive-2.1/mapr/mapr-hiveserver2-*",
                  "drill":"drill-1.*/drillbit.log*"}
    start_logs = {"os":"Initializing cgroup subsys cpuset", "mfs":"Starting fileserver", "warden":"My pid",
                  "cldb":"CLDBInit: Start CLDBServer", "nfs":"NFS server starting",
                  "apiserver":"Server Started", "adminui":"Initializing Web Server",
                  "nodemanager":"NodeManager: STARTUP_MSG:", "resourcemanager":"ResourceManager: STARTUP_MSG:",
                  "hivemeta":"Starting hive metastore on port", "hs2":"HiveServer2: Starting HiveServer2",
                  "drill":"Startup completed"}
    end_logs =   {"os":"Stopping Timers", "warden":"ShutdownHook completed", "mfs":"Shutdown ctx",
                  "cldb":"CLDB ShutDown Hook called", "apiserver":"Running shutdown hook",
                  "nodemanager":"NodeManager: SHUTDOWN_MSG:",
                  "hivemeta":"HiveMetaStore: SHUTDOWN_MSG:", "hs2":"HiveServer2: SHUTDOWN_MSG",
                  "drill":"Shutdown completed"}
    time_format = {"mfs" : format_A, "warden":format_A, "cldb":format_A, "apiserver":format_A, "adminui":format_A,
                   "nfs":format_A, "nodemanager":format_A,"resourcemanager":format_A,
                   "hivemeta":format_B, "hs2":format_B, "drill":format_A}
    cosmetics   = {"warden":"warden",
                   "cldb":"\tcldb", "mfs":"\tmfs",
                   "nodemanager":"\t\tnodemanager", "resourcemanager":"\t\tresourcemanager", "nfs":"\t\tnfs", "apiserver":"\t\tapiserver", "adminui":"\t\twebserver",
                   "hivemeta":"\t\t\thivemeta", "hs2":"\t\t\ths2", "drill":"\t\tdrill"}
    errors = {}
    fatal  = {}
    event_record = {}

    msdx_print("\n\nLogs found")
    for k,v in logs.items():
        err_counter = 0
        fatal_counter = 0
        for filename in glob.glob(working_dir + "/logs/" + v):
            msdx_print(filename)
            f = open(filename, "r")
            lines = f.readlines()
            for line in lines:
                if line.find('ERROR') != -1:
                    err_counter += 1
                if line.find('FATAL') != -1:
                    fatal_counter += 1
                if line.find(start_logs[k]) != -1:
                    try:
                        event_record[datetime.datetime.strptime(line[0:23], time_format[k])] = cosmetics[k] + " on"
                    except:
                        print("datetime error:", line)
                if k in end_logs and line.find(end_logs[k]) != -1:
                    try:
                        event_record[datetime.datetime.strptime(line[0:23], time_format[k])] = cosmetics[k] + " off"
                    except:
                        print("datetime error:", line)
                    
            f.close()
            errors[k] = err_counter
            fatal[k]  = fatal_counter
    
    msdx_print("\n\nERROR and FATAL counts")
    for k,v in errors.items():
        msdx_print(k + "\t\t\t ERROR:" + str(v) + ", FATAL:" + str(fatal[k]))

    msdx_print("\n\nSTART/END records")
    for k,v in sorted(event_record.items()):
        msdx_print(str(k) + " " + v)


def check_network():
    global working_dir
    check_ifconfig()
    check_netstat()
    check_firewall()

def check_ifconfig():
    global rhel_ver, working_dir
    msdx_print("\n\nifconfig network failure detection")
    f = open(working_dir + "/system_info/ifconfig_a", "r")
    drop_flg = False
    lines = f.readlines()
    for line in lines:
        if line.find('dropped') != -1:
            drop_flg = True
            items = re.split(" +|:", line.rstrip())
            if items[1] == 'TX':
                if rhel_ver[0] == '6' and (items[5] != '0' or items[7] != '0' or items[9] != '0' or items[11] != '0'):
                    msdx_print ("failures detected : " + line.rstrip())
                if rhel_ver[0] == '7' and (items[3] != '0' or items[5] != '0' or items[7] != '0' or items[9] != '0' or items[11] != '0'):
                    msdx_print ("failures detected : " + line.rstrip())
            else:
                if rhel_ver[0] == '7' and (items[3] != '0' or items[5] != '0' or items[7] != '0' or items[9] != '0'):
                    msdx_print ("failures detected : " + line.rstrip())
                if rhel_ver[0] == '6' and (items[5] != '0' or items[7] != '0' or items[9] != '0' or items[11] != '0'):
                    msdx_print ("failures detected : " + line.rstrip())
    if drop_flg == False:
        msdx_print("drop is not detected in ifconfig")

def check_netstat():
    global working_dir
    msdx_print("\n\nNetstat check")
    f = open(working_dir + "/system_info/netstat_s", "r")
    lines = f.readlines()
    for line in lines:
        if re.search(r"drop|error|timeout|loss|invalid|^Ip|^Icmp|^Tcp|^Udp", line) != None:
            items = re.split(" +", line.rstrip())
            zero_flg = False
            for item in items:
                if item == "0":
                    zero_flg = True
                    break
            if zero_flg == False:
                msdx_print(line.rstrip())



def check_firewall():
    global working_dir
    msdx_print("\n\nFirewall check")
    f = open(working_dir + "/system_info/ps_efly", "r")
    lines = f.readlines()
    for line in lines:
        if line.find('firewalld') != -1:
            msdx_print("firewalld IS working")
            return
    msdx_print("firewalld is NOT working")


def msdx_print(s):
    msdx_f.write(s + "\n")
    print(s)

extract_sd(args[1])
msdx_f = open(working_dir + "/msdx.txt", mode="w")
check_os()
check_logs()
check_network()
msdx_f.close()
print("\n\nCheck output in " + working_dir + "/msdx.txt")

