#!/usr/bin/env python
# ID: $Id: orclovn-setup 7493 2013-09-03 07:21:20Z andarsi $

import os,sys,re,string,commands

#=============================================================================#
class XsigoModprobeClass:
    """XsigoModprobeClass"""
    #-------------------------------------------------------------------------#
    def __init__(self,kversion,ofed_ver,install,install_initrd,dry_run,verbose):
        """Class Initiator"""
        self.kversion   = kversion
        self.ofed_ver   = ofed_ver
        self.install    = install
        self.do_install = install_initrd
        self.dry_run    = dry_run
        self.verbose    = verbose
        self.os_version = 'unknown'
        self.os_minor_version = None
        self.saved_settings = []

	# File to make changes to.  Some OSes do not have modprobe.conf
        if os.path.exists('/etc/modprobe.conf'):
            self.filename = '/etc/modprobe.conf'
        else:
            self.filename = '/etc/modprobe.d/xsigo.conf'

        # Initial settings for modprobe.conf entries
        self.mod_options = {}
        self.mod_options['ib_mthca']  = {}
        self.mod_options['mlx4_core'] = {}
        self.mod_options['xscore']    = {}
        self.mod_options['xsvnic']    = {}
        self.mod_options['xve']       = {}
        self.mod_options['ib_mthca']['rdb_per_qp']         = 64
        self.mod_options['mlx4_core']['log_rdmarc_per_qp'] = 6
        self.mod_options['xscore']['boot_flag']            = 0
        self.mod_options['xscore']['xsigod_enable']        = 1
        self.mod_options['xsvnic']['xsvnic_havnic']        = 1
        self.mod_options['xsvnic']['xs_seq_file']          = 1
        self.mod_options['xve']['xs_seq_file']             = 1

        # Call specific routes to set parameters
        self.__SetOsType__()
        self.__InitrdCapable__()

        # Load orginal file if it is there
        self.__LoadModprobeConf__()
        self.__ApplyExtraParms__()

        # Process all entries for modprobe now
        self.__SetupOvm321__()
        self.__SetupOvm322__()
        self.__SetupOvm331__()
        self.__RemoveLogrdma__()
        # __init__

    #-------------------------------------------------------------------------#
    def __PV__(self,line):
        """Prints line if self.verbose is True"""
        if self.verbose == True:
            print line
        # __PV__

    #-------------------------------------------------------------------------#
    def __Normalize__(self,line):
        """Change line to have only 1 space between words"""
        out   = []
        nline = line.rstrip()
        nline = re.sub('	',' ',nline)
        words = string.split(nline,' ')
        for x in words:
            if len(x) > 0:
                out.append(x)
        return string.join(out,' ')
        # __Normalize__

    #-------------------------------------------------------------------------#
    def __Run__(self,cmd,exit_on_error=True):
        """Run the command unless dry_run is True, than just print cmd"""
        err = 0
        if self.dry_run == False:
            self.__PV__('Running: '+str(cmd))
            err = os.system(cmd)
            if err != 0:
                if exit_on_error == True:
                    sys.stderr.write('ERROR: Child process exited with status '+str(err)+', exiting!\n')
                    sys.exit(1)
        else:
            print cmd
        return err
        # __Run__

    #-------------------------------------------------------------------------#
    def __ApplyExtraParms__(self):
        """Adds extra parameters from the saved modprobe file"""
        for line in self.saved_settings:
            line = re.sub('options ','',line)
            line = self.__Normalize__(line=line)
            words = string.split(line,' ')
            mod   = words[0]
            if mod not in self.mod_options:
                self.mod_options[mod] = {}
            for keyval in words[1:]:
                if '=' in keyval:
                    key = string.split(keyval,'=')[0]
                    val = string.split(keyval,'=')[1]
                else:
                    key = keyval
                    val = None
                if key not in self.mod_options[mod]:
                    self.mod_options[mod][key] = val
        # __ApplyExtraParms__

    #-------------------------------------------------------------------------#
    def __LoadModprobeConf__(self):
        """Loads the file named in self.filename"""
        self.__PV__('Start __LoadModprobeConf__')
        if os.path.exists(self.filename):
            self.__PV__('    Loading file: '+self.filename)
            data1 = ReadFile(fname=self.filename)
            self.saved_settings = SaveBetweenMarkers(data=data1,startm='### START xsigo entries ###',endm='### END xsigo entries ###')
            self.modprobe_conf  = RemoveBetweenMarkers(data=data1,startm='### START xsigo entries ###',endm='### END xsigo entries ###')
        else:
            self.__PV__('    '+self.filename+' not found, skipping load')
            self.modprobe_conf = []
        self.__PV__('End __LoadModprobeConf__')
        # __LoadModprobeConf__

    #-------------------------------------------------------------------------#
    def __DetermineOsVer__(self):
        """Returns the ovm version of None if it is not ovm"""
        self.__PV__('Start __DetermineOsVer__')
        data = ReadFile(fname='/etc/issue')
        for line in data:
            if line == 'Oracle VM server release 3.2.1':
                self.os_version = 'ovm321'
                break
            elif line == 'Oracle VM server release 3.2.2':
                self.os_version = 'ovm322'
                break
            elif 'Oracle VM server release 3.2.' in line:
                self.os_version = 'ovm32'
                break
            elif 'Oracle VM server release 3.3.' in line:
                self.os_version = 'ovm33'
                break
            elif line == 'Oracle Linux Server release 5.6':
                self.os_version = 'oel5'
                break
            elif line == 'Oracle Linux Server release 5.7':
                self.os_version = 'oel5'
                break
            elif line == 'Oracle Linux Server release 5.8':
                self.os_version = 'oel5'
                break
            elif line == 'Oracle Linux Server release 5.9':
                self.os_version = 'oel5'
                break
            elif line == 'Oracle Linux Server release 6.0':
                self.os_version = 'oel6'
                break
            elif line == 'Oracle Linux Server release 6.1':
                self.os_version = 'oel6'
                break
            elif line == 'Oracle Linux Server release 6.2':
                self.os_version = 'oel6'
                break
            elif line == 'Oracle Linux Server release 6.3':
                self.os_version = 'oel6'
                break
            elif line == 'Oracle Linux Server release 6.4':
                self.os_version = 'oel6'
                self.os_minor_version = '4'
                break
        data_el7 = ReadFile(fname='/etc/oracle-release')
        for line in data_el7:
            if line == 'Oracle Linux Server release 7.0':
                self.os_version = 'oel7'
                break
        self.__PV__('    Os Version: '+self.os_version)
        self.__PV__('End __DetermineOsVer__')
        # __DetermineOsVer__

    #-------------------------------------------------------------------------#
    def __SetOsType__(self):
        """Sets the os type"""
        self.__PV__('Start __SetOsType__')
        self.__DetermineOsVer__()

        if self.os_version == None:
            if 'el5' in self.kversion:
                self.os_version = 'oel5'
            elif 'el6' in self.kversion:
                self.os_version = 'oel6'
            elif 'el7' in self.kversion:
                self.os_version = 'oel7'
            else:
                self.os_version = 'unknown'
        self.__PV__('    OS is: '+self.os_version)
        self.__PV__('End __SetOsType__')
        # __SetOsType__

    #-------------------------------------------------------------------------#
    def __InitrdCapable__(self):
        """Set do_install to True if this OS is cabable of having the drivers in the initrd"""
        self.__PV__('Start __InitrdCapable__')
        if self.os_version == 'ovm321' or self.os_version == 'ovm32':
            self.do_install = False
        elif self.os_version == 'ovm322' or self.os_version == 'ovm32':
            self.do_install = False
        elif self.os_version == 'ovm331' or self.os_version == 'ovm33':
            self.do_install = False
        self.__PV__('End __InitrdCapable__')
        # __InitrdCapable__

    #-------------------------------------------------------------------------#
    def __SetupOvm321__(self):
        """Setup specific entries in modprobe.conf for ovm-321"""
        self.__PV__('Start __SetupOvm321__')
        if self.os_version == 'ovm321' or self.os_version == 'ovm32':
            self.mod_options['xscore']['xsigod_enable'] = 0
            self.mod_options['xsvnic']['xsvnic_havnic'] = 0
        self.__PV__('End __SetupOvm321__')
        # __SetupOvm321__

    #-------------------------------------------------------------------------#
    def __SetupOvm322__(self):
        """Setup specific entries in modprobe.conf for ovm-322"""
        self.__PV__('Start __SetupOvm322__')
        if self.os_version == 'ovm322' or self.os_version == 'ovm32':
            self.mod_options['xscore']['xsigod_enable'] = 0
            self.mod_options['xsvnic']['xsvnic_havnic'] = 0
        self.__PV__('End __SetupOvm322__')
        # __SetupOvm321__

    #-------------------------------------------------------------------------#
    def __SetupOvm331__(self):
        """Setup specific entries in modprobe.conf for ovm-331"""
        self.__PV__('Start __SetupOvm331__')
        if self.os_version == 'ovm331' or self.os_version == 'ovm33':
            self.mod_options['xscore']['xsigod_enable'] = 0
            self.mod_options['xsvnic']['xsvnic_havnic'] = 0
        self.__PV__('End __SetupOvm331__')
        # __SetupOvm331__

    #-------------------------------------------------------------------------#
    def __FindMxl4_core__(self):
        """Finds the location of mlx4_core.ko in the kernel tree"""
        self.__PV__('Start __FindMxl4_core__')
        ret   = None
        fname = '/lib/modules/'+self.kversion+'/modules.dep'
        data  = ReadFile(fname=fname)
        for line in data:
            words = string.split(line,':')
            if 'mlx4_core.ko' in words[0]:
                if '/lib/modules/'+self.kversion in words[0]:
                    ret = words[0]
                else:
                    ret = '/lib/modules/'+self.kversion+'/'+words[0]
                break
        if ret == None:
            sys.stderr.write('ERROR:  Could not find mlx4_core.ko, exiting!\n')
            sys.exit(1)
        self.__PV__('    mlx4_core file is at '+ret)
        self.__PV__('End __FindMxl4_core__')
        return ret
        # __FindMxl4_core__

    #-------------------------------------------------------------------------#
    def __RemoveLogrdma__(self):
        """Remove log_rdmarc_per_qp if the mlx4_core.ko module does not have it"""
        self.__PV__('Start __RemoveLogrdma__')
        parm_exists = True
        fname       = self.__FindMxl4_core__()
        cmdl        = []

        cmdl.append('modinfo ')
        cmdl.append(fname)
        cmdl.append(' 2> /dev/null')
        cmdl.append(' | grep -q log_rdmarc_per_qp')

        cmd = string.join(cmdl,'')
        err_code = self.__Run__(cmd=cmd,exit_on_error=False)
        if err_code != 0:
            parm_exists = False

        if parm_exists == False:
            del self.mod_options['mlx4_core']['log_rdmarc_per_qp']
        else:
            self.mod_options['xscore']['rdma_responder_resources'] = 64
        self.__PV__('End __RemoveLogrdma__')
    # __RemoveLogrdma__

    #-------------------------------------------------------------------------#
    def __IsKernel__(self,data):
        """Returns True if data is in the  kernel"""
        self.__PV__('Start __IsKernel__')
        ret = False
        if data in self.kversion:
            ret = True
        self.__PV__('End __IsKernel__')
        return ret
        # __IsKernel__

    #-------------------------------------------------------------------------#
    def __UninstallRulesFiles__(self):
        """Removes udev rules baseed on OS"""
        self.__PV__('Start __UninstallRulesFiles__')
        if os.path.exists('/etc/udev/rules.d/xsigo.rules'):
            self.__Run__(cmd='rm -rf /etc/udev/rules.d/xsigo.rules')
        if os.path.exists('/opt/xsigo/bin/xsigo-hotplug'):
            self.__Run__(cmd='rm -rf /opt/xsigo/bin/xsigo-hotplug')
        self.__PV__('End __UninstallRulesFiles__')
        # __UninstallRulesFiles__

    #-------------------------------------------------------------------------#
    def __InstallRulesFiles__(self):
        """Installs udev rules baseed on OS"""
        self.__PV__('Start __InstallRulesFiles__')
        if self.__IsKernel__('xen') == True:
            if self.os_version == 'ovm311':
                self.__Run__(cmd='install -m 755 /opt/xsigo/.config/ovm3/xsigo.rules /etc/udev/rules.d')
                self.__Run__(cmd='install -m 755 /opt/xsigo/.config/ovm3/xsigo-hotplug /opt/xsigo/bin/xsigo-hotplug')
            else:
                self.__Run__(cmd='install -m 755 /opt/xsigo/.config/xen/xsigo.rules /etc/udev/rules.d')
                self.__Run__(cmd='install -m 755 /opt/xsigo/.config/xen/xsigo-hotplug /opt/xsigo/bin/xsigo-hotplug')
        elif self.__IsKernel__('uek') == True:
            self.__Run__(cmd='install -m 755 /opt/xsigo/.config/ovm3/xsigo.rules /etc/udev/rules.d')
            self.__Run__(cmd='install -m 755 /opt/xsigo/.config/ovm3/xsigo-hotplug /opt/xsigo/bin/xsigo-hotplug')
        self.__PV__('End __InstallRulesFiles__')
        # __InstallRulesFiles__

    #-------------------------------------------------------------------------#
    def __Extra__(self):
        """Do extra things"""
        self.__PV__('Start __Extra__')
        if self.mod_options['xscore']['xsigod_enable'] == 0:
            if self.dry_run == False:
                data = ReadFile(fname='/etc/sysconfig/xsigo')
                out  = []
                change_made = False
                for x in data:
                    if 'XSIGO_ENABLE_USERSPACE="yes"' in x:
                        change_made = True
                        out.append('XSIGO_ENABLE_USERSPACE="no"')
                    else:
                        out.append(x)
                if change_made == True:
                    WriteFile(fname='/etc/sysconfig/xsigo',data=data)
            else:
                print 'Change XSIGO_ENABLE_USERSPACE="yes" to XSIGO_ENABLE_USERSPACE="no" in /etc/sysconfig/xsigo'
        self.__PV__('End __Extra__')
        # __Extra__

    #-------------------------------------------------------------------------#
    def __RemoveDracutModules__(self):
        """Removes dracut modules if this is an el6 system"""
        self.__PV__('Start __InstallDracutModules__')
        self.__Run__(cmd='rm -rf /usr/share/dracut/modules.d/01xsigo')
        self.__PV__('End __InstallDracutModules__')
        # __InstallDracutModules__

    #-------------------------------------------------------------------------#
    def __InstallDracutModules__(self):
        """Install dracut modules if this is an el6 system"""
        self.__PV__('Start __InstallDracutModules__')
        if not os.path.exists('/usr/share/dracut/modules.d/01xsigo'):
            self.__Run__(cmd='mkdir -p /usr/share/dracut/modules.d/01xsigo')
        self.__Run__(cmd='install -m 755 /opt/xsigo/.config/dracut/check /usr/share/dracut/modules.d/01xsigo')
        self.__Run__(cmd='install -m 755 /opt/xsigo/.config/dracut/install /usr/share/dracut/modules.d/01xsigo')
        self.__Run__(cmd='install -m 755 /opt/xsigo/.config/dracut/installkernel /usr/share/dracut/modules.d/01xsigo')
        self.__Run__(cmd='install -m 755 /opt/xsigo/.config/dracut/xsigo.sh /usr/share/dracut/modules.d/01xsigo')
        self.__Run__(cmd='install -m 755 /opt/xsigo/.config/dracut/xsigo_settle_vhba.sh /usr/share/dracut/modules.d/01xsigo')
        self.__PV__('End __InstallDracutModules__')
        # __InstallDracutModules__

    #-------------------------------------------------------------------------#
    def __GenerateModprobeEntries__(self):
        """Returns a list of entries to be put into modprobe.conf"""
        self.__PV__('Start __GenerateModprobeEntries__')
        ret = []
        slist = []

        # Add existing modprobe data
        for x in self.modprobe_conf:
            ret.append(x)

        # Get our mods and sort them
        for mod in self.mod_options:
            slist.append(mod)
        slist.sort()

        # Add our entries
        ret.append('### START xsigo entries ###')
        for mod in slist:
            if len(self.mod_options[mod]) > 0:
                data = []
                data.append('options')
                data.append(mod)
                for entry in self.mod_options[mod]:
                    if self.mod_options[mod][entry] == None:
                        data.append(entry)
                    else:
                        data.append(entry+'='+str(self.mod_options[mod][entry]))
                ret.append(string.join(data,' '))
        ret.append('### END xsigo entries ###')
        self.__PV__('End __GenerateModprobeEntries__')
        return ret
        # __GenerateModprobeEntries__

    #-------------------------------------------------------------------------#
    def __RemoveFromModprobeConf__(self):
        """Removes the Xsigo entries from /etc/modprobe.conf"""
        self.__PV__('Start __RemoveFromModprobeConf__')
        if self.dry_run == False:
            if os.path.exists(self.filename):
                data1 = ReadFile(fname=self.filename)
                data2 = RemoveBetweenMarkers(data=data1,startm='### START xsigo entries ###',endm='### END xsigo entries ###')
            
                # Only write the file if data was changed
                if len(data1) != len(data2):
                    WriteFile(fname=self.filename,data=data2)
            
                # Cleanup lists
                del data1
                del data2
        else:
            print 'Remove entries between ### START xsigo entries ### and ### END xsigo entries ### in '+self.filename
        self.__Run__(cmd='rm -f /etc/modprobe.d/xsigo.conf*')
        self.__PV__('End __RemoveFromModprobeConf__')
        # __RemoveFromModprobeConf__
    
    #-------------------------------------------------------------------------#
    def __RemoveLegacy__(self):
        """Removes legacy scripts"""
        self.__PV__('Start __RemoveLegacy__')
        fname = '/etc/rc.d/rc.sysinit'
        if self.dry_run == False:
            if os.path.exists(fname):
                data1 = ReadFile(fname)
                data2 = RemoveBetweenMarkers(data=data1,startm='###BEGINXSIGOLOAD1###',endm='###ENDXSIGOLOAD1###')
                data3 = RemoveBetweenMarkers(data=data2,startm='###BEGINXSIGOLOAD2###',endm='###ENDXSIGOLOAD2###')
            
                # Only write the file if data was changed
                if len(data1) != len(data3):
                    WriteFile(fname=fname,data=data3)
            
                # Cleanup lists
                del data1
                del data2
                del data3
        else:
            print "Remove legacy entries in "+ fname
        self.__PV__('End __RemoveLegacy__')
        # __RemoveLegacy__
    
    #-------------------------------------------------------------------------#
    def __RemoveFromInitrd__(self,):
        """Removes drivers from initrd/initramfs""" 
        self.__PV__('Start __RemoveFromInitrd__')
        if self.do_install == True:
            if self.os_version == 'oel6' or self.os_version == 'oel7':
                fname='/boot/initramfs-'+self.kversion+'.img'
            else:
                fname='/boot/initrd-'+self.kversion+'.img'
            print 'Creating '+fname+' without Xsigo drivers, please wait'
            if self.os_version == 'oel6' or self.os_version == 'oel7':
                cmd = "/sbin/dracut --force --omit-drivers 'xscore xsvhba xve xsvnic' --omit 'xsigo dm dmraid multipath' "+fname+" "+self.kversion
                print cmd
                self.__Run__(cmd=cmd+' >/dev/null 2>&1')
            else:
                self.__Run__(cmd='/sbin/mkinitrd -f '+fname+' '+self.kversion)
            print 'Done'
        else:
            print "Skipping removal from the initrd/initramfs"
        self.__PV__('End __RemoveFromInitrd__')
        # __RemoveFromInitrd__
    
    #-------------------------------------------------------------------------#
    def __AddToInitrd__(self):
        """Adds drivers to initrd/initramfs if install_initrd is True""" 
        self.__PV__('Start __AddToInitrd__')
        if self.do_install == True:
            if self.os_version == 'oel6' or self.os_version == 'oel7':
                if self.os_minor_version == '4':
                    # copying multipath-conf for oel6u4-64
                    if os.path.exists('/sbin/multipath'):
                    # Create the default multipath.conf if it is not there
                        if not os.path.exists('/etc/multipath.conf'):
                            self.__Run__(cmd='/sbin/mpathconf --enable')

                        # populate /etc/multipath if files are not there
                        if not os.path.exists('/sbin/multipath/bindings'):
                            self.__Run__(cmd='/sbin/multipath')

                    # Create cmd to inject drivers
                    lcmd = ['/sbin/dracut','--force']
                    if os.path.exists('/etc/multipath'):
                        if not os.listdir('/etc/multipath/')==[]:
                            lcmd.append('--add multipath')
                            lcmd.append('--include /etc/multipath /etc/multipath')

                    lcmd.append('/boot/initramfs-'+self.kversion+'.img')
                    lcmd.append(self.kversion)
                    cmd = string.join(lcmd,' ')

                    print 'Creating new initramfs including Xsigo drivers /boot/initramfs-'+self.kversion+'.img'
                    print '    '+cmd
                    self.__Run__(cmd=cmd)
                    print '    Please use '+cmd+' to create any new initramfs files.'
                else:
                    print 'Creating new initramfs including Xsigo drivers /boot/initramfs-'+self.kversion+'.img'
                    print '    /sbin/dracut -f /boot/initramfs-'+self.kversion+'.img '+self.kversion
                    self.__Run__(cmd='/sbin/dracut -f /boot/initramfs-'+self.kversion+'.img '+self.kversion+' >/dev/null 2>&1')
                    print '    Please use /sbin/dracut /boot/initramfs-'+self.kversion+'.img '+self.kversion+' to create any new initramfs files.'
            else:
                print 'Creating new initrd using /sbin/xgmkinitrd /boot/initrd-'+self.kversion+'.img '+self.kversion
                self.__Run__(cmd='/sbin/xgmkinitrd /boot/initrd-'+self.kversion+'.img '+self.kversion)
                print '    Please use /sbin/xgmkinitrd /boot/initrd-'+self.kversion+'.img '+self.kversion+' to create any new initrd files.'
            print '    This is a wrapper script around mkinitrd which includes the Xsigo drivers'
            print 'Done'
        else:
            print "Skipping installation into the initrd/initramfs"
        self.__PV__('End __AddToInitrd__')
        # __AddToInitrd__

    #-------------------------------------------------------------------------#
    def __CreateModProbe__(self):
        """Creates the modprobe file specified in self.filename"""
        self.__PV__('Start __CreateModProbe__')
        # Create modprobe entries
        data2 = self.__GenerateModprobeEntries__()
        if self.dry_run == False:
            WriteFile(fname=self.filename,data=data2)
        else:
            print 'Update '+self.filename+' with'
            for x in data2:
                print x
        self.__PV__('End __CreateModProbe__')
        # __CreateModProbe__

    #-------------------------------------------------------------------------#
    def Install(self):
        """Preform an install"""
        self.__PV__('Start Install')
        # Remove legacy files
        if os.path.exists('/etc/modprobe.conf') and os.path.exists('/etc/modprobe.d/xsigo.conf'):
            self.__Run__(cmd='rm -f /etc/modprobe.d/xsigo.conf')

        self.__Run__(cmd='rm -f /etc/modprobe.d/xsigo.conf.rpm*')

        # Preform other operations
        self.__RemoveLegacy__()
        self.__CreateModProbe__()
        self.__InstallRulesFiles__()
        self.__Extra__()
        self.__InstallDracutModules__()
        self.__AddToInitrd__()
        self.__PV__('End Install')
        # Install

    #-------------------------------------------------------------------------#
    def Uninstall(self):
        """Preform an uninstall"""
        self.__PV__('Start Uninstall')
        self.__UninstallRulesFiles__()
        self.__RemoveFromModprobeConf__()
        self.__RemoveDracutModules__()
        self.__RemoveFromInitrd__()
        self.__PV__('End Uninstall')
        # Uninstall
    # XsigoModprobeClass

