Skip to content

Commit

Permalink
Add a jupyter server extension to render desktop/
Browse files Browse the repository at this point in the history
A mess of a commit, should have been several.

- Finish renaming package from jupyter_desktop to
  jupyter_desktop_server
- Revert 360f9b0. Looks like
  websockify gets super confused when you put shell in the middle
  of it and the process it is spawning.
- Add a server extension that renders a slightly modified copy
  of vnc_lite.html as /desktop. This will be modified more and more
  as we go forward. This also helps us remove the mapping present
  in the jupyter server proxy entry
  • Loading branch information
yuvipanda committed Nov 20, 2019
1 parent bda9a7e commit 18d7fb7
Show file tree
Hide file tree
Showing 245 changed files with 62 additions and 14 deletions.
4 changes: 3 additions & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
graft jupyter_desktop/share
graft jupyter_desktop_server/share
graft jupyter_desktop_server/etc
graft jupyter_desktop_server/templates
25 changes: 18 additions & 7 deletions jupyter_desktop/__init__.py → jupyter_desktop_server/__init__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import os
import shlex
import tempfile
from notebook.utils import url_path_join as ujoin
from tornado.web import StaticFileHandler
from .handlers import DesktopHandler


HERE = os.path.dirname(os.path.abspath(__file__))

def setup_desktop():
def setup_vnc():
# make a secure temporary directory for sockets
# This is only readable, writeable & searchable by our uid
sockets_dir = tempfile.mkdtemp()
sockets_path = os.path.join(sockets_dir, 'vnc-socket')

vnc_command = ' '.join((shlex.quote(p) for p in [
vnc_command = [
os.path.join(HERE, 'share/tigervnc/bin/vncserver'),
'-verbose',
'-xstartup', os.path.join(HERE, 'share/xstartup'),
Expand All @@ -20,7 +23,7 @@ def setup_desktop():
'-rfbunixpath', sockets_path,
'-fg',
':1',
]))
]
return {
'command': [
'websockify', '-v',
Expand All @@ -29,10 +32,18 @@ def setup_desktop():
'5901',
'--unix-target', sockets_path,
'--',
'/bin/sh', '-c',
f'cd {os.getcwd()} && {vnc_command}'
],
] + vnc_command,
'port': 5901,
'timeout': 30,
'mappath': {'/': '/vnc_lite.html'},
}


def load_jupyter_server_extension(nbapp):
# Set up handlers picked up via config
base_url = nbapp.web_app.settings['base_url']

web_path = os.path.join(HERE, 'share/web')
nbapp.web_app.add_handlers('.*', [
(ujoin(base_url, 'desktop-server/static/(.*)'), StaticFileHandler, {'path': web_path}),
(ujoin(base_url, 'desktop'), DesktopHandler)
])
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"NotebookApp": {
"nbserver_extensions": {
"jupyter_desktop_server": true
}
}
}
24 changes: 24 additions & 0 deletions jupyter_desktop_server/handlers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from notebook.base.handlers import IPythonHandler
import jinja2
import os


class DesktopHandler(IPythonHandler):
def initialize(self):
super().initialize()
# FIXME: Is this really the best way to use jinja2 here?
# I can't seem to get the jinja2 env in the base handler to
# actually load templates from arbitrary paths ugh.
jinja2_env = self.settings['jinja2_env']
jinja2_env.loader = jinja2.ChoiceLoader([
jinja2_env.loader,
jinja2.FileSystemLoader(
os.path.join(os.path.dirname(__file__), 'templates')
)
])

def get(self):
novnc_base_url = self.base_url + "desktop-server/static/noVNC-1.1.0/"
self.write(
self.render_template('desktop.html', novnc_base_url=novnc_base_url)
)
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
</style>

<!-- Promise polyfill for IE11 -->
<script src="vendor/promise.js"></script>
<script src="{{novnc_base_url}}vendor/promise.js"></script>

<!-- ES2015/ES6 modules polyfill -->
<script type="module">
Expand All @@ -70,7 +70,7 @@
window.addEventListener("load", function() {
if (window._noVNC_has_module_support) return;
const loader = document.createElement("script");
loader.src = "vendor/browser-es-module-loader/dist/" +
loader.src = "{{novnc_base_url}}vendor/browser-es-module-loader/dist/" +
"browser-es-module-loader.js";
document.head.appendChild(loader);
});
Expand All @@ -79,7 +79,7 @@
<!-- actual script modules -->
<script type="module" crossorigin="use-credentials">
// RFB holds the API to connect and communicate with a VNC server
import RFB from './core/rfb.js';
import RFB from '../desktop-server/static/noVNC-1.1.0/core/rfb.js';

let rfb;
let desktopName;
Expand Down Expand Up @@ -155,7 +155,7 @@
let port = readQueryVariable('port', window.location.port);
const password = readQueryVariable('password', '');
// MODIFICATION FROM vnc_lite.html
const path = readQueryVariable('path', window.location.pathname.replace(/[^/]*$/, '').substring(1) + 'websockify');
const path = readQueryVariable('path', "{{base_url}}vnc/");

// | | | | | |
// | | | Connect | | |
Expand All @@ -174,7 +174,8 @@
if(port) {
url += ':' + port;
}
url += '/' + path;
// MODIFICATION FROM vnc_lite
url += path;

// Creating a new RFB object will start a new connection
rfb = new RFB(document.getElementById('screen'), url,
Expand Down
5 changes: 4 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
version='0.1.2',
entry_points={
'jupyter_serverproxy_servers': [
'desktop = jupyter_desktop:setup_desktop',
'vnc = jupyter_desktop_server:setup_vnc',
]
},
data_files=[
('etc/jupyter/jupyter_notebook_config.d', ['jupyter_desktop_server/etc/jupyter-desktop-server-serverextension.json']),
],
install_requires=['jupyter-server-proxy>=1.2.0'],
include_package_data=True,
zip_safe=False
Expand Down

0 comments on commit 18d7fb7

Please sign in to comment.