diff --git a/gns3server/handlers/project_handler.py b/gns3server/handlers/project_handler.py index 382206d0..0ab4d681 100644 --- a/gns3server/handlers/project_handler.py +++ b/gns3server/handlers/project_handler.py @@ -32,7 +32,7 @@ class ProjectHandler: pm = ProjectManager.instance() p = pm.create_project( - location=request.json.get("location"), + path=request.json.get("path"), project_id=request.json.get("project_id"), temporary=request.json.get("temporary", False) ) diff --git a/gns3server/modules/project.py b/gns3server/modules/project.py index ac74fd58..cfddbda4 100644 --- a/gns3server/modules/project.py +++ b/gns3server/modules/project.py @@ -35,11 +35,12 @@ class Project: In theory VM are isolated project/project. :param project_id: Force project identifier (None by default auto generate an UUID) + :param path: Path of the project. (None use the standard directory) :param location: Parent path of the project. (None should create a tmp directory) :param temporary: Boolean the project is a temporary project (destroy when closed) """ - def __init__(self, project_id=None, location=None, temporary=False): + def __init__(self, project_id=None, path=None, location=None, temporary=False): if project_id is None: self._id = str(uuid4()) @@ -58,12 +59,17 @@ class Project: self._vms = set() self._vms_to_destroy = set() - self._path = os.path.join(self._location, self._id) + + self.temporary = temporary + + if path is None: + path = os.path.join(self._location, self._id) try: - os.makedirs(self._path, exist_ok=True) + os.makedirs(path, exist_ok=True) except OSError as e: raise aiohttp.web.HTTPInternalServerError(text="Could not create project directory: {}".format(e)) - self.temporary = temporary + self.path = path + log.debug("Create project {id} in directory {path}".format(path=self._path, id=self._id)) def _config(self): @@ -110,8 +116,9 @@ class Project: @path.setter def path(self, path): - if path != self._path and self._config().get("local", False) is False: - raise aiohttp.web.HTTPForbidden(text="You are not allowed to modifiy the project directory location") + if hasattr(self, "_path"): + if path != self._path and self._config().get("local", False) is False: + raise aiohttp.web.HTTPForbidden(text="You are not allowed to modifiy the project directory location") self._path = path self._update_temporary_file() @@ -141,6 +148,9 @@ class Project: project status. """ + if not hasattr(self, "_path"): + return + if self._temporary: try: with open(os.path.join(self._path, ".gns3_temporary"), 'w+') as f: diff --git a/gns3server/schemas/project.py b/gns3server/schemas/project.py index 942b154b..9ebcfba0 100644 --- a/gns3server/schemas/project.py +++ b/gns3server/schemas/project.py @@ -21,8 +21,8 @@ PROJECT_CREATE_SCHEMA = { "description": "Request validation to create a new Project instance", "type": "object", "properties": { - "location": { - "description": "Base directory where the project should be created on remote server", + "path": { + "description": "Project directory", "type": "string", "minLength": 1 }, diff --git a/tests/api/test_project.py b/tests/api/test_project.py index c7383bf7..df684018 100644 --- a/tests/api/test_project.py +++ b/tests/api/test_project.py @@ -24,11 +24,11 @@ from unittest.mock import patch from tests.utils import asyncio_patch -def test_create_project_with_dir(server, tmpdir): +def test_create_project_with_path(server, tmpdir): with patch("gns3server.config.Config.get_section_config", return_value={"local": True}): - response = server.post("/projects", {"location": str(tmpdir)}) + response = server.post("/projects", {"path": str(tmpdir)}) assert response.status == 200 - assert response.json["location"] == str(tmpdir) + assert response.json["path"] == str(tmpdir) def test_create_project_without_dir(server): @@ -55,13 +55,16 @@ def test_create_project_with_uuid(server): def test_show_project(server): - query = {"project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f", "location": "/tmp", "temporary": False} + query = {"project_id": "00010203-0405-0607-0809-0a0b0c0d0e0f", "path": "/tmp", "temporary": False} with patch("gns3server.config.Config.get_section_config", return_value={"local": True}): response = server.post("/projects", query) assert response.status == 200 response = server.get("/projects/00010203-0405-0607-0809-0a0b0c0d0e0f", example=True) - query["path"] = "/tmp/00010203-0405-0607-0809-0a0b0c0d0e0f" - assert response.json == query + assert len(response.json.keys()) == 4 + assert len(response.json["location"]) > 0 + assert response.json["project_id"] == "00010203-0405-0607-0809-0a0b0c0d0e0f" + assert response.json["path"] == "/tmp" + assert response.json["temporary"] is False def test_show_project_invalid_uuid(server): diff --git a/tests/modules/test_project.py b/tests/modules/test_project.py index 45254a1f..fa0df924 100644 --- a/tests/modules/test_project.py +++ b/tests/modules/test_project.py @@ -56,6 +56,13 @@ def test_path(tmpdir): assert not os.path.exists(os.path.join(p.path, ".gns3_temporary")) +def test_init_path(tmpdir): + + with patch("gns3server.config.Config.get_section_config", return_value={"local": True}): + p = Project(path=str(tmpdir)) + assert p.path == str(tmpdir) + + def test_changing_path_temporary_flag(tmpdir): with patch("gns3server.config.Config.get_section_config", return_value={"local": True}):