diff --git a/gns3server/controller/__init__.py b/gns3server/controller/__init__.py index b2e9a56f..3afec2c0 100644 --- a/gns3server/controller/__init__.py +++ b/gns3server/controller/__init__.py @@ -116,6 +116,15 @@ class Controller: except OSError as e: log.error(str(e)) + def images_path(self): + """ + Get the image storage directory + """ + server_config = Config.instance().get_section_config("Server") + images_path = os.path.expanduser(server_config.get("images_path", "~/GNS3/projects")) + os.makedirs(images_path, exist_ok=True) + return images_path + @asyncio.coroutine def _import_gns3_gui_conf(self): """ @@ -290,7 +299,7 @@ class Controller: """ Generate a free project name base on the base name """ - names = [ p.name for p in self._projects.values() ] + names = [p.name for p in self._projects.values()] if base_name not in names: return base_name i = 1 diff --git a/gns3server/controller/import_project.py b/gns3server/controller/import_project.py index 32ff1fc1..5af68c27 100644 --- a/gns3server/controller/import_project.py +++ b/gns3server/controller/import_project.py @@ -18,6 +18,7 @@ import os import json import uuid +import shutil import asyncio import zipfile import aiohttp @@ -29,8 +30,9 @@ from ..config import Config Handle the import of project from a .gns3project """ + @asyncio.coroutine -def import_project(controller, project_id, stream, gns3vm=True): +def import_project(controller, project_id, stream): """ Import a project contain in a zip file @@ -64,6 +66,24 @@ def import_project(controller, project_id, stream, gns3vm=True): json.dump(topology, f, indent=4) os.remove(os.path.join(path, "project.gns3")) - project = yield from controller.load_project(dot_gns3_path) + if os.path.exists(os.path.join(path, "images")): + _import_images(controller, path) + + project = yield from controller.load_project(dot_gns3_path, load=False) return project + +def _import_images(controller, path): + """ + Copy images to the images directory or delete them if they + already exists. + """ + image_dir = controller.images_path() + + root = os.path.join(path, "images") + for (dirpath, dirnames, filenames) in os.walk(root): + for filename in filenames: + path = os.path.join(dirpath, filename) + dst = os.path.join(image_dir, os.path.relpath(path, root)) + os.makedirs(os.path.dirname(dst), exist_ok=True) + shutil.move(path, dst) diff --git a/gns3server/handlers/api/controller/project_handler.py b/gns3server/handlers/api/controller/project_handler.py index fc552116..107bac70 100644 --- a/gns3server/handlers/api/controller/project_handler.py +++ b/gns3server/handlers/api/controller/project_handler.py @@ -279,7 +279,7 @@ class ProjectHandler: if not packet: break temp.write(packet) - project = yield from import_project(controller, request.match_info["project_id"], temp, gns3vm=bool(int(request.GET.get("gns3vm", "1")))) + project = yield from import_project(controller, request.match_info["project_id"], temp) except OSError as e: raise aiohttp.web.HTTPInternalServerError(text="Could not import the project: {}".format(e)) @@ -367,5 +367,3 @@ class ProjectHandler: raise aiohttp.web.HTTPNotFound() except PermissionError: raise aiohttp.web.HTTPForbidden() - - diff --git a/tests/controller/test_import_project.py b/tests/controller/test_import_project.py index f8067fbf..27e0834e 100644 --- a/tests/controller/test_import_project.py +++ b/tests/controller/test_import_project.py @@ -52,7 +52,7 @@ def test_import_project(async_run, tmpdir, controller): project = async_run(import_project(controller, project_id, f)) assert project.name == "test" - assert project.id == project_id # The project should changed + assert project.id == project_id # The project should changed assert os.path.exists(os.path.join(project.path, "b.png")) assert not os.path.exists(os.path.join(project.path, "project.gns3")) @@ -66,4 +66,35 @@ def test_import_project(async_run, tmpdir, controller): assert project.name != "test" +def test_import_with_images(tmpdir, async_run, controller): + project_id = str(uuid.uuid4()) + + topology = { + "project_id": str(uuid.uuid4()), + "name": "test", + "topology": { + }, + "version": "2.0.0" + } + + with open(str(tmpdir / "project.gns3"), 'w+') as f: + json.dump(topology, f) + + with open(str(tmpdir / "test.image"), 'w+') as f: + f.write("B") + + zip_path = str(tmpdir / "project.zip") + with zipfile.ZipFile(zip_path, 'w') as myzip: + myzip.write(str(tmpdir / "project.gns3"), "project.gns3") + myzip.write(str(tmpdir / "test.image"), "images/IOS/test.image") + + with open(zip_path, "rb") as f: + project = async_run(import_project(controller, project_id, f)) + + print(project._config().get("images_path")) + # TEST import images + assert not os.path.exists(os.path.join(project.path, "images/IOS/test.image")) + + path = os.path.join(project._config().get("images_path"), "IOS", "test.image") + assert os.path.exists(path), path