Drop Python 3.4 and switch to async / await syntax for asyncio. Fixes #1425

This commit is contained in:
grossmj committed 2018-10-15 17:05:49 +07:00
1 parent 8baa480b79
commit 76af98404a
119 files changed
+2432 -3084

No files matched your search

@@ -34,11 +34,11 @@ class ApplianceHandler:
status_codes={
200: "Appliance template list returned"
})
def list_templates(request, response):
async def list_templates(request, response):
controller = Controller.instance()
if request.query.get("update", "no") == "yes":
yield from controller.download_appliance_templates()
await controller.download_appliance_templates()
controller.load_appliance_templates()
response.json([c for c in controller.appliance_templates.values()])
@@ -66,11 +66,11 @@ class ApplianceHandler:
},
input=APPLIANCE_USAGE_SCHEMA,
output=NODE_OBJECT_SCHEMA)
def create_node_from_appliance(request, response):
async def create_node_from_appliance(request, response):
controller = Controller.instance()
project = controller.get_project(request.match_info["project_id"])
yield from project.add_node_from_appliance(request.match_info["appliance_id"],
await project.add_node_from_appliance(request.match_info["appliance_id"],
x=request.json["x"],
y=request.json["y"],
compute_id=request.json.get("compute_id"))
@@ -41,9 +41,9 @@ class ComputeHandler:
},
input=COMPUTE_CREATE_SCHEMA,
output=COMPUTE_OBJECT_SCHEMA)
def create(request, response):
async def create(request, response):
compute = yield from Controller.instance().add_compute(**request.json)
compute = await Controller.instance().add_compute(**request.json)
response.set_status(201)
response.json(compute)
@@ -68,14 +68,14 @@ class ComputeHandler:
},
input=COMPUTE_UPDATE_SCHEMA,
output=COMPUTE_OBJECT_SCHEMA)
def update(request, response):
async def update(request, response):
controller = Controller.instance()
compute = controller.get_compute(request.match_info["compute_id"])
# Ignore these because we only use them when creating a node
request.json.pop("compute_id", None)
yield from compute.update(**request.json)
await compute.update(**request.json)
response.set_status(200)
response.json(compute)
@@ -89,10 +89,10 @@ class ComputeHandler:
404: "Instance doesn't exist"
},
description="Return the list of images available on compute and controller for this emulator type")
def images(request, response):
async def images(request, response):
controller = Controller.instance()
compute = controller.get_compute(request.match_info["compute_id"])
res = yield from compute.images(request.match_info["emulator"])
res = await compute.images(request.match_info["emulator"])
response.json(res)
@Route.get(
@@ -133,10 +133,10 @@ class ComputeHandler:
404: "Instance doesn't exist"
},
description="Forward call specific to compute node. Read the full compute API for available actions")
def get_forward(request, response):
async def get_forward(request, response):
controller = Controller.instance()
compute = controller.get_compute(request.match_info["compute_id"])
res = yield from compute.forward("GET", request.match_info["emulator"], request.match_info["action"])
res = await compute.forward("GET", request.match_info["emulator"], request.match_info["action"])
response.json(res)
@Route.post(
@@ -150,10 +150,10 @@ class ComputeHandler:
},
raw=True,
description="Forward call specific to compute node. Read the full compute API for available actions")
def post_forward(request, response):
async def post_forward(request, response):
controller = Controller.instance()
compute = controller.get_compute(request.match_info["compute_id"])
res = yield from compute.forward("POST", request.match_info["emulator"], request.match_info["action"], data=request.content)
res = await compute.forward("POST", request.match_info["emulator"], request.match_info["action"], data=request.content)
response.json(res)
@Route.put(
@@ -167,10 +167,10 @@ class ComputeHandler:
},
raw=True,
description="Forward call specific to compute node. Read the full compute API for available actions")
def put_forward(request, response):
async def put_forward(request, response):
controller = Controller.instance()
compute = controller.get_compute(request.match_info["compute_id"])
res = yield from compute.forward("PUT", request.match_info["emulator"], request.match_info["action"], data=request.content)
res = await compute.forward("PUT", request.match_info["emulator"], request.match_info["action"], data=request.content)
response.json(res)
@Route.get(
@@ -197,9 +197,9 @@ class ComputeHandler:
404: "Instance doesn't exist"
},
description="Delete a compute instance")
def delete(request, response):
async def delete(request, response):
controller = Controller.instance()
yield from controller.delete_compute(request.match_info["compute_id"])
await controller.delete_compute(request.match_info["compute_id"])
response.set_status(204)
@Route.post(
@@ -211,9 +211,9 @@ class ComputeHandler:
200: "Idle PC computed",
},
description="Compute IDLE PC value")
def autoidlepc(request, response):
async def autoidlepc(request, response):
controller = Controller.instance()
res = yield from controller.autoidlepc(request.match_info["compute_id"], request.json["platform"], request.json["image"], request.json["ram"])
res = await controller.autoidlepc(request.match_info["compute_id"], request.json["platform"], request.json["image"], request.json["ram"])
response.json(res)
@Route.get(
@@ -226,8 +226,8 @@ class ComputeHandler:
},
description="Get ports used by a compute",
output=COMPUTE_PORTS_OBJECT_SCHEMA)
def ports(request, response):
async def ports(request, response):
controller = Controller.instance()
res = yield from controller.compute_ports(request.match_info["compute_id"])
res = await controller.compute_ports(request.match_info["compute_id"])
response.json(res)
@@ -37,9 +37,9 @@ class DrawingHandler:
200: "List of drawings returned",
},
description="List drawings of a project")
def list_drawings(request, response):
async def list_drawings(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
response.json([v for v in project.drawings.values()])
@Route.post(
@@ -54,10 +54,10 @@ class DrawingHandler:
description="Create a new drawing instance",
input=DRAWING_OBJECT_SCHEMA,
output=DRAWING_OBJECT_SCHEMA)
def create(request, response):
async def create(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
drawing = yield from project.add_drawing(**request.json)
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
drawing = await project.add_drawing(**request.json)
response.set_status(201)
response.json(drawing)
@@ -74,9 +74,9 @@ class DrawingHandler:
},
description="Get a drawing instance",
output=DRAWING_OBJECT_SCHEMA)
def get_drawing(request, response):
async def get_drawing(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
drawing = project.get_drawing(request.match_info["drawing_id"])
response.set_status(200)
response.json(drawing)
@@ -94,11 +94,11 @@ class DrawingHandler:
description="Update a drawing instance",
input=DRAWING_OBJECT_SCHEMA,
output=DRAWING_OBJECT_SCHEMA)
def update(request, response):
async def update(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
drawing = project.get_drawing(request.match_info["drawing_id"])
yield from drawing.update(**request.json)
await drawing.update(**request.json)
response.set_status(201)
response.json(drawing)
@@ -113,8 +113,8 @@ class DrawingHandler:
400: "Invalid request"
},
description="Delete a drawing instance")
def delete(request, response):
async def delete(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
yield from project.delete_drawing(request.match_info["drawing_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
await project.delete_drawing(request.match_info["drawing_id"])
response.set_status(204)
@@ -49,9 +49,9 @@ class GNS3VMHandler:
400: "Invalid request",
},
description="Get all the available VMs for a specific virtualization engine")
def get_vms(request, response):
async def get_vms(request, response):
vms = yield from Controller.instance().gns3vm.list(request.match_info["engine"])
vms = await Controller.instance().gns3vm.list(request.match_info["engine"])
response.json(vms)
@Route.get(
@@ -72,9 +72,9 @@ class GNS3VMHandler:
status_codes={
201: "GNS3 VM updated"
})
def update(request, response):
async def update(request, response):
gns3_vm = Controller().instance().gns3vm
yield from gns3_vm.update_settings(request.json)
await gns3_vm.update_settings(request.json)
response.json(gns3_vm)
response.set_status(201)
@@ -42,9 +42,9 @@ class LinkHandler:
200: "List of links returned",
},
description="List links of a project")
def list_links(request, response):
async def list_links(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
response.json([v for v in project.links.values()])
@Route.post(
@@ -59,22 +59,22 @@ class LinkHandler:
description="Create a new link instance",
input=LINK_OBJECT_SCHEMA,
output=LINK_OBJECT_SCHEMA)
def create(request, response):
async def create(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
link = yield from project.add_link()
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
link = await project.add_link()
if "filters" in request.json:
yield from link.update_filters(request.json["filters"])
await link.update_filters(request.json["filters"])
if "suspend" in request.json:
yield from link.update_suspend(request.json["suspend"])
await link.update_suspend(request.json["suspend"])
try:
for node in request.json["nodes"]:
yield from link.add_node(project.get_node(node["node_id"]),
await link.add_node(project.get_node(node["node_id"]),
node.get("adapter_number", 0),
node.get("port_number", 0),
label=node.get("label"))
except aiohttp.web.HTTPException as e:
yield from project.delete_link(link.id)
await project.delete_link(link.id)
raise e
response.set_status(201)
response.json(link)
@@ -90,9 +90,9 @@ class LinkHandler:
400: "Invalid request"
},
description="Return the list of filters available for this link")
def list_filters(request, response):
async def list_filters(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
link = project.get_link(request.match_info["link_id"])
response.set_status(200)
response.json(link.available_filters())
@@ -110,9 +110,9 @@ class LinkHandler:
},
description="Get a link instance",
output=LINK_OBJECT_SCHEMA)
def get_link(request, response):
async def get_link(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
link = project.get_link(request.match_info["link_id"])
response.set_status(200)
response.json(link)
@@ -130,16 +130,16 @@ class LinkHandler:
description="Update a link instance",
input=LINK_OBJECT_SCHEMA,
output=LINK_OBJECT_SCHEMA)
def update(request, response):
async def update(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
link = project.get_link(request.match_info["link_id"])
if "filters" in request.json:
yield from link.update_filters(request.json["filters"])
await link.update_filters(request.json["filters"])
if "suspend" in request.json:
yield from link.update_suspend(request.json["suspend"])
await link.update_suspend(request.json["suspend"])
if "nodes" in request.json:
yield from link.update_nodes(request.json["nodes"])
await link.update_nodes(request.json["nodes"])
response.set_status(201)
response.json(link)
@@ -156,11 +156,11 @@ class LinkHandler:
input=LINK_CAPTURE_SCHEMA,
output=LINK_OBJECT_SCHEMA,
description="Start capture on a link instance. By default we consider it as an Ethernet link")
def start_capture(request, response):
async def start_capture(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
link = project.get_link(request.match_info["link_id"])
yield from link.start_capture(data_link_type=request.json.get("data_link_type", "DLT_EN10MB"), capture_file_name=request.json.get("capture_file_name"))
await link.start_capture(data_link_type=request.json.get("data_link_type", "DLT_EN10MB"), capture_file_name=request.json.get("capture_file_name"))
response.set_status(201)
response.json(link)
@@ -175,11 +175,11 @@ class LinkHandler:
400: "Invalid request"
},
description="Stop capture on a link instance")
def stop_capture(request, response):
async def stop_capture(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
link = project.get_link(request.match_info["link_id"])
yield from link.stop_capture()
await link.stop_capture()
response.set_status(201)
response.json(link)
@@ -194,10 +194,10 @@ class LinkHandler:
400: "Invalid request"
},
description="Delete a link instance")
def delete(request, response):
async def delete(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
yield from project.delete_link(request.match_info["link_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
await project.delete_link(request.match_info["link_id"])
response.set_status(204)
@Route.get(
@@ -212,16 +212,16 @@ class LinkHandler:
403: "Permission denied",
404: "The file doesn't exist"
})
def pcap(request, response):
async def pcap(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
link = project.get_link(request.match_info["link_id"])
while link.capture_file_path is None:
raise aiohttp.web.HTTPNotFound(text="pcap file not found")
while not os.path.isfile(link.capture_file_path):
yield from asyncio.sleep(0.5)
await asyncio.sleep(0.5)
try:
with open(link.capture_file_path, "rb") as f:
@@ -229,12 +229,12 @@ class LinkHandler:
response.content_type = "application/vnd.tcpdump.pcap"
response.set_status(200)
response.enable_chunked_encoding()
yield from response.prepare(request)
await response.prepare(request)
while True:
chunk = f.read(4096)
if not chunk:
yield from asyncio.sleep(0.1)
yield from response.write(chunk)
await asyncio.sleep(0.1)
await response.write(chunk)
except OSError:
raise aiohttp.web.HTTPNotFound(text="pcap file {} not found or not accessible".format(link.capture_file_path))
@@ -46,12 +46,12 @@ class NodeHandler:
description="Create a new node instance",
input=NODE_CREATE_SCHEMA,
output=NODE_OBJECT_SCHEMA)
def create(request, response):
async def create(request, response):
controller = Controller.instance()
compute = controller.get_compute(request.json.pop("compute_id"))
project = yield from controller.get_loaded_project(request.match_info["project_id"])
node = yield from project.add_node(compute, request.json.pop("name"), request.json.pop("node_id", None), **request.json)
project = await controller.get_loaded_project(request.match_info["project_id"])
node = await project.add_node(compute, request.json.pop("name"), request.json.pop("node_id", None), **request.json)
response.set_status(201)
response.json(node)
@@ -79,9 +79,9 @@ class NodeHandler:
200: "List of nodes returned",
},
description="List nodes of a project")
def list_nodes(request, response):
async def list_nodes(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
response.json([v for v in project.nodes.values()])
@Route.put(
@@ -94,8 +94,8 @@ class NodeHandler:
description="Update a node instance",
input=NODE_UPDATE_SCHEMA,
output=NODE_OBJECT_SCHEMA)
def update(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
async def update(request, response):
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
node = project.get_node(request.match_info["node_id"])
# Ignore these because we only use them when creating a node
@@ -103,7 +103,7 @@ class NodeHandler:
request.json.pop("node_type", None)
request.json.pop("compute_id", None)
yield from node.update(**request.json)
await node.update(**request.json)
response.set_status(200)
response.json(node)
@@ -119,10 +119,10 @@ class NodeHandler:
},
description="Start all nodes belonging to the project",
output=NODE_OBJECT_SCHEMA)
def start_all(request, response):
async def start_all(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
yield from project.start_all()
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
await project.start_all()
response.set_status(204)
@Route.post(
@@ -137,10 +137,10 @@ class NodeHandler:
},
description="Stop all nodes belonging to the project",
output=NODE_OBJECT_SCHEMA)
def stop_all(request, response):
async def stop_all(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
yield from project.stop_all()
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
await project.stop_all()
response.set_status(204)
@Route.post(
@@ -155,10 +155,10 @@ class NodeHandler:
},
description="Suspend all nodes belonging to the project",
output=NODE_OBJECT_SCHEMA)
def suspend_all(request, response):
async def suspend_all(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
yield from project.suspend_all()
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
await project.suspend_all()
response.set_status(204)
@Route.post(
@@ -173,11 +173,11 @@ class NodeHandler:
},
description="Reload all nodes belonging to the project",
output=NODE_OBJECT_SCHEMA)
def reload_all(request, response):
async def reload_all(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
yield from project.stop_all()
yield from project.start_all()
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
await project.stop_all()
await project.start_all()
response.set_status(204)
@Route.post(
@@ -194,11 +194,11 @@ class NodeHandler:
description="Duplicate a node instance",
input=NODE_DUPLICATE_SCHEMA,
output=NODE_OBJECT_SCHEMA)
def duplicate(request, response):
async def duplicate(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
node = project.get_node(request.match_info["node_id"])
new_node = yield from project.duplicate_node(
new_node = await project.duplicate_node(
node,
request.json["x"],
request.json["y"],
@@ -219,11 +219,11 @@ class NodeHandler:
},
description="Start a node instance",
output=NODE_OBJECT_SCHEMA)
def start(request, response):
async def start(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
node = project.get_node(request.match_info["node_id"])
yield from node.start(data=request.json)
await node.start(data=request.json)
response.json(node)
response.set_status(200)
@@ -240,11 +240,11 @@ class NodeHandler:
},
description="Stop a node instance",
output=NODE_OBJECT_SCHEMA)
def stop(request, response):
async def stop(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
node = project.get_node(request.match_info["node_id"])
yield from node.stop()
await node.stop()
response.json(node)
response.set_status(200)
@@ -261,11 +261,11 @@ class NodeHandler:
},
description="Suspend a node instance",
output=NODE_OBJECT_SCHEMA)
def suspend(request, response):
async def suspend(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
node = project.get_node(request.match_info["node_id"])
yield from node.suspend()
await node.suspend()
response.json(node)
response.set_status(200)
@@ -282,11 +282,11 @@ class NodeHandler:
},
description="Reload a node instance",
output=NODE_OBJECT_SCHEMA)
def reload(request, response):
async def reload(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
node = project.get_node(request.match_info["node_id"])
#yield from node.reload()
#await node.reload()
response.json(node)
response.set_status(200)
@@ -302,9 +302,9 @@ class NodeHandler:
404: "Instance doesn't exist"
},
description="Delete a node instance")
def delete(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
yield from project.delete_node(request.match_info["node_id"])
async def delete(request, response):
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
await project.delete_node(request.match_info["node_id"])
response.set_status(204)
@Route.get(
@@ -319,9 +319,9 @@ class NodeHandler:
404: "Instance doesn't exist"
},
description="Return all the links connected to this node")
def links(request, response):
async def links(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
node = project.get_node(request.match_info["node_id"])
links = []
for link in node.links:
@@ -341,11 +341,11 @@ class NodeHandler:
404: "Instance doesn't exist"
},
description="Compute the IDLE PC for a Dynamips node")
def auto_idlepc(request, response):
async def auto_idlepc(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
node = project.get_node(request.match_info["node_id"])
idle = yield from node.dynamips_auto_idlepc()
idle = await node.dynamips_auto_idlepc()
response.json(idle)
response.set_status(200)
@@ -361,11 +361,11 @@ class NodeHandler:
404: "Instance doesn't exist"
},
description="Compute a list of potential idle PC for a node")
def idlepc_proposals(request, response):
async def idlepc_proposals(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
node = project.get_node(request.match_info["node_id"])
idle = yield from node.dynamips_idlepc_proposals()
idle = await node.dynamips_idlepc_proposals()
response.json(idle)
response.set_status(200)
@@ -381,11 +381,11 @@ class NodeHandler:
404: "Instance doesn't exist"
},
description="Reload a node instance")
def resize_disk(request, response):
async def resize_disk(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
node = project.get_node(request.match_info["node_id"])
yield from node.post("/resize_disk", request.json)
await node.post("/resize_disk", request.json)
response.set_status(201)
@Route.get(
@@ -400,9 +400,9 @@ class NodeHandler:
404: "Instance doesn't exist"
},
description="Get a file in the node directory")
def get_file(request, response):
async def get_file(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
node = project.get_node(request.match_info["node_id"])
path = request.match_info["path"]
path = force_unix_path(path)
@@ -415,14 +415,14 @@ class NodeHandler:
node_type = node.node_type
path = "/project-files/{}/{}/{}".format(node_type, node.id, path)
res = yield from node.compute.http_query("GET", "/projects/{project_id}/files{path}".format(project_id=project.id, path=path), timeout=None, raw=True)
res = await node.compute.http_query("GET", "/projects/{project_id}/files{path}".format(project_id=project.id, path=path), timeout=None, raw=True)
response.set_status(200)
response.content_type = "application/octet-stream"
response.enable_chunked_encoding()
yield from response.prepare(request)
await response.prepare(request)
response.write(res.body)
yield from response.write_eof()
await response.write_eof()
@Route.post(
r"/projects/{project_id}/nodes/{node_id}/files/{path:.+}",
@@ -437,9 +437,9 @@ class NodeHandler:
},
raw=True,
description="Write a file in the node directory")
def post_file(request, response):
async def post_file(request, response):
project = yield from Controller.instance().get_loaded_project(request.match_info["project_id"])
project = await Controller.instance().get_loaded_project(request.match_info["project_id"])
node = project.get_node(request.match_info["node_id"])
path = request.match_info["path"]
path = force_unix_path(path)
@@ -450,6 +450,6 @@ class NodeHandler:
node_type = node.node_type
path = "/project-files/{}/{}/{}".format(node_type, node.id, path)
data = yield from request.content.read() #FIXME: are we handling timeout or large files correctly?
yield from node.compute.http_query("POST", "/projects/{project_id}/files{path}".format(project_id=project.id, path=path), data=data, timeout=None, raw=True)
data = await request.content.read() #FIXME: are we handling timeout or large files correctly?
await node.compute.http_query("POST", "/projects/{project_id}/files{path}".format(project_id=project.id, path=path), data=data, timeout=None, raw=True)
response.set_status(201)
@@ -20,16 +20,14 @@ import aiohttp
from aiohttp.web import WebSocketResponse
from gns3server.web.route import Route
from gns3server.controller import Controller
from gns3server.utils.asyncio import asyncio_ensure_future
@asyncio.coroutine
def process_websocket(ws):
async def process_websocket(ws):
"""
Process ping / pong and close message
"""
try:
yield from ws.receive()
await ws.receive()
except aiohttp.WSServerHandshakeError:
pass
@@ -42,22 +40,22 @@ class NotificationHandler:
status_codes={
200: "End of stream"
})
def notification(request, response):
async def notification(request, response):
controller = Controller.instance()
response.content_type = "application/json"
response.set_status(200)
response.enable_chunked_encoding()
yield from response.prepare(request)
await response.prepare(request)
with controller.notification.controller_queue() as queue:
while True:
try:
msg = yield from queue.get_json(5)
msg = await queue.get_json(5)
response.write(("{}\n".format(msg)).encode("utf-8"))
except asyncio.futures.CancelledError:
break
yield from response.drain()
await response.drain()
@Route.get(
r"/notifications/ws",
@@ -65,17 +63,17 @@ class NotificationHandler:
status_codes={
200: "End of stream"
})
def notification_ws(request, response):
async def notification_ws(request, response):
controller = Controller.instance()
ws = aiohttp.web.WebSocketResponse()
yield from ws.prepare(request)
await ws.prepare(request)
asyncio_ensure_future(process_websocket(ws))
asyncio.ensure_future(process_websocket(ws))
with controller.notification.controller_queue() as queue:
while True:
try:
notification = yield from queue.get_json(5)
notification = await queue.get_json(5)
except asyncio.futures.CancelledError:
break
if ws.closed:
@@ -26,7 +26,6 @@ from gns3server.controller import Controller
from gns3server.controller.import_project import import_project
from gns3server.controller.export_project import export_project
from gns3server.config import Config
from gns3server.utils.asyncio import asyncio_ensure_future
from gns3server.schemas.project import (
@@ -40,13 +39,12 @@ import logging
log = logging.getLogger()
@asyncio.coroutine
def process_websocket(ws):
async def process_websocket(ws):
"""
Process ping / pong and close message
"""
try:
yield from ws.receive()
await ws.receive()
except aiohttp.WSServerHandshakeError:
pass
@@ -62,10 +60,10 @@ class ProjectHandler:
},
output=PROJECT_OBJECT_SCHEMA,
input=PROJECT_CREATE_SCHEMA)
def create_project(request, response):
async def create_project(request, response):
controller = Controller.instance()
project = yield from controller.add_project(**request.json)
project = await controller.add_project(**request.json)
response.set_status(201)
response.json(project)
@@ -119,13 +117,13 @@ class ProjectHandler:
description="Update a project instance",
input=PROJECT_UPDATE_SCHEMA,
output=PROJECT_OBJECT_SCHEMA)
def update(request, response):
async def update(request, response):
project = Controller.instance().get_project(request.match_info["project_id"])
# Ignore these because we only use them when creating a project
request.json.pop("project_id", None)
yield from project.update(**request.json)
await project.update(**request.json)
response.set_status(200)
response.json(project)
@@ -140,11 +138,11 @@ class ProjectHandler:
404: "The project doesn't exist"
},
output=PROJECT_OBJECT_SCHEMA)
def close(request, response):
async def close(request, response):
controller = Controller.instance()
project = controller.get_project(request.match_info["project_id"])
yield from project.close()
await project.close()
response.set_status(201)
response.json(project)
@@ -159,11 +157,11 @@ class ProjectHandler:
404: "The project doesn't exist"
},
output=PROJECT_OBJECT_SCHEMA)
def open(request, response):
async def open(request, response):
controller = Controller.instance()
project = controller.get_project(request.match_info["project_id"])
yield from project.open()
await project.open()
response.set_status(201)
response.json(project)
@@ -179,7 +177,7 @@ class ProjectHandler:
},
input=PROJECT_LOAD_SCHEMA,
output=PROJECT_OBJECT_SCHEMA)
def load(request, response):
async def load(request, response):
controller = Controller.instance()
config = Config.instance()
@@ -187,7 +185,7 @@ class ProjectHandler:
log.error("Can't load the project the server is not started with --local")
response.set_status(403)
return
project = yield from controller.load_project(request.json.get("path"),)
project = await controller.load_project(request.json.get("path"),)
response.set_status(201)
response.json(project)
@@ -201,11 +199,11 @@ class ProjectHandler:
204: "Changes have been written on disk",
404: "The project doesn't exist"
})
def delete(request, response):
async def delete(request, response):
controller = Controller.instance()
project = controller.get_project(request.match_info["project_id"])
yield from project.delete()
await project.delete()
controller.remove_project(project)
response.set_status(204)
@@ -219,7 +217,7 @@ class ProjectHandler:
200: "End of stream",
404: "The project doesn't exist"
})
def notification(request, response):
async def notification(request, response):
controller = Controller.instance()
project = controller.get_project(request.match_info["project_id"])
@@ -228,22 +226,22 @@ class ProjectHandler:
response.set_status(200)
response.enable_chunked_encoding()
yield from response.prepare(request)
await response.prepare(request)
with controller.notification.project_queue(project) as queue:
while True:
try:
msg = yield from queue.get_json(5)
msg = await queue.get_json(5)
response.write(("{}\n".format(msg)).encode("utf-8"))
except asyncio.futures.CancelledError as e:
break
yield from response.drain()
await response.drain()
if project.auto_close:
# To avoid trouble with client connecting disconnecting we sleep few seconds before checking
# if someone else is not connected
yield from asyncio.sleep(5)
await asyncio.sleep(5)
if not controller.notification.project_has_listeners(project):
yield from project.close()
await project.close()
@Route.get(
r"/projects/{project_id}/notifications/ws",
@@ -255,20 +253,20 @@ class ProjectHandler:
200: "End of stream",
404: "The project doesn't exist"
})
def notification_ws(request, response):
async def notification_ws(request, response):
controller = Controller.instance()
project = controller.get_project(request.match_info["project_id"])
ws = aiohttp.web.WebSocketResponse()
yield from ws.prepare(request)
await ws.prepare(request)
asyncio_ensure_future(process_websocket(ws))
asyncio.ensure_future(process_websocket(ws))
with controller.notification.project_queue(project) as queue:
while True:
try:
notification = yield from queue.get_json(5)
notification = await queue.get_json(5)
except asyncio.futures.CancelledError as e:
break
if ws.closed:
@@ -278,9 +276,9 @@ class ProjectHandler:
if project.auto_close:
# To avoid trouble with client connecting disconnecting we sleep few seconds before checking
# if someone else is not connected
yield from asyncio.sleep(5)
await asyncio.sleep(5)
if not controller.notification.project_has_listeners(project):
yield from project.close()
await project.close()
return ws
@@ -295,14 +293,14 @@ class ProjectHandler:
200: "File returned",
404: "The project doesn't exist"
})
def export_project(request, response):
async def export_project(request, response):
controller = Controller.instance()
project = yield from controller.get_loaded_project(request.match_info["project_id"])
project = await controller.get_loaded_project(request.match_info["project_id"])
try:
with tempfile.TemporaryDirectory() as tmp_dir:
stream = yield from export_project(project,
stream = await export_project(project,
tmp_dir,
include_images=bool(int(request.query.get("include_images", "0"))))
# We need to do that now because export could failed and raise an HTTP error
@@ -310,13 +308,13 @@ class ProjectHandler:
response.content_type = 'application/gns3project'
response.headers['CONTENT-DISPOSITION'] = 'attachment; filename="{}.gns3project"'.format(project.name)
response.enable_chunked_encoding()
yield from response.prepare(request)
await response.prepare(request)
for data in stream:
response.write(data)
yield from response.drain()
await response.drain()
yield from response.write_eof()
await response.write_eof()
# Will be raise if you have no space left or permission issue on your temporary directory
# RuntimeError: something was wrong during the zip process
except (ValueError, OSError, RuntimeError) as e:
@@ -334,7 +332,7 @@ class ProjectHandler:
200: "Project imported",
403: "Forbidden to import project"
})
def import_project(request, response):
async def import_project(request, response):
controller = Controller.instance()
@@ -355,19 +353,19 @@ class ProjectHandler:
if sys.version_info >= (3, 7) and sys.version_info < (3, 8):
with tempfile.TemporaryFile() as temp:
while True:
chunk = yield from request.content.read(1024)
chunk = await request.content.read(1024)
if not chunk:
break
temp.write(chunk)
project = yield from import_project(controller, request.match_info["project_id"], temp, location=path, name=name)
project = await import_project(controller, request.match_info["project_id"], temp, location=path, name=name)
else:
with tempfile.SpooledTemporaryFile(max_size=10000) as temp:
while True:
chunk = yield from request.content.read(1024)
chunk = await request.content.read(1024)
if not chunk:
break
temp.write(chunk)
project = yield from import_project(controller, request.match_info["project_id"], temp, location=path, name=name)
project = await import_project(controller, request.match_info["project_id"], temp, location=path, name=name)
except OSError as e:
raise aiohttp.web.HTTPInternalServerError(text="Could not import the project: {}".format(e))
@@ -387,10 +385,10 @@ class ProjectHandler:
403: "The server is not the local server",
404: "The project doesn't exist"
})
def duplicate(request, response):
async def duplicate(request, response):
controller = Controller.instance()
project = yield from controller.get_loaded_project(request.match_info["project_id"])
project = await controller.get_loaded_project(request.match_info["project_id"])
if request.json.get("path"):
config = Config.instance()
@@ -401,7 +399,7 @@ class ProjectHandler:
else:
location = None
new_project = yield from project.duplicate(name=request.json.get("name"), location=location)
new_project = await project.duplicate(name=request.json.get("name"), location=location)
response.json(new_project)
response.set_status(201)
@@ -417,10 +415,10 @@ class ProjectHandler:
403: "Permission denied",
404: "The file doesn't exist"
})
def get_file(request, response):
async def get_file(request, response):
controller = Controller.instance()
project = yield from controller.get_loaded_project(request.match_info["project_id"])
project = await controller.get_loaded_project(request.match_info["project_id"])
path = request.match_info["path"]
path = os.path.normpath(path).strip('/')
@@ -435,12 +433,12 @@ class ProjectHandler:
try:
with open(path, "rb") as f:
yield from response.prepare(request)
await response.prepare(request)
while True:
data = f.read(4096)
if not data:
break
yield from response.write(data)
await response.write(data)
except FileNotFoundError:
raise aiohttp.web.HTTPNotFound()
@@ -459,10 +457,10 @@ class ProjectHandler:
403: "Permission denied",
404: "The path doesn't exist"
})
def write_file(request, response):
async def write_file(request, response):
controller = Controller.instance()
project = yield from controller.get_loaded_project(request.match_info["project_id"])
project = await controller.get_loaded_project(request.match_info["project_id"])
path = request.match_info["path"]
path = os.path.normpath(path).strip("/")
@@ -477,7 +475,7 @@ class ProjectHandler:
with open(path, 'wb+') as f:
while True:
try:
chunk = yield from request.content.read(1024)
chunk = await request.content.read(1024)
except asyncio.TimeoutError:
raise aiohttp.web.HTTPRequestTimeout(text="Timeout when writing to file '{}'".format(path))
if not chunk:
@@ -20,7 +20,6 @@ from gns3server.config import Config
from gns3server.controller import Controller
from gns3server.schemas.version import VERSION_SCHEMA
from gns3server.version import __version__
from gns3server.utils.asyncio import asyncio_ensure_future
from aiohttp.web import HTTPConflict, HTTPForbidden
@@ -44,7 +43,7 @@ class ServerHandler:
201: "Server is shutting down",
403: "Server shutdown refused"
})
def shutdown(request, response):
async def shutdown(request, response):
config = Config.instance()
if config.get_section_config("Server").getboolean("local", False) is False:
@@ -58,10 +57,10 @@ class ServerHandler:
tasks = []
for project in projects:
tasks.append(asyncio_ensure_future(project.close()))
tasks.append(asyncio.ensure_future(project.close()))
if tasks:
done, _ = yield from asyncio.wait(tasks)
done, _ = await asyncio.wait(tasks)
for future in done:
try:
future.result()
@@ -73,7 +72,7 @@ class ServerHandler:
from gns3server.web.web_server import WebServer
server = WebServer.instance()
try:
asyncio_ensure_future(server.shutdown_server())
asyncio.ensure_future(server.shutdown_server())
except asyncio.CancelledError:
pass
response.set_status(201)
@@ -105,7 +104,7 @@ class ServerHandler:
@Route.get(
r"/settings",
description="Retrieve gui settings from the server. Temporary will we removed in later release")
def read_settings(request, response):
async def read_settings(request, response):
settings = None
while True:
@@ -115,7 +114,7 @@ class ServerHandler:
if settings is not None:
break
yield from asyncio.sleep(0.5)
await asyncio.sleep(0.5)
response.json(settings)
@Route.post(
@@ -142,7 +141,7 @@ class ServerHandler:
status_codes={
201: "Written"
})
def debug(request, response):
async def debug(request, response):
config = Config.instance()
if config.get_section_config("Server").getboolean("local", False) is False:
@@ -170,7 +169,7 @@ class ServerHandler:
for compute in list(Controller.instance().computes.values()):
try:
r = yield from compute.get("/debug", raw=True)
r = await compute.get("/debug", raw=True)
data = r.body.decode("utf-8")
except Exception as e:
data = str(e)
@@ -43,10 +43,10 @@ class SnapshotHandler:
201: "Snasphot created",
404: "The project doesn't exist"
})
def create(request, response):
async def create(request, response):
controller = Controller.instance()
project = controller.get_project(request.match_info["project_id"])
snapshot = yield from project.snapshot(request.json["name"])
snapshot = await project.snapshot(request.json["name"])
response.json(snapshot)
response.set_status(201)
@@ -77,11 +77,11 @@ class SnapshotHandler:
204: "Changes have been written on disk",
404: "The project or snapshot doesn't exist"
})
def delete(request, response):
async def delete(request, response):
controller = Controller.instance()
project = controller.get_project(request.match_info["project_id"])
yield from project.delete_snapshot(request.match_info["snapshot_id"])
await project.delete_snapshot(request.match_info["snapshot_id"])
response.set_status(204)
@Route.post(
@@ -96,11 +96,11 @@ class SnapshotHandler:
201: "The snapshot has been restored",
404: "The project or snapshot doesn't exist"
})
def restore(request, response):
async def restore(request, response):
controller = Controller.instance()
project = controller.get_project(request.match_info["project_id"])
snapshot = project.get_snapshot(request.match_info["snapshot_id"])
project = yield from snapshot.restore()
project = await snapshot.restore()
response.set_status(201)
response.json(project)
@@ -47,11 +47,11 @@ class SymbolHandler:
status_codes={
200: "Symbol returned"
})
def raw(request, response):
async def raw(request, response):
controller = Controller.instance()
try:
yield from response.file(controller.symbols.get_path(request.match_info["symbol_id"]))
await response.file(controller.symbols.get_path(request.match_info["symbol_id"]))
except (KeyError, OSError) as e:
log.warning("Could not get symbol file: {}".format(e))
response.set_status(404)
@@ -63,14 +63,14 @@ class SymbolHandler:
200: "Symbol returned"
},
raw=True)
def upload(request, response):
async def upload(request, response):
controller = Controller.instance()
path = os.path.join(controller.symbols.symbols_path(), os.path.basename(request.match_info["symbol_id"]))
try:
with open(path, "wb") as f:
while True:
try:
chunk = yield from request.content.read(1024)
chunk = await request.content.read(1024)
except asyncio.TimeoutError:
raise aiohttp.web.HTTPRequestTimeout(text="Timeout when writing to symbol '{}'".format(path))
if not chunk: