From 48eefab5b360ae6be0e708496736773bc7548f5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Perrin?= <jerome@nexedi.com> Date: Sat, 10 Jan 2015 19:53:21 +0100 Subject: [PATCH] ipython notebook --- component/ipython/buildout.cfg | 27 ++++ software/ipython_notebook/instance.cfg | 120 ++++++++++++++++ software/ipython_notebook/software.cfg | 129 ++++++++++++++++++ .../template/ipython_notebook_config.jinja | 13 ++ .../template/ipython_set_password.jinja | 64 +++++++++ 5 files changed, 353 insertions(+) create mode 100644 component/ipython/buildout.cfg create mode 100644 software/ipython_notebook/instance.cfg create mode 100644 software/ipython_notebook/software.cfg create mode 100644 software/ipython_notebook/template/ipython_notebook_config.jinja create mode 100644 software/ipython_notebook/template/ipython_set_password.jinja diff --git a/component/ipython/buildout.cfg b/component/ipython/buildout.cfg new file mode 100644 index 0000000000..d1f2e39ca7 --- /dev/null +++ b/component/ipython/buildout.cfg @@ -0,0 +1,27 @@ +[buildout] +extends = + ../numpy/buildout.cfg + ../matplotlib/buildout.cfg + +parts = + ipython + +[ipython-env] +<= numpy-env + +[ipython] +recipe = zc.recipe.egg:custom +egg = ipython +environment = ipython-env +setup-eggs = ${numpy:egg} + +[ipython_notebook] +recipe = zc.recipe.egg:scripts +eggs = ipython[notebook] + ${matplotlib:egg} +environment = ipython-env +setup-eggs = ${numpy:egg} +initialization = + # https://github.com/ipython/ipython/issues/5420 + import os + os.environ['PYTHONPATH'] = ':'.join(sys.path) diff --git a/software/ipython_notebook/instance.cfg b/software/ipython_notebook/instance.cfg new file mode 100644 index 0000000000..36de927dd2 --- /dev/null +++ b/software/ipython_notebook/instance.cfg @@ -0,0 +1,120 @@ +[buildout] +parts = + instance + publish-connection-parameter +## Monitoring part XXX whe should not have to specify all parts like this +## Parts to add for monitoring + certificate-authority + cron + cron-entry-monitor + cron-entry-rss + deploy-index + deploy-settings-cgi + deploy-status-cgi + deploy-status-history-cgi + setup-static-files + certificate-authority + zero-parameters + public-symlink + cgi-httpd-wrapper + cgi-httpd-graceful-wrapper + monitor-promise + monitor-instance-log-access +## Monitor for ipython + monitor-current-log-access + monitor-deploy-set-password-cgi + +extends = ${monitor-template:output} + +eggs-directory = ${buildout:eggs-directory} +develop-eggs-directory = ${buildout:develop-eggs-directory} +offline = true + +[slapconfiguration] +recipe = slapos.cookbook:slapconfiguration +computer = $${slap_connection:computer_id} +partition = $${slap_connection:partition_id} +url = $${slap_connection:server_url} +key = $${slap_connection:key_file} +cert = $${slap_connection:cert_file} + +[instance-parameter] +port = 8888 +host = $${slapconfiguration:ipv6-random} +cert_file = $${generate-certificate:cert_file} +key_file = $${generate-certificate:key_file} +logfile = $${directory:log}/ipython_notebook.log +notebook_dir = $${directory:notebook_dir} + +[generate-certificate] +; TODO: there is a slapos recipe to generate certificates. Use it instead +recipe = plone.recipe.command +command = + if [ ! -e $${instance-parameter:key_file} ] + then + ${openssl-output:openssl} req -x509 -nodes -days 3650 \ + -subj "/C=AA/ST=X/L=X/O=Dis/CN=$${instance-parameter:host}" \ + -newkey rsa:1024 -keyout $${instance-parameter:key_file} \ + -out $${instance-parameter:cert_file} + fi +update-command = $${:command} +cert_file = $${directory:etc}/ipython_notebook_cert.crt +key_file = $${directory:etc}/ipython_notebook_cert.key + +[instance] +recipe = slapos.cookbook:wrapper +command-line = + ${buildout:bin-directory}/ipython notebook + --no-browser + --matplotlib=inline + --ip=$${instance-parameter:host} + --port=$${instance-parameter:port} + --port-retries=0 + --certfile=$${instance-parameter:cert_file} + --keyfile=$${instance-parameter:key_file} + --notebook-dir=$${instance-parameter:notebook_dir} + --logfile=$${instance-parameter:logfile} + --config=$${ipython_notebook_config:rendered} +wrapper-path = $${directory:service}/ipython_notebook +parameters-extra = true + +[ipython_notebook_config] +recipe = slapos.recipe.template:jinja2 +template = ${ipython_notebook_config:location}/${ipython_notebook_config:filename} +rendered = $${directory:etc}/ipython_notebook_config.py +mode = 0744 +context = + raw config_cfg $${buildout:directory}/knowledge0.cfg + +[monitor-current-log-access] +< = monitor-directory-access +source = $${instance-parameter:logfile} + +[monitor-deploy-set-password-cgi] +recipe = slapos.recipe.template:jinja2 +template = ${ipython_notebook_set_password:location}/${ipython_notebook_set_password:filename} +rendered = $${monitor-directory:knowledge0-cgi}/$${:filename} +filename = ipython-notebook-password.cgi +mode = 0744 +context = + raw config_cfg $${buildout:directory}/knowledge0.cfg + raw python_executable ${buildout:bin-directory}/ipython + key pwd monitor-directory:knowledge0-cgi + key this_file :filename + key httpd_graceful cgi-httpd-graceful-wrapper:rendered + +[directory] +recipe = slapos.cookbook:mkdirectory +home = $${buildout:directory} +etc = $${:home}/etc +var = $${:home}/var +script = $${:etc}/run/ +service = $${:etc}/service +promise = $${:etc}/promise/ +log = $${:var}/log +notebook_dir = $${:var}/notebooks + +[publish-connection-parameter] +recipe = slapos.cookbook:publish +url = https://[$${instance-parameter:host}]:$${instance-parameter:port} +monitor_url = $${monitor-parameters:url} diff --git a/software/ipython_notebook/software.cfg b/software/ipython_notebook/software.cfg new file mode 100644 index 0000000000..b1adcc092b --- /dev/null +++ b/software/ipython_notebook/software.cfg @@ -0,0 +1,129 @@ +[buildout] +versions = versions +extends = + ../../stack/slapos.cfg + ../../stack/monitor/buildout.cfg + ../../component/ipython/buildout.cfg + ../../component/scipy/buildout.cfg + ../../component/scikit-learn/buildout.cfg + ../../component/pandas/buildout.cfg + ../../component/manpy/buildout.cfg + ../../component/openssl/buildout.cfg +parts = + monitor-eggs + slapos-cookbook + ipython_notebook + ipython_notebook_set_password + instance + +[ipython_notebook] +; In the ipython notebook software, we use more eggs than in the minimal +; ipython notebook component +eggs += + ${scipy:egg} + ${pandas:egg} + ${scikit-learn:egg} + ${manpy:eggs} +initialization += + ${manpy:initialization} + +[ipython_notebook_config] +recipe = hexagonit.recipe.download +url = ${:_profile_base_location_}/template/${:filename} +download-only = true +md5sum = a5bc4ee8539109d1de7ab33b4c2c97ea +destination = ${buildout:parts-directory}/${:_buildout_section_name_} +filename = ipython_notebook_config.jinja +mode = 0644 + +[ipython_notebook_set_password] +recipe = hexagonit.recipe.download +url = ${:_profile_base_location_}/template/${:filename} +download-only = true +md5sum = d7d4a7e19d55bf14007819258bf42100 +destination = ${buildout:parts-directory}/${:_buildout_section_name_} +filename = ipython_set_password.jinja +mode = 0644 + +[instance] +recipe = slapos.recipe.template +url = ${:_profile_base_location_}/instance.cfg +output = ${buildout:directory}/instance.cfg + + + + +[versions] +PyRSS2Gen = 1.1 +Pygments = 2.0.2 +cns.recipe.symlink = 0.2.3 +ipython = 3.1.0 +matplotlib = 1.4.3 +mistune = 0.5.1 +nose = 1.3.6 +pandas = 0.16.0 +plone.recipe.command = 1.1 +pyzmq = 14.6.0 +scikit-learn = 0.16.1 +scipy = 0.15.1 +simpy = 3.0.7 +slapos.recipe.template = 2.6 +terminado = 0.5 +tornado = 4.1 + +# Required by: +# dream==0.0.1 +MySQL-python = 1.2.5 + +# Required by: +# tornado==4.1 +backports.ssl-match-hostname = 3.4.0.2 + +# Required by: +# tornado==4.1 +certifi = 2015.4.28 + +# Required by: +# matplotlib==1.4.3 +mock = 1.0.1 + +# Required by: +# dream==0.0.1 +numpy = 1.9.2 + +# Required by: +# terminado==0.5 +ptyprocess = 0.4 + +# Required by: +# dream==0.0.1 +pydot = 1.0.28 + +# Required by: +# matplotlib==1.4.3 +# pandas==0.16.0 +python-dateutil = 2.4.2 + +# Required by: +# dream==0.0.1 +rpy2 = 2.5.6 + +# Required by: +# rpy2==2.5.6 +singledispatch = 3.4.0.3 + +# Required by: +# dream==0.0.1 +tablib = 0.10.0 + +# Required by: +# dream==0.0.1 +xlrd = 0.9.3 + +# Required by: +# dream==0.0.1 +xlwt = 1.0.0 + +# Required by: +# dream==0.0.1 +zope.dottedname = 4.1.0 \ No newline at end of file diff --git a/software/ipython_notebook/template/ipython_notebook_config.jinja b/software/ipython_notebook/template/ipython_notebook_config.jinja new file mode 100644 index 0000000000..aafdb10161 --- /dev/null +++ b/software/ipython_notebook/template/ipython_notebook_config.jinja @@ -0,0 +1,13 @@ + +import ConfigParser + +knowledge_0 = '{{ config_cfg }}' + +c = get_config() + +parser = ConfigParser.ConfigParser() +parser.read(knowledge_0) + +if parser.has_option("ipython_notebook", "password"): + c.NotebookApp.password = parser.get("ipython_notebook", "password") + diff --git a/software/ipython_notebook/template/ipython_set_password.jinja b/software/ipython_notebook/template/ipython_set_password.jinja new file mode 100644 index 0000000000..18d6490206 --- /dev/null +++ b/software/ipython_notebook/template/ipython_set_password.jinja @@ -0,0 +1,64 @@ +#!{{ python_executable }} + +import cgi +import cgitb +import ConfigParser +import os +import re +import subprocess + +from IPython.lib import passwd + +#cgitb.enable(display=0, logdir="/tmp/cgi.log") +cgitb.enable() +form = cgi.FieldStorage() + +config_file = "{{ config_cfg }}" + + +if not os.path.exists(config_file): + print "Your software does <b>not</b> embed 0-knowledge. \ + This interface is useless in this case</body></html>" + exit(0) + + +parser = ConfigParser.ConfigParser() +parser.read(config_file) +if not parser.has_section("ipython_notebook"): + parser.add_section("ipython_notebook") + +if not parser.has_option("ipython_notebook", "password"): + parser.set("ipython_notebook", "password", "") + +if "password" in form: + parser.set("ipython_notebook", "password", passwd(form["password"].value)) + # subprocess.call('{{ httpd_graceful }}') + # TODO: we should restart ipython + +with open(config_file, 'w') as file: + parser.write(file) + +# TODO cleanup +print "<html><head>" +print "<link rel=\"stylesheet\" href=\"static/pure-min.css\">" +print "<link rel=\"stylesheet\" href=\"static/style.css\">" +print "</head><body>" +print "<h1>IPython Notebook Password :</h1>" +print "<form action=\"/index.cgi\" method=\"post\" class=\"pure-form-aligned\">" +print "<input type=\"hidden\" name=\"posting-script\" value=\"{{ pwd }}/{{ this_file }}\">" + +print """<div class="pure-control-group"> +<label for="password">Password*:</label> +<input placeholder="Set your password" type="password" name="password" id="password"></br> +</div><div class="pure-control-group"> +<label for="password">Verify Password*:</label> +<input placeholder="Verify password" type="password" name="password_2" id="password_2"></br> +</div><p id="validate-status" style="color:red"></p> +<div class="pure-controls"> +<button id="register-button" type="submit" class="pure-button pure-button-primary" disabled>Access</button></div> +</form> +<script type="text/javascript" src="static/jquery-1.10.2.min.js"></script> +<script type="text/javascript" src="static/monitor-register.js"></script> +</body></html> +""" + -- 2.30.9