From 9062490be37c518a307f53864f1bd8505ffbfe55 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Mon, 14 Mar 2016 17:40:27 +0100 Subject: [PATCH] API for deleting a list --- gns3server/controller/link.py | 14 ++++++++ gns3server/controller/udp_link.py | 33 +++++++++++++++---- gns3server/controller/vm.py | 7 ++++ .../handlers/api/controller/link_handler.py | 21 ++++++++++++ tests/controller/test_udp_link.py | 19 +++++++++++ tests/controller/test_vm.py | 5 +++ tests/handlers/api/controller/test_link.py | 14 ++++++-- 7 files changed, 105 insertions(+), 8 deletions(-) diff --git a/gns3server/controller/link.py b/gns3server/controller/link.py index 034ece2d..8787c53f 100644 --- a/gns3server/controller/link.py +++ b/gns3server/controller/link.py @@ -37,6 +37,20 @@ class Link: "port_number": port_number }) + @asyncio.coroutine + def create(self): + """ + Create the link + """ + raise NotImplemented + + @asyncio.coroutine + def delete(self): + """ + Delete the link + """ + raise NotImplemented + @property def id(self): return self._id diff --git a/gns3server/controller/udp_link.py b/gns3server/controller/udp_link.py index dff41c3c..ce04ae88 100644 --- a/gns3server/controller/udp_link.py +++ b/gns3server/controller/udp_link.py @@ -22,11 +22,16 @@ from .link import Link class UDPLink(Link): + + def __init__(self, project): + super().__init__(project) + @asyncio.coroutine def create(self): """ Create the link on the VMs """ + vm1 = self._vms[0]["vm"] adapter_number1 = self._vms[0]["adapter_number"] port_number1 = self._vms[0]["port_number"] @@ -36,23 +41,39 @@ class UDPLink(Link): # Reserve a UDP port on both side response = yield from vm1.hypervisor.post("/projects/{}/ports/udp".format(self._project.id)) - vm1_port = response.json["udp_port"] + self._vm1_port = response.json["udp_port"] response = yield from vm2.hypervisor.post("/projects/{}/ports/udp".format(self._project.id)) - vm2_port = response.json["udp_port"] + self._vm2_port = response.json["udp_port"] # Create the tunnel on both side data = { - "lport": vm1_port, + "lport": self._vm1_port, "rhost": vm2.hypervisor.host, - "rport": vm2_port, + "rport": self._vm2_port, "type": "nio_udp" } yield from vm1.post("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1), data=data) data = { - "lport": vm2_port, + "lport": self._vm2_port, "rhost": vm1.hypervisor.host, - "rport": vm1_port, + "rport": self._vm1_port, "type": "nio_udp" } yield from vm2.post("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2), data=data) + + @asyncio.coroutine + def delete(self): + """ + Delete the link and free the ressources + """ + vm1 = self._vms[0]["vm"] + adapter_number1 = self._vms[0]["adapter_number"] + port_number1 = self._vms[0]["port_number"] + vm2 = self._vms[1]["vm"] + adapter_number2 = self._vms[1]["adapter_number"] + port_number2 = self._vms[1]["port_number"] + + yield from vm1.delete("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number1, port_number=port_number1)) + yield from vm2.delete("/adapters/{adapter_number}/ports/{port_number}/nio".format(adapter_number=adapter_number2, port_number=port_number2)) + diff --git a/gns3server/controller/vm.py b/gns3server/controller/vm.py index 4b6f664b..3ec469c5 100644 --- a/gns3server/controller/vm.py +++ b/gns3server/controller/vm.py @@ -92,6 +92,13 @@ class VM: """ return (yield from self._hypervisor.post("/projects/{}/{}/vms/{}{}".format(self._project.id, self._vm_type, self._id, path), data=data)) + @asyncio.coroutine + def delete(self, path): + """ + HTTP post on the VM + """ + return (yield from self._hypervisor.delete("/projects/{}/{}/vms/{}{}".format(self._project.id, self._vm_type, self._id, path))) + def __json__(self): return { "hypervisor_id": self._hypervisor.id, diff --git a/gns3server/handlers/api/controller/link_handler.py b/gns3server/handlers/api/controller/link_handler.py index be2d3741..379d53b5 100644 --- a/gns3server/handlers/api/controller/link_handler.py +++ b/gns3server/handlers/api/controller/link_handler.py @@ -51,3 +51,24 @@ class LinkHandler: yield from link.create() response.set_status(201) response.json(link) + + @classmethod + @Route.delete( + r"/projects/{project_id}/links/{link_id}", + parameters={ + "project_id": "UUID for the project", + "link_id": "UUID of the link" + }, + status_codes={ + 201: "Link deleted", + 400: "Invalid request" + }, + description="Delete a link instance") + def delete(request, response): + + controller = Controller.instance() + project = controller.getProject(request.match_info["project_id"]) + link = project.getLink(request.match_info["link_id"]) + yield from link.delete() + response.set_status(201) + response.json(link) diff --git a/tests/controller/test_udp_link.py b/tests/controller/test_udp_link.py index 11b1d43d..97819a81 100644 --- a/tests/controller/test_udp_link.py +++ b/tests/controller/test_udp_link.py @@ -17,6 +17,7 @@ import pytest import asyncio +import aiohttp from unittest.mock import MagicMock from gns3server.controller.project import Project @@ -79,3 +80,21 @@ def test_create(async_run, project): "rport": 1024, "type": "nio_udp" }) + + + +def test_delete(async_run, project): + hypervisor1 = MagicMock() + hypervisor2 = MagicMock() + + vm1 = VM(project, hypervisor1, vm_type="vpcs") + vm2 = VM(project, hypervisor2, vm_type="vpcs") + + link = UDPLink(project) + async_run(link.addVM(vm1, 0, 4)) + async_run(link.addVM(vm2, 3, 1)) + + async_run(link.delete()) + + hypervisor1.delete.assert_any_call("/projects/{}/vpcs/vms/{}/adapters/0/ports/4/nio".format(project.id, vm1.id)) + hypervisor2.delete.assert_any_call("/projects/{}/vpcs/vms/{}/adapters/3/ports/1/nio".format(project.id, vm2.id)) diff --git a/tests/controller/test_vm.py b/tests/controller/test_vm.py index 2ba61da3..be7de1f6 100644 --- a/tests/controller/test_vm.py +++ b/tests/controller/test_vm.py @@ -78,3 +78,8 @@ def test_create(vm, hypervisor, project, async_run): def test_post(vm, hypervisor, async_run): async_run(vm.post("/test", {"a": "b"})) hypervisor.post.assert_called_with("/projects/{}/vpcs/vms/{}/test".format(vm.project.id, vm.id), data={"a": "b"}) + + +def test_delete(vm, hypervisor, async_run): + async_run(vm.delete("/test")) + hypervisor.delete.assert_called_with("/projects/{}/vpcs/vms/{}/test".format(vm.project.id, vm.id)) diff --git a/tests/handlers/api/controller/test_link.py b/tests/handlers/api/controller/test_link.py index ce82d02c..55ed51a8 100644 --- a/tests/handlers/api/controller/test_link.py +++ b/tests/handlers/api/controller/test_link.py @@ -32,6 +32,7 @@ from tests.utils import asyncio_patch from gns3server.handlers.api.controller.project_handler import ProjectHandler from gns3server.controller import Controller from gns3server.controller.vm import VM +from gns3server.controller.link import Link @pytest.fixture @@ -51,8 +52,7 @@ def test_create_link(http_controller, tmpdir, project, hypervisor, async_run): vm1 = async_run(project.addVM(hypervisor, None)) vm2 = async_run(project.addVM(hypervisor, None)) - - with asyncio_patch("gns3server.controller.udp_link.UDPLink.create"): + with asyncio_patch("gns3server.controller.udp_link.UDPLink.create") as mock: response = http_controller.post("/projects/{}/links".format(project.id), { "vms": [ { @@ -67,6 +67,16 @@ def test_create_link(http_controller, tmpdir, project, hypervisor, async_run): } ] }, example=True) + assert mock.called assert response.status == 201 assert response.json["link_id"] is not None assert len(response.json["vms"]) == 2 + + +def test_delete_link(http_controller, tmpdir, project, hypervisor, async_run): + + link = Link(project) + project._links = {link.id: link} + with asyncio_patch("gns3server.controller.udp_link.Link.delete"): + response = http_controller.delete("/projects/{}/links/{}".format(project.id, link.id), example=True) + assert response.status == 201