From 917c1c7f84a1d4e343938bdfeebe6fe38be27264 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Thu, 2 Jun 2016 16:44:38 +0200 Subject: [PATCH] Expose /virtualbox/vms /vmwares/vms and /images via controller Ref #1192, #537 --- gns3server/controller/compute.py | 8 ++++ .../api/controller/compute_handler.py | 33 ++++++++++++++- tests/controller/test_compute.py | 8 ++++ tests/handlers/api/controller/test_compute.py | 41 ++++++++++++++++++- 4 files changed, 88 insertions(+), 2 deletions(-) diff --git a/gns3server/controller/compute.py b/gns3server/controller/compute.py index 1a60ef6d..83b0cb6a 100644 --- a/gns3server/controller/compute.py +++ b/gns3server/controller/compute.py @@ -322,3 +322,11 @@ class Compute: @asyncio.coroutine def delete(self, path, **kwargs): return (yield from self.http_query("DELETE", path, **kwargs)) + + @asyncio.coroutine + def forward(self, type, path): + """ + Forward a call to the emulator on compute + """ + res = yield from self.get("/{}/{}".format(type, path)) + return res diff --git a/gns3server/handlers/api/controller/compute_handler.py b/gns3server/handlers/api/controller/compute_handler.py index 60bde7e2..f1d36dd2 100644 --- a/gns3server/handlers/api/controller/compute_handler.py +++ b/gns3server/handlers/api/controller/compute_handler.py @@ -77,6 +77,38 @@ class ComputeHandler: response.set_status(200) response.json(compute) + @Route.get( + r"/computes/{compute_id:.+}/{emulator}/images", + parameters={ + "compute_id": "Compute UUID" + }, + status_codes={ + 200: "OK", + 404: "Instance doesn't exist" + }, + description="Get the list of images available on remote compute") + def list_images(request, response): + controller = Controller.instance() + compute = controller.get_compute(request.match_info["compute_id"]) + images = yield from compute.forward(request.match_info["emulator"], "images") + response.json(images) + + @Route.get( + r"/computes/{compute_id:.+}/{emulator}/vms", + parameters={ + "compute_id": "Compute UUID" + }, + status_codes={ + 200: "OK", + 404: "Instance doesn't exist" + }, + description="Get the list of vms available on remote compute for VMware an Virtualbox") + def list_vms(request, response): + controller = Controller.instance() + compute = controller.get_compute(request.match_info["compute_id"]) + images = yield from compute.forward(request.match_info["emulator"], "vms") + response.json(images) + @Route.get( r"/computes/{compute_id:.+}", description="Get a compute server information", @@ -93,7 +125,6 @@ class ComputeHandler: @Route.delete( r"/computes/{compute_id:.+}", parameters={ - "project_id": "Project UUID", "compute_id": "Compute UUID" }, status_codes={ diff --git a/tests/controller/test_compute.py b/tests/controller/test_compute.py index 8275275f..efef050b 100644 --- a/tests/controller/test_compute.py +++ b/tests/controller/test_compute.py @@ -221,3 +221,11 @@ def test_update(compute, controller, async_run): assert compute.host == "example.org" controller.notification.emit.assert_called_with("compute.updated", compute.__json__()) assert compute.connected is False + + +def test_forward(compute, async_run): + response = MagicMock() + response.status = 200 + with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock: + async_run(compute.forward("qemu", "images")) + mock.assert_called_with("GET", "https://example.com:84/v2/compute/qemu/images", auth=None, data=None, headers={'content-type': 'application/json'}) diff --git a/tests/handlers/api/controller/test_compute.py b/tests/handlers/api/controller/test_compute.py index 0f9305ae..b52b7160 100644 --- a/tests/handlers/api/controller/test_compute.py +++ b/tests/handlers/api/controller/test_compute.py @@ -15,6 +15,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +from tests.utils import asyncio_patch + def test_compute_create_without_id(http_controller, controller): @@ -56,7 +58,6 @@ def test_compute_create_with_id(http_controller, controller): assert controller.computes["my_compute_id"].host == "example.com" - def test_compute_get(http_controller, controller): params = { @@ -152,3 +153,41 @@ def test_compute_delete(http_controller, controller): response = http_controller.get("/computes") assert len(response.json) == 0 + + +def test_compute_list_images(http_controller, controller): + + params = { + "compute_id": "my_compute", + "protocol": "http", + "host": "example.com", + "port": 84, + "user": "julien", + "password": "secure" + } + response = http_controller.post("/computes", params) + assert response.status == 201 + + with asyncio_patch("gns3server.controller.compute.Compute.forward", return_value=[]) as mock: + response = http_controller.get("/computes/my_compute/qemu/images") + assert response.json == [] + mock.assert_called_with("qemu", "images") + + +def test_compute_list_vms(http_controller, controller): + + params = { + "compute_id": "my_compute", + "protocol": "http", + "host": "example.com", + "port": 84, + "user": "julien", + "password": "secure" + } + response = http_controller.post("/computes", params) + assert response.status == 201 + + with asyncio_patch("gns3server.controller.compute.Compute.forward", return_value=[]) as mock: + response = http_controller.get("/computes/my_compute/virtualbox/vms") + assert response.json == [] + mock.assert_called_with("virtualbox", "vms")