#=============================================================================#
def ReadFile(fname):
    """Reads in fname and returns it as a list with newlines removed"""
    ret = []
    if not os.path.exists(fname):
        sys.stderr.write('ERROR: '+fname+' does not exist, exiting!\n')
        sys.exit(1)
    F     = open(fname,'r')
    lines = F.readlines()
    F.close()

    for line in lines:
        line = line.rstrip()
        ret.append(line)
    return ret
    # ReadFile

#=============================================================================#
def WriteFile(fname,data):
    """Writes data to fname.  If fname exists, it creates a .bak file"""
    if os.path.exists(fname):
        os.system('cp -f '+fname+' '+fname+'.bak')
    F = open(fname,'w')
    for line in data:
        F.write(line+'\n')
    F.close()
    # WriteFile

#=============================================================================#
def SaveBetweenMarkers(data,startm,endm):
    """Removes code from list outside of startm and endm and returns it as a list"""
    out       = []
    in_marker = False
    for line in data:
        if line == startm:
            in_marker = True
            continue
        if line == endm:
            in_marker = False
            continue
        if in_marker == True:
            out.append(line)
    return out
    # SaveBetweenMarkers

#=============================================================================#
def RemoveBetweenMarkers(data,startm,endm):
    """Removes code from list between startm and endm and returns it as a list"""
    out       = []
    in_marker = False
    for line in data:
        if line == startm:
            in_marker = True
        if line == endm:
            in_marker = False
            continue
        if in_marker == False:
            out.append(line)
    return out
    # RemoveBetweenMarkers

#=============================================================================#
def ValidateParms(opts):
    """Validates the command line parameters, errors out if there is a problem"""
    if opts['kversion'] == None:
        # Providing the kversion by reading from grub.conf if its UEK-kernel
        is_uek = os.system("grep -m1 uek /etc/grub.conf")
	is_el7uek = os.system("grep -m1 uek /etc/grub2.cfg")
        if is_uek == 0 or is_el7uek == 0:
            os_type = os.system("cat /etc/issue | grep -i 'Oracle Linux Server'")
            if os_type == 0:
                opts['kversion'] = commands.getoutput("grep -m1 uek /etc/grub.conf | awk '{print $NF}' | awk '{print substr($0, 2, length() - 2)}'")
            else:
                opts['kversion'] = commands.getoutput("grep -m1 uek /etc/grub.conf | awk '{print $NF}' | sed s'/.$//'")
            os_type_el7 = os.system("cat /etc/oracle-release | grep -i 'Oracle Linux Server'")
            if os_type_el7 == 0:
                opts['kversion'] = commands.getoutput("cat /etc/grub2.cfg | grep -m1 -o 'gnulinux.*uek.x86_64' | cut -d - -f2,3")
            opts['ofed_ver'] = 'native'
            return None
        else:
            sys.stderr.write('ERROR: --kversion is required, exiting!\n')
            Usage(1)
    # ValidateParms

