mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-04 14:31:13 +02:00
feat: add auto_connect flag and disconnect endpoint for computes
Computes can now be flagged auto_connect in the database. The controller
connects to flagged computes in the background at startup (reusing the
one-second delayed fire-and-forget mechanism), and enabling the flag via
PUT /computes/{id} triggers a background connection without the request
ever waiting for it. Disabling the flag does not drop an existing
connection.
Add POST /computes/{id}/disconnect to tear a compute down manually: the
notification stream and HTTP session are closed and every reconnection
path (retry backoff, notification stream reconnect, lazy connection in
http_query) is blocked until connect() is called again or the controller
restarts with auto_connect enabled. Disconnecting a compute used by an
opened project is rejected with 409 unless force=true; forcing only
drops the controller-side control channel, nodes keep running unmanaged.
The local compute cannot be disconnected.
Also make test_compute_list create its own compute (it relied on rows
from earlier tests and failed under reordering), and stop scheduling the
delayed add_compute connection during tests: the timer leaked real
connection attempts into other tests' event loops.
This commit is contained in:
10 files changed
+433
-14
No files matched your search
@@ -26,6 +26,7 @@ from fastapi import APIRouter, Body, Depends, Query, status
|
||||
import gns3server.db.models as models
|
||||
from gns3server import schemas
|
||||
from gns3server.controller import Controller
|
||||
from gns3server.controller.controller_error import ControllerBadRequestError, ControllerError
|
||||
from gns3server.db.repositories.computes import ComputesRepository
|
||||
from gns3server.db.repositories.rbac import RbacRepository
|
||||
from gns3server.services.computes import ComputesService
|
||||
@@ -80,6 +81,42 @@ async def connect_compute(compute_id: Union[str, UUID]) -> None:
|
||||
await compute.connect(report_failed_connection=True)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/{compute_id}/disconnect",
|
||||
status_code=status.HTTP_204_NO_CONTENT,
|
||||
responses={409: {"model": schemas.ErrorMessage, "description": "Compute is used by opened projects"}},
|
||||
# dependencies=[Depends(has_privilege("Compute.Audit"))] # FIXME: this is a temporary workaround due to a bug in the web-ui
|
||||
)
|
||||
async def disconnect_compute(compute_id: Union[str, UUID], force: Optional[bool] = False) -> None:
|
||||
"""
|
||||
Disconnect from a compute on the controller.
|
||||
|
||||
The compute is not reconnected until an explicit connection is requested,
|
||||
or the controller restarts with auto_connect enabled for this compute.
|
||||
|
||||
Rejected with 409 when an opened project still uses the compute, unless
|
||||
force is true. Forcing does not stop anything on the compute: only the
|
||||
controller-side control channel (notification stream and HTTP session) is
|
||||
torn down, nodes keep running unmanaged.
|
||||
|
||||
Required privilege: Compute.Audit
|
||||
"""
|
||||
|
||||
if str(compute_id) == "local":
|
||||
raise ControllerBadRequestError("Cannot disconnect the local compute")
|
||||
controller = Controller.instance()
|
||||
compute = controller.get_compute(str(compute_id))
|
||||
if not force:
|
||||
open_projects = controller.get_compute_open_projects(compute)
|
||||
if open_projects:
|
||||
project_names = ", ".join(f"'{project.name}'" for project in open_projects)
|
||||
raise ControllerError(
|
||||
f"Compute '{compute_id}' is used by opened projects ({project_names}), "
|
||||
"disconnect anyway with force=true"
|
||||
)
|
||||
await compute.disconnect()
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{compute_id}",
|
||||
response_model=schemas.Compute,
|
||||
|
||||
Reference in new issue
Block a user