'''
Created on June 1, 2012
Modified on June 26, 2012
@author: Dilum Bandara
@version: 0.1
@license: Apache License v2.0

   Copyright 2012 H. M. N. Dilum Bandara and Anura P. Jayasumana, Colorado State
   University

   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.
'''

'''
Extract information about machines from machines.xml file.
Extract their ID, sensor ID, & hardware information which
will not change with time
Output format
nid (machine ID), time, sensor IDs, CSp, MSize, DSize, MSwap, Threads,
OS, OSVer, CPUArc, KVer, KName,
'''

fdIn = open('machines.xml', 'r')

os = {}
machines = {}
machinesSensorIDs = {}
sensorIDs = {}
motherboards = {}
mList = False #Machine list
pList = False #Property list
mbList = False
midList = False
maID = -1
#Add state variable for any static attribute to be tracked
CSp = False #CPU speed
MSize = False #memory size
MSwap = False #memory swap
DSize = False #Disk size
Threads = False #No of CPU threads

for line in fdIn:    
    if '<machinesList' in line:
        mList = True
    elif '</machinesList' in line:
        mList = False
    elif '<machine machineID=' in line and mList == True:
        tmp = line.split('"')
        maID = tmp[1] #Machine ID
        mbID = tmp[3] #Motherbaord ID
        miID = tmp[5] #Middleware ID
        dCreate = tmp[7] #Date created
        dRetire = tmp[9] if len(tmp) > 9 else '-1'
        machines[maID] = [mbID, miID, dCreate, dRetire]
    elif '</machine>' in line and maID > -1: 
        machinesSensorIDs[maID] = sensorIDs
        sensorIDs = {}
        maID = -1
    elif '<propertiesList>' in line and mList == True:
        pList = True
    elif '</propertiesList>' in line and pList == True:
        pList == False
    elif '<textProperty name="Processors/CoreSpeed">' in line and \
            mList == True and pList == True and maID > -1:
        CSp = True
    elif '<history value=' in line and CSp == True:
        tmp = line.split('"') 
        machines[maID].append(int(tmp[1])/1000.0) #Convert to GHz
        CSp = False
    elif '<textProperty name="Memory/TotalMemory">' in line and \
            mList == True and pList == True and maID > -1:
        MSize = True
    elif '<history value=' in line and MSize == True:
        tmp = line.split('"') 
        machines[maID].append(round(int(tmp[1])/(1024.0 * 1024.0), 3)) #Convert to GB
        MSize = False
    elif '<textProperty name="Storage/TotalDiskSpace">' in line and \
            mList == True and pList == True and maID > -1:
        DSize = True
    elif '<history value=' in line and DSize == True:
        tmp = line.split('"') 
        machines[maID].append(tmp[1]) #Already in GB
        DSize = False
    elif '<textProperty name="Memory/TotalSwap">' in line and \
            mList == True and pList == True and maID > -1:
        MSwap = True
    elif '<history value=' in line and MSwap == True:
        tmp = line.split('"') 
        machines[maID].append(round(int(tmp[1])/(1024.0 * 1024.0), 3)) #Convert to GB
        MSwap = False
    elif '<textProperty name="Processors/ThreadCount">' in line and \
            mList == True and pList == True and maID > -1:
        Threads = True
    elif '<history value=' in line and Threads == True:
        tmp = line.split('"') 
        machines[maID].append(tmp[1])
        Threads = False
    elif '<motherboardsList validAtDate=' in line:
        mbList = True
    elif '<motherboard motherboardID' in line and mbList == True:
        tmp = line.split('"') 
        motherboards[tmp[1]] = [tmp[3], tmp[9].replace(' ', '')]
    elif '</motherboardsList>' in line:
        mbList = False
    elif '<middlewareList validAtDate=' in line:
        midList = True
    elif '<middleware middlewareID=' in line and midList == True:
        tmp = line.split('"') 
        if tmp[3] == 'OS':
            os[tmp[1]] = [tmp[5], tmp[7], tmp[9], tmp[11], tmp[13]]
    elif '</middlewareList>' in line and midList == True:
        midList == False
    elif '<sensor sensorID="' in line and maID > -1:
        #List of sensor IDs to extract
        if '"bytes_in"' in line:
            sensorIDs['bytes_in'] = line.split('"')[1]
        elif '"bytes_out"' in line:
            sensorIDs['bytes_out'] = line.split('"')[1]
        elif '"cpu_idle"' in line:
            sensorIDs['cpu_idle'] = line.split('"')[1]
        elif '"disk_free"' in line:
            sensorIDs['disk_free'] = line.split('"')[1]
        elif '"load_fifteen"' in line:
            sensorIDs['load_fifteen'] = line.split('"')[1]
        elif '"load_five"' in line:
            sensorIDs['load_five'] = line.split('"')[1]
        elif '"load_one"' in line:
            sensorIDs['load_one'] = line.split('"')[1]
        elif '"mem_free"' in line:
            sensorIDs['mem_free'] = line.split('"')[1]
        elif '"swap_free"' in line:
            sensorIDs['swap_free'] = line.split('"')[1]

fdIn.close()

fdOut = open('machines.txt', 'w')
#Modify header depending on what attributes being collected
fdOut.write('nid\tCreateTime\tRetireTime\tMotherBD\tCSp\tMSize\t' + \
            'DSize\tMSwap\tThreads\tCPUArc\tOS\tOSVer\tKName\tKVer\n')
for i in machines:
    tmpStr = i + '\t' + machines[i][2] + '\t' + machines[i][3] + '\t'
    tmpStr += motherboards[machines[i][0]][0] + '\t'
    tmpStr += str(machines[i][4]) + '\t' + str(machines[i][5]) + '\t'
    tmpStr += machines[i][6] + '\t' + str(machines[i][7]) + '\t'
    tmpStr += machines[i][8] + '\t'
    tmpStr += os[machines[i][1]][4] + '\t'
    tmpStr += os[machines[i][1]][0] + '\t'
    tmpStr += os[machines[i][1]][1] + '\t'
    tmpStr += os[machines[i][1]][2] + '\t'
    tmpStr += os[machines[i][1]][3] + '\t'
    tmpStr += motherboards[machines[i][0]][1] + '\n'
    fdOut.write(tmpStr) 
fdOut.close()

#Dump list of sensor IDs
fdOut = open('sensorIDs.txt', 'w')
fdOut.write('nid\tbytesIn\tbytesOut\tCFree\tDFree\t1mLd\t5mLd\t15mLd\tMFree\tSwapFree\n')
for i in machinesSensorIDs:
   if len(machinesSensorIDs[i]) == 0: continue
   tmpStr = i + '\t' + machinesSensorIDs[i]['bytes_in'] + '\t'
   #Modify depending on what sensor IDs being collected
   tmpStr += machinesSensorIDs[i]['bytes_out'] + '\t'
   tmpStr += machinesSensorIDs[i]['cpu_idle'] + '\t'
   tmpStr += machinesSensorIDs[i]['disk_free'] + '\t'
   tmpStr += machinesSensorIDs[i]['load_one'] + '\t'
   tmpStr += machinesSensorIDs[i]['load_five'] + '\t'
   tmpStr += machinesSensorIDs[i]['load_fifteen'] + '\t'
   tmpStr += machinesSensorIDs[i]['mem_free'] + '\t'
   tmpStr += machinesSensorIDs[i]['swap_free'] + '\n'
   fdOut.write(tmpStr)
fdOut.close()
