From 240d83411c37432464bd30cf16459d0b8b31b63b Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Mon, 19 Jan 2015 16:23:41 +0100 Subject: [PATCH] Create a project entity --- docs/api/examples/post_project.txt | 20 ++++++++++ gns3server/handlers/__init__.py | 2 +- gns3server/handlers/project_handler.py | 34 +++++++++++++++++ gns3server/modules/project.py | 53 ++++++++++++++++++++++++++ gns3server/schemas/project.py | 39 +++++++++++++++++++ tests/api/test_project.py | 43 +++++++++++++++++++++ tests/modules/test_project.py | 41 ++++++++++++++++++++ 7 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 docs/api/examples/post_project.txt create mode 100644 gns3server/handlers/project_handler.py create mode 100644 gns3server/modules/project.py create mode 100644 gns3server/schemas/project.py create mode 100644 tests/api/test_project.py create mode 100644 tests/modules/test_project.py diff --git a/docs/api/examples/post_project.txt b/docs/api/examples/post_project.txt new file mode 100644 index 00000000..6312959f --- /dev/null +++ b/docs/api/examples/post_project.txt @@ -0,0 +1,20 @@ +curl -i -xPOST 'http://localhost:8000/project' -d '{"location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-240/test_create_project_with_dir0"}' + +POST /project HTTP/1.1 +{ + "location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-240/test_create_project_with_dir0" +} + + +HTTP/1.1 200 +CONNECTION: close +CONTENT-LENGTH: 171 +CONTENT-TYPE: application/json +DATE: Thu, 08 Jan 2015 16:09:15 GMT +SERVER: Python/3.4 aiohttp/0.13.1 +X-ROUTE: /project + +{ + "location": "/private/var/folders/3s/r2wbv07n7wg4vrsn874lmxxh0000gn/T/pytest-240/test_create_project_with_dir0", + "uuid": "16c371ee-728c-4bb3-8062-26b9313bd67d" +} diff --git a/gns3server/handlers/__init__.py b/gns3server/handlers/__init__.py index 60c6268d..965f59e6 100644 --- a/gns3server/handlers/__init__.py +++ b/gns3server/handlers/__init__.py @@ -1 +1 @@ -__all__ = ['version_handler', 'vpcs_handler'] +__all__ = ['version_handler', 'vpcs_handler', 'project_handler'] diff --git a/gns3server/handlers/project_handler.py b/gns3server/handlers/project_handler.py new file mode 100644 index 00000000..6fbaa4b0 --- /dev/null +++ b/gns3server/handlers/project_handler.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# +# 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 . + +from ..web.route import Route +from ..schemas.project import PROJECT_OBJECT_SCHEMA +from ..modules.project import Project +from aiohttp.web import HTTPConflict + + +class ProjectHandler: + @classmethod + @Route.post( + r"/project", + description="Create a project on the server", + output=PROJECT_OBJECT_SCHEMA, + input=PROJECT_OBJECT_SCHEMA) + def create_project(request, response): + p = Project(location = request.json.get("location"), + uuid = request.json.get("uuid")) + response.json(p) diff --git a/gns3server/modules/project.py b/gns3server/modules/project.py new file mode 100644 index 00000000..9d74d480 --- /dev/null +++ b/gns3server/modules/project.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# 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 . + +import os +import tempfile +from uuid import uuid4 + + +class Project: + """ + A project contains a list of VM. + In theory VM are isolated project/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) + """ + def __init__(self, uuid = None, location = None): + if uuid is None: + self.uuid = str(uuid4()) + else: + self.uuid = uuid + + self.location = location + if location is None: + self.location = tempfile.mkdtemp() + + self.path = os.path.join(self.location, self.uuid) + if os.path.exists(self.path) is False: + os.mkdir(self.path) + os.mkdir(os.path.join(self.path, 'files')) + + def __json__(self): + return { + "uuid": self.uuid, + "location": self.location + } diff --git a/gns3server/schemas/project.py b/gns3server/schemas/project.py new file mode 100644 index 00000000..bf1e07b2 --- /dev/null +++ b/gns3server/schemas/project.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# +# 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 . + + +PROJECT_OBJECT_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}$" + }, + }, + "additionalProperties": False +} + diff --git a/tests/api/test_project.py b/tests/api/test_project.py new file mode 100644 index 00000000..69067f29 --- /dev/null +++ b/tests/api/test_project.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +# +# 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 . + +""" +This test suite check /project endpoint +""" + + +from tests.utils import asyncio_patch +from tests.api.base import server, loop +from gns3server.version import __version__ + + +def test_create_project_with_dir(server, tmpdir): + response = server.post('/project', {"location": str(tmpdir)}, example=True) + assert response.status == 200 + assert response.json['location'] == str(tmpdir) + +def test_create_project_without_dir(server): + query = {} + response = server.post('/project', query) + assert response.status == 200 + assert response.json['uuid'] is not None + +def test_create_project_with_uuid(server): + query = {'uuid': '00010203-0405-0607-0809-0a0b0c0d0e0f'} + response = server.post('/project', query) + assert response.status == 200 + assert response.json['uuid'] is not None diff --git a/tests/modules/test_project.py b/tests/modules/test_project.py new file mode 100644 index 00000000..07245afd --- /dev/null +++ b/tests/modules/test_project.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# 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 . + +from gns3server.modules.project import Project +import os + +def test_affect_uuid(): + p = Project() + assert len(p.uuid) == 36 + + p = Project(uuid = '00010203-0405-0607-0809-0a0b0c0d0e0f') + assert p.uuid == '00010203-0405-0607-0809-0a0b0c0d0e0f' + +def test_path(tmpdir): + p = Project(location = str(tmpdir)) + assert p.path == os.path.join(str(tmpdir), p.uuid) + assert os.path.exists(os.path.join(str(tmpdir), p.uuid)) + assert os.path.exists(os.path.join(str(tmpdir), p.uuid, 'files')) + +def test_temporary_path(): + p = Project() + assert os.path.exists(p.path) + +def test_json(tmpdir): + p = Project() + assert p.__json__() == {"location": p.location, "uuid": p.uuid}