#!/usr/bin/python

import os
import sys
import optparse
import subprocess


# default location of logs
from sys import platform as _platform
if _platform == "linux" or _platform == "linux2":
    # linux
    LOG_FOLDER = "/root/cms-cloud-install/log"
    TEMP_FOLDER = "/tmp"

elif _platform == "win32":
    # Windows...
    LOG_FOLDER = 'C:\\MyCMS\\cms_cloud\\'
    TEMP_FOLDER = "C:\\MyCMS\\cms_cloud\\tmp"


ID_IDX = 1
STATUS_IDX = 5
IP_IDX = 16
NAME_IDX = 4

GET_LIST = "get_list"
GET_LOG  = "get_log"
GET_ID   = "get_id"


#global variables
#using get will return `None` if a key is not present rather than raise a `KeyError`
accessKeyId = os.environ.get('AWS_ACCESS_KEY')
secretAccessKey = os.environ.get('AWS_SECRET_KEY')
region = ""


class AwsInstance:
    pass

#accessKeyId, secretAccessKey are the optional args
def getConsoleLog(instance_name, log_file,*keyargs):
    global accessKeyId
    global secretAccessKey
    global region
    
    if (len(keyargs) == 3):
        accessKeyId = keyargs[0]
        secretAccessKey = keyargs[1]
        region = keyargs[2]
    #print("accessKeyId={0} and secretAccessKey={1}".format(accessKeyId, secretAccessKey))
    
    #get the console log
    getConsoleLogUsingName(instance_name,log_file)


def getConsoleLogUsingName(instance_name, log_file):
    
    #get the instance id
    id = getAwsInstanceId(instance_name)
    
    if not log_file:
        log_file = os.path.join(LOG_FOLDER, instance_name+"_console.log")
        #log_file = "/tmp/"+instance_name+"_console.log"
    
    if (id):        
        return getConsoleLogUsingId(id, log_file)
    
    return False;
       


def getConsoleLogUsingId(id, log_file):
        
    if (id):
        
        #check if log_file is passed
        if not log_file:
            log_file = os.path.join(LOG_FOLDER, id+"_console.log")
            #log_file = "/tmp/"+id+"_console.log"
            
        with open(log_file, 'w') as f:
            #pull the console log
            if accessKeyId is not None and secretAccessKey is not None:
                p1 = subprocess.Popen(['ec2-get-console-output', id, '-O', accessKeyId, '-W', secretAccessKey, '--region', region], stdout=f, stderr=subprocess.PIPE)
            else:            
                p1 = subprocess.Popen(['ec2-get-console-output', id,  '--region', region], stdout=f, stderr=subprocess.PIPE)
            
            error = p1.communicate()[0]
            retval = p1.returncode
        
            if retval != 0:
                print ("Failed to get console log for %s: %s" %(id, error))
                return False
        
        print("Saved console log to %s" %log_file)
    
    return True; 


def getAwsInstanceId(instance_name):
    id = ''
    #print("Checking for instance : " + instance_name)

    if (instance_name):
        if accessKeyId is not None and secretAccessKey is not None:
            p1 = subprocess.Popen(['ec2-describe-instances', '-O', accessKeyId, '-W', secretAccessKey, '--region',region,'--filter', 'tag:Name='+instance_name], stdout=subprocess.PIPE)
        else:
            p1 = subprocess.Popen(['ec2-describe-instances', '--filter', 'tag:Name='+instance_name], stdout=subprocess.PIPE)
        
        output = p1.communicate()[0]
        #print ("output is %s" %output)
        
        if (output):
            #id = output.splitlines()[-1].split()[2]        
            id = output.splitlines()[1].split()[1]        
            print ("Instance id = %s" %id)
            
        else:
            print ("No such instance")
    else:
        print ("Cannot get instance id, name is null")

    return id;


