Commit e99080b1 authored by Luca Lamorte's avatar Luca Lamorte

Add Orchestrator API section

parent 2055d2aa
{"connected": false, "exchange": "default", "orchestrator": "http://locahost:50001", "url": "amqp://luca:luca@finterop1/session1", "component": "gui_tt", "version": "0.0.1"}
\ No newline at end of file
{"connected": false, "version": "0.0.1", "component": "gui_tt", "exchange": "default", "orchestrator": "http://finterop2", "url": "amqp://luca:luca@finterop1/session1"}
\ No newline at end of file
import loggingimport errnoimport os VERSION = '0.0.1'COMPONENT_ID = "gui_tt" ALLOWED_EXTENSIONS = set(['json', 'pcap'])RABBIT_MQ_CONNECTED = False logger = logging.getLogger(__name__)logger.setLevel(logging.DEBUG)sh = logging.StreamHandler()sh.setFormatter(logging.Formatter('%(asctime)s - %(name)-15s:%(lineno)d - %(levelname)s - %(message)s'))sh.setLevel(logging.DEBUG)logger.addHandler(sh) project_dir = os.path.abspath(os.path.join(os.path.realpath(__file__), os.pardir)) # Set WS LOGs level ERROR werklog = logging.getLogger('werkzeug') werklog.setLevel(logging.ERROR) if '/testing_tool_gui' in project_dir: project_dir = os.path.abspath(os.path.join(project_dir, os.pardir)) TMPDIR = os.path.join(project_dir, 'tmp') DATADIR = os.path.join(project_dir, 'data') UPLOAD_FOLDER = TMPDIR # generate dirs for d in TMPDIR, DATADIR: try: os.makedirs(d) except OSError as e: if e.errno != errno.EEXIST: raise try: AMQP_EXCHANGE = str(os.environ['AMQP_EXCHANGE']) except KeyError as e: logger.debug('Couldnt import AMQP_EXCHANGE from environment') AMQP_EXCHANGE = "default" try: AMQP_URL = str(os.environ['AMQP_URL']) except KeyError as e: print('Couldnt import AMQP_URL from environment') # TODO: REMOVE PERSONAL CONFIGURATION ## AMQP_URL = "amqp://guest:guest@localhost/" ## AMQP_URL = str(os.getenv('AMQP_URL', 'amqp://luca:luca@finterop1/session1'))
\ No newline at end of file
import loggingimport errnoimport os VERSION = '0.0.1'COMPONENT_ID = "gui_tt" ALLOWED_EXTENSIONS = set(['json', 'pcap'])RABBIT_MQ_CONNECTED = False logger = logging.getLogger(__name__)logger.setLevel(logging.DEBUG)sh = logging.StreamHandler()sh.setFormatter(logging.Formatter('%(asctime)s - %(name)-15s:%(lineno)d - %(levelname)s - %(message)s'))sh.setLevel(logging.DEBUG)logger.addHandler(sh) project_dir = os.path.abspath(os.path.join(os.path.realpath(__file__), os.pardir)) # Set WS LOGs level ERROR werklog = logging.getLogger('werkzeug') werklog.setLevel(logging.ERROR) if '/testing_tool_gui' in project_dir: project_dir = os.path.abspath(os.path.join(project_dir, os.pardir)) TMPDIR = os.path.join(project_dir, 'tmp') DATADIR = os.path.join(project_dir, 'data') STATIC = os.path.join(project_dir, 'gui/static') UPLOAD_FOLDER = TMPDIR # generate dirs for d in TMPDIR, DATADIR: try: os.makedirs(d) except OSError as e: if e.errno != errno.EEXIST: raise try: AMQP_EXCHANGE = str(os.environ['AMQP_EXCHANGE']) except KeyError as e: logger.debug('Couldnt import AMQP_EXCHANGE from environment') AMQP_EXCHANGE = "default" try: AMQP_URL = str(os.environ['AMQP_URL']) except KeyError as e: print('Couldnt import AMQP_URL from environment') # TODO: REMOVE PERSONAL CONFIGURATION ## AMQP_URL = "amqp://guest:guest@localhost/" ## AMQP_URL = str(os.getenv('AMQP_URL', 'amqp://luca:luca@finterop1/session1'))
\ No newline at end of file
......
import base64
from os import listdir
from os.path import isfile, join
from flask import Flask
from flask import render_template, flash
......@@ -13,11 +14,14 @@ from testing_tool_gui.utils.amqp_synch_call import publish_message
from testing_tool_gui.utils.messages import *
from testing_tool_gui.gui.amqp_sniffer import AmqpSniffer
from testing_tool_gui.gui.utils import *
from testing_tool_gui.gui import UPLOAD_FOLDER, ALLOWED_EXTENSIONS
from testing_tool_gui.gui import UPLOAD_FOLDER, ALLOWED_EXTENSIONS, STATIC
from testing_tool_gui.gui import logger
from testing_tool_gui.gui.render_html import create_device_table
from werkzeug.utils import secure_filename
from testing_tool_gui.gui.orchestrator_api import *
my_channel = None
amqp_listener = None
......@@ -40,6 +44,8 @@ socketio = SocketIO(app, async_mode=async_mode)
app_cfg = Configuration(socketio)
def start_amqp_sniffer():
global amqp_listener
global app_cfg
......@@ -219,6 +225,36 @@ def configuration():
return response
@app.route('/session_templates/<name>')
def session_templates(name):
global app_cfg
if name == "all":
f = []
templates = "%s/session_templates/" % STATIC
for file in os.listdir(templates):
f.append(os.path.splitext(file)[0])
response = app.response_class(
response=json.dumps(f),
status=200,
mimetype='application/json'
)
else:
file = "%s/session_templates/%s.json" % (STATIC, name)
print(file)
with open(file) as json_data:
print(json_data)
d = json.load(json_data)
json_data.close()
print(d)
response = app.response_class(
response=json.dumps(d),
status=200,
mimetype='application/json'
)
return response
@app.route('/verdict/<type>')
def verdicts(type):
global amqp_listener
......@@ -238,6 +274,20 @@ def verdicts(type):
return response
@app.route('/api_orch', methods=['POST'])
def api_orch():
orchestrator = Orchestrator()
val = orchestrator.get_cmd(request.form)
print("RESPONSE : %s" % val)
response = app.response_class(
response=json.dumps(val),
status=200,
mimetype='application/json'
)
return response
@app.route('/upload', methods=['POST'])
def upload():
......
import requests
import logging
import json
log = logging.getLogger(__name__)
ORCHESTRATOR_URL = 'http://finterop2'
class Authentication:
def __init__(self, username, passowrd):
self.user = username
self.pswd = passowrd
class Orchestrator:
"""
This Class wrap all Orchestrator API to manage Session and User on RabbitMQ.
"""
def __init__(self, url=ORCHESTRATOR_URL):
self.url = url
self.sessions = None
self.users = None
self.current_session = None
def set_url(self, url):
self.url = url
#_________ ORCHESTRATOR API _________#
def read_users(self):
"""
Read User List from Orchestrator
:return: List of user_id
"""
response = requests.get("%s/users" % self.url)
self.users = json.loads(response.content.decode("utf-8"))
return response.content.decode("utf-8")
def user_info(self, user_id):
"""
Read user Information
:param user_id:
:return: user profile
"""
response = requests.get("%s/users/%s" % (self.url, user_id))
return response.content.decode("utf-8")
def create_user(self, username, password):
"""
Create a new User in RabbitMQ
:param username:
:param passoword:
:return:
"""
url = "%s/users/%s" % (self.url, username)
response = requests.put(url, json={"password": password})
return response.content.decode("utf-8")
def delete_user(self, user_id):
"""
Delete an User in RabbitMQ
:param user_id:
:return:
"""
url = "%s/users/%s" % (self.url, user_id)
response = requests.delete(url)
return response.content.decode("utf-8")
def read_sessions(self):
"""
Read all session available in Orchestrator/RabbitMQ
:return:
"""
register_response = requests.get("%s/sessions"% self.url)
return register_response.content.decode('utf-8')
def read_session(self, session_id):
"""
Read all session available in Orchestrator/RabbitMQ
:return:
"""
response = requests.get("%s/sessions/%s" % (self.url, session_id))
return response.content.decode('utf-8')
def start_session(self, session_id):
"""
Start a new Session with Session_id
:param session_id:
:return:
"""
response = requests.patch("%s/sessions/%s" % (self.url, session_id),
json={"status": "started"})
return response.content.decode("utf-8")
def stop_session(self, session_id):
"""
Stop Session ID
:param session_id:
:return:
"""
response = requests.patch("%s/sessions/%s" % (self.url, session_id),
json={"status": "started"})
return response.content.decode("utf-8")
def create_session(self, session_id, data):
"""
Create a new Session with Session_ID
:param session_id:
:return:
"""
url = "%s/sessions/%s" %(self.url, session_id)
# data = {
# "users": ["luca"],
# "iuts": [],
# "testing_tools": "f-interop/interoperability-coap",
# "tests": []
# }
response = requests.put(url=url,
json=data)
return response.content.decode("utf-8")
def del_session(self, session_id):
"""
Delete a Session with ID
:param session_id:
:return:
"""
response = requests.delete("%s/sessions/%s" % (self.url, session_id))
return response.content.decode("utf-8")
def check_session(self, session_id):
"""
Check if sessionID is available
:param session_id:
:return:
"""
return session_id in self.sessions
def check_user(self, user_id):
"""
Check if user_id exists
:param user_id:
:return:
"""
if not self.users:
self.read_users()
return user_id in self.users
#### ________ THIS WILL CREATE THE APP FLOW _________#####
def get_current_session(self):
return self.current_session
def publish(self, json_body):
assert self.current_session
assert self.auth.pswd
assert self.auth.user
assert json_body
url = "%s/sessions/%s/publish" %(self.url, self.current_session)
response = requests.post(url, json=json_body)
return response.content.decode("utf-8")
def get_cmd(self, params):
print (dict(params))
cmd = params['cmd']
try:
if cmd == 'user_list':
return self.read_users()
elif cmd == 'user_create':
if 'username' in params and 'password' in params:
usr = params['username']
psw = params['password']
self.create_user(usr, psw)
return self.read_users()
else:
return json.dumps({"error": 'missing params user-id or user-psw'})
elif cmd == 'user_delete':
if 'username' in params:
usr = params['username']
self.delete_user(usr)
return self.read_users()
else:
return json.dumps({"error": 'missing param user-id'})
elif cmd == 'session_add':
if 'sessionid' in params:
return self.create_session(params['sessionid'])
else:
return json.dumps({"error": 'missing param session-id'})
elif cmd == 'session_read':
if 'sessionid' in params:
return self.read_session(params['sessionid'])
else:
return json.dumps({"error": 'missing param session-id'})
elif cmd == 'session_list':
return self.read_sessions()
elif cmd == 'session_start':
if 'sessionid' in params:
return self.start_session(params['sessionid'])
else:
return json.dumps({"error": 'missing param session-id'})
elif cmd == 'session_stop':
if 'sessionid' in params:
return self.stop_session(params['sessionid'])
else:
return json.dumps({"error": 'missing param session-id'})
elif cmd == 'session_del':
if 'sessionid' in params:
return self.del_session(params['sessionid'])
else:
return json.dumps({"error": 'missing param session-id'})
else:
return json.dumps({'message': "%s is not a valid command!" % cmd})
except Exception as err:
return json.dumps({'message': "Error in CMD:%s -> cause: %s" % (cmd, err)})
if __name__ == "__main__":
print("Test Orchestrator API...")
a1 = Authentication("f-interop", "f-interop")
api = Orchestrator()
print("[1] add LUCA: %s" % api.create_user("luca", "luca"))
print("[1] USERS: %s" % api.read_users())
#print("[2] Check %s = %s" %(a1.user, api.check_user(a1.user)))
#print("[3] User info: %s" % (api.user_info(a1.user)))
#print("[4] SESSIONS: %s" % api.read_sessions())
#print("[2] CHECK LUCA: %s" % api.check_session("luca"))
print("[5] CREATE LUCA: %s" % api.create_session("test1"))
#print("[6] SESSIONS: %s" % api.read_sessions())
# print("[5] CHECK LUCA: %s" % api.check_session("luca"))
#print("[6] DELETE LUCA: %s" % api.del_session("luca"))
#print("[2] Publish To session: %s" % api.publish())
......@@ -2,10 +2,14 @@
* Created by luca.lamorte on 25/04/2017.
*/
var namespace = '/ws';
var socket = null;
var index = 0
var configuration = []
var amqp_msg = []
$(document).ready(function() {
socket = io.connect('http://' + document.domain + ':' + location.port + namespace);
......@@ -57,6 +61,7 @@ $(document).ready(function() {
});
$.get('/amqp_msg_list', function(data){
amqp_msg = data
read_message_list(data, "utils_msg_list")
});
......@@ -76,6 +81,44 @@ $(document).ready(function() {
});
$( 'body' ).on( 'click', '.session', function(event) {
event.preventDefault()
var cmd = "session_" + $(this).text().toLowerCase()
call_api_orch(cmd)
});
$( 'body' ).on( 'click', '.user', function(event) {
event.preventDefault()
var cmd = "user_" + $(this).text().toLowerCase()
call_api_orch(cmd)
});
$("body").on("change", '#body_templates', function(){
$.get("/session_templates/"+$("#body_templates").val(), function(data){
$("#request_body").text( JSON.stringify(data))
});
})
$("#hide_console").on("click", function(){
var icon = $("<i>").addClass("glyphicon")
if ($("#messages").hasClass("console_show")){
icon.addClass("glyphicon-chevron-up")
$("#messages").removeClass("console_show");
$("#messages").addClass("console_hide ");
$("#hide_console").text("Show ").append(icon);
}
else{
icon.addClass("glyphicon-chevron-down")
$("#messages").removeClass("console_hide");
$("#messages").addClass("console_show");
$("#hide_console").text("Hide ").append(icon);
}
})
load_last_page()
});
......@@ -171,11 +214,26 @@ function showDetails(value){
addTestCase(testcase)
}
}
else if(value === 'orchestrator'){
$.get('/configuration', function(data){
$("#orch_url").text(data.orchestrator);
});
$.get('/session_templates/all', function(data){
console.log(data)
for(var i in data){
var opt = $("<option>").text(data[i])
$("#body_templates").append(opt)
}
});
}
else if (value === "message"){
$.get('/amqp_msg_list', function(data){
console.log(data)
//console.log(data)
read_message_list(data, "message_rk_list")
});
......@@ -231,7 +289,7 @@ function show_amqp_message(message){
console.log("Send message "+ message)
//socket.emit('send_var routing_key
$("#routing_key_input").val(message)
$("#message_body").append("")
$("#message_body").html("")
$.get( "message/"+message , function( data ) {
for (var key in data) {
......@@ -251,8 +309,8 @@ function show_amqp_message(message){
function read_configuration(cfg){
//console.log(data)
// var cfg = JSON.parse(data)
configuration = cfg
$("#amqp_url").val(cfg["url"])
$("#amqp_exchange").val(cfg["exchange"])
$("#orcherstrator_url").val(cfg["orchestrator"])
......@@ -268,7 +326,6 @@ function read_configuration(cfg){
function read_message_list(data, id_to_place){
var old_topic = ""
//$("#"+id_to_place).html("")
var submenu = $("<ul>").addClass("dropdown-submenu")
......
function call_api_orch(cmd){
var data = {
'cmd': cmd,
'body': {}
}
data.username = $("#user-id").val()
data.password = $("#user-psw").val()
data.body = $("#request_body").val()
data.sessionid = $("#session-id").val()
if (cmd === 'user_create' ||
cmd === 'user_delete'){
if (data.username === ""){
send_alert("ERROR!", "Missing User-ID param!!! ", "danger")
return
}
}
if( cmd === 'user_create' && data.password ==='' ){
send_alert("ERROR!", "Missing User-PSW param!!! ", "danger")
return
}
if (cmd === 'session_create'){
if (data.body === ""){
send_alert("ERROR!", "Missing BODY param!!! ", "danger")
return
}
}
if (cmd === 'session_add' ||
cmd === 'session_read' ||
cmd === 'session_start' ||
cmd === 'session_stop' ||
cmd === 'session_del'){
if (data.sessionid === ""){
send_alert("ERROR!", "Missing Session-ID param!!! ", "danger")
return
}
}
api_cmd(data)
}
function api_cmd(data) {
$.ajax({
type: "post",
url: '/api_orch',
data: data,
dataType: "json",
success: function (data) {
console.log(data)
$("#orch_response").val(data)
}
});
}
{
"users": [
"u1",
"f-interop"
],
"iuts": [
{
"id": "someImplementationFromAUser",
"role": "coap_client",
"execution_mode": "user-assisted",
"location":"user-facilities",
"owner": "someUserName",
"version": "0.1"
},
{
"id": "automated_iut-coap_client-coapthon-v0.1",
"role": "coap_client",
"execution_mode": "automated-iut",
"location": "central-server-docker",
"owner": "f-interop",
"version": "0.1"
}
],
"testing_tools": "f-interop/interoperability-coap",
"tests": [
"http://doc.f-interop.eu/tests/TD_COAP_CORE_01_v01",
"http://doc.f-interop.eu/tests/TD_COAP_CORE_02_v01"
]
}
\ No newline at end of file
{
"users": [
"u1",
"f-interop"
],
"iuts": [
{
"id": "someImplementationFromAUser",
"role": "coap_client",
"execution_mode": "user-assisted",
"location":"user-facilities",
"owner": "someUserName",
"version": "0.1"
},
{
"id": "automated_iut-coap_server-californium-v0.1",
"role": "coap_server",
"execution_mode": "automated-iut",
"location": "central-server-docker",
"owner": "f-interop",
"version": "0.1"
}
],
"testing_tools": "f-interop/interoperability-coap",
"tests": [
"http://doc.f-interop.eu/tests/TD_COAP_CORE_01_v01",
"http://doc.f-interop.eu/tests/TD_COAP_CORE_02_v01"
]
}
\ No newline at end of file
{
"users": [
"finterop.testing_loic"
],
"iuts": [
{
"id": "http://f-interop.paris.inria.fr/devices/device_a",
"role": "client",
"execution_mode": "user-assisted",
"owner": "a"
},
{
"id": "http://f-interop.paris.inria.fr/devices/device_b",
"role": "server",
"execution_mode": "automated",
"owner": "f-interop"
}
],
"testing_tools": "http://f-interop.paris.inria.fr/testingtools/f-interop/coap",
"tests": [
{
"testcase_id": "http://f-interop.paris.inria.fr/tests/TD_COAP_CORE_01",
"settings": {}
}
]
}
\ No newline at end of file
......@@ -27,14 +27,19 @@
}
.console{
.console_show{
background: #000000;
height: 300px;
overflow-y:auto;
}
.console_hide{
background: #000000;
height: 0px;
overflow-y:auto;
}
/*#alerts{*/
/*margin: 20px;*/
......
<div class="jumbotron">
<div class="container">
<h1> Privacy Testing Tool - v.1.0.0 </h1>
<h1> GUI - v.1.0.0 </h1>
<p> Lorem ipsum dolor sit amet, consectetur adipisci elit, sed eiusmod tempor incidunt ut
abore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrum exercitationem ullam
corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur. Quis aute iure
......
......@@ -65,7 +65,8 @@
<li><a href="http://doc.f-interop.eu/">Docs</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<ul class="nav navbar-nav navbar-right">
<li class="hide" id="privacy_alert">
<a href="#" class="yellow" onclick="show_verdict()">
<span class="glyphicon glyphicon-warning-sign"></span>
......@@ -79,6 +80,7 @@
<span class="glyphicon glyphicon-chevron-down"></span>
</a>
<ul class="dropdown-menu">
<li>
<div class="navbar-login">
<div class="row">
......@@ -136,7 +138,7 @@
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#">AMQP Console</a>
<a class="navbar-brand" styles="color:white" href="#">AMQP Console</a>
</div>
<ul class="nav navbar-nav">
......@@ -164,12 +166,16 @@
<span id="ws_status"> Disconnected</span>
</a>
</li>
<button id="hide_console" type="button" class="btn btn-primary navbar-btn pull-right">
Hide
<i class="glyphicon glyphicon-chevron-down"></i>
</button>
</ul>
</div>
</nav>
<div id="messages" class="console"> </div>
<div id="messages" class="console_show"> </div>
</div>
</div>
......
<div class="jumbotron">
<div class="container">