Temporary project

This commit is contained in:
Julien Duponchelle 2015-01-23 16:02:26 +01:00
parent 7bf121c6da
commit abc885049f
5 changed files with 74 additions and 12 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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"]
}

View File

@ -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):

View File

@ -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