#!/usr/bin/env python
#-*-coding:UTF-8-*-
"""
@Item   :  V1.0
@Author :  ShengWangQiang
@Group  :  System ITEM
@Date   :  2015-01-28
@E-mail :  swq.499809608@hotmail.com
@Funtion:

"RAID Level : Primary-1, Secondary-0, RAID Level Qualifier-0") echo "Raid Level :Raid 1";;
"RAID Level : Primary-0, Secondary-0, RAID Level Qualifier-0") echo "Raid Level :Raid 0";;
"RAID Level : Primary-5, Secondary-0, RAID Level Qualifier-3") echo "Raid Level :Raid 5";;
"RAID Level : Primary-1, Secondary-3, RAID Level Qualifier-0") echo "Raid Level :Raid 10";;

"""

import os,sys,time,socket,commands,traceback,re,fcntl,json
import struct



class DellRaid(object):
    def __init__(self):
        version = 1.0

    # Log file and save log info
    def log(self,info):
        if not os.path.exists('/var/log/autostack/'):
            os.makedirs('/var/log/autostack/')
        files = open('/var/log/autostack/autostack.log','a')
        try:
            files.write('[%s]: %s \n' %(time.ctime(),info))
        except IOError:
            files.close()
        files.close()


    # Call system commands 
    def execute(self,*cmd):
        """
        execute the cmd, and return the outpurt of cmd
        simple way to get cmd output.
        """
        cmd = list(cmd)
        cmd = map(str, cmd)
        cmd_line = ' '.join(cmd)

        code, output = commands.getstatusoutput(cmd_line)
        
        if code == 0:
            self.log(output)
            self.log(cmd_line)
            return output
        else:
            self.log(traceback.format_exc())
        self.log(cmd_line)

    # Megacli create Raid 0 
    def raid_0(self,raid_type,enclosure,slot):
        try:
            raid_type = raid_type.split('_')[-1]
            sinfo = ','.join(['%s:' %enclosure + str(i) for i in slot])
            self.execute( """/usr/bin/megacli -CfgLdAdd -r%s [%s] WB Direct -a0"""  \
                        %(raid_type,sinfo))
            self.log("Raid Group %s create is oK" %raid_type)

        except:
            self.log('raid_0 Error %s ' %traceback.format_exc())

    # Megacli create Raid 1  
    def raid_1(self,raid_type,enclosure,slot):
        try:
            raid_type = raid_type.split('_')[-1]
            sinfo = ','.join(['%s:' %enclosure + str(i) for i in slot])
            self.execute( """/usr/bin/megacli -CfgLdAdd -r%s [%s] WB Direct -a0"""  \
                        %(raid_type,sinfo))
            self.log("Raid Group %s create is oK" %raid_type)
        except:
            self.log('raid_1 Error %s ' %traceback.format_exc())

    # Megacli create Raid 5 
    def raid_5(self,raid_type,enclosure,slot):
        try:
            raid_type = raid_type.split('_')[-1]
            sinfo = ','.join(['%s:' %enclosure + str(i) for i in slot])
            self.execute( """/usr/bin/megacli -CfgLdAdd -r%s [%s] WB Direct -a0"""  \
                        %(raid_type,sinfo))
            self.log("Raid Group %s create is oK" %raid_type)
        except:
            self.log('raid_5 Error %s ' %traceback.format_exc())

    # Megacli create Raid 10 
    def raid_10(self,raid_type,enclosure,slot):
        try:
            raid_type = raid_type.split('_')[-1]
            arry_slot =  self._arry_slot(enclosure,slot)
            self.execute("""/usr/bin/megacli -CfgSpanAdd -r%s %s WB Direct -a0 """ \
                        %(raid_type,arry_slot))
            print 'yes' 
            self.log("Raid Group %s create is oK" %raid_type)
        except:
            print traceback.format_exc()
            self.log('raid_10 Error %s ' %traceback.format_exc())
 
    # Array split Raid 
    def _arry_slot(self,enclosure,slot):
        bnext = iter(slot)
        count = 0
        ret = []
        try:
            for i in bnext:
                i = int(i.encode() )
                ret.append('-Array%i[%s:%s,%s:%s]'%(count, enclosure,i,enclosure, bnext.next()))
                count += 1
            self.log('Array str %s '%' '.join(ret))
            return ' '.join(ret)
        except:
            self.log(traceback.format_exc())
            return ''

    # Split enclosure str
    def _enclosure(self,disks):
        enclosure = dict()
        try:
            for d in disks:
                rest =d['enclosure']
            if not rest:
                rest = self._esc()
            enclosure['enclosure'] = rest
        except:
            self.log(traceback.format_exc())
        
        return enclosure

    def _esc(self):
        try:
            ecs =  self.execute(""" /usr/bin/megacli   -cfgdsply -aALL |grep 'Enclosure Device ID' """)
            ecs =int(ecs.split(":")[-1].strip())
            return ecs 
        except:
            self.log(traceback.format_exc())
    # Split slot str info
    def _slot(self,disks):
        slot = list()
        try:
            for d in disks:
                slot.append(d['slot'])
        except:
            self.log(traceback.format_exc())

        return slot 

    # Delete Raid Group ,defautl values is ID
    def delete_raid_group(self):
        try:
            ids = self.execute("""/usr/bin/megacli  -cfgdsply -aALL | \
                                grep "Number of DISK GROUPS"  """)
            for i in range(int(ids.split(':')[-1])):
                self.execute(""" /usr/bin/megacli  -CfgLdDel -L%s -a0""" %i)
                self.log("Raid Group %s delete is oK" %i)
        except:
            self.log(traceback.format_exc())

    def set_ipmit_boot(self):
        try:
            self.execute(""" /usr/bin/ipmitool chassis bootdev pxe """)
            self.log("Set Service boot pxe is ok")
        except:
            self.log(traceback.format_exc())
    def work(self,data):
        # Get Raid Group  info for Create raid live
        raid_info = dict()
        for info in range(len(data)):
            raid_info[data[info]['raid_group']] = dict()
            raid_info[data[info]['raid_group']]['raid_group'] = data[info]['raid_group']
            raid_info[data[info]['raid_group']]['raid_type'] = data[info]['raid_type']
            raid_info[data[info]['raid_group']]['os_flag'] = data[info]['os_flag']
            raid_info[data[info]['raid_group']]['enclosure'] = self._enclosure(data[info]['disks'])['enclosure']
            raid_info[data[info]['raid_group']]['slot'] = self._slot(data[info]['disks'])

        # Delete old raid group 
        self.delete_raid_group()
        
        # Set Service boot is PXE
        self.set_ipmit_boot()

        # Create Raid Group ... 
        for m in  raid_info:
            # The os Raid is create
            if  raid_info[m]['os_flag']:
                if raid_info[m]['raid_type']  == 'raid_0':
                    self.raid_0(raid_info[m]['raid_type'],
                                raid_info[m]['enclosure'],
                                raid_info[m]['slot'])
                elif raid_info[m]['raid_type']  == 'raid_1':
                    self.raid_1(raid_info[m]['raid_type'],
                                raid_info[m]['enclosure'],
                                raid_info[m]['slot'])
                elif raid_info[m]['raid_type']  == 'raid_5':
                    self.raid_5(raid_info[m]['raid_type'],
                                raid_info[m]['enclosure'],
                                raid_info[m]['slot'])
                elif raid_info[m]['raid_type']  == 'raid_10':
                    self.raid_10(raid_info[m]['raid_type'],
                                raid_info[m]['enclosure'],
                                raid_info[m]['slot'])
        
        for m in  raid_info:
            # The not is os Raid 
            if not raid_info[m]['os_flag']:
                if raid_info[m]['raid_type']  == 'raid_0':
                    self.raid_0(raid_info[m]['raid_type'],
                                raid_info[m]['enclosure'],
                                raid_info[m]['slot'])
                elif raid_info[m]['raid_type']  == 'raid_1':
                    self.raid_1(raid_info[m]['raid_type'],
                                raid_info[m]['enclosure'],
                                raid_info[m]['slot'])
                elif raid_info[m]['raid_type']  == 'raid_5':
                    self.raid_5(raid_info[m]['raid_type'],
                                raid_info[m]['enclosure'],
                                raid_info[m]['slot'])
                elif raid_info[m]['raid_type']  == 'raid_10':
                    self.raid_10(raid_info[m]['raid_type'],
                                raid_info[m]['enclosure'],
                                raid_info[m]['slot'])