def getAwsInstances():
    
    awsList = list() #empty list

    print("Checking for instances")

    if accessKeyId is not None and secretAccessKey is not None:
        p1 = subprocess.Popen(['ec2-describe-instances', '-O', accessKeyId, '-W', secretAccessKey, '--region', region, '--show-empty-fields'], stdout=subprocess.PIPE)
    else:
        p1 = subprocess.Popen(['ec2-describe-instances', '--show-empty-fields'], stdout=subprocess.PIPE)
    output = p1.communicate()[0]
    #print ("output is \n%s" %output)

    if (output):
        #id = output.splitlines()[-1].split()[2]
        lines = output.splitlines()

        for line in lines:
            if (line.startswith("INSTANCE")):
                myInst = AwsInstance()   #create an empty record

                #process the line
                tokens = line.split()
                myInst.id = tokens[ID_IDX]
                myInst.status = tokens[STATUS_IDX]
                myInst.ipAddr = tokens[IP_IDX] if tokens[IP_IDX] else "Unknown"
                myInst.name   = "No idea"

                #add the instance
                awsList.append(myInst)

            elif (line.startswith("TAG")):
                #update the name on the instance
                name = line.split()[NAME_IDX]
                awsList[-1].name = line.split()[NAME_IDX]
                
                #TODO loop through tags - better way

        print ("Instance count = %d" %len(awsList))
    else:
        print ("No instances available")


    if (len(awsList) > 0):       
        #Print formatted output     
        print("\n")
        print("{0:10s}\t{1:30s}\t{2:10s}\t{3:15s}".format("ID", "NAME", "STATUS", "IpAddr"))
        print("{0:10s}\t{1:30s}\t{2:10s}\t{3:15s}".format("==", "====", "======", "======"))
        for inst in awsList:
            print("{0:10s}\t{1:30s}\t{2:10s}\t{3:15s}".format(inst.id, inst.name, inst.status, inst.ipAddr))
        print("\n")
        
    return awsList; 
    

def areAwsKeysInEnv():
    if accessKeyId is not None and secretAccessKey is not None:
        return True
    else:
        print ("Please export/set AWS_ACCESS_KEY and AWS_SECRET_KEY in ENV to ineract with AWS")
        return False
    

def main(argv):

    #command supported
    cmdList = ['get_list', 'get_id', 'get_log']
    
    #print ("AWS utils test ..")
    
    commands = "commands:\n" + \
        "get_list     show the list of all aws instances\n" + \
        "get_id       get the id of the AWS instance, pass instance name as option\n" + \
        "get_log      get the console log of the aws instance, takes either the name or id as the option\n\n"
        
    options = "options:\n" + \
        "-h, --help   show this help message and exit\n" + \
        "-n, --name   name of the AWS instance\n" + \
        "-i, --id     Id of the AWS instance\n"
    
    #parser = optparse.OptionParser()
    parser = optparse.OptionParser(usage='Usage: %prog <command> [options]\n' + commands + options)
     
    parser.add_option("-n", "--name", dest="inst_name")
    parser.add_option("-i", "--id", dest="inst_id")
    
    (options, args) = parser.parse_args()
    
    if len(args) != 1:
        parser.error("incorrect number of arguments")
        parser.print_help()
        exit(-1)
    
    #check if valid cmd is passed    
    if args[0] not in cmdList:
        parser.error("Invalid cmd [%s] passed" %args[0])
        parser.print_help()
        exit(-1)

    #we need the keys to communicate with AWS
    if not areAwsKeysInEnv():
        exit(-1)
        
    if (args[0] == GET_LIST):
        #display list of instances
        #print ("Request to get list of instances")
        getAwsInstances()
        
    elif(args[0] == GET_ID):
        #check if name is passed
        if options.inst_name is None:
            parser.error("Instance name is required to get Id")
            parser.print_help()
            exit(-1)
        else:
            print("Getting Id for instance %s" %options.inst_name)
            getAwsInstanceId(options.inst_name)
            
    elif(args[0] == GET_LOG):
        #check if name or Id is passed
        if options.inst_name is None and options.inst_id is None:
            parser.error("Instance name or Id is required to get console log")
            parser.print_help()
            exit(-1)
        else:
            print("Getting console log for instance %s" %options.inst_name)
            if options.inst_name:
                getConsoleLogUsingName(options.inst_name, "")
            elif options.inst_id:
                getConsoleLogUsingId(options.inst_id, "")


if __name__ == "__main__":
   main(sys.argv[1:])

