Skip to content

Commit b4a66dd

Browse files
committed
add Jupyter notebook environment to the Vagrant VM
1 parent 4fc572d commit b4a66dd

9 files changed

Lines changed: 309 additions & 3 deletions

File tree

‎Vagrantfile‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Vagrant.configure(2) do |config|
2222
# Create a forwarded port mapping which allows access to a specific port
2323
# within the machine from a port on the host machine. In the example below,
2424
# accessing "localhost:8080" will access port 80 on the guest machine.
25-
# config.vm.network "forwarded_port", guest: 80, host: 8080
25+
config.vm.network "forwarded_port", guest: 8888, host: 8080
2626

2727
# Create a private network, which allows host-only access to the machine
2828
# using a specific IP.
@@ -56,5 +56,5 @@ Vagrant.configure(2) do |config|
5656
inline: "sudo apt-get install ansible -y && ansible-playbook -i 'localhost,' -c local /vagrant/setup.yaml",
5757
keep_color: true
5858

59-
config.vm.post_up_message = "access the machine using the 'vagrant ssh' command or connect to 127.0.0.1:2222 via SSH"
59+
config.vm.post_up_message = "access the machine using SSH using port 2222 or with the URL 'http://localhost:8080'"
6060
end
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
"""
2+
from http://stackoverflow.com/questions/20186344/ipynb-import-another-ipynb-file
3+
"""
4+
import io, os, sys, types
5+
from IPython import get_ipython
6+
from nbformat import current
7+
from IPython.core.interactiveshell import InteractiveShell
8+
9+
10+
def find_notebook(fullname, path=None):
11+
"""find a notebook, given its fully qualified name and an optional path
12+
13+
This turns "foo.bar" into "foo/bar.ipynb"
14+
and tries turning "Foo_Bar" into "Foo Bar" if Foo_Bar
15+
does not exist.
16+
"""
17+
name = fullname.rsplit('.', 1)[-1]
18+
if not path:
19+
path = ['']
20+
for d in path:
21+
nb_path = os.path.join(d, name + ".ipynb")
22+
if os.path.isfile(nb_path):
23+
return nb_path
24+
# let import Notebook_Name find "Notebook Name.ipynb"
25+
nb_path = nb_path.replace("_", " ")
26+
if os.path.isfile(nb_path):
27+
return nb_path
28+
29+
30+
class NotebookLoader(object):
31+
"""Module Loader for Jupyter Notebooks"""
32+
def __init__(self, path=None):
33+
self.shell = InteractiveShell.instance()
34+
self.path = path
35+
36+
def load_module(self, fullname):
37+
"""import a notebook as a module"""
38+
path = find_notebook(fullname, self.path)
39+
40+
print ("importing Jupyter notebook from %s" % path)
41+
42+
# load the notebook object
43+
with io.open(path, 'r', encoding='utf-8') as f:
44+
nb = current.read(f, 'json')
45+
46+
47+
# create the module and add it to sys.modules
48+
# if name in sys.modules:
49+
# return sys.modules[name]
50+
mod = types.ModuleType(fullname)
51+
mod.__file__ = path
52+
mod.__loader__ = self
53+
mod.__dict__['get_ipython'] = get_ipython
54+
sys.modules[fullname] = mod
55+
56+
# extra work to ensure that magics that would affect the user_ns
57+
# actually affect the notebook module's ns
58+
save_user_ns = self.shell.user_ns
59+
self.shell.user_ns = mod.__dict__
60+
61+
try:
62+
for cell in nb.worksheets[0].cells:
63+
if cell.cell_type == 'code' and cell.language == 'python':
64+
# transform the input to executable Python
65+
code = self.shell.input_transformer_manager.transform_cell(cell.input)
66+
# run the code in themodule
67+
exec(code, mod.__dict__)
68+
finally:
69+
self.shell.user_ns = save_user_ns
70+
return mod
71+
72+
73+
class NotebookFinder(object):
74+
"""Module finder that locates Jupyter Notebooks"""
75+
def __init__(self):
76+
self.loaders = {}
77+
78+
def find_module(self, fullname, path=None):
79+
nb_path = find_notebook(fullname, path)
80+
if not nb_path:
81+
return
82+
83+
key = path
84+
if path:
85+
# lists aren't hashable
86+
key = os.path.sep.join(path)
87+
88+
if key not in self.loaders:
89+
self.loaders[key] = NotebookLoader(path)
90+
return self.loaders[key]
91+
92+
sys.meta_path.append(NotebookFinder())

