#!/bin/env python

import argparse
import requests
import json

import urllib3

class BMC:
    def __init__(self, server):
        self.url = "https://{0}/".format(server)
        self.session = requests.Session()
        self.login()

    def login(self):
        r = self.session.post(self.url + 'login',
                              json={'data': ['root', '0penBmc']},
                              verify=False)
        j = r.json()
        if j['status'] != 'ok':
            raise Exception("Failed to login: \n" + r.text)

    def list_events(self):
        r = self.session.get(self.url + 'xyz/openbmc_project/logging/entry/',
                             verify=False)
        j = r.json()
        if j['message'] == '404 Not Found':
            print "No error logs on system\n"
            return
        if j['status'] != 'ok':
            raise Exception("Failed to query entries: \n" + r.text)

        events = j['data']
        events.sort(key=lambda x: int(x.split("/")[-1]))

        return events

    def get_event(self, event):
        r = self.session.get(self.url + event, verify=False)

        j = r.json()
        if j['status'] != 'ok':
            raise Exception("Failed to get event " + event + ": \n" + r.text)

        return j['data']
    
    def clear_event(self,event):
        r = self.session.delete(self.url + event)
        j = r.json()
        if j['status'] != 'ok':
            raise Exception("Failed to clear event " + event + ": \n" + r.text)

    def clear_all_events(self):
        r = self.session.post(self.url + 'xyz/openbmc_project/logging/action/deleteall',
                             headers={'Content-Type': 'application/json'},
                             data='{"data":[]}',
                             verify=False)
        j = r.json()
        if j['status'] != 'ok':
            raise Exception("Failed to clear all events\n" + r.text)

    def list_dumps(self):
        r = self.session.get(self.url + 'xyz/openbmc_project/dump/entry/',
                             verify=False)
        j = r.json()
        if j['message'] == '404 Not Found':
            print "No dumps on system\n"
            return []
        if j['status'] != 'ok':
            raise Exception("Failed to list dumps: \n" + r.text)

        dumps = j['data']
        dumps.sort(key=lambda x: int(x.split("/")[-1]))

        return dumps
    
    def create_dump(self):
        r = self.session.post(self.url + 'xyz/openbmc_project/dump/action/CreateDump',
                              headers={'Content-Type': 'application/json'},
                              data='{"data":[]}')
        j = r.json()
        if j['status'] != 'ok':
            raise Exception("Failed to create dump: \n" + r.text)
        
    def get_dump(self,dump):
        r = self.session.get(self.url + "/download/dump/" + dump,
                             verify=False)
        with open("dump" + dump + ".tar.gz","wb") as dump:
            dump.write(r.content)

    def clear_dump(self,dump):
        r = self.session.delete(self.url + dump)
        j = r.json()
        if j['status'] != 'ok':
            raise Exception("Failed to clear dump " + dump + ": \n" + r.text)        

def do_list_events(args):
    s = BMC(server=args.server)
    try:
        for e in s.list_events():
            print(e)
    except:
        # ignore if we get nothing back
        return;


def do_view_event(args):
    s = BMC(server=args.server)
    print json.dumps(s.get_event(args.event), indent=4)

def do_clear_event(args):
    s = BMC(server=args.server)
    s.clear_event(args.event)

def do_clear_all_events(args):
    s = BMC(server=args.server)
    s.clear_all_events()

def do_list_dumps(args):
    s = BMC(server=args.server)
    for e in s.list_dumps():
        print(e)

def do_create_dump(args):
    s = BMC(server=args.server)
    s.create_dump()
    
def do_get_dump(args):
    s = BMC(server=args.server)
    s.get_dump(args.dump)

def do_clear_dump(args):
    s = BMC(server=args.server)
    s.clear_dump(args.dump)

def do_get_esel(args):
    s = BMC(server=args.server)
    e = s.get_event(args.event)
    if e['Message'] != 'org.open_power.Error.Host.Event' and\
       e['Message'] != 'org.open_power.Error.Host.Event.Event':
        raise Exception("Event is not from Host: " + e['Message'])
    for d in e['AdditionalData']:
        data = d.split("=")
        tag = data.pop(0)
        if tag != 'ESEL':
            continue
        data = "=".join(data)
        if args.binary:
            data = data.split(" ")
            if '' == data[-1]:
                data.pop()
            data = "".join(map(lambda x: chr(int(x, 16)), data))
        print(data)


parser = argparse.ArgumentParser()
parser.add_argument('--server', help='hostname or IP of BMC', type=str,
                    required=True)
parser.add_argument('--suppress-insecure-warnings', '-I', action="store_true",
                    default=False)

subparsers = parser.add_subparsers()

list_events = subparsers.add_parser('list', help='List all events on BMC')
list_events.set_defaults(func=do_list_events)

view_event = subparsers.add_parser(
    'view', help='View all data for an individual event')
view_event.add_argument('event', help='The event to view')
view_event.set_defaults(func=do_view_event)

get_esel = subparsers.add_parser(
    'get-esel', help='Extract OpenPOWER eSEL data for an individual event')
get_esel.add_argument('event', help='The event to get eSEL from')
get_esel.add_argument('--binary', help='Print event in raw binary',
                      action='store_const', const=True)
get_esel.set_defaults(func=do_get_esel)

clear_event = subparsers.add_parser(
    'clear', help="Clear individual event")
clear_event.add_argument('event', help="The event to clear")
clear_event.set_defaults(func=do_clear_event)

clear_all_events = subparsers.add_parser(
    'clear-all', help="Clear all event")
clear_all_events.set_defaults(func=do_clear_all_events)

list_dumps = subparsers.add_parser(
    'list-dumps', help="List all dumps")
list_dumps.set_defaults(func=do_list_dumps)

create_dump = subparsers.add_parser(
    'create-dump', help="Create a dump")
create_dump.set_defaults(func=do_create_dump)

get_dump = subparsers.add_parser(
    'get-dump', help="Get a dump")
get_dump.add_argument('dump', help="The dump to get")
get_dump.set_defaults(func=do_get_dump)

clear_dump = subparsers.add_parser(
    'clear-dump', help="Clear individual dump")
clear_dump.add_argument('dump', help="The dump to clear")
clear_dump.set_defaults(func=do_clear_dump)

args = parser.parse_args()

if args.suppress_insecure_warnings:
    from requests.packages.urllib3.exceptions import InsecureRequestWarning
    requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

if 'func' in args:
    args.func(args)
else:
    parser.print_help()
