initial commit for a take on having a restful core api, along with an example scripts leveraging the available API calls
This commit is contained in:
parent
44781d0aec
commit
7c6c5edf46
5 changed files with 485 additions and 0 deletions
|
@ -52,6 +52,19 @@ def set_node_map(node_map):
|
|||
_log_map()
|
||||
|
||||
|
||||
def get_node_type(node_class):
|
||||
"""
|
||||
Retrieve the node type given a node class.
|
||||
|
||||
:param class node_class: node class to get type for
|
||||
:return: node type
|
||||
:rtype: core.enumerations.NodeTypes
|
||||
"""
|
||||
global _NODE_MAP
|
||||
node_type_map = {v: k for k, v in _NODE_MAP.iteritems()}
|
||||
return node_type_map.get(node_class)
|
||||
|
||||
|
||||
def get_node_class(node_type):
|
||||
"""
|
||||
Retrieve the node class for a given node type.
|
||||
|
|
0
daemon/core/rest/__init__.py
Normal file
0
daemon/core/rest/__init__.py
Normal file
294
daemon/core/rest/corerest.py
Normal file
294
daemon/core/rest/corerest.py
Normal file
|
@ -0,0 +1,294 @@
|
|||
from flask import Flask
|
||||
from flask import jsonify
|
||||
from flask import request
|
||||
|
||||
from core import logger
|
||||
from core.enumerations import EventTypes, NodeTypes, LinkTypes
|
||||
from core.future.coreemu import CoreEmu
|
||||
from core.future.futuredata import NodeOptions, LinkOptions, InterfaceData
|
||||
from core.misc import nodeutils
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
coreemu = CoreEmu()
|
||||
|
||||
|
||||
def link_data_str(link, key):
|
||||
value = link.get(key)
|
||||
if value:
|
||||
link[key] = str(value)
|
||||
|
||||
|
||||
@app.route("/sessions")
|
||||
def get_sessions():
|
||||
sessions = []
|
||||
for session in coreemu.sessions.itervalues():
|
||||
sessions.append({
|
||||
"id": session.session_id,
|
||||
"nodes": session.get_node_count()
|
||||
})
|
||||
return jsonify(sessions=sessions)
|
||||
|
||||
|
||||
@app.route("/sessions", methods=["POST"])
|
||||
def create_session():
|
||||
session = coreemu.create_session()
|
||||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||
response_data = jsonify(
|
||||
id=session.session_id,
|
||||
url="/sessions/%s" % session.session_id
|
||||
)
|
||||
return response_data, 201
|
||||
|
||||
|
||||
@app.route("/sessions/<int:session_id>", methods=["DELETE"])
|
||||
def delete_session(session_id):
|
||||
result = coreemu.delete_session(session_id)
|
||||
if result:
|
||||
return jsonify()
|
||||
else:
|
||||
return jsonify(error="session does not exist"), 404
|
||||
|
||||
|
||||
@app.route("/sessions/<int:session_id>")
|
||||
def get_session(session_id):
|
||||
session = coreemu.sessions.get(session_id)
|
||||
if not session:
|
||||
return jsonify(error="session does not exist"), 404
|
||||
|
||||
nodes = []
|
||||
for node in session.objects.itervalues():
|
||||
nodes.append({
|
||||
"id": node.objid,
|
||||
"name": node.name,
|
||||
"type": nodeutils.get_node_type(node.__class__).value,
|
||||
"position": {
|
||||
"x": node.position.x,
|
||||
"y": node.position.y,
|
||||
"z": node.position.z
|
||||
},
|
||||
"url": "/sessions/%s/nodes/%s" % (session_id, node.objid)
|
||||
})
|
||||
state = EventTypes(session.state)
|
||||
|
||||
return jsonify(
|
||||
state=state.name,
|
||||
nodes=nodes
|
||||
)
|
||||
|
||||
|
||||
@app.route("/sessions/<int:session_id>/nodes", methods=["POST"])
|
||||
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_type = data.get("type", NodeTypes.DEFAULT.value)
|
||||
node_type = NodeTypes(node_type)
|
||||
logger.info("creating node: %s - %s", node_type.name, data)
|
||||
|
||||
node_options = NodeOptions(
|
||||
name=data.get("name"),
|
||||
model=data.get("model")
|
||||
)
|
||||
node_options.icon = data.get("icon")
|
||||
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)
|
||||
return jsonify(
|
||||
id=node.objid,
|
||||
url="/sessions/%s/nodes/%s" % (session_id, node.objid)
|
||||
), 201
|
||||
|
||||
|
||||
@app.route("/sessions/<int:session_id>/nodes/<node_id>")
|
||||
def get_node(session_id, node_id):
|
||||
session = coreemu.sessions.get(session_id)
|
||||
if not session:
|
||||
return jsonify(error="session does not exist"), 404
|
||||
|
||||
if node_id.isdigit():
|
||||
node_id = int(node_id)
|
||||
node = session.objects.get(node_id)
|
||||
if not node:
|
||||
return jsonify(error="node does not exist"), 404
|
||||
|
||||
interfaces = []
|
||||
for interface_id, interface in node._netif.iteritems():
|
||||
net_id = None
|
||||
if interface.net:
|
||||
net_id = interface.net.objid
|
||||
|
||||
interfaces.append({
|
||||
"id": interface_id,
|
||||
"netid": net_id,
|
||||
"name": interface.name,
|
||||
"mac": str(interface.hwaddr),
|
||||
"mtu": interface.mtu,
|
||||
"flowid": interface.flow_id
|
||||
})
|
||||
|
||||
return jsonify(
|
||||
name=node.name,
|
||||
type=nodeutils.get_node_type(node.__class__).value,
|
||||
model=node.type,
|
||||
interfaces=interfaces,
|
||||
linksurl="/sessions/%s/nodes/%s/links" % (session_id, node.objid)
|
||||
)
|
||||
|
||||
|
||||
@app.route("/sessions/<int:session_id>/nodes/<node_id>", methods=["DELETE"])
|
||||
def delete_node(session_id, node_id):
|
||||
session = coreemu.sessions.get(session_id)
|
||||
if not session:
|
||||
return jsonify(error="session does not exist"), 404
|
||||
|
||||
if node_id.isdigit():
|
||||
node_id = int(node_id)
|
||||
node = session.objects.get(node_id)
|
||||
if not node:
|
||||
return jsonify(error="node does not exist"), 404
|
||||
|
||||
result = session.delete_node(node_id)
|
||||
if result:
|
||||
return jsonify()
|
||||
else:
|
||||
return jsonify(error="failure to delete node"), 404
|
||||
|
||||
|
||||
@app.route("/sessions/<int:session_id>/state", methods=["PUT"])
|
||||
def set_session_state(session_id):
|
||||
session = coreemu.sessions.get(session_id)
|
||||
if not session:
|
||||
return jsonify(error="session does not exist"), 404
|
||||
|
||||
data = request.get_json()
|
||||
try:
|
||||
state = EventTypes(data["state"])
|
||||
session.set_state(state)
|
||||
|
||||
if state == EventTypes.INSTANTIATION_STATE:
|
||||
session.instantiate()
|
||||
elif state == EventTypes.SHUTDOWN_STATE:
|
||||
session.shutdown()
|
||||
elif state == EventTypes.DATACOLLECT_STATE:
|
||||
session.data_collect()
|
||||
elif state == EventTypes.DEFINITION_STATE:
|
||||
session.clear()
|
||||
|
||||
return jsonify()
|
||||
except KeyError:
|
||||
return jsonify(error="invalid state"), 404
|
||||
|
||||
|
||||
@app.route("/sessions/<int:session_id>/links", methods=["POST"])
|
||||
def add_link(session_id):
|
||||
session = coreemu.sessions.get(session_id)
|
||||
if not session:
|
||||
return jsonify(error="session does not exist"), 404
|
||||
|
||||
data = request.get_json()
|
||||
|
||||
node_one = data.get("node_one")
|
||||
node_two = data.get("node_two")
|
||||
|
||||
interface_one = None
|
||||
interface_one_data = data.get("interface_one")
|
||||
if interface_one_data:
|
||||
interface_one = InterfaceData(
|
||||
_id=interface_one_data.get("id"),
|
||||
name=interface_one_data.get("name"),
|
||||
mac=interface_one_data.get("mac"),
|
||||
ip4=interface_one_data.get("ip4"),
|
||||
ip4_mask=interface_one_data.get("ip4mask"),
|
||||
ip6=interface_one_data.get("ip6"),
|
||||
ip6_mask=interface_one_data.get("ip6mask"),
|
||||
)
|
||||
|
||||
interface_two = None
|
||||
interface_two_data = data.get("interface_two")
|
||||
if interface_two_data:
|
||||
interface_two = InterfaceData(
|
||||
_id=interface_two_data.get("id"),
|
||||
name=interface_two_data.get("name"),
|
||||
mac=interface_two_data.get("mac"),
|
||||
ip4=interface_two_data.get("ip4"),
|
||||
ip4_mask=interface_two_data.get("ip4mask"),
|
||||
ip6=interface_two_data.get("ip6"),
|
||||
ip6_mask=interface_two_data.get("ip6mask"),
|
||||
)
|
||||
|
||||
link_type = None
|
||||
link_type_value = data.get("type")
|
||||
if link_type_value is not None:
|
||||
link_type = LinkTypes(link_type_value)
|
||||
|
||||
options_data = data.get("options")
|
||||
link_options = LinkOptions(_type=link_type)
|
||||
if options_data:
|
||||
link_options.delay = options_data.get("delay")
|
||||
link_options.bandwidth = options_data.get("bandwidth")
|
||||
link_options.session = options_data.get("session")
|
||||
link_options.per = options_data.get("per")
|
||||
link_options.dup = options_data.get("dup")
|
||||
link_options.jitter = options_data.get("jitter")
|
||||
link_options.mer = options_data.get("mer")
|
||||
link_options.burst = options_data.get("burst")
|
||||
link_options.mburst = options_data.get("mburst")
|
||||
link_options.unidirectional = options_data.get("unidirectional")
|
||||
link_options.key = options_data.get("key")
|
||||
link_options.opaque = options_data.get("opaque")
|
||||
|
||||
link_options = LinkOptions()
|
||||
session.add_link(node_one, node_two, interface_one, interface_two, link_options=link_options)
|
||||
|
||||
return jsonify(), 201
|
||||
|
||||
|
||||
@app.route("/sessions/<int:session_id>/links", methods=["DELETE"])
|
||||
def delete_link(session_id):
|
||||
session = coreemu.sessions.get(session_id)
|
||||
if not session:
|
||||
return jsonify(error="session does not exist"), 404
|
||||
|
||||
data = request.get_json()
|
||||
node_one = data.get("node_one")
|
||||
node_two = data.get("node_two")
|
||||
interface_one = data.get("interface_one")
|
||||
interface_two = data.get("interface_two")
|
||||
session.delete_link(node_one, node_two, interface_one, interface_two)
|
||||
return jsonify()
|
||||
|
||||
|
||||
@app.route("/sessions/<int:session_id>/nodes/<node_id>/links")
|
||||
def get_node_links(session_id, node_id):
|
||||
session = coreemu.sessions.get(session_id)
|
||||
if not session:
|
||||
return jsonify(error="session does not exist"), 404
|
||||
|
||||
if node_id.isdigit():
|
||||
node_id = int(node_id)
|
||||
node = session.objects.get(node_id)
|
||||
if not node:
|
||||
return jsonify(error="node does not exist"), 404
|
||||
|
||||
links_data = node.all_link_data(0)
|
||||
links = []
|
||||
for link_data in links_data:
|
||||
link = link_data._asdict()
|
||||
del link["message_type"]
|
||||
link_data_str(link, "interface1_ip4")
|
||||
link_data_str(link, "interface1_ip6")
|
||||
link_data_str(link, "interface1_mac")
|
||||
link_data_str(link, "interface2_ip4")
|
||||
link_data_str(link, "interface2_ip6")
|
||||
link_data_str(link, "interface2_mac")
|
||||
links.append(link)
|
||||
|
||||
return jsonify(links=links)
|
||||
|
||||
|
||||
def start():
|
||||
app.run(host="0.0.0.0")
|
172
daemon/examples/rest/rest_example.py
Normal file
172
daemon/examples/rest/rest_example.py
Normal file
|
@ -0,0 +1,172 @@
|
|||
import pprint
|
||||
import sys
|
||||
import time
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
class CoreRestClient(object):
|
||||
def __init__(self, address):
|
||||
self.base_url = "http://%s" % address
|
||||
|
||||
def _create_url(self, path):
|
||||
return "%s%s" % (self.base_url, path)
|
||||
|
||||
def _delete(self, path, json_data=None):
|
||||
url = self._create_url(path)
|
||||
print "DELETE: %s" % url
|
||||
response = requests.delete(url, json=json_data)
|
||||
response_json = response.json()
|
||||
pprint.pprint(response_json)
|
||||
return response_json
|
||||
|
||||
def _post(self, path, json_data=None):
|
||||
url = self._create_url(path)
|
||||
print "POST: %s" % url
|
||||
response = requests.post(url, json=json_data)
|
||||
response_json = response.json()
|
||||
pprint.pprint(response_json)
|
||||
return response_json
|
||||
|
||||
def _put(self, path, json_data=None):
|
||||
url = self._create_url(path)
|
||||
print "PUT: %s" % url
|
||||
response = requests.put(url, json=json_data)
|
||||
response_json = response.json()
|
||||
pprint.pprint(response_json)
|
||||
return response_json
|
||||
|
||||
def _get(self, path):
|
||||
url = self._create_url(path)
|
||||
print "GET: %s" % url
|
||||
response = requests.get(url)
|
||||
response_json = response.json()
|
||||
pprint.pprint(response_json)
|
||||
return response_json
|
||||
|
||||
def create_session(self):
|
||||
return self._post("/sessions")
|
||||
|
||||
def get_sessions(self):
|
||||
return self._get("/sessions")
|
||||
|
||||
def get_session(self, session_id):
|
||||
return self._get("/sessions/%s" % session_id)
|
||||
|
||||
def delete_session(self, session_id):
|
||||
return self._delete("/sessions/%s" % session_id)
|
||||
|
||||
def set_state(self, session_id, state):
|
||||
return self._put("/sessions/%s/state" % session_id, json_data={"state": state})
|
||||
|
||||
def add_node(self, session_id, options=None):
|
||||
return self._post("/sessions/%s/nodes" % session_id, json_data=options)
|
||||
|
||||
def delete_node(self, session_id, node_id):
|
||||
return self._delete("/sessions/%s/nodes/%s" % (session_id, node_id))
|
||||
|
||||
def get_node(self, session_id, node_id):
|
||||
return self._get("/sessions/%s/nodes/%s" % (session_id, node_id))
|
||||
|
||||
def get_node_links(self, session_id, node_id):
|
||||
return self._get("/sessions/%s/nodes/%s/links" % (session_id, node_id))
|
||||
|
||||
def add_link(self, session_id, link):
|
||||
return self._post("/sessions/%s/links" % session_id, json_data=link)
|
||||
|
||||
def delete_link(self, session_id, link):
|
||||
return self._delete("/sessions/%s/links" % session_id, json_data=link)
|
||||
|
||||
|
||||
def main():
|
||||
address = sys.argv[1]
|
||||
client = CoreRestClient(address)
|
||||
|
||||
# create session
|
||||
create_response = client.create_session()
|
||||
session_id = create_response["id"]
|
||||
|
||||
# query all sessions
|
||||
client.get_sessions()
|
||||
|
||||
# query session
|
||||
client.get_session(session_id)
|
||||
|
||||
# set state to CONFIGURATION
|
||||
client.set_state(session_id, 2)
|
||||
|
||||
# create nodes for small switch networkW
|
||||
node_one_response = client.add_node(session_id)
|
||||
node_one_id = node_one_response["id"]
|
||||
node_two_response = client.add_node(session_id)
|
||||
node_two_id = node_two_response["id"]
|
||||
switch_options = {
|
||||
"type": 4
|
||||
}
|
||||
switch_node_response = client.add_node(session_id, switch_options)
|
||||
switch_id = switch_node_response["id"]
|
||||
|
||||
# link nodes to switch
|
||||
link = {
|
||||
"node_one": node_one_id,
|
||||
"node_two": switch_id,
|
||||
"interface_one": {
|
||||
"id": 0,
|
||||
"ip4": "10.0.0.2",
|
||||
"ip4mask": 16
|
||||
}
|
||||
}
|
||||
client.add_link(session_id, link)
|
||||
link = {
|
||||
"node_one": node_two_id,
|
||||
"node_two": switch_id,
|
||||
"interface_one": {
|
||||
"id": 0,
|
||||
"ip4": "10.0.0.3",
|
||||
"ip4mask": 16
|
||||
}
|
||||
}
|
||||
client.add_link(session_id, link)
|
||||
|
||||
# set state to INSTANTIATION
|
||||
client.set_state(session_id, 3)
|
||||
time.sleep(3)
|
||||
|
||||
# get node information
|
||||
client.get_node(session_id, node_one_id)
|
||||
client.get_node(session_id, node_two_id)
|
||||
client.get_node(session_id, switch_id)
|
||||
|
||||
# get links informations
|
||||
client.get_node_links(session_id, node_one_id)
|
||||
client.get_node_links(session_id, node_two_id)
|
||||
client.get_node_links(session_id, switch_id)
|
||||
|
||||
# delete links
|
||||
delete_link = {
|
||||
"node_one": node_one_id,
|
||||
"node_two": switch_id,
|
||||
"interface_one": 0,
|
||||
}
|
||||
client.delete_link(session_id, delete_link)
|
||||
delete_link = {
|
||||
"node_one": node_two_id,
|
||||
"node_two": switch_id,
|
||||
"interface_one": 0
|
||||
}
|
||||
client.delete_link(session_id, delete_link)
|
||||
|
||||
# delete nodes
|
||||
client.delete_node(session_id, node_one_id)
|
||||
client.delete_node(session_id, node_two_id)
|
||||
client.delete_node(session_id, switch_id)
|
||||
|
||||
# delete session
|
||||
client.delete_session(session_id)
|
||||
|
||||
# query all sessions
|
||||
client.get_sessions()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
6
daemon/scripts/core-rest
Normal file
6
daemon/scripts/core-rest
Normal file
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from core.rest import corerest
|
||||
|
||||
if __name__ == "__main__":
|
||||
corerest.start()
|
Loading…
Add table
Reference in a new issue