first initial working link for ptp and joining back and drawing the edge, also making use of old core icons to provide a basic look and feel, updated coloring to dark mode instead of info, seems to fit better
|
@ -320,7 +320,9 @@ class IpPrefix(object):
|
|||
|
||||
addr = ""
|
||||
prefix_endpoint = -1
|
||||
print "stop condition: %s" % (-(self.addrlen >> 3) - 1)
|
||||
for i in xrange(-1, -(self.addrlen >> 3) - 1, -1):
|
||||
print "i: %s" % i
|
||||
prefix_endpoint = i
|
||||
addr = chr(ord(self.prefix[i]) | (tmp & 0xff)) + addr
|
||||
tmp >>= 8
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
import os
|
||||
|
||||
from functools import wraps
|
||||
from threading import Lock
|
||||
|
||||
from flask import Flask
|
||||
from flask import jsonify
|
||||
from flask import render_template
|
||||
|
@ -7,13 +12,16 @@ from flask_socketio import emit
|
|||
|
||||
from core import logger
|
||||
from core.emulator.coreemu import CoreEmu
|
||||
from core.emulator.emudata import InterfaceData
|
||||
from core.emulator.emudata import InterfaceData, IpPrefixes
|
||||
from core.emulator.emudata import LinkOptions
|
||||
from core.emulator.emudata import NodeOptions
|
||||
from core.enumerations import EventTypes
|
||||
from core.enumerations import LinkTypes
|
||||
from core.enumerations import NodeTypes
|
||||
from core.misc import nodeutils
|
||||
from core.misc.ipaddress import Ipv4Prefix, Ipv6Prefix
|
||||
|
||||
CORE_LOCK = Lock()
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config["SECRET_KEY"] = "core"
|
||||
|
@ -22,6 +30,17 @@ socketio = SocketIO(app)
|
|||
coreemu = CoreEmu()
|
||||
|
||||
|
||||
def synchronized(function):
|
||||
global CORE_LOCK
|
||||
|
||||
@wraps(function)
|
||||
def wrapper(*args, **kwargs):
|
||||
with CORE_LOCK:
|
||||
return function(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def link_data_str(link, key):
|
||||
value = link.get(key)
|
||||
if value:
|
||||
|
@ -53,29 +72,53 @@ def home():
|
|||
return render_template('index.html')
|
||||
|
||||
|
||||
@app.route("/ips", methods=["POST"])
|
||||
def get_ips():
|
||||
data = request.get_json() or {}
|
||||
node_id = data["id"]
|
||||
node_id = int(node_id)
|
||||
|
||||
ip4_prefix = data.get("ip4")
|
||||
ip6_prefix = data.get("ip6")
|
||||
|
||||
ip4_prefixes = Ipv4Prefix(ip4_prefix)
|
||||
ip6_prefixes = Ipv6Prefix(ip6_prefix)
|
||||
|
||||
return jsonify(
|
||||
ip4=str(ip4_prefixes.addr(node_id)),
|
||||
ip4mask=ip4_prefixes.prefixlen,
|
||||
ip6=str(ip6_prefixes.addr(node_id)),
|
||||
ip6mask=ip6_prefixes.prefixlen
|
||||
)
|
||||
|
||||
|
||||
@app.route("/sessions")
|
||||
def get_sessions():
|
||||
sessions = []
|
||||
for session in coreemu.sessions.itervalues():
|
||||
sessions.append({
|
||||
"id": session.session_id,
|
||||
"state": session.state,
|
||||
"nodes": session.get_node_count()
|
||||
})
|
||||
return jsonify(sessions=sessions)
|
||||
|
||||
|
||||
@app.route("/sessions", methods=["POST"])
|
||||
@synchronized
|
||||
def create_session():
|
||||
session = coreemu.create_session()
|
||||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
response_data = jsonify(
|
||||
id=session.session_id,
|
||||
state=session.state,
|
||||
url="/sessions/%s" % session.session_id
|
||||
)
|
||||
return response_data, 201
|
||||
|
||||
|
||||
@app.route("/sessions/<int:session_id>", methods=["DELETE"])
|
||||
@synchronized
|
||||
def delete_session(session_id):
|
||||
result = coreemu.delete_session(session_id)
|
||||
if result:
|
||||
|
@ -96,6 +139,7 @@ def get_session(session_id):
|
|||
"id": node.objid,
|
||||
"name": node.name,
|
||||
"type": nodeutils.get_node_type(node.__class__).value,
|
||||
"model": getattr(node, "type", None),
|
||||
"position": {
|
||||
"x": node.position.x,
|
||||
"y": node.position.y,
|
||||
|
@ -112,12 +156,14 @@ def get_session(session_id):
|
|||
|
||||
|
||||
@app.route("/sessions/<int:session_id>/nodes", methods=["POST"])
|
||||
@synchronized
|
||||
def create_node(session_id):
|
||||
session = coreemu.sessions.get(session_id)
|
||||
if not session:
|
||||
return jsonify(error="session does not exist"), 404
|
||||
|
||||
data = request.get_json() or {}
|
||||
node_id = data.get("id")
|
||||
node_type = data.get("type", NodeTypes.DEFAULT.value)
|
||||
node_type = NodeTypes(node_type)
|
||||
logger.info("creating node: %s - %s", node_type.name, data)
|
||||
|
@ -130,7 +176,7 @@ def create_node(session_id):
|
|||
node_options.opaque = data.get("opaque")
|
||||
node_options.set_position(data.get("x"), data.get("y"))
|
||||
node_options.set_location(data.get("lat"), data.get("lon"), data.get("alt"))
|
||||
node = session.add_node(_type=node_type, node_options=node_options)
|
||||
node = session.add_node(_type=node_type, _id=node_id, node_options=node_options)
|
||||
return jsonify(
|
||||
id=node.objid,
|
||||
url="/sessions/%s/nodes/%s" % (session_id, node.objid)
|
||||
|
@ -174,6 +220,7 @@ def get_node(session_id, node_id):
|
|||
|
||||
|
||||
@app.route("/sessions/<int:session_id>/nodes/<node_id>", methods=["DELETE"])
|
||||
@synchronized
|
||||
def delete_node(session_id, node_id):
|
||||
session = coreemu.sessions.get(session_id)
|
||||
if not session:
|
||||
|
@ -193,6 +240,7 @@ def delete_node(session_id, node_id):
|
|||
|
||||
|
||||
@app.route("/sessions/<int:session_id>/state", methods=["PUT"])
|
||||
@synchronized
|
||||
def set_session_state(session_id):
|
||||
session = coreemu.sessions.get(session_id)
|
||||
if not session:
|
||||
|
@ -204,6 +252,9 @@ def set_session_state(session_id):
|
|||
session.set_state(state)
|
||||
|
||||
if state == EventTypes.INSTANTIATION_STATE:
|
||||
# create session directory if it does not exist
|
||||
if not os.path.exists(session.session_dir):
|
||||
os.mkdir(session.session_dir)
|
||||
session.instantiate()
|
||||
elif state == EventTypes.SHUTDOWN_STATE:
|
||||
session.shutdown()
|
||||
|
@ -218,6 +269,7 @@ def set_session_state(session_id):
|
|||
|
||||
|
||||
@app.route("/sessions/<int:session_id>/links", methods=["POST"])
|
||||
@synchronized
|
||||
def add_link(session_id):
|
||||
session = coreemu.sessions.get(session_id)
|
||||
if not session:
|
||||
|
@ -282,6 +334,7 @@ def add_link(session_id):
|
|||
|
||||
|
||||
@app.route("/sessions/<int:session_id>/links", methods=["DELETE"])
|
||||
@synchronized
|
||||
def delete_link(session_id):
|
||||
session = coreemu.sessions.get(session_id)
|
||||
if not session:
|
||||
|
|
1
webapp/static/bootstrap.min.js.map
Normal file
BIN
webapp/static/core-icon.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
|
@ -3,8 +3,7 @@
|
|||
}
|
||||
|
||||
.navbar-text {
|
||||
color: #17a2b8 !important;
|
||||
background-color: #fff;
|
||||
color: #fff !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
|
199
webapp/static/coreip.js
Normal file
|
@ -0,0 +1,199 @@
|
|||
const AF_INET = 2;
|
||||
const AF_INET6 = 23;
|
||||
|
||||
function ord (string) {
|
||||
var str = string + '';
|
||||
var code = str.charCodeAt(0);
|
||||
|
||||
if (code >= 0xD800 && code <= 0xDBFF) {
|
||||
// High surrogate (could change last hex to 0xDB7F to treat
|
||||
// high private surrogates as single characters)
|
||||
var hi = code;
|
||||
if (str.length === 1) {
|
||||
// This is just a high surrogate with no following low surrogate,
|
||||
// so we return its value;
|
||||
return code;
|
||||
// we could also throw an error as it is not a complete character,
|
||||
// but someone may want to know
|
||||
}
|
||||
var low = str.charCodeAt(1);
|
||||
return ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000
|
||||
}
|
||||
if (code >= 0xDC00 && code <= 0xDFFF) {
|
||||
// Low surrogate
|
||||
// This is just a low surrogate with no preceding high surrogate,
|
||||
// so we return its value;
|
||||
return code;
|
||||
// we could also throw an error as it is not a complete character,
|
||||
// but someone may want to know
|
||||
}
|
||||
|
||||
return code
|
||||
}
|
||||
|
||||
function inetNtop (a) {
|
||||
var i = 0;
|
||||
var m = '';
|
||||
var c = [];
|
||||
|
||||
a += '';
|
||||
if (a.length === 4) {
|
||||
// IPv4
|
||||
return [
|
||||
a.charCodeAt(0),
|
||||
a.charCodeAt(1),
|
||||
a.charCodeAt(2),
|
||||
a.charCodeAt(3)
|
||||
].join('.');
|
||||
} else if (a.length === 16) {
|
||||
// IPv6
|
||||
for (i = 0; i < 16; i++) {
|
||||
c.push(((a.charCodeAt(i++) << 8) + a.charCodeAt(i)).toString(16));
|
||||
}
|
||||
return c.join(':')
|
||||
.replace(/((^|:)0(?=:|$))+:?/g, function (t) {
|
||||
m = (t.length > m.length) ? t : m;
|
||||
return t;
|
||||
})
|
||||
.replace(m || ' ', '::');
|
||||
} else {
|
||||
// Invalid length
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function inetPton(a) {
|
||||
var r;
|
||||
var m;
|
||||
var x;
|
||||
var i;
|
||||
var j;
|
||||
var f = String.fromCharCode;
|
||||
|
||||
// IPv4
|
||||
m = a.match(/^(?:\d{1,3}(?:\.|$)){4}/);
|
||||
if (m) {
|
||||
m = m[0].split('.');
|
||||
m = f(m[0]) + f(m[1]) + f(m[2]) + f(m[3]);
|
||||
// Return if 4 bytes, otherwise false.
|
||||
return m.length === 4 ? m : false;
|
||||
}
|
||||
r = /^((?:[\da-f]{1,4}(?::|)){0,8})(::)?((?:[\da-f]{1,4}(?::|)){0,8})$/;
|
||||
|
||||
// IPv6
|
||||
m = a.match(r);
|
||||
if (m) {
|
||||
// Translate each hexadecimal value.
|
||||
for (j = 1; j < 4; j++) {
|
||||
// Indice 2 is :: and if no length, continue.
|
||||
if (j === 2 || m[j].length === 0) {
|
||||
continue;
|
||||
}
|
||||
m[j] = m[j].split(':');
|
||||
for (i = 0; i < m[j].length; i++) {
|
||||
m[j][i] = parseInt(m[j][i], 16);
|
||||
// Would be NaN if it was blank, return false.
|
||||
if (isNaN(m[j][i])) {
|
||||
// Invalid IP.
|
||||
return false;
|
||||
}
|
||||
m[j][i] = f(m[j][i] >> 8) + f(m[j][i] & 0xFF);
|
||||
}
|
||||
m[j] = m[j].join('');
|
||||
}
|
||||
x = m[1].length + m[3].length;
|
||||
if (x === 16) {
|
||||
return m[1] + m[3];
|
||||
} else if (x < 16 && m[2].length > 0) {
|
||||
return m[1] + (new Array(16 - x + 1))
|
||||
.join('\x00') + m[3];
|
||||
}
|
||||
}
|
||||
|
||||
// Invalid IP
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
class IpAddress {
|
||||
constructor(addressFamily, address) {
|
||||
console.log('ip address: ', addressFamily, address);
|
||||
this.addressFamily = addressFamily;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
str() {
|
||||
return inetNtop(this.address);
|
||||
}
|
||||
}
|
||||
|
||||
class IpPrefix {
|
||||
constructor(addressFamily, prefix) {
|
||||
this.addressFamily = addressFamily;
|
||||
if (this.addressFamily === AF_INET) {
|
||||
this.addressLength = 32;
|
||||
} else if (this.addressFamily == AF_INET6) {
|
||||
this.addressLength = 128;
|
||||
} else {
|
||||
throw Error(`invalid address family: ${addressFamily}`);
|
||||
}
|
||||
|
||||
const values = prefix.split('/');
|
||||
console.log(`split prefix: ${values}`);
|
||||
if (values.length > 2) {
|
||||
throw Error(`invalid prefix: ${prefix}`);
|
||||
}
|
||||
|
||||
if (values.length === 2) {
|
||||
this.prefixLength = parseInt(values[1]);
|
||||
} else {
|
||||
this.prefixLength = this.addressLength;
|
||||
}
|
||||
|
||||
this.prefix = inetPton(values[0]);
|
||||
|
||||
if (this.addressLength > this.prefixLength) {
|
||||
const addressBits = this.addressLength - this.prefixLength;
|
||||
let netMask = ((1 << this.prefixLength) - 1) << addressBits;
|
||||
prefix = '';
|
||||
//in xrange(-1, -(addrbits >> 3) - 2, -1)
|
||||
const stopValue = -(addressBits) - 2;
|
||||
for (let i = -1; i > stopValue; --i) {
|
||||
prefix = String.fromCharCode(ord(this.prefix[i]) & (netMask & 0xff)) + prefix;
|
||||
netMask >>= 8;
|
||||
}
|
||||
this.prefix = this.prefix.slice(0, stopValue) + prefix;
|
||||
}
|
||||
}
|
||||
|
||||
getAddress(id) {
|
||||
if (id in [-1, 0, 1] && this.addressLength === this.prefixLength) {
|
||||
return new IpAddress(this.addressFamily, this.prefix);
|
||||
}
|
||||
|
||||
const value = (1 << (this.addressLength - this.prefixLength)) - 1;
|
||||
console.log(`address length(${this.addressLength}) prefix length(${this.prefixLength}) value(${value})`);
|
||||
if (id === 0 || id > value || (this.addressFamily === AF_INET && id === value)) {
|
||||
throw Error(`invalid id for prefix ${this.prefix}: ${id}`);
|
||||
}
|
||||
|
||||
let address = '';
|
||||
let prefixEndpoint = -1;
|
||||
console.log('stop condition: ', -(this.addressLength >> 3) - 1);
|
||||
for (let i = -1; i > -(this.addressLength >> 3) - 1; --i) {
|
||||
console.log('i: ', i);
|
||||
prefixEndpoint = i;
|
||||
address = String.fromCharCode(ord(this.prefix[i]) | (id & 0xff)) + address;
|
||||
console.log('address: ', address);
|
||||
id >>= 8;
|
||||
console.log('id: ', id);
|
||||
if (!id) {
|
||||
break
|
||||
}
|
||||
}
|
||||
address = this.prefix.slice(0, prefixEndpoint) + address;
|
||||
return new IpAddress(this.addressFamily, address);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,25 +1,52 @@
|
|||
const Ip4Prefix = '10.0.0.1/24';
|
||||
const Ip6Prefix = '2001::/64';
|
||||
|
||||
const PtpNode = 12;
|
||||
const NodeTypes = {
|
||||
// default router
|
||||
0: {
|
||||
name: 'node'
|
||||
name: 'node',
|
||||
display: 'Default'
|
||||
},
|
||||
// switch
|
||||
4: {
|
||||
name: 'switch'
|
||||
name: 'switch',
|
||||
display: 'Switch'
|
||||
},
|
||||
// hub
|
||||
5: {
|
||||
name: 'hub'
|
||||
name: 'hub',
|
||||
display: 'Hub'
|
||||
},
|
||||
// wlan
|
||||
6: {
|
||||
name: 'wlan'
|
||||
name: 'wlan',
|
||||
display: 'WLAN'
|
||||
},
|
||||
12: {
|
||||
name: 'ptp',
|
||||
display: 'PTP'
|
||||
}
|
||||
};
|
||||
|
||||
function getNodeType(nodeType) {
|
||||
return NodeTypes[nodeType];
|
||||
}
|
||||
|
||||
const NodeIcons = {
|
||||
router: 'static/router.svg',
|
||||
host: 'static/host.gif',
|
||||
PC: 'static/pc.gif',
|
||||
mdr: 'static/mdr.svg',
|
||||
switch: 'static/lanswitch.svg',
|
||||
hub: 'static/hub.svg',
|
||||
wlan: 'static/wlan.gif'
|
||||
};
|
||||
|
||||
class CoreNode {
|
||||
constructor(id, name, x, y) {
|
||||
constructor(id, type, name, x, y) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.model = null;
|
||||
this.canvas = null;
|
||||
|
@ -32,35 +59,54 @@ class CoreNode {
|
|||
this.lon = null;
|
||||
this.alt = null;
|
||||
this.emulation_id = null;
|
||||
this.emulation_server = null;
|
||||
this.emulation_server = null
|
||||
this.interfaces = {};
|
||||
}
|
||||
|
||||
getNetworkNode() {
|
||||
let iconName = getNodeType(this.type).name;
|
||||
if (this.type === 0) {
|
||||
iconName = this.model;
|
||||
}
|
||||
const icon = NodeIcons[iconName];
|
||||
|
||||
return {
|
||||
id: this.id,
|
||||
x: this.x,
|
||||
y: this.y,
|
||||
label: this.name,
|
||||
node: this
|
||||
coreNode: this,
|
||||
//color: '#FFF',
|
||||
//shape: 'image',
|
||||
//shapeProperties: {
|
||||
// useBorderWithImage: true
|
||||
//},
|
||||
//image: nodeMode.image,
|
||||
//type: nodeMode.nodeType
|
||||
shape: 'image',
|
||||
image: icon
|
||||
};
|
||||
}
|
||||
|
||||
json() {
|
||||
return {
|
||||
id: this.id,
|
||||
type: this.type,
|
||||
name: this.name,
|
||||
model: this.model,
|
||||
x: this.x,
|
||||
y: this.y,
|
||||
lat: this.lat,
|
||||
lon: this.lon,
|
||||
alt: this.alt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CoreNetwork {
|
||||
constructor(elementId) {
|
||||
this.nodeType = NodeTypes['0'];
|
||||
this.nodeModel = null;
|
||||
constructor(elementId, coreRest) {
|
||||
this.coreRest = coreRest;
|
||||
this.nodeType = 0;
|
||||
this.nodeModel = 'router';
|
||||
this.nodeId = 0;
|
||||
this.container = document.getElementById(elementId);
|
||||
this.nodes = new vis.DataSet();
|
||||
this.edges = new vis.DataSet();
|
||||
this.links = {};
|
||||
this.networkData = {
|
||||
nodes: this.nodes,
|
||||
edges: this.edges
|
||||
|
@ -88,18 +134,120 @@ class CoreNetwork {
|
|||
this.edges.on('add', this.addEdge.bind(this));
|
||||
}
|
||||
|
||||
getCoreNodes() {
|
||||
const coreNodes = [];
|
||||
for (let node of this.nodes.get()) {
|
||||
coreNodes.push(node.coreNode.json());
|
||||
}
|
||||
return coreNodes;
|
||||
}
|
||||
|
||||
addCoreNode(node) {
|
||||
const position = node.position;
|
||||
const coreNode = new CoreNode(node.id, node.type, node.name, position.x, position.y);
|
||||
coreNode.model = node.model;
|
||||
this.nodes.add(coreNode.getNetworkNode());
|
||||
}
|
||||
|
||||
nextNodeId() {
|
||||
this.nodeId += 1;
|
||||
return this.nodeId;
|
||||
}
|
||||
|
||||
joinedSessions(nodes) {
|
||||
const self = this;
|
||||
for (let node of nodes) {
|
||||
if (node.type === PtpNode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.addCoreNode(node);
|
||||
}
|
||||
|
||||
for (let node of nodes) {
|
||||
if (![4, 5, 6, 12].includes(node.type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.coreRest.getLinks(node.id)
|
||||
.then(function(response) {
|
||||
console.log('link response: ', response);
|
||||
for (let linkData of response.links) {
|
||||
self.createEdgeFromLink(linkData);
|
||||
}
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log('get link error: ', err);
|
||||
});
|
||||
}
|
||||
|
||||
if (nodes.length) {
|
||||
this.nodeId = Math.max.apply(Math, nodes.map(function (node) {
|
||||
return node.id
|
||||
}));
|
||||
} else {
|
||||
this.nodeId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
createEdgeFromLink(linkData) {
|
||||
const fromNode = this.nodes.get(linkData.node1_id).coreNode;
|
||||
const toNode = this.nodes.get(linkData.node2_id).coreNode;
|
||||
const linkId = `${fromNode.id}-${toNode.id}`;
|
||||
|
||||
const interfaceOne = {
|
||||
id: linkData.interface1_id,
|
||||
ip4: linkData.interface1_ip4,
|
||||
ip4mask: linkData.interface1_ip4_mask,
|
||||
ip6: linkData.interface1_ip6,
|
||||
ip6mask: linkData.interface1_ip6_mask
|
||||
};
|
||||
fromNode.interfaces[linkData.interface1_id] = interfaceOne;
|
||||
|
||||
const interfaceTwo = {
|
||||
id: linkData.interface2_id,
|
||||
ip4: linkData.interface2_ip4,
|
||||
ip4mask: linkData.interface2_ip4_mask,
|
||||
ip6: linkData.interface2_ip6,
|
||||
ip6mask: linkData.interface2_ip6_mask
|
||||
};
|
||||
toNode.interfaces[linkData.interface2_id] = interfaceTwo;
|
||||
|
||||
this.links[linkId] = {
|
||||
node_one: fromNode.id,
|
||||
node_two: toNode.id,
|
||||
interface_one: interfaceOne,
|
||||
interface_two: interfaceTwo
|
||||
};
|
||||
|
||||
const edge = {from: fromNode.id, to: toNode.id};
|
||||
this.edges.add(edge);
|
||||
}
|
||||
|
||||
async start() {
|
||||
const nodes = coreNetwork.getCoreNodes();
|
||||
for (let node of nodes) {
|
||||
const response = await coreRest.createNode(node);
|
||||
console.log('created node: ', response);
|
||||
}
|
||||
|
||||
for (let linkId in this.links) {
|
||||
const link = this.links[linkId];
|
||||
const response = await coreRest.createLink(link);
|
||||
console.log('created link: ', response);
|
||||
}
|
||||
|
||||
return await coreRest.setSessionState(SessionStates.instantiation);
|
||||
}
|
||||
|
||||
addNode(properties) {
|
||||
console.log('add node event: ', properties);
|
||||
if (properties.nodes.length === 0) {
|
||||
const {x, y} = properties.pointer.canvas;
|
||||
const nodeId = this.nextNodeId();
|
||||
const name = `${this.nodeType.name}${nodeId}`;
|
||||
const coreNode = new CoreNode(nodeId, name, x, y);
|
||||
const nodeTypeData = getNodeType(this.nodeType);
|
||||
const name = `${nodeTypeData.name}${nodeId}`;
|
||||
const coreNode = new CoreNode(nodeId, this.nodeType, name, x, y);
|
||||
coreNode.model = this.nodeModel;
|
||||
this.nodes.add(coreNode.getNetworkNode());
|
||||
console.log('added node: ', coreNode.getNetworkNode());
|
||||
|
@ -115,10 +263,55 @@ class CoreNetwork {
|
|||
this.edges.remove(edge.id);
|
||||
}
|
||||
|
||||
const fromNode = this.nodes.get(edge.from).coreNode;
|
||||
const toNode = this.nodes.get(edge.to).coreNode;
|
||||
|
||||
this.addEdgeLink(edge, fromNode, toNode)
|
||||
.then(function() {
|
||||
console.log('create edge link success!');
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log('create link error: ', err);
|
||||
});
|
||||
|
||||
// keep edge mode enabled
|
||||
setTimeout(() => this.network.addEdgeMode(), 250);
|
||||
}
|
||||
|
||||
async addEdgeLink(edge, fromNode, toNode) {
|
||||
const fromIps = await this.coreRest.getNodeIps(fromNode.id, Ip4Prefix, Ip6Prefix);
|
||||
const toIps = await this.coreRest.getNodeIps(toNode.id, Ip4Prefix, Ip6Prefix);
|
||||
console.log('link ips: ', fromIps, toIps);
|
||||
|
||||
const linkId = `${fromNode.id}-${toNode.id}`;
|
||||
const interfaceOneId =Object.keys(fromNode.interfaces).length;
|
||||
const interfaceOne = {
|
||||
id: interfaceOneId,
|
||||
ip4: fromIps.ip4,
|
||||
ip4mask: fromIps.ip4mask,
|
||||
ip6: fromIps.ip6,
|
||||
ip6mask: fromIps.ip6mask
|
||||
};
|
||||
fromNode.interfaces[interfaceOneId] = interfaceOne;
|
||||
|
||||
const interfaceTwoId = Object.keys(toNode.interfaces).length;
|
||||
const interfaceTwo = {
|
||||
id: interfaceTwoId,
|
||||
ip4: toIps.ip4,
|
||||
ip4mask: toIps.ip4mask,
|
||||
ip6: toIps.ip6,
|
||||
ip6mask: toIps.ip6mask
|
||||
};
|
||||
toNode.interfaces[interfaceTwoId] = interfaceTwo;
|
||||
|
||||
this.links[linkId] = {
|
||||
node_one: fromNode.id,
|
||||
node_two: toNode.id,
|
||||
interface_one: interfaceOne,
|
||||
interface_two: interfaceTwo
|
||||
};
|
||||
}
|
||||
|
||||
linkMode(enabled) {
|
||||
console.log('link mode:', enabled);
|
||||
if (enabled) {
|
||||
|
@ -129,7 +322,7 @@ class CoreNetwork {
|
|||
}
|
||||
|
||||
setNodeMode(nodeType, model) {
|
||||
this.nodeType = NodeTypes[nodeType];
|
||||
this.nodeType = nodeType;
|
||||
this.nodeModel = model || null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,106 @@
|
|||
const SessionStates = {
|
||||
definition: 1,
|
||||
configuration: 2,
|
||||
instantiation: 3,
|
||||
runtime: 4,
|
||||
dataCollect: 5,
|
||||
shutdown: 6
|
||||
};
|
||||
|
||||
const SessionStateDisplay = {
|
||||
1: 'Definition',
|
||||
2: 'Configuration',
|
||||
3: 'Instantiation',
|
||||
4: 'Runtime',
|
||||
5: 'Data Collect',
|
||||
6: 'Shutdown'
|
||||
};
|
||||
|
||||
async function sendJson(url, data, type) {
|
||||
return await $.ajax({
|
||||
url,
|
||||
type,
|
||||
data: JSON.stringify(data),
|
||||
contentType: 'application/json',
|
||||
dataType: 'json'
|
||||
});
|
||||
}
|
||||
|
||||
async function postJson(url, data) {
|
||||
console.log('POST: ', url);
|
||||
return await sendJson(url, data, 'POST');
|
||||
}
|
||||
|
||||
async function putJson(url, data) {
|
||||
console.log('PUT: ', url);
|
||||
return await sendJson(url, data, 'PUT');
|
||||
}
|
||||
|
||||
class CoreRest {
|
||||
constructor() {
|
||||
this.currentSession = null;
|
||||
}
|
||||
|
||||
async sessions(callback) {
|
||||
const response = await $.getJSON('/sessions');
|
||||
callback(response);
|
||||
getStateName(state) {
|
||||
return SessionStateDisplay[state];
|
||||
}
|
||||
|
||||
async getSession() {
|
||||
return await $.getJSON(`/sessions/${this.currentSession}`);
|
||||
}
|
||||
|
||||
async getSessions() {
|
||||
return await $.getJSON('/sessions');
|
||||
}
|
||||
|
||||
async createSession() {
|
||||
return await postJson('/sessions');
|
||||
}
|
||||
|
||||
async shutdownSession() {
|
||||
return await this.setSessionState(SessionStates.shutdown);
|
||||
}
|
||||
|
||||
async setSessionState(state) {
|
||||
return await putJson(`/sessions/${this.currentSession}/state`, {state})
|
||||
}
|
||||
|
||||
async createNode(node) {
|
||||
return await postJson(`/sessions/${this.currentSession}/nodes`, node);
|
||||
}
|
||||
|
||||
async createLink(link) {
|
||||
return await postJson(`/sessions/${this.currentSession}/links`, link);
|
||||
}
|
||||
|
||||
async getLinks(nodeId) {
|
||||
return await $.getJSON(`/sessions/${this.currentSession}/nodes/${nodeId}/links`)
|
||||
}
|
||||
|
||||
async getNodeIps(nodeId, ip4Prefix, ip6Prefix) {
|
||||
return await postJson('/ips', {
|
||||
id: nodeId,
|
||||
ip4: ip4Prefix,
|
||||
ip6: ip6Prefix
|
||||
});
|
||||
}
|
||||
|
||||
async retrieveSession() {
|
||||
let response = await this.getSessions();
|
||||
const sessions = response.sessions;
|
||||
console.log('current sessions: ', sessions);
|
||||
const session = {id: 0, state: 0};
|
||||
|
||||
if (sessions.length) {
|
||||
this.currentSession = sessions[0].id;
|
||||
session.state = sessions[0].state;
|
||||
} else {
|
||||
response = await this.createSession();
|
||||
this.currentSession = response.id;
|
||||
session.state = response.state;
|
||||
}
|
||||
|
||||
session.id = this.currentSession;
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
|
BIN
webapp/static/host.gif
Normal file
After Width: | Height: | Size: 1.7 KiB |
197
webapp/static/hub.svg
Normal file
|
@ -0,0 +1,197 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="146"
|
||||
height="100"
|
||||
id="svg3868"
|
||||
version="1.1"
|
||||
inkscape:version="0.47 r22583"
|
||||
sodipodi:docname="hub.svg">
|
||||
<defs
|
||||
id="defs3870">
|
||||
<linearGradient
|
||||
id="linearGradient5149">
|
||||
<stop
|
||||
id="stop5151"
|
||||
offset="0"
|
||||
style="stop-color:#5dacd1;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop5153"
|
||||
offset="1"
|
||||
style="stop-color:#1b4a78;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4902">
|
||||
<stop
|
||||
style="stop-color:#484848;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4904" />
|
||||
<stop
|
||||
style="stop-color:#8f8f90;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4906" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective3876" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient12001"
|
||||
id="linearGradient4908"
|
||||
x1="5.8083773"
|
||||
y1="68.180191"
|
||||
x2="84.600281"
|
||||
y2="68.180191"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.269166,0,0,1.2912385,-2.3717949,931.82545)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient12001"
|
||||
id="linearGradient5039"
|
||||
x1="105"
|
||||
y1="55"
|
||||
x2="140"
|
||||
y2="55"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<inkscape:perspective
|
||||
id="perspective5049"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient12001"
|
||||
id="linearGradient3844"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.471308,0,0,0.471308,9.3066001,-238.48173)"
|
||||
x1="175.71875"
|
||||
y1="737.01562"
|
||||
x2="470.00089"
|
||||
y2="737.01562" />
|
||||
<linearGradient
|
||||
id="linearGradient12001">
|
||||
<stop
|
||||
style="stop-color:#1b4a78;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop12003" />
|
||||
<stop
|
||||
style="stop-color:#5dacd1;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop12005" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
id="perspective5135"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective5165"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="91.162404"
|
||||
inkscape:cy="35.126778"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="914"
|
||||
inkscape:window-height="668"
|
||||
inkscape:window-x="2157"
|
||||
inkscape:window-y="214"
|
||||
inkscape:window-maximized="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4935"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true"
|
||||
spacingx="0.5px"
|
||||
spacingy="0.5px" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata3873">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-952.36218)">
|
||||
<rect
|
||||
style="fill:url(#linearGradient4908);fill-opacity:1.0;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="rect4390"
|
||||
width="100"
|
||||
height="45"
|
||||
x="5"
|
||||
y="997.36218" />
|
||||
<path
|
||||
style="fill:url(#linearGradient5039);stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;fill-opacity:1.0"
|
||||
d="m 105,45 35,-40 0,45 -35,40 0,-45 z"
|
||||
id="path5031"
|
||||
transform="translate(0,952.36218)"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#3a78a0;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
|
||||
d="M 105,45 5,45 40,5 140,5 105,45 z"
|
||||
id="path5079"
|
||||
transform="translate(0,952.36218)" />
|
||||
<path
|
||||
style="fill:#f2fdff;fill-opacity:0.70980392000000003;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
d="m 32.5,979.86218 7.5,-7.5 77.5,0 -7.5,7.5 -77.5,0 z"
|
||||
id="path5255" />
|
||||
<path
|
||||
style="fill:#f2fdff;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:0.70980394"
|
||||
d="m 45,27.5 -7.5,7.5 10,0 7.5,-7.5 -10,0 z"
|
||||
id="path5259"
|
||||
transform="translate(0,952.36218)" />
|
||||
<path
|
||||
id="path5261"
|
||||
d="m 77.5,979.86218 -7.5,7.5 10,0 7.5,-7.5 -10,0 z"
|
||||
style="fill:#f2fdff;fill-opacity:0.70980392;stroke:none" />
|
||||
<path
|
||||
style="fill:#f2fdff;fill-opacity:0.70980392;stroke:none"
|
||||
d="m 70,964.86218 -7.5,7.5 10,0 7.5,-7.5 -10,0 z"
|
||||
id="path5263" />
|
||||
<path
|
||||
id="path5265"
|
||||
d="m 102.5,964.86218 -7.5,7.5 10,0 7.5,-7.5 -10,0 z"
|
||||
style="fill:#f2fdff;fill-opacity:0.70980392;stroke:none" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.4 KiB |
190
webapp/static/lanswitch.svg
Normal file
|
@ -0,0 +1,190 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="146"
|
||||
height="100"
|
||||
id="svg3868"
|
||||
version="1.1"
|
||||
inkscape:version="0.47 r22583"
|
||||
sodipodi:docname="switch.svg">
|
||||
<defs
|
||||
id="defs3870">
|
||||
<linearGradient
|
||||
id="linearGradient5149">
|
||||
<stop
|
||||
id="stop5151"
|
||||
offset="0"
|
||||
style="stop-color:#5dacd1;stop-opacity:1;" />
|
||||
<stop
|
||||
id="stop5153"
|
||||
offset="1"
|
||||
style="stop-color:#1b4a78;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient4902">
|
||||
<stop
|
||||
style="stop-color:#484848;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop4904" />
|
||||
<stop
|
||||
style="stop-color:#8f8f90;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4906" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 526.18109 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||
id="perspective3876" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient12001"
|
||||
id="linearGradient4908"
|
||||
x1="5.8083773"
|
||||
y1="68.180191"
|
||||
x2="84.600281"
|
||||
y2="68.180191"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(1.269166,0,0,1.2912385,-2.3717949,931.82545)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient12001"
|
||||
id="linearGradient5039"
|
||||
x1="105"
|
||||
y1="55"
|
||||
x2="140"
|
||||
y2="55"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<inkscape:perspective
|
||||
id="perspective5049"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient12001"
|
||||
id="linearGradient3844"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.471308,0,0,0.471308,9.3066001,-238.48173)"
|
||||
x1="175.71875"
|
||||
y1="737.01562"
|
||||
x2="470.00089"
|
||||
y2="737.01562" />
|
||||
<linearGradient
|
||||
id="linearGradient12001">
|
||||
<stop
|
||||
style="stop-color:#1b4a78;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop12003" />
|
||||
<stop
|
||||
style="stop-color:#5dacd1;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop12005" />
|
||||
</linearGradient>
|
||||
<inkscape:perspective
|
||||
id="perspective5135"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
<inkscape:perspective
|
||||
id="perspective5165"
|
||||
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
|
||||
inkscape:vp_z="1 : 0.5 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_x="0 : 0.5 : 1"
|
||||
sodipodi:type="inkscape:persp3d" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.8284271"
|
||||
inkscape:cx="91.162404"
|
||||
inkscape:cy="35.126778"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="809"
|
||||
inkscape:window-height="852"
|
||||
inkscape:window-x="605"
|
||||
inkscape:window-y="185"
|
||||
inkscape:window-maximized="0">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4935"
|
||||
empspacing="5"
|
||||
visible="true"
|
||||
enabled="true"
|
||||
snapvisiblegridlinesonly="true" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata3873">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-952.36218)">
|
||||
<rect
|
||||
style="fill:url(#linearGradient4908);fill-opacity:1.0;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
|
||||
id="rect4390"
|
||||
width="100"
|
||||
height="45"
|
||||
x="5"
|
||||
y="997.36218" />
|
||||
<path
|
||||
style="fill:url(#linearGradient5039);stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;fill-opacity:1.0"
|
||||
d="m 105,45 35,-40 0,45 -35,40 0,-45 z"
|
||||
id="path5031"
|
||||
transform="translate(0,952.36218)"
|
||||
sodipodi:nodetypes="ccccc" />
|
||||
<path
|
||||
style="fill:#3a78a0;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
|
||||
d="M 105,45 5,45 40,5 140,5 105,45 z"
|
||||
id="path5079"
|
||||
transform="translate(0,952.36218)" />
|
||||
<path
|
||||
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none"
|
||||
d="m 63.720704,982.3378 12.656877,-3.10116 12.656905,-3.10105 -3.523923,3.28427 18.978167,0.15164 -6.571234,6.1243 -18.978156,-0.15164 -3.523925,3.28426 -5.843452,-3.24896 -5.851259,-3.24166 z"
|
||||
id="path13511" />
|
||||
<path
|
||||
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none"
|
||||
d="M 80.174263,970.7443 74.367199,967.43074 68.560125,964.11719 65,967.36218 46.024691,967.0001 l -6.638732,6.05106 18.975309,0.36208 -3.560123,3.24499 12.690524,-2.96052 12.682595,-2.95341 z"
|
||||
id="path13513" />
|
||||
<path
|
||||
id="path5195"
|
||||
d="M 65.174263,985.7443 59.367199,982.43074 53.560125,979.11719 50,982.36218 31.024691,982.0001 l -6.638732,6.05106 18.975309,0.36208 -3.560123,3.24499 12.690524,-2.96052 12.682595,-2.95341 z"
|
||||
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none" />
|
||||
<path
|
||||
id="path5209"
|
||||
d="m 78.9675,967.75499 12.656877,-3.10116 12.656903,-3.10105 -3.52392,3.28427 18.97816,0.15164 -6.57123,6.1243 -18.978154,-0.15164 -3.523925,3.28426 -5.843452,-3.24896 -5.851259,-3.24166 z"
|
||||
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.5 KiB |
178
webapp/static/mdr.svg
Normal file
|
@ -0,0 +1,178 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="146"
|
||||
height="100"
|
||||
id="svg13653"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.47 r22583"
|
||||
sodipodi:docname="router.svg"
|
||||
version="1.0">
|
||||
<defs
|
||||
id="defs13655">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 99.931252 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="199.10001 : 99.931252 : 1"
|
||||
inkscape:persp3d-origin="99.550003 : 66.620834 : 1"
|
||||
id="perspective3835" />
|
||||
<linearGradient
|
||||
id="linearGradient12828">
|
||||
<stop
|
||||
id="stop12830"
|
||||
offset="0"
|
||||
style="stop-color:#484849;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#434344;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop12862" />
|
||||
<stop
|
||||
id="stop12832"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#8f8f90;stop-opacity:0.0000000;" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient12828"
|
||||
id="radialGradient13651"
|
||||
cx="328.57144"
|
||||
cy="602.7193"
|
||||
fx="328.57144"
|
||||
fy="602.7193"
|
||||
r="147.14285"
|
||||
gradientTransform="matrix(1,0,0,0.177184,0,495.9268)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient12001">
|
||||
<stop
|
||||
style="stop-color:#1b4a78;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop12003" />
|
||||
<stop
|
||||
style="stop-color:#5dacd1;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop12005" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient12001"
|
||||
id="linearGradient13633"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.471308,0,0,0.471308,118.8781,123.5182)"
|
||||
x1="175.71875"
|
||||
y1="737.01562"
|
||||
x2="470.00089"
|
||||
y2="737.01562" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient12001"
|
||||
id="linearGradient3844"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.471308,0,0,0.471308,-45.6934,-239.9103)"
|
||||
x1="175.71875"
|
||||
y1="737.01562"
|
||||
x2="470.00089"
|
||||
y2="737.01562" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="118.57814"
|
||||
inkscape:cy="50.488033"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="949"
|
||||
inkscape:window-x="1631"
|
||||
inkscape:window-y="29"
|
||||
showgrid="false"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata13658">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Capa 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-33.124945,-44.636248)">
|
||||
<path
|
||||
style="fill:url(#linearGradient3844);fill-opacity:1;stroke:none"
|
||||
d="m 37.14136,72.27878 0,0.29457 c 0.006,-0.0975 0.0206,-0.19729 0.0295,-0.29457 l -0.0295,0 z m 138.62351,0 c 0.0302,0.33044 0.0589,0.66821 0.0589,1.00153 l 0,-1.00153 -0.0589,0 z m 0.0589,1.00153 c -1e-5,15.05224 -31.07495,27.26223 -69.35594,27.26223 -37.68286,1e-5 -68.3765,-11.82771 -69.32649,-26.55527 l 0,40.67979 c -0.0151,0.23376 -0.0147,0.45704 -0.0147,0.69223 0,0.22546 8.7e-4,0.45335 0.0147,0.67751 0.91151,14.74102 31.61889,26.59945 69.32649,26.59945 37.7076,0 68.41498,-11.85843 69.32648,-26.59945 l 0.0295,0 0,-0.50077 c 9.5e-4,-0.0587 0,-0.11794 0,-0.17674 0,-0.0588 9.4e-4,-0.11803 0,-0.17674 l 0,-41.90224 z"
|
||||
id="path13626" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#3a78a0;fill-opacity:1;stroke:none"
|
||||
id="path11090"
|
||||
sodipodi:cx="328.57144"
|
||||
sodipodi:cy="602.7193"
|
||||
sodipodi:rx="147.14285"
|
||||
sodipodi:ry="26.071428"
|
||||
d="m 475.71429,602.7193 c 0,14.39885 -65.87809,26.07143 -147.14285,26.07143 -81.26475,0 -147.14285,-11.67258 -147.14285,-26.07143 0,-14.39885 65.8781,-26.07143 147.14285,-26.07143 81.26476,0 147.14285,11.67258 147.14285,26.07143 z"
|
||||
transform="matrix(0.471308,0,0,1.045917,-48.3838,-554.9944)" />
|
||||
<g
|
||||
id="g13565"
|
||||
style="fill:#f2fdff;fill-opacity:0.71171169"
|
||||
transform="matrix(0.84958,0.276715,-0.703617,0.334119,278.6313,-230.2001)">
|
||||
<path
|
||||
id="path13507"
|
||||
d="m 328.66945,592.8253 -5.97867,10.35298 -5.97867,10.35297 6.18436,0 0,21.24074 11.53226,0 0,-21.24074 6.18435,0 -5.97867,-10.35297 -5.96496,-10.35298 z"
|
||||
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none" />
|
||||
<path
|
||||
id="path13509"
|
||||
d="m 328.66945,687.10951 -5.97867,-10.35298 -5.97867,-10.35297 6.18436,0 0,-21.24074 11.53226,0 0,21.24074 6.18435,0 -5.97867,10.35297 -5.96496,10.35298 z"
|
||||
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none" />
|
||||
<path
|
||||
id="path13511"
|
||||
d="m 333.74751,639.82449 10.35297,-5.97867 10.35297,-5.97867 0,6.18436 21.24074,0 0,11.53225 -21.24074,0 0,6.18436 -10.35297,-5.97867 -10.35297,-5.96496 z"
|
||||
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none" />
|
||||
<path
|
||||
id="path13513"
|
||||
d="m 323.35667,639.82449 -10.35297,-5.97867 -10.35298,-5.97867 0,6.18436 -21.24073,0 0,11.53225 21.24073,0 0,6.18436 10.35298,-5.97867 10.35297,-5.96496 z"
|
||||
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none" />
|
||||
</g>
|
||||
<rect
|
||||
style="fill:#f2fdff;fill-opacity:0.70980394;stroke:#000000;stroke-opacity:1"
|
||||
id="rect6161"
|
||||
width="91.923882"
|
||||
height="37.476658"
|
||||
x="52.679455"
|
||||
y="60.048466"
|
||||
transform="translate(33.124945,44.636248)"
|
||||
rx="5.454824"
|
||||
ry="5.454824" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-size:32px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:DejaVu Sans;-inkscape-font-specification:Bitstream Charter Bold"
|
||||
x="91.107697"
|
||||
y="135.0903"
|
||||
id="text6673"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan6675"
|
||||
x="91.107697"
|
||||
y="135.0903">MDR</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.8 KiB |
BIN
webapp/static/pc.gif
Normal file
After Width: | Height: | Size: 1.8 KiB |
158
webapp/static/router.svg
Normal file
|
@ -0,0 +1,158 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="146"
|
||||
height="100"
|
||||
id="svg13653"
|
||||
sodipodi:version="0.32"
|
||||
inkscape:version="0.47 r22583"
|
||||
sodipodi:docname="router.svg"
|
||||
version="1.0">
|
||||
<defs
|
||||
id="defs13655">
|
||||
<inkscape:perspective
|
||||
sodipodi:type="inkscape:persp3d"
|
||||
inkscape:vp_x="0 : 99.931252 : 1"
|
||||
inkscape:vp_y="0 : 1000 : 0"
|
||||
inkscape:vp_z="199.10001 : 99.931252 : 1"
|
||||
inkscape:persp3d-origin="99.550003 : 66.620834 : 1"
|
||||
id="perspective3835" />
|
||||
<linearGradient
|
||||
id="linearGradient12828">
|
||||
<stop
|
||||
id="stop12830"
|
||||
offset="0"
|
||||
style="stop-color:#484849;stop-opacity:1;" />
|
||||
<stop
|
||||
style="stop-color:#434344;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop12862" />
|
||||
<stop
|
||||
id="stop12832"
|
||||
offset="1.0000000"
|
||||
style="stop-color:#8f8f90;stop-opacity:0.0000000;" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient12828"
|
||||
id="radialGradient13651"
|
||||
cx="328.57144"
|
||||
cy="602.7193"
|
||||
fx="328.57144"
|
||||
fy="602.7193"
|
||||
r="147.14285"
|
||||
gradientTransform="matrix(1,0,0,0.177184,0,495.9268)"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
id="linearGradient12001">
|
||||
<stop
|
||||
style="stop-color:#1b4a78;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop12003" />
|
||||
<stop
|
||||
style="stop-color:#5dacd1;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop12005" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient12001"
|
||||
id="linearGradient13633"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.471308,0,0,0.471308,118.8781,123.5182)"
|
||||
x1="175.71875"
|
||||
y1="737.01562"
|
||||
x2="470.00089"
|
||||
y2="737.01562" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient12001"
|
||||
id="linearGradient3844"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.471308,0,0,0.471308,-45.6934,-239.9103)"
|
||||
x1="175.71875"
|
||||
y1="737.01562"
|
||||
x2="470.00089"
|
||||
y2="737.01562" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.8"
|
||||
inkscape:cx="118.57814"
|
||||
inkscape:cy="50.488033"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="949"
|
||||
inkscape:window-x="289"
|
||||
inkscape:window-y="87"
|
||||
showgrid="false"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata13658">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Capa 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-33.124945,-44.636248)">
|
||||
<path
|
||||
style="fill:url(#linearGradient3844);fill-opacity:1;stroke:none"
|
||||
d="m 37.14136,72.27878 0,0.29457 c 0.006,-0.0975 0.0206,-0.19729 0.0295,-0.29457 l -0.0295,0 z m 138.62351,0 c 0.0302,0.33044 0.0589,0.66821 0.0589,1.00153 l 0,-1.00153 -0.0589,0 z m 0.0589,1.00153 c -1e-5,15.05224 -31.07495,27.26223 -69.35594,27.26223 -37.68286,1e-5 -68.3765,-11.82771 -69.32649,-26.55527 l 0,40.67979 c -0.0151,0.23376 -0.0147,0.45704 -0.0147,0.69223 0,0.22546 8.7e-4,0.45335 0.0147,0.67751 0.91151,14.74102 31.61889,26.59945 69.32649,26.59945 37.7076,0 68.41498,-11.85843 69.32648,-26.59945 l 0.0295,0 0,-0.50077 c 9.5e-4,-0.0587 0,-0.11794 0,-0.17674 0,-0.0588 9.4e-4,-0.11803 0,-0.17674 l 0,-41.90224 z"
|
||||
id="path13626" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#3a78a0;fill-opacity:1;stroke:none"
|
||||
id="path11090"
|
||||
sodipodi:cx="328.57144"
|
||||
sodipodi:cy="602.7193"
|
||||
sodipodi:rx="147.14285"
|
||||
sodipodi:ry="26.071428"
|
||||
d="m 475.71429,602.7193 c 0,14.39885 -65.87809,26.07143 -147.14285,26.07143 -81.26475,0 -147.14285,-11.67258 -147.14285,-26.07143 0,-14.39885 65.8781,-26.07143 147.14285,-26.07143 81.26476,0 147.14285,11.67258 147.14285,26.07143 z"
|
||||
transform="matrix(0.471308,0,0,1.045917,-48.3838,-554.9944)" />
|
||||
<g
|
||||
id="g13565"
|
||||
style="fill:#f2fdff;fill-opacity:0.71171169"
|
||||
transform="matrix(0.84958,0.276715,-0.703617,0.334119,278.6313,-230.2001)">
|
||||
<path
|
||||
id="path13507"
|
||||
d="m 328.66945,592.8253 -5.97867,10.35298 -5.97867,10.35297 6.18436,0 0,21.24074 11.53226,0 0,-21.24074 6.18435,0 -5.97867,-10.35297 -5.96496,-10.35298 z"
|
||||
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none" />
|
||||
<path
|
||||
id="path13509"
|
||||
d="m 328.66945,687.10951 -5.97867,-10.35298 -5.97867,-10.35297 6.18436,0 0,-21.24074 11.53226,0 0,21.24074 6.18435,0 -5.97867,10.35297 -5.96496,10.35298 z"
|
||||
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none" />
|
||||
<path
|
||||
id="path13511"
|
||||
d="m 333.74751,639.82449 10.35297,-5.97867 10.35297,-5.97867 0,6.18436 21.24074,0 0,11.53225 -21.24074,0 0,6.18436 -10.35297,-5.97867 -10.35297,-5.96496 z"
|
||||
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none" />
|
||||
<path
|
||||
id="path13513"
|
||||
d="m 323.35667,639.82449 -10.35297,-5.97867 -10.35298,-5.97867 0,6.18436 -21.24073,0 0,11.53225 21.24073,0 0,6.18436 10.35298,-5.97867 10.35297,-5.96496 z"
|
||||
style="fill:#f2fdff;fill-opacity:0.71171169;stroke:none" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 6.1 KiB |
1
webapp/static/socket.io.js.map
Normal file
BIN
webapp/static/wlan.gif
Normal file
After Width: | Height: | Size: 259 B |
|
@ -9,8 +9,11 @@
|
|||
</head>
|
||||
<body>
|
||||
<div class="container-fluid d-flex flex-column p-0">
|
||||
<nav class="navbar navbar-expand navbar-dark bg-info mb-2">
|
||||
<span class="navbar-brand mb-0 h1">CORE</span>
|
||||
<nav class="navbar navbar-expand navbar-dark bg-dark mb-2">
|
||||
<div class="navbar-brand mb-0 h1">
|
||||
<img src="static/core-icon.png" />
|
||||
<span>CORE</span>
|
||||
</div>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#nb-content"
|
||||
aria-controls="nb-content" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
|
@ -51,16 +54,15 @@
|
|||
</li>
|
||||
</ul>
|
||||
|
||||
<span class="navbar-text border rounded border-white p-2 mr-3">Session #</span>
|
||||
<span class="navbar-text border rounded border-white p-2">Node: Default</span>
|
||||
<span id="session-id" class="navbar-text p-2 mr-3">Session #</span>
|
||||
<span id="node-display" class="navbar-text p-2">Node: Default</span>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="row col">
|
||||
<div class="col-2 col-xl-1">
|
||||
<div class="btn-group-vertical w-100" role="group" aria-label="Side Menu">
|
||||
<button type="button" class="btn btn-secondary">Select</button>
|
||||
<button type="button" class="btn btn-secondary">Start</button>
|
||||
<button id="run-button" type="button" class="btn btn-success">Start</button>
|
||||
<button id="link-button" type="button" class="btn btn-secondary" data-toggle="button">Link Mode</button>
|
||||
<div class="btn-group dropright node-buttons" role="group">
|
||||
<button id="menu-nodes" type="button" class="btn btn-secondary dropdown-toggle"
|
||||
|
@ -100,25 +102,85 @@
|
|||
<script src="static/bootstrap.min.js"></script>
|
||||
<script src="static/vis.min.js"></script>
|
||||
<script src="static/socket.io.js"></script>
|
||||
<script src="static/coreip.js"></script>
|
||||
<script src="static/corerest.js"></script>
|
||||
<script src="static/corenetwork.js"></script>
|
||||
|
||||
<script>
|
||||
const core = new CoreRest();
|
||||
core.sessions(function (response) {
|
||||
console.log('session response: ', response);
|
||||
const $linkButton = $('#link-button');
|
||||
const $nodeButtons = $('.node-buttons a');
|
||||
const $sessionId = $('#session-id');
|
||||
const $nodeDisplay = $('#node-display');
|
||||
const $sessionsModel = $('#sessions-modal');
|
||||
const $sessionsTable = $('#sessions-table');
|
||||
const $runButton = $('#run-button');
|
||||
|
||||
function setRunButton(start) {
|
||||
const $runButton = $('#run-button');
|
||||
$runButton.removeClass('btn-danger btn-success');
|
||||
if (start) {
|
||||
$runButton.text('Start');
|
||||
$runButton.addClass('btn-success');
|
||||
} else {
|
||||
$runButton.text('Stop');
|
||||
$runButton.addClass('btn-danger');
|
||||
}
|
||||
}
|
||||
|
||||
// initial core setup
|
||||
const coreRest = new CoreRest();
|
||||
coreRest.retrieveSession()
|
||||
.then(function (session) {
|
||||
console.log('get session: ', session);
|
||||
$sessionId.text(`Session: ${session.id}`);
|
||||
if (session.state === SessionStates.runtime) {
|
||||
setRunButton(false);
|
||||
}
|
||||
|
||||
return coreRest.getSession();
|
||||
})
|
||||
.then(function(response) {
|
||||
console.log('session: ', response);
|
||||
const nodes = response.nodes;
|
||||
coreNetwork.joinedSessions(nodes);
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.log('get session error: ', err);
|
||||
});
|
||||
|
||||
const coreNetwork = new CoreNetwork('core-network');
|
||||
const coreNetwork = new CoreNetwork('core-network', coreRest);
|
||||
|
||||
const $linkButton = $('#link-button');
|
||||
// page interactions
|
||||
$linkButton.click(function () {
|
||||
const linkMode = !$(this).hasClass('active');
|
||||
coreNetwork.linkMode(linkMode);
|
||||
$(this).blur();
|
||||
});
|
||||
|
||||
const $nodeButtons = $('.node-buttons a');
|
||||
$runButton.click(function () {
|
||||
const $this = $(this);
|
||||
const start = $this.text() === 'Start';
|
||||
if (start) {
|
||||
coreNetwork.start()
|
||||
.then(function() {
|
||||
setRunButton(false);
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.log('start error: ', err);
|
||||
});
|
||||
} else {
|
||||
coreRest.shutdownSession()
|
||||
.then(function (response) {
|
||||
console.log('shutdown session: ', response);
|
||||
setRunButton(true);
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.log('shutdown error: ', err);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$nodeDisplay.text(`Node: ${coreNetwork.nodeModel}`);
|
||||
$nodeButtons.click(function () {
|
||||
const $this = $(this);
|
||||
const nodeType = $this.data('node');
|
||||
|
@ -126,6 +188,35 @@
|
|||
console.log('node creation: ', nodeType, model);
|
||||
console.log('clicked: ', this);
|
||||
coreNetwork.setNodeMode(nodeType, model);
|
||||
const currentType = getNodeType(coreNetwork.nodeType);
|
||||
const defaultType = getNodeType(0);
|
||||
let nodeDisplay = currentType.display;
|
||||
if (currentType.display === defaultType.display) {
|
||||
nodeDisplay = coreNetwork.nodeModel;
|
||||
}
|
||||
$nodeDisplay.text(`Node: ${nodeDisplay}`);
|
||||
});
|
||||
|
||||
// show sessions
|
||||
$sessionsModel.on('shown.bs.modal', function () {
|
||||
console.log('show sessions');
|
||||
$sessionsTable.find('tbody tr').remove();
|
||||
coreRest.getSessions()
|
||||
.then(function (response) {
|
||||
const sessions = response.sessions;
|
||||
for (let session of sessions) {
|
||||
console.log('show sessions: ', session);
|
||||
const $idCell = $('<th>', {scope: 'row', text: session.id});
|
||||
const $nodeCell = $('<td>', {text: session.nodes});
|
||||
const stateName = coreRest.getStateName(session.state);
|
||||
const $stateCell = $('<td>', {text: stateName});
|
||||
const $row = $('<tr>').append([$idCell, $nodeCell, $stateCell]);
|
||||
$sessionsTable.find('tbody').append($row);
|
||||
}
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.log('error getting sessions: ', err);
|
||||
});
|
||||
});
|
||||
|
||||
console.log('connecting to ws');
|
||||
|
|
|
@ -1,17 +1,27 @@
|
|||
<div id="sessions-modal" class="modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Modal title</h5>
|
||||
<div class="modal-header bg-dark text-white">
|
||||
<h5 class="modal-title">Sessions</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Modal body text goes here.</p>
|
||||
<table id="sessions-table" class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">ID</th>
|
||||
<th scope="col">Nodes</th>
|
||||
<th scope="col">State</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary">Save changes</button>
|
||||
<button type="button" class="btn btn-primary">Join</button>
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|