‎jupyter-config/about.ipynb‎

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# about\n",
8+
"\n",
9+
"This VM provides a Jupyter/IPython environment bundled with **python 3** and the following modules/libraries:\n",
10+
"\n",
11+
"* Jinja2\n",
12+
"* ciscoconfparse\n",
13+
"* textfsm\n",
14+
"* requests\n",
15+
"\n",
16+
"These modules were part of previous post on my blog at the [Coding Networker](https://codingnetworker.com).\n"
17+
]
18+
},
19+
{
20+
"cell_type": "markdown",
21+
"metadata": {},
22+
"source": [
23+
"## jupyter home directory\n",
24+
"\n",
25+
"The following directories are availalable on the home directory:\n",
26+
"\n",
27+
"* **examples** - link to the `/vagrant` directory, that incudes all previous python examples\n",
28+
"* **notebooks** - link to the `/vagrant/notebooks` directory, that contains all example notebooks\n",
29+
"* **github** - repositories, that are cloned from GitHub during the provisioning of the machine"
30+
]
31+
},
32+
{
33+
"cell_type": "markdown",
34+
"metadata": {},
35+
"source": [
36+
"## import other notebooks\n",
37+
"\n",
38+
"This environment is preconfigured to import other notebooks, which are located in a directory with a `__init__.py` file.\n",
39+
"\n",
40+
"The following code shows an example of this function:"
41+
]
42+
},
43+
{
44+
"cell_type": "code",
45+
"execution_count": 1,
46+
"metadata": {
47+
"collapsed": false
48+
},
49+
"outputs": [
50+
{
51+
"name": "stdout",
52+
"output_type": "stream",
53+
"text": [
54+
"importing Jupyter notebook from /home/vagrant/notebooks/import_test.ipynb\n"
55+
]
56+
}
57+
],
58+
"source": [
59+
"from notebooks.import_test import echo_function"
60+
]
61+
},
62+
{
63+
"cell_type": "code",
64+
"execution_count": 2,
65+
"metadata": {
66+
"collapsed": false
67+
},
68+
"outputs": [
69+
{
70+
"name": "stdout",
71+
"output_type": "stream",
72+
"text": [
73+
"Hello\n"
74+
]
75+
},
76+
{
77+
"data": {
78+
"text/plain": [
79+
"'Hello'"
80+
]
81+
},
82+
"execution_count": 2,
83+
"metadata": {},
84+
"output_type": "execute_result"
85+
}
86+
],
87+
"source": [
88+
"echo_function(\"Hello\")"
89+
]
90+
}
91+
],
92+
"metadata": {
93+
"kernelspec": {
94+
"display_name": "Python 3",
95+
"language": "python",
96+
"name": "python3"
97+
},
98+
"language_info": {
99+
"codemirror_mode": {
100+
"name": "ipython",
101+
"version": 3
102+
},
103+
"file_extension": ".py",
104+
"mimetype": "text/x-python",
105+
"name": "python",
106+
"nbconvert_exporter": "python",
107+
"pygments_lexer": "ipython3",
108+
"version": "3.4.3"
109+
}
110+
},
111+
"nbformat": 4,
112+
"nbformat_minor": 0
113+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
description "Jupyter Upstart script"
2+
3+
start on filesystem or runlevel [2345]
4+
stop on shutdown
5+
6+
script
7+
export HOME="/home/vagrant/" cd $HOME
8+
echo $$ > /var/run/jupyter_start.pid
9+
exec jupyter-notebook --config='/home/vagrant/.jupyter/jupyter_notebook.config.py'
10+
end script
11+
12+
pre-start script
13+
echo "[`date`] Starting Jupyter Notebook Server" >> /var/log/jupyter-ntb.log
14+
end script
15+
16+
pre-stop script
17+
rm /var/run/ipython_start.pid
18+
echo "[`date`] Stopping Jupyter Notebook" >> /var/jupyter/Jupyter-ntb.log
19+
end script
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
# configuration file for jupyter
3+
c.NotebookApp.notebook_dir = u"/home/vagrant/"
4+
c.NotebookApp.ip = "*"
5+
c.NotebookApp.open_browser = False

