Skip to content
Snippets Groups Projects
Commit 67595eb8 authored by jerryshao's avatar jerryshao Committed by Andrew Or
Browse files

[SPARK-5495][UI] Add app and driver kill function in master web UI

Add application kill function in master web UI for standalone mode. Details can be seen in [SPARK-5495](https://issues.apache.org/jira/browse/SPARK-5495).

The snapshot of UI shows as below:
![snapshot](https://dl.dropboxusercontent.com/u/19230832/master_ui.png)

Please help to review, thanks a lot.

Author: jerryshao <saisai.shao@intel.com>

Closes #4288 from jerryshao/SPARK-5495 and squashes the following commits:

fa3e486 [jerryshao] Add some conditions
9a7be93 [jerryshao] Add kill Driver function
a239776 [jerryshao] Change the code format
ff5195d [jerryshao] Add app kill function in master web UI
parent 12135e90
No related branches found
No related tags found
No related merge requests found
......@@ -21,7 +21,7 @@ private[spark] object ApplicationState extends Enumeration {
type ApplicationState = Value
val WAITING, RUNNING, FINISHED, FAILED, UNKNOWN = Value
val WAITING, RUNNING, FINISHED, FAILED, KILLED, UNKNOWN = Value
val MAX_NUM_RETRY = 10
}
......@@ -26,8 +26,8 @@ import akka.pattern.ask
import org.json4s.JValue
import org.apache.spark.deploy.JsonProtocol
import org.apache.spark.deploy.DeployMessages.{MasterStateResponse, RequestMasterState}
import org.apache.spark.deploy.master.{ApplicationInfo, DriverInfo, WorkerInfo}
import org.apache.spark.deploy.DeployMessages.{RequestKillDriver, MasterStateResponse, RequestMasterState}
import org.apache.spark.deploy.master._
import org.apache.spark.ui.{WebUIPage, UIUtils}
import org.apache.spark.util.Utils
......@@ -41,6 +41,31 @@ private[spark] class MasterPage(parent: MasterWebUI) extends WebUIPage("") {
JsonProtocol.writeMasterState(state)
}
def handleAppKillRequest(request: HttpServletRequest): Unit = {
handleKillRequest(request, id => {
parent.master.idToApp.get(id).foreach { app =>
parent.master.removeApplication(app, ApplicationState.KILLED)
}
})
}
def handleDriverKillRequest(request: HttpServletRequest): Unit = {
handleKillRequest(request, id => { master ! RequestKillDriver(id) })
}
private def handleKillRequest(request: HttpServletRequest, action: String => Unit): Unit = {
if (parent.killEnabled &&
parent.master.securityMgr.checkModifyPermissions(request.getRemoteUser)) {
val killFlag = Option(request.getParameter("terminate")).getOrElse("false").toBoolean
val id = Option(request.getParameter("id"))
if (id.isDefined && killFlag) {
action(id.get)
}
Thread.sleep(100)
}
}
/** Index view listing applications and executors */
def render(request: HttpServletRequest): Seq[Node] = {
val stateFuture = (master ? RequestMasterState)(timeout).mapTo[MasterStateResponse]
......@@ -167,9 +192,20 @@ private[spark] class MasterPage(parent: MasterWebUI) extends WebUIPage("") {
}
private def appRow(app: ApplicationInfo, active: Boolean): Seq[Node] = {
val killLink = if (parent.killEnabled &&
(app.state == ApplicationState.RUNNING || app.state == ApplicationState.WAITING)) {
val killLinkUri = s"app/kill?id=${app.id}&terminate=true"
val confirm = "return window.confirm(" +
s"'Are you sure you want to kill application ${app.id} ?');"
<span class="kill-link">
(<a href={killLinkUri} onclick={confirm}>kill</a>)
</span>
}
<tr>
<td>
<a href={"app?appId=" + app.id}>{app.id}</a>
{killLink}
</td>
<td>
<a href={app.desc.appUiUrl}>{app.desc.name}</a>
......@@ -203,8 +239,19 @@ private[spark] class MasterPage(parent: MasterWebUI) extends WebUIPage("") {
}
private def driverRow(driver: DriverInfo): Seq[Node] = {
val killLink = if (parent.killEnabled &&
(driver.state == DriverState.RUNNING ||
driver.state == DriverState.SUBMITTED ||
driver.state == DriverState.RELAUNCHING)) {
val killLinkUri = s"driver/kill?id=${driver.id}&terminate=true"
val confirm = "return window.confirm(" +
s"'Are you sure you want to kill driver ${driver.id} ?');"
<span class="kill-link">
(<a href={killLinkUri} onclick={confirm}>kill</a>)
</span>
}
<tr>
<td>{driver.id} </td>
<td>{driver.id} {killLink}</td>
<td>{driver.submitDate}</td>
<td>{driver.worker.map(w => <a href={w.webUiAddress}>{w.id.toString}</a>).getOrElse("None")}
</td>
......
......@@ -32,15 +32,21 @@ class MasterWebUI(val master: Master, requestedPort: Int)
val masterActorRef = master.self
val timeout = AkkaUtils.askTimeout(master.conf)
val killEnabled = master.conf.getBoolean("spark.ui.killEnabled", true)
initialize()
/** Initialize all components of the server. */
def initialize() {
val masterPage = new MasterPage(this)
attachPage(new ApplicationPage(this))
attachPage(new HistoryNotFoundPage(this))
attachPage(new MasterPage(this))
attachPage(masterPage)
attachHandler(createStaticHandler(MasterWebUI.STATIC_RESOURCE_DIR, "/static"))
attachHandler(
createRedirectHandler("/app/kill", "/", masterPage.handleAppKillRequest))
attachHandler(
createRedirectHandler("/driver/kill", "/", masterPage.handleDriverKillRequest))
}
/** Attach a reconstructed UI to this Master UI. Only valid after bind(). */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment