diff --git a/gns3server/handlers/api/dynamips_vm_handler.py b/gns3server/handlers/api/dynamips_vm_handler.py index 2953b0c0..bd131e18 100644 --- a/gns3server/handlers/api/dynamips_vm_handler.py +++ b/gns3server/handlers/api/dynamips_vm_handler.py @@ -20,12 +20,12 @@ import base64 from ...web.route import Route from ...schemas.nio import NIO_SCHEMA +from ...schemas.vm import VM_LIST_IMAGES_SCHEMA from ...schemas.dynamips_vm import VM_CREATE_SCHEMA from ...schemas.dynamips_vm import VM_UPDATE_SCHEMA from ...schemas.dynamips_vm import VM_CAPTURE_SCHEMA from ...schemas.dynamips_vm import VM_OBJECT_SCHEMA from ...schemas.dynamips_vm import VM_CONFIGS_SCHEMA -from ...schemas.dynamips_vm import VMS_LIST_SCHEMA from ...modules.dynamips import Dynamips from ...modules.dynamips.dynamips_error import DynamipsError from ...modules.project_manager import ProjectManager @@ -460,7 +460,7 @@ class DynamipsVMHandler: 200: "List of Dynamips VM retrieved", }, description="Retrieve the list of Dynamips VMS", - output=VMS_LIST_SCHEMA) + output=VM_LIST_IMAGES_SCHEMA) def list_vms(request, response): dynamips_manager = Dynamips.instance() @@ -469,7 +469,7 @@ class DynamipsVMHandler: response.json(vms) @Route.post( - r"/dynamips/vms/{filename}", + r"/dynamips/vms/{path}", status_codes={ 204: "Image uploaded", }, @@ -478,5 +478,5 @@ class DynamipsVMHandler: def upload_vm(request, response): dynamips_manager = Dynamips.instance() - yield from dynamips_manager.write_image(request.match_info["filename"], request.content) + yield from dynamips_manager.write_image(request.match_info["path"], request.content) response.set_status(204) diff --git a/gns3server/handlers/api/iou_handler.py b/gns3server/handlers/api/iou_handler.py index 28c26b68..5606cd8b 100644 --- a/gns3server/handlers/api/iou_handler.py +++ b/gns3server/handlers/api/iou_handler.py @@ -26,7 +26,7 @@ from ...schemas.iou import IOU_UPDATE_SCHEMA from ...schemas.iou import IOU_OBJECT_SCHEMA from ...schemas.iou import IOU_CAPTURE_SCHEMA from ...schemas.iou import IOU_CONFIGS_SCHEMA -from ...schemas.iou import IOU_LIST_VMS_SCHEMA +from ...schemas.vm import VM_LIST_IMAGES_SCHEMA from ...modules.iou import IOU @@ -373,7 +373,7 @@ class IOUHandler: 200: "List of IOU VM retrieved", }, description="Retrieve the list of IOU VMS", - output=IOU_LIST_VMS_SCHEMA) + output=VM_LIST_IMAGES_SCHEMA) def list_vms(request, response): iou_manager = IOU.instance() @@ -382,7 +382,7 @@ class IOUHandler: response.json(vms) @Route.post( - r"/iou/vms/{filename}", + r"/iou/vms/{path}", status_codes={ 204: "Image uploaded", }, @@ -391,5 +391,5 @@ class IOUHandler: def upload_vm(request, response): iou_manager = IOU.instance() - yield from iou_manager.write_image(request.match_info["filename"], request.content) + yield from iou_manager.write_image(request.match_info["path"], request.content) response.set_status(204) diff --git a/gns3server/handlers/api/qemu_handler.py b/gns3server/handlers/api/qemu_handler.py index f2edd9b3..085ac286 100644 --- a/gns3server/handlers/api/qemu_handler.py +++ b/gns3server/handlers/api/qemu_handler.py @@ -26,8 +26,8 @@ from ...schemas.qemu import QEMU_CREATE_SCHEMA from ...schemas.qemu import QEMU_UPDATE_SCHEMA from ...schemas.qemu import QEMU_OBJECT_SCHEMA from ...schemas.qemu import QEMU_BINARY_LIST_SCHEMA -from ...schemas.qemu import QEMU_LIST_IMAGES_SCHEMA from ...schemas.qemu import QEMU_IMAGE_CREATE_SCHEMA +from ...schemas.vm import VM_LIST_IMAGES_SCHEMA from ...modules.qemu import Qemu from ...config import Config @@ -348,7 +348,7 @@ class QEMUHandler: 200: "List of Qemu images retrieved", }, description="Retrieve the list of Qemu images", - output=QEMU_LIST_IMAGES_SCHEMA) + output=VM_LIST_IMAGES_SCHEMA) def list_vms(request, response): qemu_manager = Qemu.instance() @@ -357,7 +357,7 @@ class QEMUHandler: response.json(vms) @Route.post( - r"/qemu/vms/{filename}", + r"/qemu/vms/{path}", status_codes={ 204: "Image uploaded", }, @@ -366,5 +366,5 @@ class QEMUHandler: def upload_vm(request, response): qemu_manager = Qemu.instance() - yield from qemu_manager.write_image(request.match_info["filename"], request.content) + yield from qemu_manager.write_image(request.match_info["path"], request.content) response.set_status(204) diff --git a/gns3server/modules/base_manager.py b/gns3server/modules/base_manager.py index d2bc532d..79dbf1b6 100644 --- a/gns3server/modules/base_manager.py +++ b/gns3server/modules/base_manager.py @@ -439,15 +439,15 @@ class BaseManager: :returns: Array of hash """ - try: - files = os.listdir(self.get_images_directory()) - except FileNotFoundError: - return [] - files.sort() images = [] - for filename in files: - if filename[0] != "." and not filename.endswith(".md5sum"): - images.append({"filename": filename}) + img_dir = self.get_images_directory() + for root, dirs, files in os.walk(img_dir): + for filename in files: + if filename[0] != "." and not filename.endswith(".md5sum"): + path = os.path.relpath(os.path.join(root, filename), img_dir) + images.append({ + "filename": filename, + "path": path}) return images def get_images_directory(self): diff --git a/gns3server/schemas/dynamips_vm.py b/gns3server/schemas/dynamips_vm.py index 05f8554e..942e9a06 100644 --- a/gns3server/schemas/dynamips_vm.py +++ b/gns3server/schemas/dynamips_vm.py @@ -777,21 +777,3 @@ VM_CONFIGS_SCHEMA = { }, "additionalProperties": False, } - -VMS_LIST_SCHEMA = { - "$schema": "http://json-schema.org/draft-04/schema#", - "description": "List available Dynamips images", - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "filename": { - "description": "Image filename", - "type": ["string"] - }, - }, - } - ], - "additionalProperties": False, -} diff --git a/gns3server/schemas/iou.py b/gns3server/schemas/iou.py index f541ba1a..cd6a9f4a 100644 --- a/gns3server/schemas/iou.py +++ b/gns3server/schemas/iou.py @@ -299,21 +299,3 @@ IOU_CONFIGS_SCHEMA = { }, "additionalProperties": False, } - -IOU_LIST_VMS_SCHEMA = { - "$schema": "http://json-schema.org/draft-04/schema#", - "description": "List available IOU images", - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "filename": { - "description": "Image filename", - "type": ["string"] - }, - }, - } - ], - "additionalProperties": False, -} diff --git a/gns3server/schemas/qemu.py b/gns3server/schemas/qemu.py index 0eb8e54b..eb18fa1c 100644 --- a/gns3server/schemas/qemu.py +++ b/gns3server/schemas/qemu.py @@ -577,25 +577,6 @@ QEMU_BINARY_LIST_SCHEMA = { "additionalProperties": False, } -QEMU_LIST_IMAGES_SCHEMA = { - "$schema": "http://json-schema.org/draft-04/schema#", - "description": "List available QEMU images", - "type": "array", - "items": [ - { - "type": "object", - "properties": { - "filename": { - "description": "Image filename", - "type": "string" - }, - }, - "additionalProperties": False - } - ], - "additionalProperties": False, -} - QEMU_IMAGE_CREATE_SCHEMA = { "$schema": "http://json-schema.org/draft-04/schema#", "description": "Create a new qemu image. Options can be specific to a format. Read qemu-img manual for more information", diff --git a/gns3server/schemas/vm.py b/gns3server/schemas/vm.py new file mode 100644 index 00000000..3eb77877 --- /dev/null +++ b/gns3server/schemas/vm.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# +# Copyright (C) 2015 GNS3 Technologies Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + + +VM_LIST_IMAGES_SCHEMA = { + "$schema": "http://json-schema.org/draft-04/schema#", + "description": "List of disk images", + "type": "array", + "items": [ + { + "type": "object", + "properties": { + "filename": { + "description": "Image filename", + "type": "string" + }, + "path": { + "description": "Image path", + "type": "string" + } + }, + "additionalProperties": False + } + ], + "additionalProperties": False, +} diff --git a/tests/handlers/api/test_iou.py b/tests/handlers/api/test_iou.py index d97452b5..7f9845b4 100644 --- a/tests/handlers/api/test_iou.py +++ b/tests/handlers/api/test_iou.py @@ -332,7 +332,7 @@ def test_vms(server, tmpdir, fake_iou_bin): with patch("gns3server.modules.IOU.get_images_directory", return_value=str(tmpdir)): response = server.get("/iou/vms", example=True) assert response.status == 200 - assert response.json == [{"filename": "iou.bin"}] + assert response.json == [{"filename": "iou.bin", "path": "iou.bin"}] def test_upload_vm(server, tmpdir): diff --git a/tests/handlers/api/test_qemu.py b/tests/handlers/api/test_qemu.py index 8df589ce..80cd7600 100644 --- a/tests/handlers/api/test_qemu.py +++ b/tests/handlers/api/test_qemu.py @@ -216,7 +216,7 @@ def test_vms(server, tmpdir, fake_qemu_vm): with patch("gns3server.modules.Qemu.get_images_directory", return_value=str(tmpdir), example=True): response = server.get("/qemu/vms") assert response.status == 200 - assert response.json == [{"filename": "linux.img"}] + assert response.json == [{"filename": "linux.img", "path": "linux.img"}] def test_upload_vm(server, tmpdir): diff --git a/tests/modules/test_manager.py b/tests/modules/test_manager.py index 4ad3b31a..d76c61cc 100644 --- a/tests/modules/test_manager.py +++ b/tests/modules/test_manager.py @@ -132,8 +132,28 @@ def test_list_images(loop, qemu, tmpdir): with patch("gns3server.modules.Qemu.get_images_directory", return_value=str(tmpdir)): assert loop.run_until_complete(qemu.list_images()) == [ - {"filename": "a.bin"}, - {"filename": "b.bin"} + {"filename": "a.bin", "path": "a.bin"}, + {"filename": "b.bin", "path": "b.bin"} + ] + + +def test_list_images_recursives(loop, qemu, tmpdir): + + fake_images = ["a.bin", "b.bin", ".blu.bin", "a.bin.md5sum"] + for image in fake_images: + with open(str(tmpdir / image), "w+") as f: + f.write("1") + os.makedirs(str(tmpdir / "c")) + fake_images = ["c.bin", "c.bin.md5sum"] + for image in fake_images: + with open(str(tmpdir / "c" / image), "w+") as f: + f.write("1") + + with patch("gns3server.modules.Qemu.get_images_directory", return_value=str(tmpdir)): + assert loop.run_until_complete(qemu.list_images()) == [ + {"filename": "a.bin", "path": "a.bin"}, + {"filename": "b.bin", "path": "b.bin"}, + {"filename": "c.bin", "path": os.path.sep.join(["c", "c.bin"])} ]