CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
397 lines
17 KiB
Python
397 lines
17 KiB
Python
################################################################################
|
|
#
|
|
# Copyright (C) 2021-2022 Advanced Micro Devices, Inc. All rights reserved.
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
# in the Software without restriction, including without limitation the rights
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be included in
|
|
# all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
# SOFTWARE.
|
|
#
|
|
################################################################################
|
|
|
|
import os
|
|
|
|
class ScriptHelper(object):
|
|
"""
|
|
Helper class to facilitate formatting when
|
|
writing bash scripts.
|
|
"""
|
|
|
|
@classmethod
|
|
def genLine(cls, text):
|
|
return str("{0}\n").format(text)
|
|
|
|
@classmethod
|
|
def genComment(cls, text):
|
|
return cls.genLine(str("#") + str(text))
|
|
|
|
@classmethod
|
|
def genEcho(cls, text):
|
|
return cls.genLine(str("echo \"{0}\";").format(str(text)))
|
|
|
|
@classmethod
|
|
def makeExecutable(cls, path):
|
|
mode = os.stat(path).st_mode
|
|
mode |= (mode & 0o444) >> 2 # copy R bits to X
|
|
os.chmod(path, mode)
|
|
|
|
class ScriptWriter(object):
|
|
"""
|
|
A script writing utility class that holds a string
|
|
buffer and wraps writing to the buffer.
|
|
Has factory functions to build scripts with regular
|
|
workflow interface.
|
|
"""
|
|
def __init__(self):
|
|
self._buffer = ""
|
|
|
|
def writeLine(self, text):
|
|
self._buffer += ScriptHelper.genLine(text)
|
|
|
|
def writeComment(self, text):
|
|
self._buffer += ScriptHelper.genComment(text)
|
|
|
|
def writeEcho(self, text):
|
|
self._buffer += ScriptHelper.genEcho(text)
|
|
|
|
def dumpToFile(self, fileName, outputDir = "."):
|
|
scriptPath = os.path.join(outputDir, fileName)
|
|
with open(scriptPath, "w") as f:
|
|
f.write(self._buffer)
|
|
ScriptHelper.makeExecutable(scriptPath)
|
|
|
|
def __str__(self):
|
|
return self._buffer
|
|
|
|
@classmethod
|
|
def writeScript(bufferClass, writerClass, fileName, outputDir = "."):
|
|
buffer = bufferClass()
|
|
writerClass.writeHeader(buffer)
|
|
writerClass.writeBody(buffer)
|
|
writerClass.writeEpilogue(buffer)
|
|
buffer.dumpToFile(fileName, outputDir)
|
|
|
|
@classmethod
|
|
def previewScript(bufferClass, writerClass):
|
|
buffer = bufferClass()
|
|
writerClass.writeHeader(buffer)
|
|
writerClass.writeBody(buffer)
|
|
writerClass.writeEpilogue(buffer)
|
|
print(buffer)
|
|
|
|
@classmethod
|
|
def writeBenchmarkNodeScript(cls, fileName, outputDir="."):
|
|
cls.writeScript(BenchmarkNodeWriter, fileName, outputDir)
|
|
|
|
@classmethod
|
|
def writeBenchmarkTaskScript(cls, fileName, outputDir="."):
|
|
cls.writeScript(BenchmarkTaskWriter, fileName, outputDir)
|
|
|
|
@classmethod
|
|
def writeBenchmarkJobScript(cls, fileName, outputDir="."):
|
|
cls.writeScript(BenchmarkJobWriter, fileName, outputDir)
|
|
|
|
|
|
class BenchmarkNodeWriter(object):
|
|
"""
|
|
Node host run script.
|
|
Creates an instance of the docker image and
|
|
mounts the logs, results and tasks directories
|
|
and finally invokes the benchmark on the
|
|
supplied yaml.
|
|
"""
|
|
@staticmethod
|
|
def __initHeader(sBuffer):
|
|
sBuffer.writeComment("!/bin/bash")
|
|
sBuffer.writeComment("Benchmark node script")
|
|
sBuffer.writeComment("Actual host task to be run by a SLURM worker node")
|
|
sBuffer.writeLine("")
|
|
|
|
@staticmethod
|
|
def __initializeFuncs(sBuffer):
|
|
sBuffer.writeComment("Funcs")
|
|
sBuffer.writeLine("usage() { echo \"Usage: $0 [-i <path_to_docker_image>] [-l <log_dir>] [-r <result_dir>] [-t <task_dir>]\" 1>&2; exit 1; }")
|
|
sBuffer.writeLine("failAndExit() { echo \"FAILED: $1\" 1>&2; exit 1; }")
|
|
sBuffer.writeLine("")
|
|
|
|
@staticmethod
|
|
def __parseArgs(sBuffer):
|
|
sBuffer.writeComment("Parse arguments")
|
|
sBuffer.writeLine("while getopts i:l:r:t: flag")
|
|
sBuffer.writeLine("do")
|
|
sBuffer.writeLine(" case \"${flag}\" in")
|
|
sBuffer.writeLine(" i) dockerImagePath=${OPTARG};;")
|
|
sBuffer.writeLine(" l) logDir=${OPTARG};;")
|
|
sBuffer.writeLine(" r) resultDir=${OPTARG};;")
|
|
sBuffer.writeLine(" t) taskDir=${OPTARG};;")
|
|
sBuffer.writeLine(" *) usage;;")
|
|
sBuffer.writeLine(" esac")
|
|
sBuffer.writeLine("done")
|
|
sBuffer.writeLine("[ -z \"${dockerImagePath}\" ] || [ -z \"${logDir}\" ] || [ -z \"${resultDir}\" ] || [ -z \"${taskDir}\" ] && usage;")
|
|
sBuffer.writeLine("[ -d \"${logDir}\" ] && [ -d \"${resultDir}\" ] && [ -d \"${taskDir}\" ] || failAndExit \"Directory not found\";")
|
|
sBuffer.writeLine("[ -f \"${dockerImagePath}\" ] || failAndExit \"Docker image not found: $dockerImagePath\";")
|
|
sBuffer.writeEcho("Docker image path: $dockerImagePath")
|
|
sBuffer.writeEcho("Path to log: $logDir")
|
|
sBuffer.writeEcho("Path to task: $taskDir")
|
|
sBuffer.writeEcho("Path to result: $resultDir")
|
|
sBuffer.writeLine("")
|
|
|
|
@staticmethod
|
|
def __loadDockerImage(sBuffer):
|
|
sBuffer.writeComment("Import docker image")
|
|
sBuffer.writeComment("Successful output is \"Loaded image: imageName:TAG\"")
|
|
sBuffer.writeEcho("Loading docker image...")
|
|
sBuffer.writeLine("dockerLoadOutput=`docker load < $dockerImagePath || failAndExit \"Importing docker image\"`")
|
|
sBuffer.writeLine("")
|
|
sBuffer.writeEcho("Docker Load Result: $dockerLoadOutput")
|
|
sBuffer.writeLine("[ -z \"${dockerLoadOutput}\" ] && failAndExit \"Loading docker image $dockerImagePath\"")
|
|
sBuffer.writeLine("")
|
|
sBuffer.writeComment("Split the output on ':' or spaces")
|
|
sBuffer.writeComment("Capture the docker image name and tag")
|
|
sBuffer.writeLine("outputSplit=(${dockerLoadOutput//:/ })")
|
|
sBuffer.writeLine("dockerName=${outputSplit[2]}")
|
|
sBuffer.writeLine("dockerTag=${outputSplit[3]}")
|
|
sBuffer.writeLine("")
|
|
sBuffer.writeComment("Find docker image record with correct name and tag")
|
|
sBuffer.writeLine("dockerImageQuery=`docker images | grep -i \"$dockerName\" | grep -i \"$dockerTag\"`")
|
|
sBuffer.writeLine("[ -z \"${dockerImageQuery}\" ] && failAndExit \"Finding docker image record for $dockerName:$dockerTag\"")
|
|
sBuffer.writeLine("")
|
|
sBuffer.writeComment("Get docker image ID")
|
|
sBuffer.writeLine("outputSplit=(${dockerImageQuery// / })")
|
|
sBuffer.writeLine("dockerImageId=${outputSplit[2]}")
|
|
sBuffer.writeLine("[ -z \"${dockerImageId}\" ] && failAndExit \"Finding docker image id for $dockerName:$dockerTag\"")
|
|
sBuffer.writeEcho("Success: Loaded Image ID: ${dockerImageId}")
|
|
sBuffer.writeLine("")
|
|
|
|
@staticmethod
|
|
def __runTask(sBuffer):
|
|
sBuffer.writeComment("Check the task dir exists")
|
|
sBuffer.writeLine("")
|
|
sBuffer.writeComment("Run container with mounted taskDir")
|
|
sBuffer.writeEcho("Running container... (this might take some time):")
|
|
sBuffer.writeLine("runCmd=\"docker run --rm --network=host --device=/dev/kfd --device=/dev/dri --group-add video --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -v \"$taskDir\":\"/TaskDir\" -v \"$resultDir\":\"/ResultDir\" -v \"$logDir\":\"/LogDir\" $dockerImageId\"")
|
|
sBuffer.writeEcho("$runCmd")
|
|
sBuffer.writeLine("$runCmd")
|
|
sBuffer.writeLine("returnCode=$?")
|
|
|
|
@staticmethod
|
|
def __exit(sBuffer):
|
|
sBuffer.writeEcho("Done!")
|
|
sBuffer.writeLine("exit $returnCode")
|
|
|
|
@classmethod
|
|
def writeHeader(cls, sBuffer):
|
|
cls.__initHeader(sBuffer)
|
|
|
|
@classmethod
|
|
def writeBody(cls, sBuffer):
|
|
cls.__initializeFuncs(sBuffer)
|
|
cls.__parseArgs(sBuffer)
|
|
cls.__loadDockerImage(sBuffer)
|
|
cls.__runTask(sBuffer)
|
|
|
|
@classmethod
|
|
def writeEpilogue(cls, sBuffer):
|
|
cls.__exit(sBuffer)
|
|
|
|
class BenchmarkTaskWriter(object):
|
|
"""
|
|
SLURM specific script.
|
|
Invokes the 'srun' command to queue a task.
|
|
SLURM environment variables tell us which
|
|
indexed task to run as part of the array.
|
|
The final task submitted is the node script
|
|
which will run on one of the hosts.
|
|
"""
|
|
@staticmethod
|
|
def __initHeader(sBuffer):
|
|
sBuffer.writeComment("!/bin/bash")
|
|
sBuffer.writeComment("Benchmark task enqueue script")
|
|
sBuffer.writeComment("This script will configure and commit a single task to the cluster.")
|
|
sBuffer.writeComment("Intended to be the run target of SLURM SBATCH multiplexer")
|
|
sBuffer.writeLine("")
|
|
|
|
@staticmethod
|
|
def __initializeFuncs(sBuffer):
|
|
sBuffer.writeComment("Funcs")
|
|
sBuffer.writeLine("usage() { echo \"Usage: $0 [-i <image_dir>] [-l <logs_dir>] [-r <results_dir>] [-t <tasks_dir>] \" 1>&2; exit 1; }")
|
|
sBuffer.writeLine("failAndExit() { echo \"FAILED: $1\" 1>&2; exit 1; }")
|
|
sBuffer.writeLine("")
|
|
|
|
@staticmethod
|
|
def __parseArgs(sBuffer):
|
|
sBuffer.writeComment("Parse arguments")
|
|
sBuffer.writeLine("while getopts i:l:r:t: flag")
|
|
sBuffer.writeLine("do")
|
|
sBuffer.writeLine(" case \"${flag}\" in")
|
|
sBuffer.writeLine(" i) imageDir=${OPTARG};; ")
|
|
sBuffer.writeLine(" l) logsDir=${OPTARG};;")
|
|
sBuffer.writeLine(" r) resultsDir=${OPTARG};;")
|
|
sBuffer.writeLine(" t) tasksDir=${OPTARG};;")
|
|
sBuffer.writeLine(" *) usage;;")
|
|
sBuffer.writeLine(" esac")
|
|
sBuffer.writeLine("done")
|
|
sBuffer.writeLine("[ -z \"${imageDir}\" ] || [ -z \"${logsDir}\" ] || [ -z \"${resultsDir}\" ] || [ -z \"${tasksDir}\" ] && usage;")
|
|
sBuffer.writeLine("[ -d \"${imageDir}\" ] && [ -d \"${logsDir}\" ] && [ -d \"${resultsDir}\" ] && [ -d \"${tasksDir}\" ] || failAndExit \"Directory not found\";")
|
|
sBuffer.writeEcho("Image dir: $imageDir")
|
|
sBuffer.writeEcho("Logs dir: $logsDir")
|
|
sBuffer.writeEcho("Tasks dir: $tasksDir")
|
|
sBuffer.writeEcho("Results dir: $resultsDir")
|
|
sBuffer.writeLine("")
|
|
|
|
@staticmethod
|
|
def __configureTask(sBuffer):
|
|
sBuffer.writeComment("Setup task parameters")
|
|
sBuffer.writeLine("pushd $tasksDir")
|
|
sBuffer.writeLine("subDirs=(*)")
|
|
sBuffer.writeLine("taskName=${subDirs[$SLURM_ARRAY_TASK_ID]}")
|
|
sBuffer.writeLine("taskDir=$tasksDir/$taskName")
|
|
sBuffer.writeLine("taskResultDir=$resultsDir/$taskName")
|
|
sBuffer.writeLine("mkdir -p $taskResultDir")
|
|
sBuffer.writeLine("taskLogDir=$logsDir/$taskName")
|
|
sBuffer.writeLine("mkdir -p $taskLogDir")
|
|
sBuffer.writeLine("task=($taskDir/*.sh)")
|
|
sBuffer.writeLine("image=($imageDir/*.tar.gz)")
|
|
sBuffer.writeEcho("Task ID: $SLURM_ARRAY_TASK_ID / $SLURM_TASK_MAX")
|
|
sBuffer.writeEcho("Task Name: $taskName")
|
|
sBuffer.writeEcho("Host Name: `hostname`")
|
|
sBuffer.writeLine("")
|
|
|
|
@staticmethod
|
|
def __submitTask(sBuffer):
|
|
sBuffer.writeComment("Enqueue node task")
|
|
sBuffer.writeLine("srun -N 1 \"$task\" -i \"$image\" -l \"$taskLogDir\" -r \"$taskResultDir\" -t \"$taskDir\"")
|
|
sBuffer.writeLine("returnCode=$?")
|
|
|
|
@staticmethod
|
|
def __exit(sBuffer):
|
|
sBuffer.writeEcho("Done!")
|
|
sBuffer.writeLine("exit $returnCode")
|
|
|
|
@classmethod
|
|
def writeHeader(cls, sBuffer):
|
|
cls.__initHeader(sBuffer)
|
|
|
|
@classmethod
|
|
def writeBody(cls, sBuffer):
|
|
cls.__initializeFuncs(sBuffer)
|
|
cls.__parseArgs(sBuffer)
|
|
cls.__configureTask(sBuffer)
|
|
cls.__submitTask(sBuffer)
|
|
|
|
@classmethod
|
|
def writeEpilogue(cls, sBuffer):
|
|
cls.__exit(sBuffer)
|
|
|
|
class BenchmarkJobWriter(object):
|
|
"""
|
|
SLURM specific script.
|
|
Invokes the 'sbatch' and allocates resources.
|
|
Will create an array of N tasks that will each
|
|
run one instance of the task script.
|
|
N = number of sub-folders inside task folder
|
|
Assumes one node per task.
|
|
Will wait until the entire batch is complete
|
|
before exiting.
|
|
NOTE: the wait feature requires that all task
|
|
scripts have a return code, or will hang forever!
|
|
"""
|
|
@staticmethod
|
|
def __initHeader(sBuffer):
|
|
sBuffer.writeComment("!/bin/bash")
|
|
sBuffer.writeComment("Benchmark batch job script")
|
|
sBuffer.writeComment("This script will configure and submit a batch job to the cluster")
|
|
sBuffer.writeComment("This is the SLURM cluster benchmark entry-point")
|
|
sBuffer.writeLine("")
|
|
|
|
@staticmethod
|
|
def __initializeFuncs(sBuffer):
|
|
sBuffer.writeComment("Funcs")
|
|
sBuffer.writeLine("usage() { echo \"Usage: $0 [-i <image_dir>] [-l <logs_dir>] [-r <results_dir>] [-s <path_to_task_script>] [-t <tasks_dir>] \" 1>&2; exit 1; }")
|
|
sBuffer.writeLine("failAndExit() { echo \"FAILED: $1\" 1>&2; exit 1; }")
|
|
sBuffer.writeLine("")
|
|
|
|
@staticmethod
|
|
def __parseArgs(sBuffer):
|
|
sBuffer.writeComment("Parse arguments")
|
|
sBuffer.writeLine("while getopts i:l:r:s:t: flag")
|
|
sBuffer.writeLine("do")
|
|
sBuffer.writeLine(" case \"${flag}\" in")
|
|
sBuffer.writeLine(" i) imageDir=${OPTARG};;")
|
|
sBuffer.writeLine(" l) logsDir=${OPTARG};;")
|
|
sBuffer.writeLine(" r) resultsDir=${OPTARG};;")
|
|
sBuffer.writeLine(" s) taskScript=${OPTARG};;")
|
|
sBuffer.writeLine(" t) tasksDir=${OPTARG};;")
|
|
sBuffer.writeLine(" *) usage;;")
|
|
sBuffer.writeLine(" esac")
|
|
sBuffer.writeLine("done")
|
|
sBuffer.writeLine("[ -z \"${imageDir}\" ] || [ -z \"${logsDir}\" ] || [ -z \"${resultsDir}\" ] || [ -z \"${tasksDir}\" ] && usage;")
|
|
sBuffer.writeLine("[ -d \"${imageDir}\" ] && [ -d \"${logsDir}\" ] && [ -d \"${resultsDir}\" ] && [ -d \"${tasksDir}\" ] || failAndExit \"Directory not found\";")
|
|
sBuffer.writeLine("[ -f \"${taskScript}\" ] || failAndExit \"Task script not found\";")
|
|
sBuffer.writeEcho("Image dir: $imageDir")
|
|
sBuffer.writeEcho("Logs dir: $logsDir")
|
|
sBuffer.writeEcho("Tasks dir: $tasksDir")
|
|
sBuffer.writeEcho("Results dir: $resultsDir")
|
|
sBuffer.writeEcho("Enqueue script: $taskScript")
|
|
sBuffer.writeLine("")
|
|
|
|
@staticmethod
|
|
def __configureJob(sBuffer):
|
|
sBuffer.writeComment("Setup local environment")
|
|
sBuffer.writeComment("Get in the directory where this script lives")
|
|
sBuffer.writeLine("pushd $( dirname `greadlink -f ${BASH_SOURCE[0]} || readlink -f ${BASH_SOURCE[0]}` )")
|
|
sBuffer.writeComment("Enumerate the tasks and set up batch params based on task count")
|
|
sBuffer.writeLine("subDirs=($tasksDir/*)")
|
|
sBuffer.writeLine("let arraySize=${#subDirs[@]}")
|
|
sBuffer.writeLine("[ -z \"${arraySize}\" ] && failAndExit \"No task count\";")
|
|
sBuffer.writeLine("let arrayStart=0")
|
|
sBuffer.writeLine("let arrayEnd=$arraySize-1")
|
|
sBuffer.writeComment("Create logs directory for SLURM")
|
|
sBuffer.writeLine("slurmLogsDir=$logsDir/SLURM")
|
|
sBuffer.writeLine("mkdir -p $slurmLogsDir")
|
|
sBuffer.writeLine("")
|
|
|
|
@staticmethod
|
|
def __submitJob(sBuffer):
|
|
sBuffer.writeComment("Invoke batch request to SLURM")
|
|
sBuffer.writeComment("Will wait until the task completes before exiting")
|
|
sBuffer.writeLine("runCmd=\"sbatch --nodes=1 --array=$arrayStart-$arrayEnd -o $slurmLogsDir/slurm-%A_%a.out --wait $taskScript -i $imageDir -l $logsDir -r $resultsDir -t $tasksDir\"")
|
|
sBuffer.writeEcho("Submitting batch job to SLURM. This may take a while...")
|
|
sBuffer.writeEcho("$runCmd")
|
|
sBuffer.writeLine("$runCmd")
|
|
sBuffer.writeLine("returnCode=$?")
|
|
sBuffer.writeLine("popd")
|
|
|
|
@staticmethod
|
|
def __exit(sBuffer):
|
|
sBuffer.writeEcho("Done!")
|
|
sBuffer.writeLine("exit $returnCode")
|
|
|
|
@classmethod
|
|
def writeHeader(cls, sBuffer):
|
|
cls.__initHeader(sBuffer)
|
|
|
|
@classmethod
|
|
def writeBody(cls, sBuffer):
|
|
cls.__initializeFuncs(sBuffer)
|
|
cls.__parseArgs(sBuffer)
|
|
cls.__configureJob(sBuffer)
|
|
cls.__submitJob(sBuffer)
|
|
|
|
@classmethod
|
|
def writeEpilogue(cls, sBuffer):
|
|
cls.__exit(sBuffer)
|