diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..4c0deeb5
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.Python
+*.crt
diff --git a/README.md b/README.md
index 724b0c21..95f1abef 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,45 @@
-# {{ project_name }}
+# PaddlePaddle Cloud
## Getting Started
+### Pre-Requirements
+- PaddlePaddle Cloud needs python to support `OPENSSL 1.2`. To check it out, simply run:
+ ```python
+ >>> import ssl
+ >>> ssl.OPENSSL_VERSION
+ 'OpenSSL 1.0.2k 26 Jan 2017'
+ ```
+- Make sure you have `Python > 2.7.10` installed.
+
+### Run on kubernetes
+```bash
+# build docker image
+git clone https://github.com/PaddlePaddle/cloud.git
+cd cloud/paddlecloud
+docker build -t [your_docker_registry]/pcloud .
+docker push [your_docker_registry]/pcloud
+# submit to kubernetes
+kubectl create -f ./k8s
+```
+
+To test or visit the web site, find out the kubernetes [ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) ip addresses, and bind it to your `/etc/hosts` file:
+```
+# your ingress ip address
+192.168.1.100 cloud.paddlepaddle.org
+```
+
+Then open your browser and visit http://cloud.paddlepaddle.org.
+
+### Run locally
Make sure you are using a virtual environment of some sort (e.g. `virtualenv` or
`pyenv`).
+```
+virtualenv paddlecloudenv
+# enable the virtualenv
+source paddlecloudenv/bin/activate
+```
+To run for the first time, you need to:
```
npm install
pip install -r requirements.txt
@@ -13,4 +48,10 @@ pip install -r requirements.txt
npm run dev
```
-Browse to http://localhost:3000/
+Browse to http://localhost:8000/
+
+If you are starting the server for the second time, just run:
+```
+./manage.py runserver
+```
+
diff --git a/paddlecloud/Dockerfile b/paddlecloud/Dockerfile
new file mode 100644
index 00000000..eff2cb3c
--- /dev/null
+++ b/paddlecloud/Dockerfile
@@ -0,0 +1,8 @@
+FROM python:2.7.13-alpine
+RUN apk add --update nodejs openssl
+
+ADD requirements.txt package.json /pcloud/
+RUN cd /pcloud && npm install && pip install -r requirements.txt && npm build
+WORKDIR /pcloud
+
+CMD ["sh", "-c", "./manage.py migrate; ./manage.py loaddata sites; npm run dev"]
diff --git a/paddlecloud/ca.crt b/paddlecloud/ca.crt
deleted file mode 100644
index 428f5f43..00000000
--- a/paddlecloud/ca.crt
+++ /dev/null
@@ -1,18 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIC5zCCAc+gAwIBAgIBATANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwptaW5p
-a3ViZUNBMB4XDTE3MDQxODA2MDMxNFoXDTI3MDQxNjA2MDMxNFowFTETMBEGA1UE
-AxMKbWluaWt1YmVDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKyM
-dvvKvO9q/qkiXhb0cBwyvfW3/wCVttmjjnysA0+eeza/7FVYoHXK8MZBP748Iden
-T+DocKxxiyJ8wpa4DLJlbgMOWfWinZvZHeILmzblq/6rcLYe28TdkwUCgkJBhJaH
-jcPYg6flYom2NbS2tVxajt3dZiCl6HUF0TTOOnULHK5+ATRu+DaQSKmBW9Ro0SM5
-UDr2Q7gBXcql5dsJDRiqWA2tzn3/GqSTcXT5IAA5GXs3cN1yvxSH/PbNFyx8QrK0
-YDzRzinvzQcrTJcLDV52Oxgo/bkWBqvtZYON4ATxB1gRvKvHMK7hcmQdfXv/nqh5
-IRQOdA35RmleofmfPyUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgKkMB0GA1UdJQQW
-MBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
-DQEBCwUAA4IBAQCcfTBVHvVDkImrx5blMqrMH7OMYYQlzZiXaliTgwMBKgSs7zGV
-dtYokFRVwHnniK677MU2BQ3DBrQq9SxwdVG4DvuMuOjmfuJWtSIgnmvBXQlKqh+Y
-eyPgLAZTjsun+iFHye4KhcmE01A42Gp//zBMUhX9SC48QtsFLG94H/DNcy/zO7Qc
-NAlNmazHv27cy4am9Cd/rWSTt3t3NkuDEYM/LW11mIdR8P1MbbsTCQyI2ayKNccU
-0FplEqsjFQIGrW00vMPqKIvNK3Z2l1lR9O5s/U8p3k05aVocpMbRZb2A+TxnQcDp
-s8fv8SswDNmK1fXxQ7o2DFWM5Ck1jW7ighph
------END CERTIFICATE-----
diff --git a/paddlecloud/k8s/cloud_deployment.yaml b/paddlecloud/k8s/cloud_deployment.yaml
new file mode 100644
index 00000000..77af650d
--- /dev/null
+++ b/paddlecloud/k8s/cloud_deployment.yaml
@@ -0,0 +1,24 @@
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+ name: paddle-cloud
+spec:
+ replicas: 1
+ template:
+ metadata:
+ labels:
+ app: paddle-cloud
+ spec:
+ volumes:
+ - name: pcloud-volume
+ hostPath:
+ path: "/Users/wuyi/go/src/github.com/typhoonzero/PaddleCloud/paddlecloud"
+ containers:
+ - name: paddle-cloud
+ imagePullPolicy: Always
+ volumeMounts:
+ - mountPath: /pcloud
+ name: pcloud-volume
+ image: docker.paddlepaddlehub.com/pcloud:latest
+ ports:
+ - containerPort: 8000
diff --git a/paddlecloud/k8s/cloud_ingress.yaml b/paddlecloud/k8s/cloud_ingress.yaml
new file mode 100644
index 00000000..bfe8ae7e
--- /dev/null
+++ b/paddlecloud/k8s/cloud_ingress.yaml
@@ -0,0 +1,13 @@
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+ name: paddle-cloud-ingress
+spec:
+ rules:
+ - host: cloud.paddlepaddle.org
+ http:
+ paths:
+ - path: /
+ backend:
+ serviceName: paddle-cloud-service
+ servicePort: 8000
diff --git a/paddlecloud/k8s/cloud_service.yaml b/paddlecloud/k8s/cloud_service.yaml
new file mode 100644
index 00000000..a0192013
--- /dev/null
+++ b/paddlecloud/k8s/cloud_service.yaml
@@ -0,0 +1,11 @@
+kind: Service
+apiVersion: v1
+metadata:
+ name: paddle-cloud-service
+spec:
+ selector:
+ app: paddle-cloud
+ ports:
+ - protocol: TCP
+ port: 8000
+ targetPort: 8000
diff --git a/paddlecloud/nginx.conf b/paddlecloud/nginx.conf
index 77adb977..a416b864 100644
--- a/paddlecloud/nginx.conf
+++ b/paddlecloud/nginx.conf
@@ -37,12 +37,20 @@ server {
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
+ location ~ ^/notebook/([a-z0-9]+) {
+ proxy_redirect off;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_pass http://192.168.64.2:80;
+ }
+
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_pass http://172.20.166.33:8000/;
+ proxy_pass http://172.20.166.33:8000;
}
}
diff --git a/paddlecloud/notebook/frame_middleware.py b/paddlecloud/notebook/frame_middleware.py
new file mode 100644
index 00000000..362d6f29
--- /dev/null
+++ b/paddlecloud/notebook/frame_middleware.py
@@ -0,0 +1,10 @@
+class NotebookMiddleware:
+
+ def __init__(self, get_response):
+ self.get_response = get_response
+
+ def __call__(self, request):
+ response = self.get_response(request)
+ response["Content-Security-Policy"] = "frame-ancestors 'self' http://notebook.paddlepaddle.org"
+ response["X-Frame-Options"] = "ALLOW-FROM http://notebook.paddlepaddle.org"
+ return response
diff --git a/paddlecloud/notebook/templates/notebook.html b/paddlecloud/notebook/templates/notebook.html
index ec073128..5e2408df 100644
--- a/paddlecloud/notebook/templates/notebook.html
+++ b/paddlecloud/notebook/templates/notebook.html
@@ -7,9 +7,16 @@
{% block body_class %}home{% endblock %}
{% block body_base %}
-
-
-
- {{ notebook_id }}
+
+
+
+
+
{% endblock %}
diff --git a/paddlecloud/notebook/tls.py b/paddlecloud/notebook/tls.py
index ad738cdb..5322362f 100644
--- a/paddlecloud/notebook/tls.py
+++ b/paddlecloud/notebook/tls.py
@@ -1,5 +1,6 @@
import subprocess
import os
+from django.conf import settings
def __check_cert_requirements__(program):
def is_exe(fpath):
@@ -29,13 +30,13 @@ def create_user_cert(ca_path, username):
user_cert_cmds = []
user_cert_dir = os.path.join(settings.USER_CERTS_PATH, username)
user_cert_cmds.append("mkdir -p %s" % user_cert_dir)
- user_cert_cmd.append("openssl genrsa -out \
+ user_cert_cmds.append("openssl genrsa -out \
%s/%s-key.pem 2048"%(user_cert_dir, username))
- user_cert_cmd.append("openssl req -new -key %s/%s-key.pem -out\
+ user_cert_cmds.append("openssl req -new -key %s/%s-key.pem -out\
%s/%s.csr -subj \"/CN=%s\""%\
(user_cert_dir, username,
user_cert_dir, username, username))
- user_cert_cmd.append("openssl x509 -req -in %s/%s.csr -CA %s -CAkey %s \
+ user_cert_cmds.append("openssl x509 -req -in %s/%s.csr -CA %s -CAkey %s \
-CAcreateserial -out %s/%s.pem -days 365"% \
(user_cert_dir, username,
settings.CA_PATH, settings.CA_KEY_PATH,
diff --git a/paddlecloud/notebook/utils.py b/paddlecloud/notebook/utils.py
new file mode 100644
index 00000000..a34f74db
--- /dev/null
+++ b/paddlecloud/notebook/utils.py
@@ -0,0 +1,188 @@
+from django.conf import settings
+import os
+import kubernetes
+import hashlib
+import copy
+
+def email_escape(email):
+ """
+ escape email to a safe string of kubernetes namespace
+ """
+ safe_email = email.replace("@", "-")
+ safe_email = safe_email.replace(".", "-")
+ safe_email = safe_email.replace("_", "-")
+ return safe_email
+
+
+def get_user_api_client(username):
+ """
+ update kubernetes client to use current logined user's crednetials
+ """
+
+ conf_obj = kubernetes.client.Configuration()
+ conf_obj.host = settings.K8S_HOST
+ conf_obj.ssl_ca_cert = os.path.join(settings.CA_PATH)
+ conf_obj.cert_file = os.path.join(settings.USER_CERTS_PATH, username, "%s.pem"%username)
+ conf_obj.key_file = os.path.join(settings.USER_CERTS_PATH, username, "%s-key.pem"%username)
+ #kubernetes.config.load_kube_config(client_configuration=conf_obj)
+ api_client = kubernetes.client.ApiClient(config=conf_obj)
+ return api_client
+
+# a class for creating jupyter notebook resources
+class UserNotebook():
+ dep_body = {
+ "apiVersion": "extensions/v1beta1",
+ "kind": "Deployment",
+ "metadata": {
+ "name": "paddle-book-deployment"
+ },
+ "spec": {
+ "replicas": 1,
+ "template": {
+ "metadata": {
+ "labels": {
+ "app": "paddle-book"
+ }
+ },
+ "spec": {
+ "containers": [{
+ "name": "paddle-book",
+ "image": settings.PADDLE_BOOK_IMAGE,
+ "command": ["sh", "-c",
+ "mkdir -p /root/.jupyter; echo \"c.NotebookApp.base_url = '/notebook/%s'\" > /root/.jupyter/jupyter_notebook_config.py; jupyter notebook --debug --ip=0.0.0.0 --no-browser --allow-root --NotebookApp.token='' --NotebookApp.disable_check_xsrf=True /book/"],
+ "ports": [{
+ "containerPort": settings.PADDLE_BOOK_PORT
+ }]
+ }]
+ }
+ }
+ }
+ }
+ service_body = {
+ "apiVersion": "v1",
+ "kind": "Service",
+ "metadata": {
+ "name": "paddle-book-service"
+ },
+ "spec": {
+ "selector": {
+ "app": "paddle-book"
+ },
+ "ports": [{
+ "protocol": "TCP",
+ "port": 8888,
+ "targetPort": 8888
+ }]
+ }
+ }
+ ing_body = {
+ "apiVersion": "extensions/v1beta1",
+ "kind": "Ingress",
+ "metadata": {
+ "name": "paddle-book-ingress"
+ },
+ "spec": {
+ "rules": [{
+ "host": "cloud.paddlepaddle.org",
+ "http": {
+ "paths": [{
+ "path": "/",
+ "backend": {
+ "serviceName": "paddle-book-service",
+ "servicePort": 8888
+ }
+ },
+ ]
+ }
+ }]
+ }
+ }
+ def get_notebook_id(self, username):
+ # notebook id is md5(username)
+ m = hashlib.md5()
+ m.update(username)
+
+ return m.hexdigest()[:8]
+
+ def __wait_api_response(self, resp):
+ print resp.status
+
+ def __find_item(self, resource_list, match_name):
+ item_found = False
+ for item in resource_list.items:
+ if item.metadata.name == match_name:
+ item_found = True
+ return item_found
+
+ def __create_deployment(self, username, namespace):
+ v1beta1api = kubernetes.client.ExtensionsV1beta1Api(api_client=get_user_api_client(username))
+ dep_list = v1beta1api.list_namespaced_deployment(namespace)
+ if not self.__find_item(dep_list, "paddle-book-deployment"):
+ self.dep_body["spec"]["template"]["spec"]["containers"][0]["command"][2] = \
+ self.dep_body["spec"]["template"]["spec"]["containers"][0]["command"][2] % self.get_notebook_id(username)
+ resp = v1beta1api.create_namespaced_deployment(namespace, body=self.dep_body, pretty=True)
+ self.__wait_api_response(resp)
+
+ def __create_service(self, username, namespace):
+ v1api = kubernetes.client.CoreV1Api(api_client=get_user_api_client(username))
+ service_list = v1api.list_namespaced_service(namespace)
+ if not self.__find_item(service_list, "paddle-book-service"):
+ resp = v1api.create_namespaced_service(namespace, body=self.service_body)
+ self.__wait_api_response(resp)
+
+ # service for notebook websocket
+ service_ws = copy.deepcopy(self.service_body)
+ service_ws["metadata"]["name"] = "paddle-book-service-ws"
+ if not self.__find_item(service_list, "paddle-book-service-ws"):
+ resp = v1api.create_namespaced_service(namespace, body=service_ws)
+ self.__wait_api_response(resp)
+
+ def __create_ingress(self, username, namespace):
+ v1beta1api = kubernetes.client.ExtensionsV1beta1Api(api_client=get_user_api_client(username))
+ ing_list = v1beta1api.list_namespaced_ingress(namespace)
+ if not self.__find_item(ing_list, "paddle-book-ingress"):
+ # FIXME: must split this for different users
+ self.ing_body["spec"]["rules"][0]["http"]["paths"][0]["path"] = "/notebook/" + self.get_notebook_id(username)
+ #self.ing_body["spec"]["rules"][0]["http"]["paths"][1]["path"] = "/notebook/" + self.get_notebook_id(username) + "/api/kernels/*"
+ resp = v1beta1api.create_namespaced_ingress(namespace, body=self.ing_body)
+ self.__wait_api_response(resp)
+
+ def start_all(self, username, namespace):
+ """
+ start deployment, service, ingress to start a notebook service for current user
+ """
+ self.__create_deployment(username, namespace)
+ self.__create_service(username, namespace)
+ self.__create_ingress(username, namespace)
+
+ def stop_all(self, username, namespace):
+ v1beta1api = kubernetes.client.ExtensionsV1beta1Api(api_client=get_user_api_client(username))
+ v1api = kubernetes.client.CoreV1Api(api_client=get_user_api_client(username))
+ v1beta1api.delete_namespaced_deployment("paddle-book-deployment", namespace)
+ v1beta1api.delete_namespaced_ingress("paddle-book-ingress", namespace)
+ v1api.delete_namespaced_service("paddle-book-service", namespace)
+
+ def status(self, username, namespace):
+ """
+ check notebook deployment status
+ @return: running starting stopped
+ """
+ v1api = kubernetes.client.CoreV1Api(api_client=get_user_api_client(username))
+ v1beta1api = kubernetes.client.ExtensionsV1beta1Api(api_client=get_user_api_client(username))
+ d, s, i = (True, True, True)
+ dep_list = v1beta1api.list_namespaced_deployment(namespace)
+ if not self.__find_item(dep_list, "paddle-book-deployment"):
+ d = False
+ service_list = v1api.list_namespaced_service(namespace)
+ if not self.__find_item(service_list, "paddle-book-service"):
+ s = False
+ ing_list = v1beta1api.list_namespaced_ingress(namespace)
+ if not self.__find_item(ing_list, "paddle-book-ingress"):
+ i = False
+
+ if d and s and i:
+ return "running"
+ elif d or s or i:
+ return "starting"
+ else:
+ return "stopped"
diff --git a/paddlecloud/notebook/views.py b/paddlecloud/notebook/views.py
index 4dc4c21a..b0145c69 100644
--- a/paddlecloud/notebook/views.py
+++ b/paddlecloud/notebook/views.py
@@ -19,6 +19,7 @@
import logging
import hashlib
import kubernetes
+import utils
@receiver(post_save, sender=User)
def handle_user_save(sender, instance, created, **kwargs):
@@ -35,11 +36,11 @@ class SignupView(account.views.SignupView):
def after_signup(self, form):
self.update_profile(form)
- try:
- logging.info("creating default user certs...")
- tls.create_user_cert(settings.CA_PATH, form.get_user())
- except Exception, e:
- logging.error("create user certs error: %s", str(e))
+ #try:
+ logging.info("creating default user certs...")
+ tls.create_user_cert(settings.CA_PATH, form.cleaned_data["email"])
+ #except Exception, e:
+ # logging.error("create user certs error: %s", str(e))
super(SignupView, self).after_signup(form)
@@ -57,125 +58,6 @@ def generate_username(self, form):
username = form.cleaned_data["email"]
return username
-# a class for creating jupyter notebook resources
-class UserNotebook():
- dep_body = {
- "apiVersion": "extensions/v1beta1",
- "kind": "Deployment",
- "metadata": {
- "name": "paddle-book-deployment"
- },
- "spec": {
- "replicas": 1,
- "template": {
- "metadata": {
- "labels": {
- "app": "paddle-book"
- }
- },
- "spec": {
- "containers": [{
- "name": "paddle-book",
- "image": settings.PADDLE_BOOK_IMAGE,
- "ports": [{
- "containerPort": settings.PADDLE_BOOK_PORT
- }]
- }]
- }
- }
- }
- }
- service_body = {
- "apiVersion": "v1",
- "kind": "Service",
- "metadata": {
- "name": "paddle-book-service"
- },
- "spec": {
- "selector": {
- "app": "paddle-book"
- },
- "ports": [{
- "protocol": "TCP",
- "port": 8888,
- "targetPort": 8888
- }]
- }
- }
- ing_body = {
- "apiVersion": "extensions/v1beta1",
- "kind": "Ingress",
- "metadata": {
- "name": "paddle-book-ingress"
- },
- "spec": {
- "rules": [{
- "host": "notebook.paddlepaddle.org",
- "http": {
- "paths": [{
- "path": "/",
- "backend": {
- "serviceName": "paddle-book-service",
- "servicePort": 8888
- }
- }]
- }
- }]
- }
- }
- def get_notebook_id(self, username):
- # notebook id is md5(username)
- m = hashlib.md5()
- m.update(username)
-
- return m.hexdigest()[:8]
-
- def __wait_api_response(self, resp):
- print resp.status
-
- def __find_item(self, resource_list, match_name):
- item_found = False
- for item in resource_list.items:
- if item.metadata.name == match_name:
- item_found = True
- return item_found
-
- def __create_deployment(self, namespace):
- v1beta1api = kubernetes.client.ExtensionsV1beta1Api()
- dep_list = v1beta1api.list_namespaced_deployment(namespace)
- if not self.__find_item(dep_list, "paddle-book-deployment"):
- resp = v1beta1api.create_namespaced_deployment(namespace, body=self.dep_body, pretty=True)
- self.__wait_api_response(resp)
-
- def __create_service(self, namespace):
- v1api = kubernetes.client.CoreV1Api()
- service_list = v1api.list_namespaced_service(namespace)
- if not self.__find_item(service_list, "paddle-book-service"):
- resp = v1api.create_namespaced_service(namespace, body=self.service_body)
- self.__wait_api_response(resp)
-
- def __create_ingress(self, username, namespace):
- v1beta1api = kubernetes.client.ExtensionsV1beta1Api()
- ing_list = v1beta1api.list_namespaced_ingress(namespace)
- if not self.__find_item(ing_list, "paddle-book-ingress"):
- # FIXME: must split this for different users
- #self.ing_body["spec"]["rules"][0]["http"]["paths"][0]["path"] = "/" + self.get_notebook_id(username)
- resp = v1beta1api.create_namespaced_ingress(namespace, body=self.ing_body)
- self.__wait_api_response(resp)
-
- def start_all(self, username, namespace):
- self.__create_deployment(namespace)
- self.__create_service(namespace)
- self.__create_ingress(username, namespace)
-
-def email_escape(email):
- """
- escape email to a safe string of kubernetes namespace
- """
- safe_email = email.replace("@", "-")
- safe_email = safe_email.replace(".", "-")
- safe_email = safe_email.replace("_", "-")
- return safe_email
@login_required
def notebook_view(request):
@@ -186,17 +68,12 @@ def notebook_view(request):
# NOTICE: username is the same to user's email
# NOTICE: escape the username to safe string to create namespaces
username = request.user.username
- conf_obj = kubernetes.client.Configuration()
- conf_obj.host = settings.K8S_HOST
- conf_obj.ssl_ca_cert = os.path.join(settings.CA_PATH)
- conf_obj.cert_file = os.path.join(settings.USER_CERTS_PATH, username, username, ".pem")
- conf_obj.key_file = os.path.join(settings.USER_CERTS_PATH, username, username, "-key.pem")
- kubernetes.config.load_kube_config(client_configuration=conf_obj)
+
# FIXME: notebook must be started under username's namespace
- v1api = kubernetes.client.CoreV1Api()
+ v1api = kubernetes.client.CoreV1Api(utils.get_user_api_client(username))
namespaces = v1api.list_namespace()
user_namespace_found = False
- user_namespace = email_escape(username)
+ user_namespace = utils.email_escape(username)
for ns in namespaces.items:
# must commit to user's namespace
if ns.metadata.name == user_namespace:
@@ -209,7 +86,16 @@ def notebook_view(request):
"name": user_namespace
}})
- ub = UserNotebook()
+ ub = utils.UserNotebook()
ub.start_all(username, user_namespace)
- return render(request, "notebook.html", context={"notebook_id": ub.get_notebook_id(username)})
+ return render(request, "notebook.html",
+ context={"notebook_id": ub.get_notebook_id(username)})
+
+@login_required
+def stop_notebook_backend(request):
+ username = request.user.username
+ utils.update_user_k8s_config(username)
+ ub = utils.UserNotebook()
+ ub.start_all(username, user_namespace)
+ return HttpResponseRedirect("/")
diff --git a/paddlecloud/paddlecloud/settings.py b/paddlecloud/paddlecloud/settings.py
index d0622886..1ecf97c1 100644
--- a/paddlecloud/paddlecloud/settings.py
+++ b/paddlecloud/paddlecloud/settings.py
@@ -15,7 +15,8 @@
}
ALLOWED_HOSTS = [
- "localhost",
+ "127.0.0.1",
+ "cloud.paddlepaddle.org",
]
# Local time zone for this installation. Choices can be found here:
@@ -114,6 +115,7 @@
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"account.middleware.ExpiredPasswordMiddleware",
+ "notebook.frame_middleware.NotebookMiddleware"
]
ROOT_URLCONF = "paddlecloud.urls"
@@ -198,10 +200,10 @@
]
-CA_PATH = os.path.join(BASE_DIR, "ca.crt")
-CA_KEY_PATH = os.path.join(BASE_DIR, "ca.key")
+CA_PATH = os.path.join(BASE_DIR, "..", "ca.crt")
+CA_KEY_PATH = os.path.join(BASE_DIR, "..", "ca.key")
USER_CERTS_PATH="/tmp"
-K8S_HOST = "https://192.168.64.2:8443"
+K8S_HOST = "https://192.168.99.100:8443"
PADDLE_BOOK_IMAGE="docker.paddlepaddle.org/book:0.10.0rc2"
PADDLE_BOOK_PORT=8888
diff --git a/paddlecloud/paddlecloud/templates/homepage.html b/paddlecloud/paddlecloud/templates/homepage.html
index 0e53943b..f8d82270 100644
--- a/paddlecloud/paddlecloud/templates/homepage.html
+++ b/paddlecloud/paddlecloud/templates/homepage.html
@@ -46,7 +46,7 @@ {% blocktrans %}What is PaddlePaddle Cloud?{% endblocktr
Starter projects provide project layout,
scaffolding, already integrated components and
ready-to-go code.
- Launch Paddle notebook
+ Launch Paddle notebook
{% endblocktrans %}
diff --git a/paddlecloud/paddlecloud/templates/site_base.html b/paddlecloud/paddlecloud/templates/site_base.html
index 00cc5d32..4aed4f69 100644
--- a/paddlecloud/paddlecloud/templates/site_base.html
+++ b/paddlecloud/paddlecloud/templates/site_base.html
@@ -3,7 +3,27 @@
{% load staticfiles %}
{% load pinax_webanalytics_tags %}
{% load i18n %}
-
+{% load notebook_status_tags %}
+
+{% block nav %}
+ {% get_user_notebook_status request.user as status %}
+
+{% endblock %}
{% block styles %}
diff --git a/paddlecloud/paddlecloud/templatetags/__init__.py b/paddlecloud/paddlecloud/templatetags/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/paddlecloud/paddlecloud/templatetags/notebook_status_tags.py b/paddlecloud/paddlecloud/templatetags/notebook_status_tags.py
new file mode 100644
index 00000000..8125be08
--- /dev/null
+++ b/paddlecloud/paddlecloud/templatetags/notebook_status_tags.py
@@ -0,0 +1,28 @@
+from __future__ import unicode_literals
+from django import template
+from django.contrib.messages.utils import get_level_tags
+from django.utils.encoding import force_text
+from notebook.utils import email_escape, UserNotebook, get_user_api_client
+import kubernetes
+
+LEVEL_TAGS = get_level_tags()
+
+register = template.Library()
+
+
+def _get_notebook_id(self, username):
+ # notebook id is md5(username)
+ m = hashlib.md5()
+ m.update(username)
+
+ return m.hexdigest()[:8]
+
+@register.simple_tag()
+def get_user_notebook_status(user):
+ if not user.is_authenticated:
+ return ""
+ username = user.username
+ namespace = email_escape(user.email)
+ ub = UserNotebook()
+
+ return ub.status(username, namespace)
diff --git a/paddlecloud/paddlecloud/urls.py b/paddlecloud/paddlecloud/urls.py
index 7287a7ed..a2b3db4f 100644
--- a/paddlecloud/paddlecloud/urls.py
+++ b/paddlecloud/paddlecloud/urls.py
@@ -13,7 +13,8 @@
url(r"^account/signup/$", notebook.views.SignupView.as_view(), name="account_signup"),
url(r"^account/login/$", notebook.views.LoginView.as_view(), name="account_login"),
url(r"^account/", include("account.urls")),
- url(r"^notebook/", notebook.views.notebook_view),
+ url(r"^notedash/", notebook.views.notebook_view),
+ url(r"^notestop/", notebook.views.stop_notebook_backend),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)