‎notebooks/__init__.py‎

Whitespace-only changes.

‎notebooks/import_test.ipynb‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"metadata": {},
6+
"source": [
7+
"# import test notebook\n",
8+
"\n",
9+
"This notebook is only to test the import notebook function."
10+
]
11+
},
12+
{
13+
"cell_type": "code",
14+
"execution_count": 1,
15+
"metadata": {
16+
"collapsed": true
17+
},
18+
"outputs": [],
19+
"source": [
20+
"def echo_function(text):\n",
21+
" # simple echo function\n",
22+
" print(text)\n",
23+
" return text"
24+
]
25+
}
26+
],
27+
"metadata": {
28+
"kernelspec": {
29+
"display_name": "Python 3",
30+
"language": "python",
31+
"name": "python3"
32+
},
33+
"language_info": {
34+
"codemirror_mode": {
35+
"name": "ipython",
36+
"version": 3
37+
},
38+
"file_extension": ".py",
39+
"mimetype": "text/x-python",
40+
"name": "python",
41+
"nbconvert_exporter": "python",
42+
"pygments_lexer": "ipython3",
43+
"version": "3.4.3"
44+
}
45+
},
46+
"nbformat": 4,
47+
"nbformat_minor": 0
48+
}

‎requirements.txt‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ MarkupSafe==0.23
33
textfsm==0.3.0
44
requests
55
python-slugify
6+
psutil
7+
jupyter

‎setup.yaml‎

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
- python3-pip
1111
- ansible
1212
- git
13+
- build-essential
14+
- python3-dev
15+
1316
# clone python3 compatible textfsm-fork
1417
- name: clone textfsm repository form Github
1518
git: repo=https://github.com/jonathanslenders/textfsm.git dest=/home/vagrant/github/textfsm accept_hostkey=yes
@@ -20,6 +23,30 @@
2023
- name: install other python requirements form the examples repository
2124
sudo: true
2225
pip: requirements=/vagrant/requirements.txt executable=pip3
26+
2327
# create a symlink in the home directory to the shared directory
24-
- name: create 'example' link
28+
- name: create 'examples' link
2529
file: src=/vagrant dest=/home/vagrant/examples owner=vagrant group=vagrant state=link
30+
31+
# setup the jupyter notebook service
32+
- name: ensure that the .jupyter directory exists
33+
file: path=/home/vagrant/.jupyter state=directory
34+
- name: create 'notebooks' link in the home directory
35+
file: src=/vagrant/notebooks dest=/home/vagrant/notebooks owner=vagrant group=vagrant state=link
36+
- name: copy jupyter notebook configuration file
37+
copy: src=jupyter-config/jupyter_notebook_config.py dest=/home/vagrant/.jupyter/jupyter_notebook.config.py force=yes
38+
- name: link about notebook
39+
file: src=/vagrant/jupyter-config/about.ipynb dest=/home/vagrant/about.ipynb owner=vagrant group=vagrant state=link
40+
41+
# add startup script to enable the import notebook function
42+
- name: verify that the profile directory exists
43+
sudo: true
44+
file: path=/home/vagrant/.ipython/profile_default/startup state=directory
45+
- name: copy notebook import as startup script
46+
copy: src=jupyter-config/10-nb-import-hook.py dest=/home/vagrant/.ipython/profile_default/startup/10-nb-import-hook.py force=yes
47+
48+
# install jupyter notebook as a service
49+
- name: copy jupyter upstart script
50+
copy: src=jupyter-config/jupyter-notebook.upstart dest=/etc/init/jupyter-notebook.conf force=yes
51+
- name: start jupyter service
52+
service: name=jupyter-notebook state=restarted enabled=yes

0 commit comments

Comments
 (0)