#!/usr/bin/python
# -*- coding: latin-1 -*-
# INTEL CONFIDENTIAL
# Copyright 2007 Intel Corporation All Rights Reserved.
#
# The source code contained or described herein and all documents related to the
# source code (“Material”) are owned by Intel Corporation or its suppliers or
# licensors. Title to the Material remains with Intel Corporation or its
# suppliers and licensors. The Material may contain trade secrets and
# proprietary and confidential information of Intel Corporation and its
# suppliers and licensors, and is protected by worldwide copyright and trade
# secret laws and treaty provisions. No part of the Material may be used,
# copied, reproduced, modified, published, uploaded, posted, transmitted,
# distributed, or disclosed in any way without Intel’s prior express written
# permission. 
# No license under any patent, copyright, trade secret or other intellectual
# property right is granted to or conferred upon you by disclosure or delivery
# of the Materials, either expressly, by implication, inducement, estoppel or
# otherwise. Any license under such intellectual property rights must be express
# and approved by Intel in writing.
#
# Include any supplier copyright notices as supplier requires Intel to use.
#
# Include supplier trademarks or logos as supplier requires Intel to use, preceded
# by an asterisk. An asterisked footnote can be added as follows:
# *Third Party trademarks are the property of their respective owners.
#
# Unless otherwise agreed by Intel in writing, you may not remove or alter this
# notice or any other notice embedded in Materials by Intel or Intel’s suppliers
# or licensors in any way.

"""
This module detects the BIOS RAID settings
This module is very chassis, BIOS, and syscfg sensitive
"""
__author__ = 'Todd C Davis'
__Product__ = 'Intel_PDK'

import sys, os, os.path, popen2, string
from systemMgr import openSysInfo, closeSysInfo, addProperty, queryProperty
from logMgr import addLogRecord,CRITICAL,ERROR,WARNING,INFO,DEBUG
from config import BMCfamilies, DeployPath
try:
    __file__
except:
    __file__ = __name__

SWataRAIDgroup = { #ESB2 ATA controller
    'NSW1U'   : '"ATA Controller Configuration" "Configure SATA as RAID"',
    'NSC2U'   : '"ATA Controller Configuration" "Configure SATA as RAID"',
    'NSN2U'   : '"Mass Storage Controller Configuration" "SATA Mode"',
    'S3000'   : '"IDE Controller" "Configure SATA as RAID"',
    'SR2500LX': '"ATA Controller Configuration" "Configure SATA as RAID"',
    'TIGH2U'  : '"ATA Controller Configuration" "Configure SATA as RAID"',
}

SWscsiRAIDgroup = { #LSI 1068 SCSI controller
    'NSC2U'   : '"Mass Storage Controller Configuration" "Configure SAS as SW RAID"',
    'NSN2U'   : '"Mass Storage Controller Configuration" "Intel(R) SAS Entry RAID Module"',
    'SR2500LX': '"Mass Storage Controller Configuration" "Configure SAS as SW RAID"',
    'TIGH2U'  : '"Mass Storage Controller Configuration" "Configure SAS as SW RAID"',
    'TIGW1U'  : '"Mass Storage Controller Configuration" "Configure SAS as SW RAID"',
}

def runSyscfg(args):
    cwd = os.getcwd()
    status = 0
    cmd = "syscfg %s"%args

    if sys.platform == 'win32':
        filePath = os.path.join(DeployPath,'win32','syscfg')
        os.chdir(filePath)
        r, w, e = popen2.popen3('%s'%cmd,-1,'b')
        elines = e.read()
        e.close()
        lines = r.read()
        r.close()
        w.close()
        if elines:
            print elines
            status = 1
        elif lines.find('FAILURE') >= 0 or lines.find('failed') >= 0:
            status = 1
    
    elif sys.platform == 'linux2':
        filePath = os.path.join(DeployPath,'Linux','syscfg')
        os.chdir(filePath)
        cmdObj = popen2.Popen4('./%s'%cmd)
        status = cmdObj.wait()
        lines = cmdObj.fromchild.read()

    if status:
        addLogRecord(0,__file__, ERROR,'%s command failed: status = 0x%x, %s'%(cmd,status,lines))
    os.chdir(cwd)
    return status, lines

