diff --git a/conf/shiro.ini.template b/conf/shiro.ini.template
index 6721d175f91..47c6ad49e34 100644
--- a/conf/shiro.ini.template
+++ b/conf/shiro.ini.template
@@ -118,8 +118,14 @@ admin = *
#
/api/version = anon
/api/cluster/address = anon
-# Allow all authenticated users to restart interpreters on a notebook page.
-# Comment out the following line if you would like to authorize only admin users to restart interpreters.
+# Interpreter restart endpoints:
+# - /api/interpreter/setting/restart/** : Restart interpreter for a specific note (requires noteId in request body)
+# - /api/interpreter/setting/restart-all/** : Restart interpreter globally (affects all users/sessions)
+#
+# Allow all authenticated users to restart interpreters on a notebook page and globally.
+# Comment out the following line and uncomment the next line if you would like to authorize only admin users to restart interpreters globally.
+/api/interpreter/setting/restart-all/** = authc
+#/api/interpreter/setting/restart-all/** = authc, roles[admin]
/api/interpreter/setting/restart/** = authc
/api/interpreter/** = authc, roles[admin]
/api/notebook-repositories/** = authc, roles[admin]
diff --git a/docs/usage/rest_api/interpreter.md b/docs/usage/rest_api/interpreter.md
index 9d81dd60e06..2c637a616a6 100644
--- a/docs/usage/rest_api/interpreter.md
+++ b/docs/usage/rest_api/interpreter.md
@@ -478,13 +478,13 @@ The role of registered interpreters, settings and interpreters group are describ
-### Restart an interpreter
+### Restart an interpreter for a specific note
| Description |
- This ```PUT``` method restarts the given interpreter id. |
+ This ```PUT``` method restarts the given interpreter for a specific note. The ```noteId``` is required in the request body. |
| URL |
@@ -496,10 +496,10 @@ The role of registered interpreters, settings and interpreters group are describ
| Fail code |
- 500 |
+ 400 (if noteId is missing), 403 (no permission), 404 (interpreter not found), 500 |
- | Sample JSON input (Optional) |
+ Sample JSON input (Required) |
```json
@@ -520,6 +520,42 @@ The role of registered interpreters, settings and interpreters group are describ
|
+
+### Restart an interpreter globally
+
+
+
+
+ | Description |
+ This ```PUT``` method restarts the given interpreter globally (affects all users/sessions). This endpoint can be restricted to admin users only via shiro.ini configuration. |
+
+
+ | URL |
+ ```http://[zeppelin-server]:[zeppelin-port]/api/interpreter/setting/restart-all/[interpreter ID]``` |
+
+
+ | Success code |
+ 200 |
+
+
+ | Fail code |
+ 403 (no permission), 404 (interpreter not found), 500 |
+
+
+ | Sample JSON input |
+ None |
+
+
+ | Sample JSON response |
+
+
+```json
+{"status":"OK"}
+```
+ |
+
+
+
### Add a new repository for dependency resolving
diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/InterpreterRestApi.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/InterpreterRestApi.java
index 3b9d754e919..ef543e9d946 100644
--- a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/InterpreterRestApi.java
+++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/InterpreterRestApi.java
@@ -190,7 +190,8 @@ public Response removeSetting(@PathParam("settingId") String settingId) throws I
}
/**
- * Restart interpreter setting.
+ * Restart interpreter setting for a specific note.
+ * Requires noteId in request body.
*/
@PUT
@Path("setting/restart/{settingId}")
@@ -204,7 +205,8 @@ public Response restartSetting(String message, @PathParam("settingId") String se
String noteId = request == null ? null : request.getNoteId();
if (null == noteId) {
- interpreterSettingManager.close(settingId);
+ return new JsonResponse<>(Status.BAD_REQUEST, "noteId is required. Use /restart-all endpoint for global restart.")
+ .build();
} else {
Set entities = new HashSet<>();
entities.add(authenticationService.getPrincipal());
@@ -229,6 +231,24 @@ public Response restartSetting(String message, @PathParam("settingId") String se
return new JsonResponse<>(Status.OK, "", setting).build();
}
+ /**
+ * Restart interpreter setting globally (all sessions).
+ * This endpoint should be protected by shiro.ini for admin only.
+ */
+ @PUT
+ @Path("setting/restart-all/{settingId}")
+ @ZeppelinApi
+ public Response restartSettingAll(@PathParam("settingId") String settingId) {
+ LOGGER.info("Restart ALL interpreterSetting {}, user={}", settingId, authenticationService.getPrincipal());
+
+ InterpreterSetting setting = interpreterSettingManager.get(settingId);
+ if (setting == null) {
+ return new JsonResponse<>(Status.NOT_FOUND, "", settingId).build();
+ }
+ interpreterSettingManager.close(settingId);
+ return new JsonResponse<>(Status.OK, "", setting).build();
+ }
+
/**
* List all available interpreters by group.
*/
diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java
index 19435b32112..91eb22e1953 100644
--- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java
+++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java
@@ -342,11 +342,11 @@ void testInterpreterRestart() throws IOException, InterruptedException {
return note.getBindedInterpreterSettings(new ArrayList<>());
});
- // when: restart interpreter
+ // when: restart interpreter globally
for (InterpreterSetting setting : settings) {
if (setting.getName().equals("md")) {
- // call restart interpreter API
- CloseableHttpResponse put = httpPut("/interpreter/setting/restart/" + setting.getId(), "");
+ // call restart interpreter API (global restart)
+ CloseableHttpResponse put = httpPut("/interpreter/setting/restart-all/" + setting.getId(), "");
assertThat("test interpreter restart:", put, isAllowed());
put.close();
break;
diff --git a/zeppelin-web-angular/src/app/services/interpreter.service.ts b/zeppelin-web-angular/src/app/services/interpreter.service.ts
index e0f60bf8361..d488231a34f 100644
--- a/zeppelin-web-angular/src/app/services/interpreter.service.ts
+++ b/zeppelin-web-angular/src/app/services/interpreter.service.ts
@@ -82,6 +82,6 @@ export class InterpreterService extends BaseRest {
}
restartInterpreterSetting(settingId: string) {
- return this.http.put(this.restUrl`/interpreter/setting/restart/${settingId}`, null);
+ return this.http.put(this.restUrl`/interpreter/setting/restart-all/${settingId}`, null);
}
}
diff --git a/zeppelin-web/src/app/interpreter/interpreter.controller.js b/zeppelin-web/src/app/interpreter/interpreter.controller.js
index dddae0022cf..d8ba1ff238e 100644
--- a/zeppelin-web/src/app/interpreter/interpreter.controller.js
+++ b/zeppelin-web/src/app/interpreter/interpreter.controller.js
@@ -468,7 +468,7 @@ function InterpreterCtrl($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeou
message: 'Do you want to restart this interpreter?',
callback: function(result) {
if (result) {
- $http.put(baseUrlSrv.getRestApiBase() + '/interpreter/setting/restart/' + settingId)
+ $http.put(baseUrlSrv.getRestApiBase() + '/interpreter/setting/restart-all/' + settingId)
.then(function(res) {
let index = _.findIndex($scope.interpreterSettings, {'id': settingId});
$scope.interpreterSettings[index] = res.data.body;