###############################################################################
# Class: JobSubmitter_qsub_LLNL
#
# Purpose:    Custom "qsub" job submitter for LLNL.
#
# Programmer: Brad Whitlock
# Date:       Thu May 17 14:22:04 PDT 2012
#
# Modifications:
#
###############################################################################

class JobSubmitter_qsub_LLNL(JobSubmitter_qsub):
    def __init__(self, launcher):
        super(JobSubmitter_qsub_LLNL, self).__init__(launcher)
        self.usettc = self.sectorname() in ("borax", "rzalastor")

    def IsRunningOnXchem(self):
        return self.sectorname() == "xchem"

    def mpiexec(self):
        if self.IsRunningOnXchem():
            return ["/opt/mpiexec/bin/mpiexec"]
        return super(JobSubmitter_qsub_LLNL, self).mpiexec()

###############################################################################
# Class: LLNLLauncher
#
# Purpose:    Custom launcher for LLNL
#
# Programmer: Brad Whitlock
# Date:       Thu May 17 14:22:04 PDT 2012
#
# Modifications:
#   Eric Brugger, Tue Nov 20 11:25:07 PST 2012
#   I removed the DetermineArchitecture method, which launched a chaos 4
#   version on some machines. Those machines are either retired or have been
#   upgraded to chaos 5.
#
#   Brad Whitlock, Wed Jun  5 16:24:26 PDT 2013
#   Special handling of networking arguments for BG/Q.
#
#   Cyrus Harrison, Tue Aug 23 08:21:12 PDT 2016
#   Added check for sequioa (seqlac)
#
#   Eric Brugger, Wed Mar 22 13:43:49 PDT 2017
#   I added the MPI library paths to the LD_LIBRARY_PATH for borax, quartz,
#   rzgenie and rztrona.
#
###############################################################################

class LLNLLauncher(MainLauncher):
    def __init__(self):
        super(LLNLLauncher, self).__init__()

    # Get the IP address for eth0.
    def GetIPAddress(self):
        p = subprocess.Popen(["/sbin/ifconfig"], stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
        output = p.communicate()
        iplines = [x for x in string.split(output[0], "\n") if string.find(x, "inet addr") != -1]
        start = string.find(iplines[0], "inet addr")
        end = string.find(iplines[0], "Bcast:")
        IP = string.replace(iplines[0][start + 10:end], " ", "")
        return IP

    def Customize(self):
        # ----
        # Hoth @ LLNL
        # ----
        if self.nodename() == "hoth" and self.domainname() == "llnl.gov":
            SETENV("LIBGL_ALWAYS_INDIRECT", "1")

        #
        # BG/Q networking changes for parallel engine. We override the host
        # with an IP address.
        #
        if self.parallelArgs.parallel and \
           (string.find(self.generalArgs.exe_name, "_par") != -1 or \
            string.find(self.generalArgs.exe_name, "_ser") != -1):
            if self.sectorname() == "vulcanlac" or \
               self.sectorname() == "rzuseqlac" or \
               self.sectorname() == "seqlac":
                self.generalArgs.host = self.GetIPAddress()
                self.generalArgs.guesshost = 0
                self.generalArgs.sshtunneling = 0
                self.generalArgs.noloopback = 1

        #
        # Set the LD_LIBRARY_PATH to include the path to MPI on borax,
        # quartz, rzgenie and rztrona.
        #
        if self.sectorname() == "borax" or \
           self.sectorname() == "quartz" or \
           self.sectorname() == "rzgenie" or \
           self.sectorname() == "rztrona":
            mpi_ld_library_paths = ["/usr/tce/packages/mvapich2/mvapich2-2.2-intel-16.0.3/lib", "/usr/tce/packages/intel/intel-16.0.3/lib/intel64"]
            SETENV("LD_LIBRARY_PATH", self.joinpaths(mpi_ld_library_paths))

    #
    # Override the JobSubmitterFactory method so the custom job submitter can
    # be returned.
    #
    def JobSubmitterFactory(self, launch):
        if launch[:4] == "qsub" or launch[:4] == "msub":
            return JobSubmitter_qsub_LLNL(self)
        return super(LLNLLauncher, self).JobSubmitterFactory(launch)

# Launcher creation function
def createlauncher():
    return LLNLLauncher()