def setSWRAID(enable,SATA,Matrix=0):
    ret, family = queryProperty(0,'IntelBIOSID','BoardFamilyID','',{})
    if ret or not family:
        addLogRecord(0,__name__, ERROR,'IntelBIOSID BoardFamilyID unavailable: status = 0x%x'%(ret))
    if family in BMCfamilies:
        ret, chassis = queryProperty(0,'FRU','Chassis OEM Field','',{'info':'Mainboard FRU'})
        if ret or not chassis:
            addLogRecord(0,__file__, ERROR,'chassis unavailable: ret = %d'%ret)
    else:   #S3000 family
        chassis = family
    ret, SWRAID = queryProperty(0,'BIOSRAID','SWRAID','',{})
    if ret or not SWRAID:
        addLogRecord(0,__name__, ERROR,'BIOSRAID SWRAID unavailable: status = 0x%x'%(ret))
    ret, HWRAID = queryProperty(0,'BIOSRAID','HWRAID','',{})
    if ret or not HWRAID:
        addLogRecord(0,__name__, ERROR,'BIOSRAID HWRAID unavailable: status = 0x%x'%(ret))
    ret, vendor = queryProperty(0,'BIOSRAID','Vendor','',{})
    if ret or not vendor:
        addLogRecord(0,__name__, ERROR,'BIOSRAID Vendor unavailable: status = 0x%x'%(ret))
    if not family or not chassis or not SWRAID or not HWRAID or not vendor:
        print "One or more BIOS settings are not available, run 'prepareDeployment'"
        return 2
    if enable:
        if SWRAID == 'Enabled':
            if family == 'S3000':
                if Matrix and not vendor == 'Intel':
                    # enable Matrix RAID
                    args = '/bcs "IDE Controller" "SATA RAID OPROM" 0001'
                    ret, lines = runSyscfg(args)
                    print "Matrix SW RAID configured for the %s system"%(family)
                    print "reboot required"
                    return 1
                elif not Matrix and not vendor == 'LSI':
                    # enable LSI RAID
                    args = '/bcs "IDE Controller" "SATA RAID OPROM" 0000'
                    ret, lines = runSyscfg(args)
                    print "LSI SW RAID configured for the %s system"%(family)
                    print "reboot required"
                    return 1
            addLogRecord(0,__name__, INFO,'SW RAID already enabled')
            print "SW RAID is already enabled"
            return 0
        if HWRAID == 'Enabled':
            if not SATA:
                addLogRecord(0,__name__, INFO,'SAS SW RAID not enabled, HW RAID Enabled')
                print "HW RAID is enabled"
                return 2
        if SATA:
            if family == 'S3000':
                if Matrix:
                    # enable Matrix RAID
                    print "Matrix SW RAID configured for the %s system"%(family)
                    args = '/bcs "IDE Controller" "SATA RAID OPROM" 0001'
                    ret, lines = runSyscfg(args)
                else:
                    # enable LSI RAID
                    print "LSI SW RAID configured for the %s system"%(family)
                    args = '/bcs "IDE Controller" "SATA RAID OPROM" 0000'
                    ret, lines = runSyscfg(args)
            if SWataRAIDgroup.has_key(chassis):
                if family == 'S5500':
                    args = '/bcs %s 0002'%SWataRAIDgroup[chassis]
                else:
                    args = '/bcs %s 0001'%SWataRAIDgroup[chassis]
                ret, lines = runSyscfg(args)
                print "SATA SW RAID enabled"
                print "reboot required"
                return 1
            else:
                addLogRecord(0,__name__, INFO,'SATA SW RAID not supported for this %s system'%(family))
                print 'SATA SW RAID not supported for this %s system'%(family)
                return 2
        else:
            if SWscsiRAIDgroup.has_key(chassis):
                args = '/bcs %s 0001'%SWscsiRAIDgroup[chassis]
                ret, lines = runSyscfg(args)
                print "SAS SW RAID enabled"
                print "reboot required"
                return 1
            else:
                addLogRecord(0,__name__, INFO,'SAS SW RAID not supported for this %s system'%(family))
                print 'SAS SW RAID not supported for this %s system'%(family)
                return 2
    # not enable ('disable') branches to here:
    if SWRAID == 'Disabled':
        addLogRecord(0,__name__, INFO,'SW RAID already disabled')
        print "SW RAID is already disabled"
        return 0
    if SATA:
        if SWataRAIDgroup.has_key(chassis):
            args = '/bcs %s 0000'%SWataRAIDgroup[chassis]
            ret, lines = runSyscfg(args)
            print "SATA SW RAID disabled"
            print "reboot required"
            return 1
        else:
            addLogRecord(0,__name__, INFO,'SATA SW RAID not supported for this %s system'%(family))
            print 'SATA SW RAID not supported for this %s system'%(family)
            return 2
    if SWscsiRAIDgroup.has_key(chassis):
        args = '/bcs %s 0000'%SWscsiRAIDgroup[chassis]
        ret, lines = runSyscfg(args)
        print "SAS SW RAID disabled"
        print "reboot required"
        return 1
    else:
        addLogRecord(0,__name__, INFO,'SAS SW RAID not supported for this %s system'%(family))
        print 'SAS SW RAID not supported for this %s system'%(family)
        return 2

