@@ -60,11 +60,11 @@ object SparkSubmit {
6060 private [spark] var exitFn : () => Unit = () => System .exit(- 1 )
6161
6262 private [spark] def printErrorAndExit (str : String ) = {
63- printStream.println(" error : " + str)
64- printStream.println(" run with --help for more information or --verbose for debugging output" )
63+ printStream.println(" Error : " + str)
64+ printStream.println(" Run with --help for usage help or --verbose for debug output" )
6565 exitFn()
6666 }
67- private [spark] def printWarning (str : String ) = printStream.println(" warning : " + str)
67+ private [spark] def printWarning (str : String ) = printStream.println(" Warning : " + str)
6868
6969 /**
7070 * @return
@@ -83,7 +83,7 @@ object SparkSubmit {
8383 } else if (appArgs.master.startsWith(" mesos" )) {
8484 clusterManager = MESOS
8585 } else {
86- printErrorAndExit(" master must start with yarn, mesos, spark, or local" )
86+ printErrorAndExit(" Master must start with yarn, mesos, spark, or local" )
8787 }
8888
8989 // Because "yarn-cluster" and "yarn-client" encapsulate both the master
@@ -116,9 +116,20 @@ object SparkSubmit {
116116 var childMainClass = " "
117117
118118 if (clusterManager == MESOS && deployOnCluster) {
119- printErrorAndExit(" Mesos does not support running the driver on the cluster" )
119+ printErrorAndExit(" Cannot run driver on the cluster in Mesos " )
120120 }
121121
122+ // If we're running a Python app, set the Java class to run to be our PythonRunner, add
123+ // Python files to deployment list, and pass the main file and Python path to PythonRunner
124+ if (appArgs.isPython) {
125+ appArgs.mainClass = " org.apache.spark.deploy.PythonRunner"
126+ appArgs.files = mergeFileLists(appArgs.files, appArgs.pyFiles, appArgs.primaryResource)
127+ val pyFiles = Option (appArgs.pyFiles).getOrElse(" " )
128+ appArgs.childArgs = ArrayBuffer (appArgs.primaryResource, pyFiles) ++ appArgs.childArgs
129+ appArgs.primaryResource = RESERVED_JAR_NAME
130+ }
131+
132+ // If we're deploying into YARN, use yarn.Client as a wrapper around the user class
122133 if (! deployOnCluster) {
123134 childMainClass = appArgs.mainClass
124135 if (appArgs.primaryResource != RESERVED_JAR_NAME ) {
@@ -130,8 +141,8 @@ object SparkSubmit {
130141 childArgs += (" --class" , appArgs.mainClass)
131142 }
132143
144+ // Make sure YARN is included in our build if we're trying to use it
133145 if (clusterManager == YARN ) {
134- // The choice of class is arbitrary, could use any spark-yarn class
135146 if (! Utils .classIsLoadable(" org.apache.spark.deploy.yarn.Client" ) && ! Utils .isTesting) {
136147 val msg = " Could not load YARN classes. This copy of Spark may not have been compiled " +
137148 " with YARN support."
@@ -142,38 +153,39 @@ object SparkSubmit {
142153 // Special flag to avoid deprecation warnings at the client
143154 sysProps(" SPARK_SUBMIT" ) = " true"
144155
156+ // A list of rules to map each argument to system properties or command-line options in
157+ // each deploy mode; we iterate through these below
145158 val options = List [OptionAssigner ](
146- new OptionAssigner (appArgs.master, ALL_CLUSTER_MGRS , false , sysProp = " spark.master" ),
147- new OptionAssigner (appArgs.driverExtraClassPath, STANDALONE | YARN , true ,
159+ OptionAssigner (appArgs.master, ALL_CLUSTER_MGRS , false , sysProp = " spark.master" ),
160+ OptionAssigner (appArgs.driverExtraClassPath, STANDALONE | YARN , true ,
148161 sysProp = " spark.driver.extraClassPath" ),
149- new OptionAssigner (appArgs.driverExtraJavaOptions, STANDALONE | YARN , true ,
162+ OptionAssigner (appArgs.driverExtraJavaOptions, STANDALONE | YARN , true ,
150163 sysProp = " spark.driver.extraJavaOptions" ),
151- new OptionAssigner (appArgs.driverExtraLibraryPath, STANDALONE | YARN , true ,
164+ OptionAssigner (appArgs.driverExtraLibraryPath, STANDALONE | YARN , true ,
152165 sysProp = " spark.driver.extraLibraryPath" ),
153- new OptionAssigner (appArgs.driverMemory, YARN , true , clOption = " --driver-memory" ),
154- new OptionAssigner (appArgs.name, YARN , true , clOption = " --name" ),
155- new OptionAssigner (appArgs.queue, YARN , true , clOption = " --queue" ),
156- new OptionAssigner (appArgs.queue, YARN , false , sysProp = " spark.yarn.queue" ),
157- new OptionAssigner (appArgs.numExecutors, YARN , true , clOption = " --num-executors" ),
158- new OptionAssigner (appArgs.numExecutors, YARN , false , sysProp = " spark.executor.instances" ),
159- new OptionAssigner (appArgs.executorMemory, YARN , true , clOption = " --executor-memory" ),
160- new OptionAssigner (appArgs.executorMemory, STANDALONE | MESOS | YARN , false ,
166+ OptionAssigner (appArgs.driverMemory, YARN , true , clOption = " --driver-memory" ),
167+ OptionAssigner (appArgs.name, YARN , true , clOption = " --name" ),
168+ OptionAssigner (appArgs.queue, YARN , true , clOption = " --queue" ),
169+ OptionAssigner (appArgs.queue, YARN , false , sysProp = " spark.yarn.queue" ),
170+ OptionAssigner (appArgs.numExecutors, YARN , true , clOption = " --num-executors" ),
171+ OptionAssigner (appArgs.numExecutors, YARN , false , sysProp = " spark.executor.instances" ),
172+ OptionAssigner (appArgs.executorMemory, YARN , true , clOption = " --executor-memory" ),
173+ OptionAssigner (appArgs.executorMemory, STANDALONE | MESOS | YARN , false ,
161174 sysProp = " spark.executor.memory" ),
162- new OptionAssigner (appArgs.driverMemory, STANDALONE , true , clOption = " --memory" ),
163- new OptionAssigner (appArgs.driverCores, STANDALONE , true , clOption = " --cores" ),
164- new OptionAssigner (appArgs.executorCores, YARN , true , clOption = " --executor-cores" ),
165- new OptionAssigner (appArgs.executorCores, YARN , false , sysProp = " spark.executor.cores" ),
166- new OptionAssigner (appArgs.totalExecutorCores, STANDALONE | MESOS , false ,
175+ OptionAssigner (appArgs.driverMemory, STANDALONE , true , clOption = " --memory" ),
176+ OptionAssigner (appArgs.driverCores, STANDALONE , true , clOption = " --cores" ),
177+ OptionAssigner (appArgs.executorCores, YARN , true , clOption = " --executor-cores" ),
178+ OptionAssigner (appArgs.executorCores, YARN , false , sysProp = " spark.executor.cores" ),
179+ OptionAssigner (appArgs.totalExecutorCores, STANDALONE | MESOS , false ,
167180 sysProp = " spark.cores.max" ),
168- new OptionAssigner (appArgs.files, YARN , false , sysProp = " spark.yarn.dist.files" ),
169- new OptionAssigner (appArgs.files, YARN , true , clOption = " --files" ),
170- new OptionAssigner (appArgs.archives, YARN , false , sysProp = " spark.yarn.dist.archives" ),
171- new OptionAssigner (appArgs.archives, YARN , true , clOption = " --archives" ),
172- new OptionAssigner (appArgs.jars, YARN , true , clOption = " --addJars" ),
173- new OptionAssigner (appArgs.files, LOCAL | STANDALONE | MESOS , true , sysProp = " spark.files" ),
174- new OptionAssigner (appArgs.jars, LOCAL | STANDALONE | MESOS , false , sysProp = " spark.jars" ),
175- new OptionAssigner (appArgs.name, LOCAL | STANDALONE | MESOS , false ,
176- sysProp = " spark.app.name" )
181+ OptionAssigner (appArgs.files, YARN , false , sysProp = " spark.yarn.dist.files" ),
182+ OptionAssigner (appArgs.files, YARN , true , clOption = " --files" ),
183+ OptionAssigner (appArgs.archives, YARN , false , sysProp = " spark.yarn.dist.archives" ),
184+ OptionAssigner (appArgs.archives, YARN , true , clOption = " --archives" ),
185+ OptionAssigner (appArgs.jars, YARN , true , clOption = " --addJars" ),
186+ OptionAssigner (appArgs.files, LOCAL | STANDALONE | MESOS , true , sysProp = " spark.files" ),
187+ OptionAssigner (appArgs.jars, LOCAL | STANDALONE | MESOS , false , sysProp = " spark.jars" ),
188+ OptionAssigner (appArgs.name, LOCAL | STANDALONE | MESOS , false , sysProp = " spark.app.name" )
177189 )
178190
179191 // For client mode make any added jars immediately visible on the classpath
@@ -183,9 +195,10 @@ object SparkSubmit {
183195 }
184196 }
185197
198+ // Map all arguments to command-line options or system properties for our chosen mode
186199 for (opt <- options) {
187200 if (opt.value != null && deployOnCluster == opt.deployOnCluster &&
188- (clusterManager & opt.clusterManager) != 0 ) {
201+ (clusterManager & opt.clusterManager) != 0 ) {
189202 if (opt.clOption != null ) {
190203 childArgs += (opt.clOption, opt.value)
191204 } else if (opt.sysProp != null ) {
@@ -230,8 +243,8 @@ object SparkSubmit {
230243 }
231244
232245 private def launch (childArgs : ArrayBuffer [String ], childClasspath : ArrayBuffer [String ],
233- sysProps : Map [String , String ], childMainClass : String , verbose : Boolean = false ) {
234-
246+ sysProps : Map [String , String ], childMainClass : String , verbose : Boolean = false )
247+ {
235248 if (verbose) {
236249 printStream.println(s " Main class: \n $childMainClass" )
237250 printStream.println(s " Arguments: \n ${childArgs.mkString(" \n " )}" )
@@ -273,15 +286,26 @@ object SparkSubmit {
273286 val url = localJarFile.getAbsoluteFile.toURI.toURL
274287 loader.addURL(url)
275288 }
289+
290+ /**
291+ * Merge a sequence of comma-separated file lists, some of which may be null to indicate
292+ * no files, into a single comma-separated string.
293+ */
294+ private [spark] def mergeFileLists (lists : String * ): String = {
295+ val merged = lists.filter(_ != null )
296+ .flatMap(_.split(" ," ))
297+ .mkString(" ," )
298+ if (merged == " " ) null else merged
299+ }
276300}
277301
278302/**
279303 * Provides an indirection layer for passing arguments as system properties or flags to
280304 * the user's driver program or to downstream launcher tools.
281305 */
282- private [spark] class OptionAssigner (val value : String ,
283- val clusterManager : Int ,
284- val deployOnCluster : Boolean ,
285- val clOption : String = null ,
286- val sysProp : String = null
287- ) { }
306+ private [spark] case class OptionAssigner (
307+ value : String ,
308+ clusterManager : Int ,
309+ deployOnCluster : Boolean ,
310+ clOption : String = null ,
311+ sysProp : String = null )
0 commit comments