Commit ecd07550 authored by Sabino Papagna's avatar Sabino Papagna

restore original web folder

parent cc24d582
# Copyright (c) 2015, Daniele Venzano
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Flask initialization for the web interface."""
from typing import List
import tornado.web
import zoe_api.web.start
import zoe_api.web.executions
from zoe_lib.version import ZOE_API_VERSION, ZOE_VERSION
def web_init(api_endpoint) -> List[tornado.web.URLSpec]:
"""Flask init for the web interface."""
# def before_request():
# """Use the Flask global to hold the api endpoint reference."""
# g.api_endpoint = api_endpoint
# web_bp = Blueprint('web', __name__, template_folder='templates', static_folder='static')
route_args = {
'api_endpoint': api_endpoint
}
web_routes = [
tornado.web.url(r'/', zoe_api.web.start.RootWeb, route_args, name='root'),
tornado.web.url(r'/user', zoe_api.web.start.HomeWeb, route_args, name='home_user'),
tornado.web.url(r'/executions/new', zoe_api.web.executions.ExecutionDefineWeb, route_args, name='execution_define'),
tornado.web.url(r'/executions/start', zoe_api.web.executions.ExecutionStartWeb, route_args, name='execution_start'),
tornado.web.url(r'/executions/restart/([0-9]+)', zoe_api.web.executions.ExecutionRestartWeb, route_args, name='execution_restart'),
tornado.web.url(r'/executions/terminate/([0-9]+)', zoe_api.web.executions.ExecutionTerminateWeb, route_args, name='execution_terminate'),
tornado.web.url(r'/executions/delete/([0-9]+)', zoe_api.web.executions.ExecutionDeleteWeb, route_args, name='execution_delete'),
tornado.web.url(r'/executions/inspect/([0-9]+)', zoe_api.web.executions.ExecutionInspectWeb, route_args, name='execution_inspect')
]
return web_routes
def inject_version():
"""Inject some template variables in all templates."""
return {
'zoe_version': ZOE_VERSION,
'zoe_api_version': ZOE_API_VERSION,
}
# Copyright (c) 2014 thkang2
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""Jinja2 templating for Tornado, taken from https://github.com/thkang2/jinja_tornado"""
import json
import datetime
from jinja2 import Environment, FileSystemLoader, Markup
from tornado.escape import squeeze, linkify, url_escape, xhtml_escape
import tornado.web
import zoe_lib.version
import zoe_api.web.utils
class JinjaApp(object):
"""A Jinja2-capable Tornado application."""
def __init__(self, application, jinja_options=None):
self.application = application
self.jinja_options = jinja_options
self.init_app(application, jinja_options)
@classmethod
def init_app(cls, application, jinja_options=None):
"""Init the application."""
app_settings = application.settings
_loader = FileSystemLoader(
app_settings.get('template_path', 'templates')
)
_jinja_config = {
'extensions': ['jinja2.ext.autoescape', 'jinja2.ext.with_'],
'auto_reload': app_settings.get('autoreload', False),
'loader': _loader,
'cache_size': 50 if app_settings.get('compiled_template_cache', True) else 0,
'autoescape': True if app_settings.get('autoescape', 'xhtml_escape') == "xhtml_escape" else False,
}
_jinja_config.update(**(jinja_options or {}))
environment = Environment(**_jinja_config)
application.jinja_environment = environment
app_settings['jinja_environment'] = environment
environment.filters.update(tojson=tojson_filter, xhtml_escape=xhtml_escape, url_escape=url_escape, squeeze=squeeze, linkify=linkify)
return environment
def dumps(obj, **kwargs):
"""Escape characters."""
# https://github.com/mitsuhiko/flask/blob/master/flask/json.py
return json.dumps(obj, **kwargs) \
.replace(u'<', u'\\u003c') \
.replace(u'>', u'\\u003e') \
.replace(u'&', u'\\u0026') \
.replace(u"'", u'\\u0027')
def tojson_filter(obj, **kwargs):
"""Filter for JSON output in templates."""
# https://github.com/mitsuhiko/flask/blob/master/flask/json.py
return Markup(dumps(obj, **kwargs))
class ZoeRequestHandler(tornado.web.RequestHandler):
"""usage:
class JinjaPoweredHandler(JinjaTemplateMixin, tornado.web.RequestHandler):
pass
"""
def initialize(self, *args_, **kwargs_):
"""Initialize the Jinja template system."""
# jinja environment is shared among an application
if 'jinja_environment' not in self.application.settings:
raise RuntimeError("Needs jinja2 Environment. Initialize with JinjaApp.init_app first")
else:
self._jinja_env = self.application.settings['jinja_environment']
def _render(self, template, **kwargs):
""" todo: support multiple template preprocessors """
ctx = {
'request': self.request,
'path_args': self.path_args,
'path_kwargs': self.path_kwargs,
'settings': self.application.settings,
'reverse_url': self.application.reverse_url,
'static_url': self.static_url,
'xsrf_form_html': self.xsrf_form_html,
'datetime': datetime,
'locale': self.locale,
'handler': self,
'zoe_version': zoe_lib.version.ZOE_VERSION
}
ctx.update(kwargs)
return template.render(ctx)
def render(self, template_name, **kwargs):
""" renders a template file. """
template = self._jinja_env.get_template(template_name)
try:
html = self._render(template, **kwargs)
except Exception:
zoe_api.web.utils.error_page(self, 'Jinja2 template exception', 500)
return
self.finish(html)
def render_string(self, source, **kwargs):
""" renders a template source string. """
template = self._jinja_env.from_string(source)
return self._render(template, **kwargs)
def data_received(self, chunk):
"""Not implemented as we do not use stream uploads"""
pass
# Copyright (c) 2015, Daniele Venzano
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Web pages and functions related to executions."""
import json
import zoe_api.exceptions
from zoe_api.web.utils import get_auth, catch_exceptions
from zoe_api.api_endpoint import APIEndpoint # pylint: disable=unused-import
from zoe_api.web.custom_request_handler import ZoeRequestHandler
class ExecutionDefineWeb(ZoeRequestHandler):
"""Handler class"""
def initialize(self, **kwargs):
"""Initializes the request handler."""
super().initialize(**kwargs)
self.api_endpoint = kwargs['api_endpoint'] # type: APIEndpoint
@catch_exceptions
def get(self):
"""Define a new execution."""
get_auth(self)
self.render('execution_new.html')
class ExecutionStartWeb(ZoeRequestHandler):
"""Handler class"""
def initialize(self, **kwargs):
"""Initializes the request handler."""
super().initialize(**kwargs)
self.api_endpoint = kwargs['api_endpoint'] # type: APIEndpoint
@catch_exceptions
def post(self):
"""Start an execution."""
uid, role = get_auth(self)
app_descr_json = self.request.files['file'][0]['body'].decode('utf-8')
app_descr = json.loads(app_descr_json)
exec_name = self.get_argument('exec_name')
new_id = self.api_endpoint.execution_start(uid, role, exec_name, app_descr)
self.redirect(self.reverse_url('execution_inspect', new_id))
class ExecutionRestartWeb(ZoeRequestHandler):
"""Handler class"""
def initialize(self, **kwargs):
"""Initializes the request handler."""
super().initialize(**kwargs)
self.api_endpoint = kwargs['api_endpoint'] # type: APIEndpoint
@catch_exceptions
def get(self, execution_id: int):
"""Restart an already defined (and not running) execution."""
uid, role = get_auth(self)
e = self.api_endpoint.execution_by_id(uid, role, execution_id)
new_id = self.api_endpoint.execution_start(uid, role, e.name, e.description)
self.redirect(self.reverse_url('execution_inspect', new_id))
class ExecutionTerminateWeb(ZoeRequestHandler):
"""Handler class"""
def initialize(self, **kwargs):
"""Initializes the request handler."""
super().initialize(**kwargs)
self.api_endpoint = kwargs['api_endpoint'] # type: APIEndpoint
@catch_exceptions
def get(self, execution_id: int):
"""Terminate an execution."""
uid, role = get_auth(self)
success, message = self.api_endpoint.execution_terminate(uid, role, execution_id)
if not success:
raise zoe_api.exceptions.ZoeException(message)
self.redirect(self.reverse_url('home_user'))
class ExecutionDeleteWeb(ZoeRequestHandler):
"""Handler class"""
def initialize(self, **kwargs):
"""Initializes the request handler."""
super().initialize(**kwargs)
self.api_endpoint = kwargs['api_endpoint'] # type: APIEndpoint
@catch_exceptions
def get(self, execution_id: int):
"""Delete an execution."""
uid, role = get_auth(self)
success, message = self.api_endpoint.execution_delete(uid, role, execution_id)
if not success:
raise zoe_api.exceptions.ZoeException(message)
self.redirect(self.reverse_url('home_user'))
class ExecutionInspectWeb(ZoeRequestHandler):
"""Handler class"""
def initialize(self, **kwargs):
"""Initializes the request handler."""
super().initialize(**kwargs)
self.api_endpoint = kwargs['api_endpoint'] # type: APIEndpoint
@catch_exceptions
def get(self, execution_id):
"""Gather details about an execution."""
uid, role = get_auth(self)
e = self.api_endpoint.execution_by_id(uid, role, execution_id)
services_info = []
for service in e.services:
services_info.append(self.api_endpoint.service_by_id(uid, role, service.id))
template_vars = {
"e": e,
"services_info": services_info
}
self.render('execution_inspect.html', **template_vars)
# Copyright (c) 2016, Daniele Venzano
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Main points of entry for the Zoe web interface."""
from random import randint
import json
from zoe_api.api_endpoint import APIEndpoint # pylint: disable=unused-import
from zoe_api.web.utils import get_auth, catch_exceptions
from zoe_api.web.custom_request_handler import ZoeRequestHandler
class RootWeb(ZoeRequestHandler):
"""Handler class"""
def initialize(self, **kwargs):
"""Initializes the request handler."""
super().initialize(**kwargs)
self.api_endpoint = kwargs['api_endpoint'] # type: APIEndpoint
@catch_exceptions
def get(self):
"""Home page without authentication."""
self.render('index.html')
class HomeWeb(ZoeRequestHandler):
"""Handler class"""
def initialize(self, **kwargs):
"""Initializes the request handler."""
super().initialize(**kwargs)
self.api_endpoint = kwargs['api_endpoint'] # type: APIEndpoint
@catch_exceptions
def get(self):
"""Home page with authentication."""
uid, role = get_auth(self)
if role == 'user' or role == 'admin':
executions = self.api_endpoint.execution_list(uid, role)
template_vars = {
'executions': sorted(executions, key=lambda e: e.id),
'is_admin': role == 'admin',
}
self.render('home_user.html', **template_vars)
else:
template_vars = {
'refresh': randint(2, 8),
'execution_status': 'Please wait...',
'execution_urls': [],
}
app_descr = json.load(open('contrib/zoeapps/eurecom_aml_lab.json', 'r'))
execution = self.api_endpoint.execution_list(uid, role, name='aml-lab')
if len(execution) == 0 or execution[0]['status'] == 'terminated' or execution[0]['status'] == 'finished':
self.api_endpoint.execution_start(uid, role, 'aml-lab', app_descr)
template_vars['execution_status'] = 'submitted'
return self.render('home_guest.html', **template_vars)
else:
execution = execution[0]
if execution['status'] != 'running':
template_vars['execution_status'] = execution['status']
return self.render('home_guest.html', **template_vars)
else:
template_vars['refresh'] = -1
template_vars['execution_status'] = execution['status']
# for c_id in execution['services']:
# c = cont_api.get(c_id)
# ip = list(c['ip_address'].values())[0] # FIXME how to decide which network is the right one?
# for p in c['ports']:
# template_vars['execution_urls'].append(('{}'.format(p['name']), '{}://{}:{}{}'.format(p['protocol'], ip, p['port_number'], p['path'])))
return self.render('home_guest.html', **template_vars)
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
body {
font-family: sans-serif;
max-width: 90%;
margin-left: 20px;
}
a:link {
color: rgba(79, 140, 30, 1);
text-decoration: none;
}
a:visited {
color: rgba(79, 140, 30, 1);
text-decoration: none;
}
div.user_info {
font-size: smaller;
clear: both;
padding-top: 20px;
}
table.app_list {
border-collapse: collapse;
}
table.app_list tr {
border-top: 1px black solid;
}
table.app_list td {
padding-right: 1.5em;
}
div.status_line {
float: left;
}
span#app_name {
font-family: cursive;
font-size: larger;
}
span#status {
font-size: smaller;
}
div.copyright {
float: left;
padding-left: 3em;
}
textarea#log {
width: 90%;
height: 40em;
}
span.fakelink {
color: rgba(79, 140, 30, 1);
text-decoration: none;
cursor: pointer;
}
#wrapper {
width: 800px;
}
#navigation {
background-color: #fff;
border: #ddd 1px solid;
border-radius: 10px;
margin: 10px;
padding: 10px;
}
#navigation li {
margin: 2px 0;
}
label.error {
color: #ff0000;
margin-left: 10px;
position: relative;
}
.wizard {
background-color: #fff;
border: #ddd 1px solid;
border-radius: 10px;
margin: 10px;
padding: 10px;
}
.wizard .wizard-header {
background-color: #f4f4f4;
border-bottom: #ddd 1px solid;
border-top-left-radius: 10px;
border-top-right-radius: 10px;
padding: 5px 10px;
margin: 0 0 10px 0;
}
.wizard .wizard-step {
margin: 10px 0;
}
.wizard .wizard-step p {
padding: 5px;
}
.navigation {
border-top: #ddd 1px solid;
margin-top: 10px;
padding-top: 10px;
}
.navigation ul {
margin: 0;
padding: 0;
list-style: none;
}
.navigation li {
float: left;
margin-right: 10px;
}
.clearfix:before, .clearfix:after {
content: "\0020";
display: block;
height: 0;
visibility: hidden;
}
.clearfix:after {
clear: both;
}
input {
margin-top: 5px;
}
section {
padding-bottom: 10px;
}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
{% block head %}
<meta charset="UTF-8">
<title>{% block title %}{% endblock %} - Zoe</title>
<script src="/static/jquery-2.1.4.min.js" type="application/javascript"></script>
<script src="/static/jquery-ui-1.11.4/jquery-ui.min.js" type="application/javascript"></script>
<script src="/static/jquery.wizard.js" type="application/javascript"></script>
<script src="/static/jquery.validate.min.js" type="application/javascript"></script>
<script src="/static/sorttable.js" type="application/javascript"></script>
<script src="/static/moment.min.js" type="application/javascript"></script>
<link rel="stylesheet" href="/static/zoe.css" type="text/css">
<link rel="stylesheet" href="/static/jquery-ui-1.11.4/jquery-ui.min.css">
{% endblock %}
{% block custom_head %}
{% endblock %}
</head>
<body>
<script>
/* function update_status() {
$.getJSON("")
.done(function( data ) {
$("#num_nodes").text(data.num_nodes);
$("#num_containers").text(data.num_containers);
}).error(function( data ) {
$("#num_nodes").text("N/A");
$("#num_containers").text("N/A");
});
}
update_status();
window.setInterval(update_status, 5000);
*/
moment.locale(window.navigator.userLanguage || window.navigator.language);
function format_timestamp(ts) {
document.write(moment(ts).calendar())
}
function format_bytes(bytes, decimals) {
if(bytes == 0) {
document.write('0 Byte');
return;
}
var k = 1000;
var dm = decimals + 1 || 3;
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
var i = Math.floor(Math.log(bytes) / Math.log(k));
document.write((bytes / Math.pow(k, i)).toPrecision(dm) + ' ' + sizes[i]);
}
</script>
<h1>Zoe - Analytics on demand</h1>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
<div class="status_line">
<p>
<span id="app_name"><a href="http://zoe-analytics.eu">Zoe</a> v. {{ zoe_version }}</span>
<!-- <span id="status">
[<span id="num_nodes">N/A</span> swarm nodes, <span id="num_containers">N/A</span> active containers]
</span> -->
<span>
&mdash;Submit issues and ideas for improvement at <a href="https://github.com/DistributedSystemsGroup/zoe/issues">Zoe's issue tracker</a>.
</span>
</p>
</div>
<div class="copyright">
<h6>&copy; Copyright 2016 by <a href="http://distsysgroup.wordpress.com/">DSG</a></h6>
</div>
{% endblock %}
</div>
</body>
</html>
{% extends "base.html" %}
{% block footer %}
<p><a href="{{ reverse_url("home_user") }}">Home</a></p>
{{ super() }}
{% endblock %}
{% extends "base.html" %}
{% block title %}Error{% endblock %}
{% block content %}
<h1 style="color: red">Error!</h1>
<p>{{ error }}</p>