You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@submarine.apache.org by pi...@apache.org on 2021/12/20 05:45:04 UTC

[submarine] branch master updated: SUBMARINE-1126. Let Jupyter Notebook save user setting after pod restarted.

This is an automated email from the ASF dual-hosted git repository.

pingsutw pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/submarine.git


The following commit(s) were added to refs/heads/master by this push:
     new a0f5a49  SUBMARINE-1126. Let Jupyter Notebook save user setting after pod restarted.
a0f5a49 is described below

commit a0f5a49d74f01f00929c9d4e5048161c6bee23d8
Author: cdmikechen <cd...@hotmail.com>
AuthorDate: Thu Dec 16 17:17:55 2021 +0800

    SUBMARINE-1126. Let Jupyter Notebook save user setting after pod restarted.
    
    ### What is this PR for?
    Jupyter Notebook have created a workspace volume `/home/jovyan/workspace` , but the user settings are saved in `/home/jovyan/.jupyter/lab/user-settings/jupyterlab/`.
    So that after pod restart, submarine will lost user settings. I think we should add a new volume to save user settings in `/home/jovyan/.jupyter/`.
    
    ### What type of PR is it?
    Improvement
    
    ### Todos
    * [x] - Add a new PVC named `notebook-pvc-user-*` when creating notebook pod CRD
    
    ### What is the Jira issue?
    https://issues.apache.org/jira/browse/SUBMARINE-1126
    
    ### How should this be tested?
    There are no new test cases right now.
    
    ### Screenshots (if appropriate)
    ![image](https://user-images.githubusercontent.com/12069428/146344069-5c92950b-cbd0-41d9-bc01-69625e9945a0.png)
    
    ### Questions:
    * Do the license files need updating? No
    * Are there breaking changes for older versions? No
    * Does this need new documentation? Maybe No
    
    Author: cdmikechen <cd...@hotmail.com>
    
    Signed-off-by: Kevin <pi...@apache.org>
    
    Closes #834 from cdmikechen/SUBMARINE-1126 and squashes the following commits:
    
    5696a8cb [cdmikechen] SUBMARINE-1126. Let Jupyter Notebook save user setting after pod restarted.
---
 .../server/submitter/k8s/K8sSubmitter.java         | 29 +++++++-----
 .../submitter/k8s/parser/NotebookSpecParser.java   | 52 +++++++++++++++-------
 .../server/submitter/k8s/util/NotebookUtils.java   |  7 +--
 3 files changed, 58 insertions(+), 30 deletions(-)

diff --git a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
index 1befeca..8ee8439 100644
--- a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
+++ b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
@@ -383,8 +383,8 @@ public class K8sSubmitter implements Submitter {
     final String name = spec.getMeta().getName();
     final String scName = NotebookUtils.SC_NAME;
     final String host = NotebookUtils.HOST_PATH;
-    final String storage = NotebookUtils.STORAGE;
-    final String pvcName = NotebookUtils.PVC_PREFIX + name;
+    final String workspacePvc = String.format("%s-%s", NotebookUtils.PVC_PREFIX, name);
+    final String userPvc = String.format("%s-user-%s", NotebookUtils.PVC_PREFIX, name);
     String namespace = getServerNamespace();
 
     // parse notebook custom resource
@@ -401,7 +401,10 @@ public class K8sSubmitter implements Submitter {
 
     // create persistent volume claim
     try {
-      createPersistentVolumeClaim(pvcName, namespace, scName, storage);
+      // workspace
+      createPersistentVolumeClaim(workspacePvc, namespace, scName, NotebookUtils.STORAGE);
+      // user setting
+      createPersistentVolumeClaim(userPvc, namespace, scName, NotebookUtils.DEFAULT_USER_STORAGE);
     } catch (ApiException e) {
       LOG.error("K8s submitter: Create persistent volume claim for Notebook object failed by " +
           e.getMessage(), e);
@@ -416,11 +419,11 @@ public class K8sSubmitter implements Submitter {
       notebook = NotebookUtils.parseObject(object, NotebookUtils.ParseOpt.PARSE_OPT_CREATE);
     } catch (JsonSyntaxException e) {
       LOG.error("K8s submitter: parse response object failed by " + e.getMessage(), e);
-      rollbackCreationPVC(pvcName, namespace);
+      rollbackCreationPVC(namespace, workspacePvc, userPvc);
       throw new SubmarineRuntimeException(500, "K8s Submitter parse upstream response failed.");
     } catch (ApiException e) {
       LOG.error("K8s submitter: parse Notebook object failed by " + e.getMessage(), e);
-      rollbackCreationPVC(pvcName, namespace);
+      rollbackCreationPVC(namespace, workspacePvc, userPvc);
       throw new SubmarineRuntimeException(e.getCode(), "K8s submitter: parse Notebook object failed by " +
           e.getMessage());
     }
@@ -432,7 +435,7 @@ public class K8sSubmitter implements Submitter {
       LOG.error("K8s submitter: Create ingressroute for Notebook object failed by " +
           e.getMessage(), e);
       rollbackCreationNotebook(notebookCR, namespace);
-      rollbackCreationPVC(pvcName, namespace);
+      rollbackCreationPVC(namespace, workspacePvc, userPvc);
       throw new SubmarineRuntimeException(e.getCode(), "K8s submitter: ingressroute for Notebook " +
           "object failed by " + e.getMessage());
     }
@@ -481,7 +484,6 @@ public class K8sSubmitter implements Submitter {
   public Notebook deleteNotebook(NotebookSpec spec) throws SubmarineRuntimeException {
     Notebook notebook;
     final String name = spec.getMeta().getName();
-    final String pvcName = NotebookUtils.PVC_PREFIX + name;
     String namespace = getServerNamespace();
 
     try {
@@ -492,7 +494,12 @@ public class K8sSubmitter implements Submitter {
               null, new V1DeleteOptionsBuilder().withApiVersion(notebookCR.getApiVersion()).build());
       notebook = NotebookUtils.parseObject(object, NotebookUtils.ParseOpt.PARSE_OPT_DELETE);
       deleteIngressRoute(namespace, notebookCR.getMetadata().getName());
-      deletePersistentVolumeClaim(pvcName, namespace);
+
+      // delete pvc
+      // workspace pvc
+      deletePersistentVolumeClaim(String.format("%s-%s", NotebookUtils.PVC_PREFIX, name), namespace);
+      // user set pvc
+      deletePersistentVolumeClaim(String.format("%s-user-%s", NotebookUtils.PVC_PREFIX, name), namespace);
     } catch (ApiException e) {
       throw new SubmarineRuntimeException(e.getCode(), e.getMessage());
     }
@@ -799,9 +806,11 @@ public class K8sSubmitter implements Submitter {
     return seldonDeployment;
   }
 
-  private void rollbackCreationPVC(String pvcName, String namespace) {
+  private void rollbackCreationPVC(String namespace, String ... pvcNames) {
     try {
-      deletePersistentVolumeClaim(pvcName, namespace);
+      for (String pvcName : pvcNames) {
+        deletePersistentVolumeClaim(pvcName, namespace);
+      }
     } catch (ApiException e) {
       LOG.error("K8s submitter: delete persistent volume claim failed by {}, may cause some dirty data",
           e.getMessage());
diff --git a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/parser/NotebookSpecParser.java b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/parser/NotebookSpecParser.java
index 0ed30b1..2067364 100644
--- a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/parser/NotebookSpecParser.java
+++ b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/parser/NotebookSpecParser.java
@@ -49,7 +49,12 @@ import java.util.Map;
 
 public class NotebookSpecParser {
 
-  private static SubmarineConfiguration conf =
+  // jupyter workspace path
+  private static final String DEFAULT_WORKSPACE_MOUNT_PATH = "/home/jovyan/workspace";
+  // jupyter user setting path, avoid losing user setting after pod restarted
+  private static final String DEFAULT_USER_SET_MOUNT_PATH = "/home/jovyan/.jupyter";
+
+  private static final SubmarineConfiguration conf =
           SubmarineConfiguration.getInstance();
 
 
@@ -75,13 +80,15 @@ public class NotebookSpecParser {
   }
 
   private static V1PodTemplateSpec parseTemplateSpec(NotebookSpec notebookSpec) {
+    String name = notebookSpec.getMeta().getName();
+
     NotebookPodSpec notebookPodSpec = notebookSpec.getSpec();
     V1PodTemplateSpec podTemplateSpec = new V1PodTemplateSpec();
     V1PodSpec podSpec = new V1PodSpec();
     // Set container
     List<V1Container> containers = new ArrayList<>();
     V1Container container = new V1Container();
-    container.setName(notebookSpec.getMeta().getName());
+    container.setName(name);
 
     // Environment variables
     if (notebookPodSpec.getEnvVars() != null) {
@@ -147,13 +154,17 @@ public class NotebookSpecParser {
     }
 
     // Volume spec
-    final String DEFAULT_MOUNT_PATH = "/home/jovyan/workspace";
-
     List<V1VolumeMount> volumeMountList = new ArrayList<>();
-    V1VolumeMount  volumeMount = new V1VolumeMount();
-    volumeMount.setMountPath(DEFAULT_MOUNT_PATH);
-    volumeMount.setName(NotebookUtils.STORAGE_PREFIX + notebookSpec.getMeta().getName());
-    volumeMountList.add(volumeMount);
+    // workspace path
+    V1VolumeMount workspace = new V1VolumeMount();
+    workspace.setMountPath(DEFAULT_WORKSPACE_MOUNT_PATH);
+    workspace.setName(String.format("%s-%s", NotebookUtils.STORAGE_PREFIX, name));
+    volumeMountList.add(workspace);
+    // user setting path
+    V1VolumeMount userSetting = new V1VolumeMount();
+    userSetting.setMountPath(DEFAULT_USER_SET_MOUNT_PATH);
+    userSetting.setName(String.format("%s-user-%s", NotebookUtils.STORAGE_PREFIX, name));
+    volumeMountList.add(userSetting);
     container.setVolumeMounts(volumeMountList);
 
     containers.add(container);
@@ -161,17 +172,24 @@ public class NotebookSpecParser {
 
     // create volume object for persistent volume
     List<V1Volume> volumeList = new ArrayList<>();
-    V1Volume volume = new V1Volume();
-    String volumeName = NotebookUtils.STORAGE_PREFIX + notebookSpec.getMeta().getName();
-    V1PersistentVolumeClaimVolumeSource persistentVolumeClaim = new V1PersistentVolumeClaimVolumeSource();
-    String claimName = NotebookUtils.PVC_PREFIX + notebookSpec.getMeta().getName();
-    persistentVolumeClaim.setClaimName(claimName);
-    volume.setName(volumeName);
-    volume.setPersistentVolumeClaim(persistentVolumeClaim);
-    volumeList.add(volume);
-    podSpec.setVolumes(volumeList);
+    // workspace
+    V1Volume workspaceVolume = new V1Volume();
+    workspaceVolume.setName(String.format("%s-%s", NotebookUtils.STORAGE_PREFIX, name));
+    V1PersistentVolumeClaimVolumeSource workspacePvc = new V1PersistentVolumeClaimVolumeSource();
+    workspacePvc.setClaimName(String.format("%s-%s", NotebookUtils.PVC_PREFIX, name));
+    workspaceVolume.setPersistentVolumeClaim(workspacePvc);
+    volumeList.add(workspaceVolume);
+    // user setting
+    V1Volume userVolume = new V1Volume();
+    userVolume.setName(String.format("%s-user-%s", NotebookUtils.STORAGE_PREFIX, name));
+    V1PersistentVolumeClaimVolumeSource userPvc = new V1PersistentVolumeClaimVolumeSource();
+    userPvc.setClaimName(String.format("%s-user-%s", NotebookUtils.PVC_PREFIX, name));
+    userVolume.setPersistentVolumeClaim(userPvc);
+    volumeList.add(userVolume);
 
+    podSpec.setVolumes(volumeList);
     podTemplateSpec.setSpec(podSpec);
+
     return podTemplateSpec;
   }
 
diff --git a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/util/NotebookUtils.java b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/util/NotebookUtils.java
index c567520..8805997 100644
--- a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/util/NotebookUtils.java
+++ b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/util/NotebookUtils.java
@@ -44,10 +44,11 @@ public class NotebookUtils {
 
   private static final Logger LOG = LoggerFactory.getLogger(NotebookUtils.class);
   public static final String STORAGE = "10Gi";
+  public static final String DEFAULT_USER_STORAGE = "100Mi";
   public static final String SC_NAME = "submarine-storageclass";
-  public static final String STORAGE_PREFIX = "notebook-storage-";
-  public static final String PV_PREFIX = "notebook-pv-";
-  public static final String PVC_PREFIX = "notebook-pvc-";
+  public static final String STORAGE_PREFIX = "notebook-storage";
+  public static final String PV_PREFIX = "notebook-pv";
+  public static final String PVC_PREFIX = "notebook-pvc";
   public static final String HOST_PATH = "/mnt";
 
   public enum ParseOpt {

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@submarine.apache.org
For additional commands, e-mail: dev-help@submarine.apache.org