mirror of
https://github.com/GNS3/gns3-server.git
synced 2024-12-19 04:47:54 +00:00
Temporary project
This commit is contained in:
parent
7bf121c6da
commit
abc885049f
@ -16,7 +16,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from ..web.route import Route
|
||||
from ..schemas.project import PROJECT_OBJECT_SCHEMA
|
||||
from ..schemas.project import PROJECT_OBJECT_SCHEMA, PROJECT_CREATE_SCHEMA
|
||||
from ..modules.project_manager import ProjectManager
|
||||
from aiohttp.web import HTTPConflict
|
||||
|
||||
@ -28,13 +28,14 @@ class ProjectHandler:
|
||||
r"/project",
|
||||
description="Create a project on the server",
|
||||
output=PROJECT_OBJECT_SCHEMA,
|
||||
input=PROJECT_OBJECT_SCHEMA)
|
||||
input=PROJECT_CREATE_SCHEMA)
|
||||
def create_project(request, response):
|
||||
|
||||
pm = ProjectManager.instance()
|
||||
p = pm.create_project(
|
||||
location=request.json.get("location"),
|
||||
uuid=request.json.get("uuid")
|
||||
uuid=request.json.get("uuid"),
|
||||
temporary=request.json.get("temporary", False)
|
||||
)
|
||||
response.json(p)
|
||||
|
||||
|
@ -29,9 +29,10 @@ class Project:
|
||||
|
||||
:param uuid: Force project uuid (None by default auto generate an UUID)
|
||||
: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, uuid=None, location=None):
|
||||
def __init__(self, uuid=None, location=None, temporary=False):
|
||||
|
||||
if uuid is None:
|
||||
self._uuid = str(uuid4())
|
||||
@ -46,6 +47,7 @@ class Project:
|
||||
if location is None:
|
||||
self._location = tempfile.mkdtemp()
|
||||
|
||||
self._temporary = temporary
|
||||
self._vms = set()
|
||||
self._vms_to_destroy = set()
|
||||
self._path = os.path.join(self._location, self._uuid)
|
||||
@ -102,7 +104,8 @@ class Project:
|
||||
|
||||
return {
|
||||
"uuid": self._uuid,
|
||||
"location": self._location
|
||||
"location": self._location,
|
||||
"temporary": self._temporary
|
||||
}
|
||||
|
||||
def add_vm(self, vm):
|
||||
@ -110,7 +113,7 @@ class Project:
|
||||
Add a VM to the project.
|
||||
In theory this should be called by the VM manager.
|
||||
|
||||
:params vm: A VM instance
|
||||
:param vm: A VM instance
|
||||
"""
|
||||
|
||||
self._vms.add(vm)
|
||||
@ -120,7 +123,7 @@ class Project:
|
||||
Remove a VM from the project.
|
||||
In theory this should be called by the VM manager.
|
||||
|
||||
:params vm: A VM instance
|
||||
:param vm: A VM instance
|
||||
"""
|
||||
|
||||
if vm in self._vms:
|
||||
@ -129,8 +132,19 @@ class Project:
|
||||
def close(self):
|
||||
"""Close the project, but keep informations on disk"""
|
||||
|
||||
self._close_and_clean(self._temporary)
|
||||
|
||||
def _close_and_clean(self, cleanup):
|
||||
"""
|
||||
Close the project, and cleanup the disk if cleanup is True
|
||||
|
||||
:param cleanup: If True drop the project directory
|
||||
"""
|
||||
|
||||
for vm in self._vms:
|
||||
vm.close()
|
||||
if cleanup and os.path.exists(self.path):
|
||||
shutil.rmtree(self.path)
|
||||
|
||||
def commit(self):
|
||||
"""Write project changes on disk"""
|
||||
@ -145,6 +159,4 @@ class Project:
|
||||
def delete(self):
|
||||
"""Remove project from disk"""
|
||||
|
||||
self.close()
|
||||
if os.path.exists(self.path):
|
||||
shutil.rmtree(self.path)
|
||||
self._close_and_clean(True)
|
||||
|
@ -16,6 +16,31 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
PROJECT_CREATE_SCHEMA = {
|
||||
"$schema": "http://json-schema.org/draft-04/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",
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"uuid": {
|
||||
"description": "Project UUID",
|
||||
"type": "string",
|
||||
"minLength": 36,
|
||||
"maxLength": 36,
|
||||
"pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
|
||||
},
|
||||
"temporary": {
|
||||
"description": "If project is a temporary project",
|
||||
"type": "boolean"
|
||||
},
|
||||
},
|
||||
"additionalProperties": False,
|
||||
}
|
||||
|
||||
PROJECT_OBJECT_SCHEMA = {
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"description": "Request validation to create a new Project instance",
|
||||
@ -33,6 +58,11 @@ PROJECT_OBJECT_SCHEMA = {
|
||||
"maxLength": 36,
|
||||
"pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
|
||||
},
|
||||
"temporary": {
|
||||
"description": "If project is a temporary project",
|
||||
"type": "boolean"
|
||||
},
|
||||
"additionalProperties": False
|
||||
},
|
||||
"additionalProperties": False,
|
||||
"required": ["location", "uuid", "temporary"]
|
||||
}
|
||||
|
@ -34,6 +34,15 @@ def test_create_project_without_dir(server):
|
||||
response = server.post("/project", query)
|
||||
assert response.status == 200
|
||||
assert response.json["uuid"] is not None
|
||||
assert response.json["temporary"] is False
|
||||
|
||||
|
||||
def test_create_temporary_project(server):
|
||||
query = {"temporary": True}
|
||||
response = server.post("/project", query)
|
||||
assert response.status == 200
|
||||
assert response.json["uuid"] is not None
|
||||
assert response.json["temporary"] is True
|
||||
|
||||
|
||||
def test_create_project_with_uuid(server):
|
||||
|
@ -58,7 +58,7 @@ def test_temporary_path():
|
||||
|
||||
def test_json(tmpdir):
|
||||
p = Project()
|
||||
assert p.__json__() == {"location": p.location, "uuid": p.uuid}
|
||||
assert p.__json__() == {"location": p.location, "uuid": p.uuid, "temporary": False}
|
||||
|
||||
|
||||
def test_vm_working_directory(tmpdir, vm):
|
||||
@ -111,3 +111,13 @@ def test_project_close(tmpdir, manager):
|
||||
with patch("gns3server.modules.vpcs.vpcs_vm.VPCSVM.close") as mock:
|
||||
project.close()
|
||||
assert mock.called
|
||||
|
||||
|
||||
def test_project_close_temporary_project(tmpdir, manager):
|
||||
"""A temporary project is deleted when closed"""
|
||||
|
||||
project = Project(location=str(tmpdir), temporary=True)
|
||||
directory = project.path
|
||||
assert os.path.exists(directory)
|
||||
project.close()
|
||||
assert os.path.exists(directory) is False
|
||||
|
Loading…
Reference in New Issue
Block a user