18
18
package org .apache .spark .scheduler .cluster .mesos
19
19
20
20
import java .text .SimpleDateFormat
21
-
22
21
import java .util .concurrent .atomic .AtomicLong
23
22
import java .util .concurrent .{LinkedBlockingQueue , TimeUnit }
24
23
import java .util .{List => JList }
25
24
import java .util .{Collections , Date }
26
-
27
25
import org .apache .mesos .{SchedulerDriver , Scheduler }
28
26
import org .apache .mesos .Protos ._
29
-
30
27
import org .apache .spark .deploy .DriverDescription
31
28
import org .apache .spark .deploy .master .DriverState
32
29
import org .apache .spark .deploy .master .DriverState .DriverState
33
-
34
30
import org .apache .spark .SparkConf
35
31
import org .apache .spark .util .Utils
36
-
37
32
import scala .collection .mutable
38
33
import scala .collection .JavaConversions ._
39
34
import org .apache .mesos .Protos .Environment .Variable
35
+ import org .apache .spark .SparkException
36
+ import java .io .File
40
37
38
+ case class DriverRequest (desc : DriverDescription , conf : SparkConf )
41
39
42
40
private [spark] class DriverSubmission (
43
41
val submissionId : String ,
44
- val desc : DriverDescription ,
42
+ val req : DriverRequest ,
45
43
val submitDate : Date ) {
46
44
47
45
def canEqual (other : Any ): Boolean = other.isInstanceOf [DriverSubmission ]
@@ -76,7 +74,7 @@ private[spark] case class ClusterSchedulerState(
76
74
finishedDrivers : Iterable [ClusterTaskState ])
77
75
78
76
private [spark] trait ClusterScheduler {
79
- def submitDriver (desc : DriverDescription ): SubmitResponse
77
+ def submitDriver (desc : DriverRequest ): SubmitResponse
80
78
def killDriver (submissionId : String ): KillResponse
81
79
def getStatus (submissionId : String ): StatusResponse
82
80
def getState (): ClusterSchedulerState
@@ -88,7 +86,6 @@ private[spark] class MesosClusterScheduler(conf: SparkConf)
88
86
val master = conf.get(" spark.master" )
89
87
val appName = conf.get(" spark.app.name" )
90
88
val capacity = conf.getInt(" spark.mesos.driver.capacity" , 200 )
91
- val executorUri = conf.getOption(" spark.executor.uri" )
92
89
val stateLock = new Object
93
90
val launchedDrivers = new mutable.HashMap [String , ClusterTaskState ]()
94
91
@@ -105,10 +102,10 @@ private[spark] class MesosClusterScheduler(conf: SparkConf)
105
102
createDateFormat.format(submitDate), nextDriverNumber.incrementAndGet())
106
103
}
107
104
108
- def submitDriver (desc : DriverDescription ): SubmitResponse = {
105
+ def submitDriver (req : DriverRequest ): SubmitResponse = {
109
106
val submitDate : Date = new Date ()
110
107
val submissionId : String = newDriverId(submitDate)
111
- val submission = new DriverSubmission (submissionId, desc , submitDate)
108
+ val submission = new DriverSubmission (submissionId, req , submitDate)
112
109
if (queue.offer(submission)) {
113
110
SubmitResponse (submissionId, true , None )
114
111
} else {
@@ -147,9 +144,16 @@ private[spark] class MesosClusterScheduler(conf: SparkConf)
147
144
markRegistered()
148
145
}
149
146
150
- private def buildCommand (desc : DriverDescription ): CommandInfo = {
147
+ private def buildCommand (req : DriverRequest ): CommandInfo = {
148
+
149
+ val desc = req.desc
150
+
151
+ val cleanedJarUrl = desc.jarUrl.stripPrefix(" file:" )
152
+
153
+ logInfo(s " jarUrl: $cleanedJarUrl" )
154
+
151
155
val builder = CommandInfo .newBuilder()
152
- .addUris(CommandInfo .URI .newBuilder().setValue(desc.jarUrl ).build())
156
+ .addUris(CommandInfo .URI .newBuilder().setValue(cleanedJarUrl ).build())
153
157
154
158
val entries =
155
159
(conf.getOption(" spark.executor.extraLibraryPath" ).toList ++ desc.command.libraryPathEntries)
@@ -160,11 +164,7 @@ private[spark] class MesosClusterScheduler(conf: SparkConf)
160
164
" "
161
165
}
162
166
163
- val stringBuilder = new StringBuilder
164
- stringBuilder
165
- .append(desc.command.mainClass)
166
- .append(" " )
167
- .append(desc.command.arguments.mkString(" \" " , " \" " , " \" " ))
167
+ // TODO: add support for more spark-submit parameters
168
168
169
169
val envBuilder = Environment .newBuilder()
170
170
desc.command.environment.foreach {
@@ -175,14 +175,35 @@ private[spark] class MesosClusterScheduler(conf: SparkConf)
175
175
176
176
builder.setEnvironment(envBuilder.build())
177
177
178
+ val executorUri = req.conf.getOption(" spark.executor.uri" )
178
179
if (executorUri.isDefined) {
179
180
builder.addUris(CommandInfo .URI .newBuilder().setValue(executorUri.get).build())
181
+
180
182
val basename = executorUri.get.split('/' ).last.split('.' ).head
183
+ val cmd =
184
+ Seq (" bin/spark-submit" ,
185
+ " --class" , desc.command.mainClass,
186
+ " --master" , s " mesos:// ${conf.get(" spark.master" )}" ,
187
+ s " ../ ${desc.jarUrl.split(" /" ).last}" )
188
+ .mkString(" " )
189
+
181
190
builder.setValue(
182
- s " cd $basename*; $prefixEnv ${stringBuilder.toString()} " )
191
+ s " cd $basename*; $prefixEnv $cmd " )
183
192
} else {
193
+ val executorSparkHome = req.conf.getOption(" spark.mesos.executor.home" )
194
+ .getOrElse {
195
+ throw new SparkException (" Executor Spark home `spark.mesos.executor.home` is not set!" )
196
+ }
197
+
198
+ val cmd =
199
+ Seq (new File (executorSparkHome, " ./bin/spark-submit" ),
200
+ " --class" , desc.command.mainClass,
201
+ " --master" , s " mesos:// ${conf.get(" spark.master" )}" ,
202
+ desc.jarUrl.split(" /" ).last)
203
+ .mkString(" " )
204
+
184
205
builder.setValue(
185
- s " $prefixEnv ${stringBuilder.toString()} " )
206
+ s " $prefixEnv $cmd " )
186
207
}
187
208
188
209
builder.build
@@ -203,8 +224,8 @@ private[spark] class MesosClusterScheduler(conf: SparkConf)
203
224
204
225
var remainingOffers = offers
205
226
206
- val driverCpu = submission.desc.cores
207
- val driverMem = submission.desc.mem
227
+ val driverCpu = submission.req. desc.cores
228
+ val driverMem = submission.req. desc.mem
208
229
209
230
// Should use the passed in driver cpu and memory.
210
231
val offerOption = offers.find { o =>
@@ -216,15 +237,18 @@ private[spark] class MesosClusterScheduler(conf: SparkConf)
216
237
val taskId = TaskID .newBuilder().setValue(submission.submissionId).build()
217
238
218
239
val cpuResource = Resource .newBuilder()
219
- .setName(" cpus" ).setScalar(Value .Scalar .newBuilder().setValue(driverCpu)).build()
240
+ .setName(" cpus" ).setType(Value .Type .SCALAR )
241
+ .setScalar(Value .Scalar .newBuilder().setValue(driverCpu)).build()
220
242
221
243
val memResource = Resource .newBuilder()
222
- .setName(" mem" ).setScalar(Value .Scalar .newBuilder().setValue(driverMem)).build()
244
+ .setName(" mem" ).setType(Value .Type .SCALAR )
245
+ .setScalar(Value .Scalar .newBuilder().setValue(driverMem)).build()
223
246
224
- val commandInfo = buildCommand(submission.desc )
247
+ val commandInfo = buildCommand(submission.req )
225
248
226
249
val taskInfo = TaskInfo .newBuilder()
227
250
.setTaskId(taskId)
251
+ .setName(s " driver for ${submission.req.desc.command.mainClass}" )
228
252
.setSlaveId(offer.getSlaveId)
229
253
.setCommand(commandInfo)
230
254
.addResources(cpuResource)
0 commit comments