mirror of
https://github.com/GNS3/gns3-server
synced 2024-12-25 16:28:11 +00:00
Global project lock and unlock
This commit is contained in:
parent
43e60c31c7
commit
ca3bf592d6
@ -36,7 +36,6 @@ from fastapi.responses import StreamingResponse, FileResponse
|
||||
from websockets.exceptions import ConnectionClosed, WebSocketException
|
||||
from typing import List, Optional
|
||||
from uuid import UUID
|
||||
from pathlib import Path
|
||||
|
||||
from gns3server import schemas
|
||||
from gns3server.controller import Controller
|
||||
@ -46,7 +45,6 @@ from gns3server.controller.import_project import import_project as import_contro
|
||||
from gns3server.controller.export_project import export_project as export_controller_project
|
||||
from gns3server.utils.asyncio import aiozipstream
|
||||
from gns3server.utils.path import is_safe_path
|
||||
from gns3server.config import Config
|
||||
from gns3server.db.repositories.rbac import RbacRepository
|
||||
from gns3server.db.repositories.templates import TemplatesRepository
|
||||
from gns3server.services.templates import TemplatesService
|
||||
@ -397,6 +395,24 @@ async def duplicate_project(
|
||||
return new_project.asdict()
|
||||
|
||||
|
||||
@router.post("/{project_id}/lock", status_code=status.HTTP_204_NO_CONTENT)
|
||||
async def lock_project(project: Project = Depends(dep_project)) -> None:
|
||||
"""
|
||||
Lock all drawings and nodes in a given project.
|
||||
"""
|
||||
|
||||
project.lock()
|
||||
|
||||
|
||||
@router.post("/{project_id}/unlock", status_code=status.HTTP_204_NO_CONTENT)
|
||||
async def unlock_project(project: Project = Depends(dep_project)) -> None:
|
||||
"""
|
||||
Unlock all drawings and nodes in a given project.
|
||||
"""
|
||||
|
||||
project.unlock()
|
||||
|
||||
|
||||
@router.get("/{project_id}/files/{file_path:path}")
|
||||
async def get_file(file_path: str, project: Project = Depends(dep_project)) -> FileResponse:
|
||||
"""
|
||||
|
@ -1112,6 +1112,38 @@ class Project:
|
||||
return True
|
||||
return False
|
||||
|
||||
@open_required
|
||||
def lock(self):
|
||||
"""
|
||||
Lock all drawings and nodes
|
||||
"""
|
||||
|
||||
for drawing in self._drawings.values():
|
||||
if not drawing.locked:
|
||||
drawing.locked = True
|
||||
self.emit_notification("drawing.updated", drawing.asdict())
|
||||
for node in self.nodes.values():
|
||||
if not node.locked:
|
||||
node.locked = True
|
||||
self.emit_notification("node.updated", node.asdict())
|
||||
self.dump()
|
||||
|
||||
@open_required
|
||||
def unlock(self):
|
||||
"""
|
||||
Unlock all drawings and nodes
|
||||
"""
|
||||
|
||||
for drawing in self._drawings.values():
|
||||
if drawing.locked:
|
||||
drawing.locked = False
|
||||
self.emit_notification("drawing.updated", drawing.asdict())
|
||||
for node in self.nodes.values():
|
||||
if node.locked:
|
||||
node.locked = False
|
||||
self.emit_notification("node.updated", node.asdict())
|
||||
self.dump()
|
||||
|
||||
def dump(self):
|
||||
"""
|
||||
Dump topology to disk
|
||||
|
@ -24,11 +24,12 @@ import pytest_asyncio
|
||||
from fastapi import FastAPI, status
|
||||
from httpx import AsyncClient
|
||||
from unittest.mock import patch, MagicMock
|
||||
from tests.utils import asyncio_patch
|
||||
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||
|
||||
import gns3server.utils.zipfile_zstd as zipfile_zstd
|
||||
from gns3server.controller import Controller
|
||||
from gns3server.controller.project import Project
|
||||
from gns3server.controller.compute import Compute
|
||||
|
||||
pytestmark = pytest.mark.asyncio
|
||||
|
||||
@ -36,10 +37,10 @@ pytestmark = pytest.mark.asyncio
|
||||
@pytest_asyncio.fixture
|
||||
async def project(app: FastAPI, client: AsyncClient, controller: Controller) -> Project:
|
||||
|
||||
u = str(uuid.uuid4())
|
||||
params = {"name": "test", "project_id": u}
|
||||
project_id = str(uuid.uuid4())
|
||||
params = {"name": "test", "project_id": project_id}
|
||||
await client.post(app.url_path_for("create_project"), json=params)
|
||||
return controller.get_project(u)
|
||||
return controller.get_project(project_id)
|
||||
|
||||
|
||||
async def test_create_project_with_path(app: FastAPI, client: AsyncClient, controller: Controller, config) -> None:
|
||||
@ -473,3 +474,47 @@ async def test_duplicate(app: FastAPI, client: AsyncClient, project: Project) ->
|
||||
response = await client.post(app.url_path_for("duplicate_project", project_id=project.id), json={"name": "hello"})
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
assert response.json()["name"] == "hello"
|
||||
|
||||
|
||||
async def test_lock_unlock(app: FastAPI, client: AsyncClient, project: Project, compute: Compute) -> None:
|
||||
|
||||
# add a drawing and node to the project
|
||||
params = {
|
||||
"svg": '<svg height="210" width="500"><line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" /></svg>',
|
||||
"x": 10,
|
||||
"y": 20,
|
||||
"z": 0
|
||||
}
|
||||
|
||||
response = await client.post(app.url_path_for("create_drawing", project_id=project.id), json=params)
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
|
||||
response = MagicMock()
|
||||
response.json = {"console": 2048}
|
||||
compute.post = AsyncioMagicMock(return_value=response)
|
||||
|
||||
response = await client.post(app.url_path_for("create_node", project_id=project.id), json={
|
||||
"name": "test",
|
||||
"node_type": "vpcs",
|
||||
"compute_id": "example.com",
|
||||
"properties": {
|
||||
"startup_script": "echo test"
|
||||
}
|
||||
})
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
|
||||
response = await client.post(app.url_path_for("lock_project", project_id=project.id))
|
||||
assert response.status_code == status.HTTP_204_NO_CONTENT
|
||||
|
||||
for drawing in project.drawings.values():
|
||||
assert drawing.locked is True
|
||||
for node in project.nodes.values():
|
||||
assert node.locked is True
|
||||
|
||||
response = await client.post(app.url_path_for("unlock_project", project_id=project.id))
|
||||
assert response.status_code == status.HTTP_204_NO_CONTENT
|
||||
|
||||
for drawing in project.drawings.values():
|
||||
assert drawing.locked is False
|
||||
for node in project.nodes.values():
|
||||
assert node.locked is False
|
||||
|
Loading…
Reference in New Issue
Block a user