def initBIOSRAIDProperties(sInfo,HW='Unavailable',SW='Disabled',vendor='n/a'):
    addProperty(sInfo,'BIOSRAID','HWRAID',HW,{})
    addProperty(sInfo,'BIOSRAID','SWRAID',SW,{})
    addProperty(sInfo,'BIOSRAID','Vendor',vendor,{})

def detectBIOSRAID():
    ret, family = queryProperty(0,'IntelBIOSID','BoardFamilyID','',{})
    if ret:
        addLogRecord(0,__name__, ERROR,'IntelBIOSID BoardFamilyID unavailable: status = 0x%x'%(ret))
        return ret
    if family in BMCfamilies:
        ret, chassis = queryProperty(0,'FRU','Chassis OEM Field','',{'info':'Mainboard FRU'})
        if ret:
            addLogRecord(0,__file__, ERROR,'chassis unavailable: ret = %d'%ret)
            return ret
    else:   #S3000 family
        chassis = family
    if not SWscsiRAIDgroup.has_key(chassis) and not SWataRAIDgroup.has_key(chassis):
        addLogRecord(0,__name__, INFO,'RAID not supported on %s systems'%(chassis))
        return 0
    sInfo = openSysInfo()
    initBIOSRAIDProperties(sInfo)
    SWRAIDenabled = 0
    if SWscsiRAIDgroup.has_key(chassis):
        addProperty(sInfo,'BIOSRAID','HWRAID','Disabled',{})
        args = '/d biossettings group %s'%SWscsiRAIDgroup[chassis]
        ret, lines = runSyscfg(args)
        if not ret:
            # LSI 1068 HW RAID enabled?
            if lines.find('Unable to read the BIOS settings group') >= 0:
                addProperty(sInfo,'BIOSRAID','HWRAID','Enabled',{})
                # RAID Vendor LSI
                addProperty(sInfo,'BIOSRAID','Vendor','LSI',{})
            # LSI 1068 SW RAID enabled?
            elif lines.find('Current Value : Enabled') >= 0:
                SWRAIDenabled = 1
                addProperty(sInfo,'BIOSRAID','SWRAID','Enabled',{})
                # RAID Vendor LSI
                addProperty(sInfo,'BIOSRAID','Vendor','LSI',{})
    if not SWRAIDenabled and SWataRAIDgroup.has_key(chassis):
        args = '/d biossettings group %s'%SWataRAIDgroup[chassis]
        ret, lines = runSyscfg(args)
        if not ret:
            if family == 'S5500':
                if lines.find('Current Value : SW RAID') >= 0:
                    addProperty(sInfo,'BIOSRAID','SWRAID','Enabled',{})
                    addProperty(sInfo,'BIOSRAID','Vendor','LSI',{})
            elif lines.find('Current Value : Enabled') >= 0:
                addProperty(sInfo,'BIOSRAID','SWRAID','Enabled',{})
                if family == 'S3000':
                    args = '/d biossettings group "IDE Controller" "SATA RAID OPROM"'
                    ret, lines = runSyscfg(args)
                    if not ret:
                        # RAID Vendor?
                        if lines.find('Current Value : Intel Matrix') >= 0:
                            addProperty(sInfo,'BIOSRAID','Vendor','Intel',{})
                        else:
                            # RAID Vendor LSI
                            addProperty(sInfo,'BIOSRAID','Vendor','LSI',{})
                else:
                    # RAID Vendor LSI
                    addProperty(sInfo,'BIOSRAID','Vendor','LSI',{})
    closeSysInfo(sInfo)
    return ret

if __name__ == '__main__':
    #print "executing detect BIOS RAID settings ... "
    sys.exit(detectBIOSRAID())
