#!/usr/bin/python
# -*- coding: utf8 -*-

# Показывает открытые hw-watcher-ные тикеты, сгруппированные по хостам и подсистемам + текущий статус по хосту/подсистеме
# Звать скрипт так: STARTREK_TOKEN=<токен для Стартрека> hw-watcher-issues-stat
# если уже пользовался perl-клиентом к Стартреку, то токен возьмется из файла ~/.startrek_client_token

import os
import re
import sys

sys.path.insert(0, '/opt/direct-py/startrek-python-client-sni-fix')

import subprocess, datetime, time, signal
from collections import defaultdict
import dateutil.parser 

from startrek_client import Startrek

STARTREK_TOKEN_FILE = '~/.startrek_client_token'

def format_dt(dt):
    return dateutil.parser.parse(dt).strftime("%Y-%m-%d")

def st_link(key):
    return "https://st.yandex-team.ru/%s" % key


def hw_m(module):
    """ превращает название из тикета в то, что можно передать самому hw-watcher-у
    """
    h = {
            'memory': 'mem',
            }
    if module in h:
        return h[module]
    else:
        return module


def check_current_status(host, module):
    if not re.match(r'^[a-z0-9-\.]*$', host):
        print "skipping host %s" % host
        return
    if not re.match(r'^[a-z0-9-\.]*$', module):
        print "skipping host %s" % host
        return
    cmd = "ssh -q root@%s sudo -u hw-watcher /usr/sbin/hw_watcher %s status" % (host, hw_m(module))
    print '\nto exec: %s' % cmd
    c = timeout_command(cmd)
    if c > 0: 
        print "non-zero exit status: %s" % (c)
    elif c < 0:
        print "Timeout"
    print ""

    return


def timeout_command(command, timeout=5):
    """Выполняет команду с таймаутом
    возвращает код выхода или -1, если случился таймаут"""
    start = datetime.datetime.now()
    process = subprocess.Popen(command, stdout=sys.stdout, stderr=sys.stderr, shell=True)
    while process.poll() is None:
      time.sleep(0.1)
      now = datetime.datetime.now()
      if (now - start).seconds > timeout:
        os.kill(process.pid, signal.SIGKILL)
        os.waitpid(-1, os.WNOHANG)
        return -1
    return process.returncode


def get_startrek_token():
    if os.environ.get('STARTREK_TOKEN'):
        return os.environ.get('STARTREK_TOKEN')
    elif os.path.isfile(os.path.expanduser(STARTREK_TOKEN_FILE)):
        with open(os.path.expanduser(STARTREK_TOKEN_FILE), 'r') as f:
            token = f.readline().rstrip()
            return token
    else:
        sys.exit("Startrek token not found, run using STARTREK_TOKEN=<token> %s" % sys.argv[0])


"""
hw-watcher: failed link speed on usdev3.advq.yandex.ru
hw-watcher: correctable ecc errors on ppcdom03f.yandex.ru
hw-watcher: failed disk on ppcbackup06i.yandex.ru
hw-watcher: failed disk on bmcollect02h.yandex.ru
hw-watcher: failed disk on ppcbackup06i.yandex.ru
hw-watcher: failed disk on ppcbackup06i.yandex.ru
"""

def run():
    startrek = Startrek(token=get_startrek_token(), useragent='Direct Tools')
    issues = startrek.issues.find('Queue: DAHW Status: Open')

    unexpected = []
    stat = defaultdict(lambda: defaultdict(list))
    for issue in issues:
        m = re.search(r'^hw-watcher: (failed|unknown status of check|lost) ([^ ]+) on ([^ ]+)( .*)?$', issue.summary)
        if not m:
            unexpected += [ issue ]
            continue
        host = m.group(3)
        if ('-H' in sys.argv) and not host.startswith(sys.argv[sys.argv.index('-H')+1]):
            continue
        if ('-m' in sys.argv) and not re.search(sys.argv[sys.argv.index('-m')+1], host):
            continue
        module = m.group(2)
        stat[host][module] += [ issue ]
        
    if (('-m' in sys.argv) or ('-H' in sys.argv)) and stat == {} and len(issues)>0:
        print "### Tickets not found, use another mask."
    for host in stat: 
            print "### %s" % host 
            for module in stat[host]:
                print "  #### %s" % module
                for issue in stat[host][module]:
                    print "    %s  %s  (%s)" % (st_link(issue.key), format_dt(issue.createdAt), issue.summary)
                if '--no-check' not in sys.argv: 
                    check_current_status(host, module)

    print "### CAN'T PARSE"  
    for issue in unexpected:
        print "    %s  %s  %s" % (st_link(issue.key), format_dt(issue.createdAt), issue.summary)

if __name__ == '__main__':
    run()

