#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Copyright (c) 2015 Intel Corporation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import subprocess
import os
import sys

# Keys names in entry dictonary
TRAY_TYPE = 'rsa-tc'
ISCSI_TYPE = 'iSCSI'
ASSET_MAC  = 'mac'
ASSET_IP   = 'ip'
ASSET_TYPE = 'type'
ASSET_LID  = 'lid'
LEASES_PATH='/tmp/leases'

# Types of assets in leases file which this script parses
ACCEPTED_TYPES = [TRAY_TYPE, ISCSI_TYPE]

# Defaut value of ping requests
PING_MAX_TRIES = 4

# Shell commands
PING_CMD = ["ping", "-c", str(PING_MAX_TRIES)]
IPMI_CMD = ["ipmitool", "mc", "info", "-U", "USERID", "-P", "PASSW0RD", "-H"]
ISNS_CMD = ["isnsadm", "-q", "iscsi", "-a"]


def _dict_cmp(x, y):
    '''Compares strings. Used for sorting entries from leases.'''
    if x[ASSET_LID] == y[ASSET_LID]:
        return 0;
    elif x[ASSET_LID] < y[ASSET_LID]:
        return -1
    else:
        return 1 

def read_leases_struct(file_path):
    '''
        Reads leases file and converts it to list of dictonaries. Each
        dictionary has 4 values: lid, ip, mac, type.
        list(dict())
    '''
    leases_list = []
    
    # For each entry in file: mac ip type lid filters out only supported types
    # and creates list of dictionaries with fieds: type, lid, ip, mac
    with open(file_path, 'r') as fd:
        for line in fd:
            entry_dict = dict()
            
            # Gets only supported entries from file as a list of list
            line_list = filter(lambda x: x[2] in ACCEPTED_TYPES,
                               [line.split()])

            # Filters out empty lists
            if line_list:
                # Packs compatible types into dict.
                asset_mac, asset_ip, asset_type, asset_lid = line_list[0]
    
                entry_dict[ASSET_MAC ] = asset_mac
                entry_dict[ASSET_IP  ] = asset_ip
                entry_dict[ASSET_TYPE] = asset_type
                entry_dict[ASSET_LID ] = asset_lid
                
                # Adds dict to list
                leases_list = leases_list + [entry_dict]
                
    # Sorts list by lid field in dict
    leases_list.sort(cmp=_dict_cmp)
    
    return leases_list


def execute_command_and_print_output(cmd):
    print 'Executing command: ' + ' '.join(cmd) + '\n'
    sp = subprocess.Popen(cmd,
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE)
    out, err = sp.communicate()
    print out
    print err
    print 'Return code: ' + str(sp.returncode) + '\n'


def check_asset_connection(leases_struct):
    if leases_struct:
        
        for entry in leases_struct:
            with open(os.devnull, 'wb') as fd_null:
                print "Asset \n Type: %s \n Lid: %s \n Ip: %s \n Mac: %s\nTests" % (entry[ASSET_TYPE],
                                                         entry[ASSET_LID],
                                                         entry[ASSET_IP],
                                                         entry[ASSET_MAC])

                sys.stdout.flush()
                cmd = PING_CMD + [entry[ASSET_IP]]

                retval = subprocess.call(cmd,
                                         stdout=fd_null,
                                         stderr=fd_null,
                                         shell=False)

                if retval == 0:
                    print ' %s'%'PING: OK\n',
                    sys.stdout.flush()

                    if entry[ASSET_TYPE] == TRAY_TYPE:
                        cmd = IPMI_CMD + [entry[ASSET_IP]]
                    else: # iSCSI
                        cmd = ISNS_CMD + [entry[ASSET_IP]]

                    execute_command_and_print_output(cmd)
                else:
                    print ' %s'%'PING: FAILED\n'
                sys.stdout.flush()
        
    else:
        pass        

if __name__ == '__main__':

    try:
        leases_list = read_leases_struct(LEASES_PATH);
        check_asset_connection(leases_list);
    except Exception as ex:
        sys.stderr.write("Error {0}: {1} {2}\n".format(ex.errno, ex.strerror, ex.filename)) # if ex.filename != None ?
        exit(ex.errno)
        
    