#=============================================================================#
def Usage(exit_status=0):
    """Displays the programs usage and exits"""
    print "usage:"
    print '       '+sys.argv[0]+' --kversion <kversion> --install   [--dry-run] [--verbose] [--skip-initrd]'
    print '       '+sys.argv[0]+' --kversion <kversion> --ofed-version <ofed version> --install   [--dry-run] [--verbose] [--skip-initrd]'
    print '       '+sys.argv[0]+' --kversion <kversion> --ofed-version <ofed version> --uninstall [--dry-run] [--verbose]'
    print ''
    print '    -h, --help         show help and exit'
    print '    -d, --dry-run      Do not perform tasks, just show what would be done'
    print '    -i, --install      Install Xsigo drivers on the system - default'
    print '    -k, --kversion     Specify kernel to setup'
    print '    -o, --ofed-version Specify ofed version to use'
    print '    -s, --skip-initrd  Do not install drivers into the initrd'
    print '    -u, --uninstall    Remove Xsigo drivers from system'
    print '    -v, --verbose      Lots of ugly debug output'
    sys.exit(exit_status)
    # Usage

#=============================================================================#
def ReadParms():
    """Reads in the command line parameters and returns them in opts"""
    opts             = {}
    opts['kversion'] = None
    opts['ofed_ver'] = None
    opts['verbose']  = False
    opts['install']  = True
    opts['dry_run']  = False
    opts['install_initrd']  = True
    args             = sys.argv[1:]

    # Make sure install and uninstall were not called togather
    if '--install' in args and '--uninstall' in args:
        sys.stderr.write('ERROR: --install and --uninstall are mutually exclusive, exiting!\n')
        Usage(1)

    # Get the arguements we care about and dump the rest
    while len(args) > 0:
        item = args.pop(0)
        if item == '-k' or item == '--kversion':
            opts['kversion'] = args.pop(0)
        elif item == '-o' or item == '--ofed-version':
            opts['ofed_ver'] = args.pop(0)
        elif item == '-i' or item == '--install':
            opts['install'] = True
        elif item == '-u' or item == '--uninstall':
            opts['install'] = False
        elif item == '-s' or item == '--skip-initrd':
            opts['install_initrd'] = False
        elif item == '-v' or item == '--verbose':
            opts['verbose'] = True
        elif item == '-d' or item == '--dry-run':
            opts['dry_run'] = True
        elif item == '-h' or item == '--help':
            Usage()
        else:
            sys.stderr.write('ERROR:  Unknown option '+item+', exiting!\n')
            Usage(1)
    return opts
    # ReadParms

#=============================================================================#
def main():
    """Main def for script"""
    opts = ReadParms()
    ValidateParms(opts)

    # setup variables
    sup = XsigoModprobeClass(kversion=opts['kversion'],ofed_ver=opts['ofed_ver'],
                 install=opts['install'], install_initrd=opts['install_initrd'],
                 verbose=opts['verbose'],dry_run=opts['dry_run'])

    if opts['install'] == True:
        sup.Install()
    else:
        sup.Uninstall()
    # main

#=============================================================================#
# Script starts here                                                          #
#=============================================================================#
if __name__ == '__main__':
    main()

