Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
zoe
main
Commits
04ac52e9
Commit
04ac52e9
authored
Jun 16, 2016
by
Daniele Venzano
Browse files
Modify existing pages for the new internal organization (templates are not yet revised)
parent
6501c61e
Changes
8
Hide whitespace changes
Inline
Side-by-side
zoe_web/__init__.py
View file @
04ac52e9
# 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.
from
flask
import
Flask
from
zoe_web.web
import
web_bp
app
=
Flask
(
__name__
,
static_url_path
=
'/does-not-exist'
)
app
.
register_blueprint
(
web_bp
,
url_prefix
=
''
)
zoe_web/config.py
View file @
04ac52e9
...
...
@@ -15,6 +15,8 @@
from
zoe_lib.configargparse
import
ArgumentParser
,
Namespace
api_endpoint
=
None
# singleton
config_paths
=
[
'zoe-web.conf'
,
'/etc/zoe/zoe-web.conf'
...
...
@@ -33,8 +35,23 @@ def load_configuration():
argparser
.
add_argument
(
'--debug'
,
action
=
'store_true'
,
help
=
'Enable debug output'
)
argparser
.
add_argument
(
'--listen-address'
,
type
=
str
,
help
=
'Address to listen to for incoming connections'
,
default
=
"0.0.0.0"
)
argparser
.
add_argument
(
'--listen-port'
,
type
=
int
,
help
=
'Port to listen to for incoming connections'
,
default
=
5001
)
argparser
.
add_argument
(
'--master-url'
,
help
=
'URL of the Zoe master process'
,
default
=
'http://127.0.0.1:4850'
)
argparser
.
add_argument
(
'--cookie-secret'
,
help
=
'key used to encrypt cookies'
,
default
=
"hr4h3H'kmn F8fz/;CJN5a!"
)
argparser
.
add_argument
(
'--master-url'
,
help
=
'URL of the Zoe master process'
,
default
=
'tcp://127.0.0.1:4850'
)
argparser
.
add_argument
(
'--deployment-name'
,
help
=
'name of this Zoe deployment'
,
default
=
'prod'
)
# argparser.add_argument('--cookie-secret', help='key used to encrypt cookies', default="hr4h3H'kmn F8fz/;CJN5a!")
argparser
.
add_argument
(
'--ldap-server-uri'
,
help
=
'LDAP server to use for authentication'
,
default
=
'ldap://localhost'
)
argparser
.
add_argument
(
'--ldap-base-dn'
,
help
=
'LDAP base DN for users'
,
default
=
'ou=something,dc=any,dc=local'
)
argparser
.
add_argument
(
'--ldap-bind-user'
,
help
=
'LDAP user to bind as for user lookup'
,
default
=
'cn=guest,dc=bigfoot,dc=eurecom,dc=fr'
)
argparser
.
add_argument
(
'--ldap-bind-password'
,
help
=
'LDAP user password'
,
default
=
'notsosecret'
)
argparser
.
add_argument
(
'--ldap-admin-gid'
,
type
=
int
,
help
=
'LDAP group ID for admins'
,
default
=
5000
)
argparser
.
add_argument
(
'--ldap-user-gid'
,
type
=
int
,
help
=
'LDAP group ID for users'
,
default
=
5001
)
argparser
.
add_argument
(
'--ldap-guest-gid'
,
type
=
int
,
help
=
'LDAP group ID for guests'
,
default
=
5002
)
argparser
.
add_argument
(
'--dbname'
,
help
=
'DB name'
,
default
=
'zoe'
)
argparser
.
add_argument
(
'--dbuser'
,
help
=
'DB user'
,
default
=
'zoe'
)
argparser
.
add_argument
(
'--dbpass'
,
help
=
'DB password'
,
default
=
'zoe'
)
argparser
.
add_argument
(
'--dbhost'
,
help
=
'DB hostname'
,
default
=
'localhost'
)
argparser
.
add_argument
(
'--dbport'
,
type
=
int
,
help
=
'DB port'
,
default
=
5432
)
opts
=
argparser
.
parse_args
()
if
opts
.
debug
:
...
...
zoe_web/entrypoint.py
View file @
04ac52e9
# Copyright (c) 201
5
, Daniele Venzano
# Copyright (c) 201
6
, Daniele Venzano
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
...
...
@@ -15,12 +15,16 @@
import
logging
from
flask
import
Flask
from
tornado.wsgi
import
WSGIContainer
from
tornado.httpserver
import
HTTPServer
from
tornado.ioloop
import
IOLoop
from
zoe_web
import
app
from
zoe_web.config
import
load_configuration
,
get_conf
import
zoe_web.config
as
config
import
zoe_web.db_init
import
zoe_web.api_endpoint
import
zoe_web.rest_api
import
zoe_web.web
log
=
logging
.
getLogger
(
"zoe_web"
)
LOG_FORMAT
=
'%(asctime)-15s %(levelname)s %(name)s (%(threadName)s): %(message)s'
...
...
@@ -31,8 +35,8 @@ def zoe_web_main() -> int:
This is the entry point for the Zoe Web script.
:return: int
"""
load_configuration
()
args
=
get_conf
()
config
.
load_configuration
()
args
=
config
.
get_conf
()
if
args
.
debug
:
logging
.
basicConfig
(
level
=
logging
.
DEBUG
,
format
=
LOG_FORMAT
)
else
:
...
...
@@ -41,8 +45,15 @@ def zoe_web_main() -> int:
logging
.
getLogger
(
"tornado"
).
setLevel
(
logging
.
DEBUG
)
log
.
info
(
"Starting HTTP server..."
)
app
=
Flask
(
__name__
,
static_url_path
=
'/does-not-exist'
)
app
.
config
[
'MAX_CONTENT_LENGTH'
]
=
16
*
1024
*
1024
app
.
secret_key
=
args
.
cookie_secret
app
.
register_blueprint
(
zoe_web
.
rest_api
.
api_init
())
app
.
register_blueprint
(
zoe_web
.
web
.
web_init
())
zoe_web
.
db_init
.
init
()
config
.
api_endpoint
=
zoe_web
.
api_endpoint
.
APIEndpoint
()
http_server
=
HTTPServer
(
WSGIContainer
(
app
))
http_server
.
listen
(
args
.
listen_port
,
args
.
listen_address
)
...
...
zoe_web/exceptions.py
0 → 100644
View file @
04ac52e9
# 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.
class
ZoeException
(
Exception
):
"""
A generic exception.
"""
def
__init__
(
self
,
message
=
'Something happened'
):
self
.
message
=
message
def
__str__
(
self
):
return
self
.
message
class
ZoeAuthException
(
ZoeException
):
pass
class
ZoeNotFoundException
(
ZoeException
):
pass
class
ZoeRestAPIException
(
ZoeException
):
"""
An exception generated by the REST API.
"""
def
__init__
(
self
,
message
,
status_code
=
400
,
headers
=
None
):
super
().
__init__
(
message
)
self
.
status_code
=
status_code
self
.
headers
=
headers
def
__str__
(
self
):
return
'[{}] {}'
.
format
(
self
.
status_code
,
self
.
message
)
zoe_web/web/__init__.py
View file @
04ac52e9
...
...
@@ -14,16 +14,29 @@
# limitations under the License.
from
flask
import
Blueprint
web_bp
=
Blueprint
(
'web'
,
__name__
,
template_folder
=
'templates'
,
static_folder
=
'static'
)
import
zoe_web.web.start
import
zoe_web.web.executions
from
zoe_lib.version
import
ZOE_API_VERSION
,
ZOE_VERSION
@
web_bp
.
context_processor
def
web_init
()
->
Blueprint
:
web_bp
=
Blueprint
(
'web'
,
__name__
,
template_folder
=
'templates'
,
static_folder
=
'static'
)
web_bp
.
context_processor
(
inject_version
)
web_bp
.
add_url_rule
(
'/'
,
'index'
,
zoe_web
.
web
.
start
.
index
)
web_bp
.
add_url_rule
(
'/user'
,
'home_user'
,
zoe_web
.
web
.
start
.
home_user
)
web_bp
.
add_url_rule
(
'/executions/new'
,
'execution_define'
,
zoe_web
.
web
.
executions
.
execution_define
)
web_bp
.
add_url_rule
(
'/executions/start'
,
'execution_start'
,
zoe_web
.
web
.
executions
.
execution_start
,
methods
=
[
'POST'
])
web_bp
.
add_url_rule
(
'/executions/restart/<int:execution_id>'
,
'execution_restart'
,
zoe_web
.
web
.
executions
.
execution_restart
)
web_bp
.
add_url_rule
(
'/executions/terminate/<int:execution_id>'
,
'execution_terminate'
,
zoe_web
.
web
.
executions
.
execution_terminate
)
web_bp
.
add_url_rule
(
'/executions/inspect/<int:execution_id>'
,
'execution_inspect'
,
zoe_web
.
web
.
executions
.
execution_inspect
)
return
web_bp
def
inject_version
():
return
{
'zoe_version'
:
ZOE_VERSION
,
...
...
zoe_web/web/executions.py
View file @
04ac52e9
...
...
@@ -14,106 +14,65 @@
# limitations under the License.
import
json
import
re
from
flask
import
render_template
,
request
,
redirect
,
url_for
from
zoe_
lib.services
import
ZoeServiceAPI
from
zoe_lib.executions
import
ZoeExecutionsAPI
import
zoe_
lib.exceptions
import
zoe_
lib.applica
tions
from
zoe_
web.web.utils
import
get_auth
,
catch_exceptions
import
zoe_web.config
as
config
import
zoe_
web.api_endpoint
import
zoe_
web.excep
tions
from
zoe_web.config
import
get_conf
from
zoe_web.web
import
web_bp
from
zoe_web.web.auth
import
missing_auth
def
error_page
(
error_message
,
status
):
return
render_template
(
'error.html'
,
error
=
error_message
),
status
@
web_bp
.
route
(
'/executions/new'
)
@
catch_exceptions
def
execution_define
():
auth
=
request
.
authorization
if
not
auth
:
return
missing_auth
()
get_auth
(
request
)
return
render_template
(
'execution_new.html'
)
@
web_bp
.
route
(
'/executions/start'
,
methods
=
[
'POST'
])
@
catch_exceptions
def
execution_start
():
auth
=
request
.
authorization
if
not
auth
:
return
missing_auth
()
guest_identifier
=
auth
.
username
guest_password
=
auth
.
password
app_descr_json
=
request
.
files
[
'file'
].
read
()
app_descr
=
json
.
loads
(
app_descr_json
.
decode
(
'utf-8'
))
try
:
zoe_lib
.
applications
.
app_validate
(
app_descr
)
except
zoe_lib
.
exceptions
.
InvalidApplicationDescription
as
e
:
return
error_page
(
e
.
message
,
400
)
uid
,
role
=
get_auth
(
request
)
assert
isinstance
(
config
.
api_endpoint
,
zoe_web
.
api_endpoint
.
APIEndpoint
)
app_descr_json
=
request
.
files
[
'file'
].
read
().
decode
(
'utf-8'
)
app_descr
=
json
.
loads
(
app_descr_json
)
exec_name
=
request
.
form
[
'exec_name'
]
if
3
>
len
(
exec_name
)
>
128
:
return
error_page
(
"Execution name must be between 4 and 128 characters long"
,
400
)
if
not
re
.
match
(
r
'^[a-zA-Z0-9\-]+$'
,
exec_name
):
return
error_page
(
"Execution name can contain only letters, numbers and dashes. '{}' is not valid."
.
format
(
exec_name
))
exec_api
=
ZoeExecutionsAPI
(
get_conf
().
master_url
,
guest_identifier
,
guest_password
)
new_id
=
exec_api
.
execution_start
(
exec_name
,
app_descr
)
new_id
=
config
.
api_endpoint
.
execution_start
(
uid
,
role
,
exec_name
,
app_descr
)
return
redirect
(
url_for
(
'web.execution_inspect'
,
execution_id
=
new_id
))
@
web_bp
.
route
(
'/executions/restart/<int:execution_id>'
)
@
catch_exceptions
def
execution_restart
(
execution_id
):
auth
=
request
.
authorization
if
not
auth
:
return
missing_auth
()
uid
,
role
=
get_auth
(
request
)
assert
isinstance
(
config
.
api_endpoint
,
zoe_web
.
api_endpoint
.
APIEndpoint
)
guest_identifier
=
auth
.
username
guest_password
=
auth
.
password
exec_api
=
ZoeExecutionsAPI
(
get_conf
().
master_url
,
guest_identifier
,
guest_password
)
e
=
exec_api
.
execution_get
(
execution_id
)
new_id
=
exec_api
.
execution_start
(
e
[
'name'
],
e
[
'application'
])
e
=
config
.
api_endpoint
.
execution_by_id
(
uid
,
role
,
execution_id
)
new_id
=
config
.
api_endpoint
.
execution_start
(
uid
,
role
,
e
.
name
,
e
.
description
)
return
redirect
(
url_for
(
'web.execution_inspect'
,
execution_id
=
new_id
))
@
web_bp
.
route
(
'/executions/terminate/<int:execution_id>'
)
@
catch_exceptions
def
execution_terminate
(
execution_id
):
auth
=
request
.
authorization
if
not
auth
:
return
missing_auth
()
guest_identifier
=
auth
.
username
guest_password
=
auth
.
password
uid
,
role
=
get_auth
(
request
)
assert
isinstance
(
config
.
api_endpoint
,
zoe_web
.
api_endpoint
.
APIEndpoint
)
exec_api
=
ZoeExecutionsAPI
(
get_conf
().
master_url
,
guest_identifier
,
guest_passwor
d
)
e
=
exec_api
.
execution_get
(
execution_id
)
exec_api
.
terminate
(
execution_id
)
success
,
message
=
config
.
api_endpoint
.
execution_terminate
(
uid
,
role
,
execution_i
d
)
if
not
success
:
raise
zoe_web
.
exceptions
.
ZoeException
(
message
)
return
redirect
(
url_for
(
'web.home_user'
))
@
web_bp
.
route
(
'/executions/inspect/<int:execution_id>'
)
@
catch_exceptions
def
execution_inspect
(
execution_id
):
auth
=
request
.
authorization
if
not
auth
:
return
missing_auth
()
guest_identifier
=
auth
.
username
guest_password
=
auth
.
password
exec_api
=
ZoeExecutionsAPI
(
get_conf
().
master_url
,
guest_identifier
,
guest_password
)
cont_api
=
ZoeServiceAPI
(
get_conf
().
master_url
,
guest_identifier
,
guest_password
)
uid
,
role
=
get_auth
(
request
)
assert
isinstance
(
config
.
api_endpoint
,
zoe_web
.
api_endpoint
.
APIEndpoint
)
e
=
exec_api
.
execution_get
(
execution_id
)
e
=
config
.
api_endpoint
.
execution_by_id
(
uid
,
role
,
execution_id
)
services
=
[]
for
sid
in
e
[
'services'
]:
...
...
zoe_web/web/start.py
View file @
04ac52e9
...
...
@@ -19,61 +19,43 @@ import json
from
flask
import
render_template
,
request
from
zoe_lib.services
import
ZoeServiceAPI
from
zoe_lib.executions
import
ZoeExecutionsAPI
from
zoe_lib.query
import
ZoeQueryAPI
from
zoe_lib.users
import
ZoeUserAPI
from
zoe_lib.exceptions
import
ZoeAPIException
from
zoe_web.config
import
get_
conf
from
zoe_web.
web
import
web_bp
from
zoe_web.web.
a
ut
h
import
missing_auth
import
zoe_web.config
as
conf
ig
import
zoe_web.
api_endpoint
from
zoe_web.web.ut
ils
import
get_auth
,
catch_exceptions
guest_id_pattern
=
re
.
compile
(
'^\w+$'
)
@
web_bp
.
route
(
'/'
,
methods
=
[
'GET'
,
'POST'
])
@
catch_exceptions
def
index
():
return
render_template
(
'index.html'
)
@
web_bp
.
route
(
'/guest'
)
def
home_guest
():
auth
=
request
.
authorization
if
not
auth
:
return
missing_auth
()
guest_identifier
=
auth
.
username
guest_password
=
auth
.
password
match
=
guest_id_pattern
.
match
(
guest_identifier
)
if
match
is
None
:
return
missing_auth
()
query_api
=
ZoeQueryAPI
(
get_conf
().
master_url
,
guest_identifier
,
guest_password
)
user_api
=
ZoeUserAPI
(
get_conf
().
master_url
,
guest_identifier
,
guest_password
)
@
catch_exceptions
def
home_user
():
uid
,
role
=
get_auth
(
request
)
assert
isinstance
(
config
.
api_endpoint
,
zoe_web
.
api_endpoint
.
APIEndpoint
)
template_vars
=
{
'refresh'
:
randint
(
2
,
8
),
'user_gateway'
:
'Please wait...'
,
'execution_status'
:
'Please wait...'
,
'execution_urls'
:
[],
'guest_identifier'
:
guest_identifier
}
if
role
==
'user'
or
role
==
'admin'
:
executions
=
config
.
api_endpoint
.
execution_list
(
uid
,
role
)
try
:
user
=
user_api
.
get
(
guest_identifier
)
except
ZoeAPIException
:
return
missing_auth
()
if
user
is
None
:
return
missing_auth
()
template_vars
=
{
'executions'
:
executions
,
'is_admin'
:
role
==
'admin'
,
}
return
render_template
(
'home_user.html'
,
**
template_vars
)
else
:
template_vars
[
'user_gateway'
]
=
user
[
'gateway_urls'
][
0
]
template_vars
[
'gateway_ip'
]
=
user
[
'gateway_urls'
][
0
].
split
(
'/'
)[
2
].
split
(
':'
)[
0
]
exec_api
=
ZoeExecutionsAPI
(
get_conf
().
master_url
,
guest_identifier
,
guest_password
)
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
=
query_api
.
query
(
'execution'
,
name
=
'aml-lab'
)
execution
=
config
.
api_endpoint
.
execution_list
(
uid
,
role
,
name
=
'aml-lab'
)
if
len
(
execution
)
==
0
or
execution
[
0
][
'status'
]
==
'terminated'
or
execution
[
0
][
'status'
]
==
'finished'
:
exec_api
.
execution_start
(
'aml-lab'
,
app_descr
)
config
.
api_endpoint
.
execution_start
(
uid
,
role
,
'aml-lab'
,
app_descr
)
template_vars
[
'execution_status'
]
=
'submitted'
return
render_template
(
'home_guest.html'
,
**
template_vars
)
else
:
...
...
@@ -91,35 +73,3 @@ def home_guest():
for
p
in
c
[
'ports'
]:
template_vars
[
'execution_urls'
].
append
((
'{}'
.
format
(
p
[
'name'
]),
'{}://{}:{}{}'
.
format
(
p
[
'protocol'
],
ip
,
p
[
'port_number'
],
p
[
'path'
])))
return
render_template
(
'home_guest.html'
,
**
template_vars
)
@
web_bp
.
route
(
'/user'
)
def
home_user
():
auth
=
request
.
authorization
if
not
auth
:
return
missing_auth
()
guest_identifier
=
auth
.
username
guest_password
=
auth
.
password
query_api
=
ZoeQueryAPI
(
get_conf
().
master_url
,
guest_identifier
,
guest_password
)
try
:
user
=
query_api
.
query
(
'user'
,
name
=
guest_identifier
)
except
ZoeAPIException
:
return
missing_auth
()
if
len
(
user
)
==
0
:
return
missing_auth
()
user
=
user
[
0
]
if
user
[
'role'
]
==
'guest'
:
return
missing_auth
()
executions
=
query_api
.
query
(
'execution'
)
template_vars
=
{
'executions'
:
executions
,
'is_admin'
:
user
[
'role'
]
==
'admin'
,
'user_gateway'
:
user
[
'gateway_urls'
][
0
]
}
return
render_template
(
'home_user.html'
,
**
template_vars
)
zoe_web/web/utils.py
0 → 100644
View file @
04ac52e9
# 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.
import
logging
from
flask
import
Response
,
render_template
from
zoe_web.auth.ldap
import
LDAPAuthenticator
import
zoe_web.exceptions
log
=
logging
.
getLogger
(
__name__
)
def
catch_exceptions
(
func
):
"""
Decorator function used to work around the static exception system available in Flask-RESTful
:param func:
:return:
"""
def
func_wrapper
(
*
args
,
**
kwargs
):
try
:
return
func
(
*
args
,
**
kwargs
)
except
zoe_web
.
exceptions
.
ZoeAuthException
:
return
missing_auth
()
except
zoe_web
.
exceptions
.
ZoeNotFoundException
as
e
:
return
error_page
(
e
.
message
,
404
)
except
zoe_web
.
exceptions
.
ZoeException
as
e
:
return
error_page
(
e
,
400
)
except
Exception
as
e
:
log
.
exception
(
str
(
e
))
return
{
'message'
:
str
(
e
)},
500
return
func_wrapper
def
missing_auth
():
"""Sends a 401 response that enables basic auth"""
return
Response
(
'Could not verify your access level for that URL.
\n
You have to login with proper credentials'
,
401
,
{
'WWW-Authenticate'
:
'Basic realm="Login Required"'
})
def
get_auth
(
request
):
auth
=
request
.
authorization
if
not
auth
:
raise
zoe_web
.
exceptions
.
ZoeAuthException
authenticator
=
LDAPAuthenticator
()
uid
,
role
=
authenticator
.
auth
(
auth
.
username
,
auth
.
password
)
if
uid
is
None
:
raise
zoe_web
.
exceptions
.
ZoeAuthException
return
uid
,
role
def
error_page
(
error_message
,
status
):
return
render_template
(
'error.html'
,
error
=
error_message
),
status
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment