Repository: zeppelin
Updated Branches:
  refs/heads/master dd70a5729 -> c9e3a6a43


[ZEPPELIN-940] Allow zeppelin server to connect to already executing Remote 
Interpreter

### What is this PR for?
Currenlty zeppelin server starts interpreter on localhost and with random 
port.The purpose of this pull request is to allow zeppelin server to connect to 
remotely executing zeppelin interpreter that user might have started in his 
service.This feature will be further helpful while cluster manager is to be 
implemented.(https://cwiki.apache.org/confluence/display/ZEPPELIN/Cluster+Manager+Proposal)

### What type of PR is it?
Improvement

### Todos
[ ] -Add documentation

### What is the Jira issue?
* [ZEPPELIN-940] https://issues.apache.org/jira/browse/ZEPPELIN-940

### How should this be tested?
Added Junit test in RemoteInterpreterProcessTest and it passes

### Screenshots (if appropriate)

### Questions:
* Does the licenses files need update? No
* Is there breaking changes for older versions? No
* Does this needs documentation? Yes for the new properties

Author: Sachin <[email protected]>
Author: SachinJanani <[email protected]>

Closes #955 from SachinJanani/master and squashes the following commits:

f279767 [Sachin] Changed the Markdown style for code block in document
f57eb78 [Sachin] Incorporated review comments related to documentation
067a06e [Sachin] Add documentation for connecting to existing remote interpreter
84d2347 [Sachin] Added checkbox for Connecting to existing process and renamed 
the variables
c7fdc66 [Sachin] Merge remote-tracking branch 'upstream/master'
9762134 [Sachin] Merge branch 'master' of 
https://github.com/SachinJanani/incubator-zeppelin
4d51cd9 [Sachin] Add UI component for the accepting Host and Port when 
executing option is selected
2e30e3d [Sachin] [ZEPPELIN-940] Allow zeppelin server to connect to already 
executing Remote Interpreter
355c1f2 [Sachin] Add UI component for the accepting Host and Port when 
executing option is selected
7af8112 [Sachin] Merge branch 'master' of 
https://github.com/SachinJanani/incubator-zeppelin
fbe2346 [Sachin] [ZEPPELIN-940] Allow zeppelin server to connect to already 
executing Remote Interpreter
53c1eea [SachinJanani] Merge pull request #1 from apache/master


Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo
Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/c9e3a6a4
Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/c9e3a6a4
Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/c9e3a6a4

Branch: refs/heads/master
Commit: c9e3a6a43d15d7c084a1f9fe0330e01cd802f194
Parents: dd70a57
Author: Sachin <[email protected]>
Authored: Fri Jun 10 12:21:21 2016 +0530
Committer: Damien CORNEAU <[email protected]>
Committed: Mon Jun 13 10:30:26 2016 +0900

----------------------------------------------------------------------
 .../img/screenshots/existing_interpreter.png    | Bin 0 -> 7350 bytes
 docs/manual/interpreters.md                     |  16 ++++
 .../apache/zeppelin/interpreter/Constants.java  |  31 ++++++
 .../remote/RemoteInterpreterProcess.java        |  95 ++++++++++++-------
 .../remote/RemoteInterpreterProcessTest.java    |  33 +++++++
 .../interpreter-create/interpreter-create.html  |  18 ++++
 .../app/interpreter/interpreter.controller.js   |   5 +
 .../src/app/interpreter/interpreter.html        |  22 +++++
 .../interpreter/InterpreterFactory.java         |   5 +-
 .../zeppelin/interpreter/InterpreterOption.java |  33 +++++++
 .../interpreter/InterpreterSetting.java         |   4 +-
 .../notebook/NoteInterpreterLoader.java         |   5 +-
 12 files changed, 231 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zeppelin/blob/c9e3a6a4/docs/assets/themes/zeppelin/img/screenshots/existing_interpreter.png
----------------------------------------------------------------------
diff --git 
a/docs/assets/themes/zeppelin/img/screenshots/existing_interpreter.png 
b/docs/assets/themes/zeppelin/img/screenshots/existing_interpreter.png
new file mode 100644
index 0000000..ad32da4
Binary files /dev/null and 
b/docs/assets/themes/zeppelin/img/screenshots/existing_interpreter.png differ

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/c9e3a6a4/docs/manual/interpreters.md
----------------------------------------------------------------------
diff --git a/docs/manual/interpreters.md b/docs/manual/interpreters.md
index ca73bef..488d5e9 100644
--- a/docs/manual/interpreters.md
+++ b/docs/manual/interpreters.md
@@ -60,3 +60,19 @@ Each Interpreter Setting can choose one of 'shared', 
'scoped', 'isolated' interp
 In 'shared' mode, every notebook bound to the Interpreter Setting will share 
the single Interpreter instance. In 'scoped' mode, each notebook will create 
new Interpreter instance in the same interpreter process. In 'isolated' mode, 
each notebook will create new Interpreter process.
 
 <img 
src="../assets/themes/zeppelin/img/screenshots/interpreter_persession.png" 
width="400px">
+
+
+## Connecting to the Existing Remote Interpreter
+
+Zeppelin users can start interpreter thread embedded in their service. This 
will provide flexibility to user to start interpreter on remote host. To start 
interpreter along with your service you have to create an instance of 
``RemoteInterpreterServer`` and start it as follows:
+
+```
+RemoteInterpreterServer interpreter=new RemoteInterpreterServer(3678); 
+// Here, 3678 is the port on which interpreter will listen.    
+interpreter.start()  
+
+```
+
+The above code will start interpreter thread inside your process. Once the 
interpreter is started you can configure zeppelin to connect to 
RemoteInterpreter by checking **Connect to existing process** checkbox and then 
provide **Host** and **Port** on which interpreter porocess is listening as 
shown in the image below:
+
+<img src="../assets/themes/zeppelin/img/screenshots/existing_interpreter.png" 
width="400px">

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/c9e3a6a4/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Constants.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Constants.java
 
b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Constants.java
new file mode 100644
index 0000000..0ab94ac
--- /dev/null
+++ 
b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Constants.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.zeppelin.interpreter;
+/**
+ * Interpreter related constants
+ * 
+ *
+ */
+public class Constants {
+  public static final String ZEPPELIN_INTERPRETER_PORT = 
"zeppelin.interpreter.port";
+
+  public static final String ZEPPELIN_INTERPRETER_HOST = 
"zeppelin.interpreter.host";
+
+  public static final String EXISTING_PROCESS = "existing_process";
+
+}

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/c9e3a6a4/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcess.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcess.java
 
b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcess.java
index 67a048b..05baf62 100644
--- 
a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcess.java
+++ 
b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcess.java
@@ -22,6 +22,7 @@ import org.apache.commons.exec.*;
 import org.apache.commons.exec.environment.EnvironmentUtils;
 import org.apache.commons.pool2.impl.GenericObjectPool;
 import org.apache.thrift.TException;
+import org.apache.zeppelin.interpreter.Constants;
 import org.apache.zeppelin.interpreter.InterpreterException;
 import org.apache.zeppelin.interpreter.InterpreterGroup;
 import org.apache.zeppelin.interpreter.thrift.RemoteInterpreterService.Client;
@@ -31,13 +32,13 @@ import org.slf4j.LoggerFactory;
 import java.io.IOException;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.Properties;
 
 /**
  *
  */
 public class RemoteInterpreterProcess implements ExecuteResultHandler {
   private static final Logger logger = 
LoggerFactory.getLogger(RemoteInterpreterProcess.class);
-
   private final AtomicInteger referenceCount;
   private DefaultExecutor executor;
   private ExecuteWatchdog watchdog;
@@ -52,6 +53,8 @@ public class RemoteInterpreterProcess implements 
ExecuteResultHandler {
   private final RemoteInterpreterEventPoller remoteInterpreterEventPoller;
   private final InterpreterContextRunnerPool interpreterContextRunnerPool;
   private int connectTimeout;
+  String host = "localhost";
+  boolean isInterpreterAlreadyExecuting = false;
 
   public RemoteInterpreterProcess(String intpRunner,
       String intpDir,
@@ -91,54 +94,80 @@ public class RemoteInterpreterProcess implements 
ExecuteResultHandler {
   public int reference(InterpreterGroup interpreterGroup) {
     synchronized (referenceCount) {
       if (executor == null) {
-        // start server process
-        try {
-          port = 
RemoteInterpreterUtils.findRandomAvailablePortOnAllLocalInterfaces();
-        } catch (IOException e1) {
-          throw new InterpreterException(e1);
+        if (interpreterGroup.containsKey(Constants.EXISTING_PROCESS)) {
+          Properties properties = interpreterGroup.getProperty();
+          isInterpreterAlreadyExecuting = true;
+          if (isInterpreterAlreadyExecuting) {
+            if (properties.containsKey(Constants.ZEPPELIN_INTERPRETER_HOST)) {
+              host = 
properties.getProperty(Constants.ZEPPELIN_INTERPRETER_HOST);
+
+            } else {
+              throw new InterpreterException("Can't find value for option 
Host."
+                  + "Please specify the host on which interpreter is 
executing");
+            }
+            if (properties.containsKey(Constants.ZEPPELIN_INTERPRETER_PORT)) {
+              port = Integer.parseInt(
+                  
interpreterGroup.getProperty().getProperty(Constants.ZEPPELIN_INTERPRETER_PORT));
+            } else {
+              throw new InterpreterException("Can't find value for option 
Port."
+                  + "Please specify the port on which interpreter is 
listening");
+            }
+          }
+          running = true;
         }
 
-        CommandLine cmdLine = CommandLine.parse(interpreterRunner);
-        cmdLine.addArgument("-d", false);
-        cmdLine.addArgument(interpreterDir, false);
-        cmdLine.addArgument("-p", false);
-        cmdLine.addArgument(Integer.toString(port), false);
-        cmdLine.addArgument("-l", false);
-        cmdLine.addArgument(localRepoDir, false);
-
-        executor = new DefaultExecutor();
-
-        watchdog = new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT);
-        executor.setWatchdog(watchdog);
+        if (!isInterpreterAlreadyExecuting) {
+          try {
+            port = 
RemoteInterpreterUtils.findRandomAvailablePortOnAllLocalInterfaces();
+          } catch (IOException e1) {
+            throw new InterpreterException(e1);
+          }
+          CommandLine cmdLine = CommandLine.parse(interpreterRunner);
+          cmdLine.addArgument("-d", false);
+          cmdLine.addArgument(interpreterDir, false);
+          cmdLine.addArgument("-p", false);
+          cmdLine.addArgument(Integer.toString(port), false);
+          cmdLine.addArgument("-l", false);
+          cmdLine.addArgument(localRepoDir, false);
+
+          executor = new DefaultExecutor();
+
+          watchdog = new ExecuteWatchdog(ExecuteWatchdog.INFINITE_TIMEOUT);
+          executor.setWatchdog(watchdog);
+
+          running = true;
+          try {
+            Map procEnv = EnvironmentUtils.getProcEnvironment();
+            procEnv.putAll(env);
+
+            logger.info("Run interpreter process {}", cmdLine);
+            executor.execute(cmdLine, procEnv, this);
+
+          } catch (IOException e) {
+            running = false;
+            throw new InterpreterException(e);
+          }
 
-        running = true;
-        try {
-          Map procEnv = EnvironmentUtils.getProcEnvironment();
-          procEnv.putAll(env);
-
-          logger.info("Run interpreter process {}", cmdLine);
-          executor.execute(cmdLine, procEnv, this);
-        } catch (IOException e) {
-          running = false;
-          throw new InterpreterException(e);
+        } else {
+          logger.info(
+              "Not starting interpreter as \"isExistingProcess\" is enabled");
         }
 
-
         long startTime = System.currentTimeMillis();
         while (System.currentTimeMillis() - startTime < connectTimeout) {
-          if 
(RemoteInterpreterUtils.checkIfRemoteEndpointAccessible("localhost", port)) {
+          if (RemoteInterpreterUtils.checkIfRemoteEndpointAccessible(host, 
port)) {
             break;
           } else {
             try {
               Thread.sleep(500);
             } catch (InterruptedException e) {
-              logger.error("Exception in RemoteInterpreterProcess while 
synchronized reference " +
-                  "Thread.sleep", e);
+              logger.error("Exception in RemoteInterpreterProcess while 
synchronized reference "
+                  + "Thread.sleep", e);
             }
           }
         }
 
-        clientPool = new GenericObjectPool<Client>(new 
ClientFactory("localhost", port));
+        clientPool = new GenericObjectPool<Client>(new ClientFactory(host, 
port));
 
         remoteInterpreterEventPoller.setInterpreterGroup(interpreterGroup);
         remoteInterpreterEventPoller.setInterpreterProcess(this);

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/c9e3a6a4/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcessTest.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcessTest.java
 
b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcessTest.java
index 52d3858..f9d7d39 100644
--- 
a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcessTest.java
+++ 
b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterProcessTest.java
@@ -22,7 +22,11 @@ import static org.junit.Assert.assertFalse;
 import static org.mockito.Mockito.*;
 
 import java.util.HashMap;
+import java.util.Properties;
 
+import org.apache.thrift.TException;
+import org.apache.thrift.transport.TTransportException;
+import org.apache.zeppelin.interpreter.Constants;
 import org.apache.zeppelin.interpreter.InterpreterGroup;
 import org.apache.zeppelin.interpreter.thrift.RemoteInterpreterService.Client;
 import org.junit.Test;
@@ -32,6 +36,7 @@ public class RemoteInterpreterProcessTest {
           System.getProperty("os.name").startsWith("Windows") ?
                   "../bin/interpreter.cmd" :
                   "../bin/interpreter.sh";
+  private static final int DUMMY_PORT=3678;
 
   @Test
   public void testStartStop() {
@@ -70,4 +75,32 @@ public class RemoteInterpreterProcessTest {
 
     rip.dereference();
   }
+
+  @Test
+  public void testStartStopRemoteInterpreter() throws TException, 
InterruptedException {
+    RemoteInterpreterServer server = new RemoteInterpreterServer(3678);
+    server.start();
+    boolean running = false;
+    long startTime = System.currentTimeMillis();
+    while (System.currentTimeMillis() - startTime < 10 * 1000) {
+      if (server.isRunning()) {
+        running = true;
+        break;
+      } else {
+        Thread.sleep(200);
+      }
+    }
+    Properties properties = new Properties();
+    properties.setProperty(Constants.ZEPPELIN_INTERPRETER_PORT, "3678");
+    properties.setProperty(Constants.ZEPPELIN_INTERPRETER_HOST, "localhost");
+    InterpreterGroup intpGroup = mock(InterpreterGroup.class);
+    when(intpGroup.getProperty()).thenReturn(properties);
+    when(intpGroup.containsKey(Constants.EXISTING_PROCESS)).thenReturn(true);
+    RemoteInterpreterProcess rip = new 
RemoteInterpreterProcess(INTERPRETER_SCRIPT, "nonexists",
+        "fakeRepo", new HashMap<String, String>(), 10 * 1000, null);
+    assertFalse(rip.isRunning());
+    assertEquals(0, rip.referenceCount());
+    assertEquals(1, rip.reference(intpGroup));
+    assertEquals(true, rip.isRunning());
+  }
 }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/c9e3a6a4/zeppelin-web/src/app/interpreter/interpreter-create/interpreter-create.html
----------------------------------------------------------------------
diff --git 
a/zeppelin-web/src/app/interpreter/interpreter-create/interpreter-create.html 
b/zeppelin-web/src/app/interpreter/interpreter-create/interpreter-create.html
index f41dbfb..d802b53 100644
--- 
a/zeppelin-web/src/app/interpreter/interpreter-create/interpreter-create.html
+++ 
b/zeppelin-web/src/app/interpreter/interpreter-create/interpreter-create.html
@@ -69,6 +69,24 @@ limitations under the License.
           <span>Interpreter for note</span>
         </div>
         <br />
+        
+        <div class="col-md-12" style="padding-left:0px">
+          <div class="checkbox">
+            <span class="input-group">
+              <label><input type="checkbox" style="width:0%;height:0%" 
ng-model="newInterpreterSetting.option.isExistingProcess"> </input> Connect to 
existing process </label>
+            </span>
+          </div>
+        </div>
+        <div ng-show="newInterpreterSetting.option.isExistingProcess" 
class="form-group" style="width:200px">
+          <b>Host</b>
+            <input id="newInterpreterSettingHost" input pu-elastic-input
+              pu-elastic-input-minwidth="180px" 
ng-model="newInterpreterSetting.option.host" />
+        </div>
+        <div ng-show="newInterpreterSetting.option.isExistingProcess" 
class="form-group" style="width:200px">
+          <b>Port</b>
+           <input id="newInterpreterSettingPort" input pu-elastic-input
+            pu-elastic-input-minwidth="180px" 
ng-model="newInterpreterSetting.option.port" />
+        </div>
 
         <b>Properties</b>
         <table class="table table-striped properties">

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/c9e3a6a4/zeppelin-web/src/app/interpreter/interpreter.controller.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/app/interpreter/interpreter.controller.js 
b/zeppelin-web/src/app/interpreter/interpreter.controller.js
index 5d561a7..8610910 100644
--- a/zeppelin-web/src/app/interpreter/interpreter.controller.js
+++ b/zeppelin-web/src/app/interpreter/interpreter.controller.js
@@ -120,6 +120,9 @@ 
angular.module('zeppelinWebApp').controller('InterpreterCtrl', function($scope,
           if (!setting.option) {
             setting.option = {};
           }
+          if (setting.option.isExistingProcess === undefined) {
+            setting.option.isExistingProcess = false;
+          }
           if (setting.option.remote === undefined) {
             // remote always true for now
             setting.option.remote = true;
@@ -273,8 +276,10 @@ 
angular.module('zeppelinWebApp').controller('InterpreterCtrl', function($scope,
       dependencies: [],
       option: {
         remote: true,
+        isExistingProcess: false,
         perNoteSession: false,
         perNoteProcess: false
+
       }
     };
     emptyNewProperty($scope.newInterpreterSetting);

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/c9e3a6a4/zeppelin-web/src/app/interpreter/interpreter.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/app/interpreter/interpreter.html 
b/zeppelin-web/src/app/interpreter/interpreter.html
index 24831bc..c840f89 100644
--- a/zeppelin-web/src/app/interpreter/interpreter.html
+++ b/zeppelin-web/src/app/interpreter/interpreter.html
@@ -152,6 +152,28 @@ limitations under the License.
         </span>
         <span>Interpreter for note</span>
       </div>
+      
+      <br />
+      <div class="col-md-12">
+        <div class="checkbox">
+          <span class="input-group">
+            <label><input type="checkbox" style="width:0%;height:0%" 
id="isExistingProcess" ng-model="setting.option.isExistingProcess" 
ng-disabled="!valueform.$visible"> </input>
+            Connect to existing process <label>
+          </span>
+        </div>
+      </div>
+
+      <div class="col-md-12" ng-show="setting.option.isExistingProcess">
+        <b>Host</b>
+          <input id="newInterpreterSettingHost" input pu-elastic-input
+            pu-elastic-input-minwidth="180px" ng-model="setting.option.host" 
ng-disabled="!valueform.$visible"  />
+      </div>
+      <div class="col-md-12" ng-show="setting.option.isExistingProcess">
+         <b>Port</b>
+         <input id="newInterpreterSettingPort" input pu-elastic-input
+            pu-elastic-input-minwidth="180px" ng-model="setting.option.port"  
ng-disabled="!valueform.$visible" />
+      </div>
+
 
 
       <div ng-show="_.isEmpty(setting.properties) && 
_.isEmpty(setting.dependencies) || valueform.$hidden" class="col-md-12 
gray40-message">

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/c9e3a6a4/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java
 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java
index 1772840..bad18c0 100644
--- 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java
+++ 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java
@@ -544,7 +544,10 @@ public class InterpreterFactory implements 
InterpreterGroupFactory {
     String groupName = interpreterSetting.getGroup();
     InterpreterOption option = interpreterSetting.getOption();
     Properties properties = interpreterSetting.getProperties();
-
+    if (option.isExistingProcess) {
+      properties.put(Constants.ZEPPELIN_INTERPRETER_HOST, option.getHost());
+      properties.put(Constants.ZEPPELIN_INTERPRETER_PORT, option.getPort());
+    }
     // if interpreters are already there, wait until they're being removed
     synchronized (interpreterGroup) {
       long interpreterRemovalWaitStart = System.nanoTime();

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/c9e3a6a4/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterOption.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterOption.java
 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterOption.java
index ba6f7b9..f9e43ab 100644
--- 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterOption.java
+++ 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterOption.java
@@ -24,6 +24,39 @@ public class InterpreterOption {
   boolean remote;
   boolean perNoteSession;
   boolean perNoteProcess;
+  
+  boolean isExistingProcess;
+
+  String host;
+  String port;
+
+
+  
+
+  public boolean isExistingProcess() {
+    return isExistingProcess;
+  }
+
+  public void setExistingProcess(boolean isExistingProcess) {
+    this.isExistingProcess = isExistingProcess;
+  }
+
+  public String getPort() {
+    return port;
+  }
+
+  public void setPort(String port) {
+    this.port = port;
+  }
+
+  public String getHost() {
+    return host;
+  }
+
+  public void setHost(String host) {
+    this.host = host;
+  }
+
 
   public InterpreterOption() {
     remote = false;

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/c9e3a6a4/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java
 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java
index 91eb2c8..2060714 100644
--- 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java
+++ 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java
@@ -124,7 +124,9 @@ public class InterpreterSetting {
 
 
   private String getInterpreterProcessKey(String noteId) {
-    if (getOption().isPerNoteProcess()) {
+    if (getOption().isExistingProcess) {
+      return Constants.EXISTING_PROCESS;
+    } else if (getOption().isPerNoteProcess()) {
       return noteId;
     } else {
       return SHARED_PROCESS;

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/c9e3a6a4/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NoteInterpreterLoader.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NoteInterpreterLoader.java
 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NoteInterpreterLoader.java
index 7e22ca0..b1719c5 100644
--- 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NoteInterpreterLoader.java
+++ 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/NoteInterpreterLoader.java
@@ -21,6 +21,7 @@ import java.io.IOException;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.apache.zeppelin.interpreter.Constants;
 import org.apache.zeppelin.interpreter.Interpreter;
 import org.apache.zeppelin.interpreter.Interpreter.RegisteredInterpreter;
 import org.apache.zeppelin.interpreter.InterpreterException;
@@ -75,7 +76,9 @@ public class NoteInterpreterLoader {
   }
 
   private String getInterpreterInstanceKey(InterpreterSetting setting) {
-    if (setting.getOption().isPerNoteSession() || 
setting.getOption().isPerNoteProcess()) {
+    if (setting.getOption().isExistingProcess()) {
+      return Constants.EXISTING_PROCESS;
+    } else if (setting.getOption().isPerNoteSession() || 
setting.getOption().isPerNoteProcess()) {
       return noteId;
     } else {
       return SHARED_SESSION;

Reply via email to