mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 05:51:15 +02:00
Merge branch '3.1' into api-issue-06-8s9swu
This commit is contained in:
24 files changed
+378
-70
No files matched your search
@@ -31,6 +31,7 @@ from gns3server.compute.compute_error import (
|
||||
from gns3server.compute.error import ImageMissingError, NodeError
|
||||
from gns3server.compute.ubridge.ubridge_error import UbridgeError
|
||||
from gns3server.controller.gns3vm.gns3_vm_error import GNS3VMError
|
||||
from gns3server.version import __api_version__
|
||||
|
||||
from . import (
|
||||
atm_switch_nodes,
|
||||
@@ -60,7 +61,8 @@ log = logging.getLogger(__name__)
|
||||
compute_api = FastAPI(
|
||||
title="GNS3 compute API",
|
||||
description="This page describes the private compute API for GNS3. PLEASE DO NOT USE DIRECTLY!",
|
||||
version="3.0.0",
|
||||
version=__api_version__,
|
||||
servers=[{"url": "/v3/compute"}],
|
||||
)
|
||||
|
||||
compute_api.state.controller_host = None
|
||||
|
||||
@@ -18,6 +18,7 @@ from fastapi import APIRouter, Depends, HTTPException, status
|
||||
|
||||
# Check AI Copilot availability
|
||||
from gns3server.agent import AI_COPILOT_AVAILABLE
|
||||
from gns3server.config import Config
|
||||
|
||||
# Conditionally import AI-dependent routes
|
||||
if AI_COPILOT_AVAILABLE:
|
||||
@@ -32,9 +33,11 @@ else:
|
||||
_copilot_router = APIRouter()
|
||||
_llm_router = APIRouter()
|
||||
|
||||
@_chat_router.api_route("/{path:path}", methods=["GET", "POST", "DELETE", "PATCH", "PUT"])
|
||||
@_copilot_router.api_route("/{path:path}", methods=["GET", "POST", "DELETE", "PATCH", "PUT"])
|
||||
@_llm_router.api_route("/{path:path}", methods=["GET", "POST", "DELETE", "PATCH", "PUT"])
|
||||
@_chat_router.api_route("/{path:path}", methods=["GET", "POST", "DELETE", "PATCH", "PUT"], include_in_schema=False)
|
||||
@_copilot_router.api_route(
|
||||
"/{path:path}", methods=["GET", "POST", "DELETE", "PATCH", "PUT"], include_in_schema=False
|
||||
)
|
||||
@_llm_router.api_route("/{path:path}", methods=["GET", "POST", "DELETE", "PATCH", "PUT"], include_in_schema=False)
|
||||
async def ai_not_available(path: str = ""):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED,
|
||||
@@ -67,6 +70,8 @@ from . import (
|
||||
)
|
||||
from .dependencies.authentication import get_current_active_user
|
||||
|
||||
_include_ai_in_schema = Config.instance().settings.Server.openapi_include_ai
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
router.include_router(controller.router, tags=["Controller"])
|
||||
@@ -116,11 +121,19 @@ router.include_router(
|
||||
)
|
||||
|
||||
router.include_router(
|
||||
_llm_router, prefix="/access", dependencies=[Depends(get_current_active_user)], tags=["LLM Model Configurations"]
|
||||
_llm_router,
|
||||
prefix="/access",
|
||||
dependencies=[Depends(get_current_active_user)],
|
||||
tags=["LLM Model Configurations"],
|
||||
include_in_schema=_include_ai_in_schema,
|
||||
)
|
||||
|
||||
router.include_router(
|
||||
_copilot_router, prefix="/copilot", dependencies=[Depends(get_current_active_user)], tags=["GNS3 Copilot"]
|
||||
_copilot_router,
|
||||
prefix="/copilot",
|
||||
dependencies=[Depends(get_current_active_user)],
|
||||
tags=["GNS3 Copilot"],
|
||||
include_in_schema=_include_ai_in_schema,
|
||||
)
|
||||
|
||||
router.include_router(
|
||||
@@ -128,6 +141,7 @@ router.include_router(
|
||||
prefix="/copilot/projects/{project_id}/chat",
|
||||
dependencies=[Depends(get_current_active_user)],
|
||||
tags=["GNS3 Copilot"],
|
||||
include_in_schema=_include_ai_in_schema,
|
||||
)
|
||||
|
||||
router.include_router(api_keys.router, dependencies=[Depends(get_current_active_user)], tags=["API Keys"])
|
||||
@@ -19,7 +19,7 @@ API routes for appliances.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from typing import List, Optional, Union
|
||||
from typing import List, Optional
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import APIRouter, Depends, status
|
||||
@@ -85,9 +85,7 @@ def get_appliance(appliance_id: UUID) -> schemas.Appliance:
|
||||
status_code=status.HTTP_201_CREATED,
|
||||
dependencies=[Depends(has_privilege("Appliance.Allocate"))],
|
||||
)
|
||||
def add_appliance_version(
|
||||
appliance_id: UUID, appliance_version: Union[schemas.ApplianceVersion, schemas.ApplianceVersionV8]
|
||||
) -> dict:
|
||||
def add_appliance_version(appliance_id: UUID, appliance_version: schemas.ApplianceVersionCreate) -> dict:
|
||||
"""
|
||||
Add a version to an appliance.
|
||||
|
||||
@@ -109,7 +107,7 @@ def add_appliance_version(
|
||||
if version.get("name") == appliance_version.name:
|
||||
raise ControllerError(message=f"Appliance '{appliance_id}' already has version '{appliance_version.name}'")
|
||||
|
||||
appliance.versions.append(appliance_version.model_dump(exclude_unset=True))
|
||||
appliance.versions.append(appliance_version.model_dump(exclude_unset=True, exclude={"registry_version"}))
|
||||
return appliance.asdict()
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ API routes for links.
|
||||
|
||||
import logging
|
||||
import os
|
||||
from typing import Any, List, Optional, Union
|
||||
from typing import Any, List, Optional
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
import aiohttp
|
||||
@@ -545,7 +545,7 @@ async def update_marker(marker_name: str, marker_data: schemas.MarkerUpdate, lin
|
||||
|
||||
@router.get(
|
||||
"/{link_id}/iface",
|
||||
response_model=Union[schemas.UDPPortInfo, schemas.EthernetPortInfo],
|
||||
response_model=schemas.LinkIfaceInfo,
|
||||
dependencies=[Depends(has_privilege("Link.Audit"))],
|
||||
)
|
||||
async def get_iface(link: Link = Depends(dep_link)) -> dict:
|
||||
@@ -576,6 +576,7 @@ async def get_iface(link: Link = Depends(dep_link)) -> dict:
|
||||
port_type = port.get("type", "")
|
||||
if "udp" in port_type.lower():
|
||||
ifaces_info = {
|
||||
"kind": "udp",
|
||||
"node_id": node.id,
|
||||
"type": f"{port_type}",
|
||||
"lport": port["lport"],
|
||||
@@ -584,6 +585,7 @@ async def get_iface(link: Link = Depends(dep_link)) -> dict:
|
||||
}
|
||||
else:
|
||||
ifaces_info = {
|
||||
"kind": "ethernet",
|
||||
"node_id": node.id,
|
||||
"type": f"{port_type}",
|
||||
"interface": port["interface"],
|
||||
|
||||
+12
-11
@@ -39,6 +39,7 @@ from gns3server.agent import MCP_AVAILABLE
|
||||
from gns3server.api.errors import customize_openapi_errors, error_response
|
||||
from gns3server.api.routes import controller, index
|
||||
from gns3server.api.routes.compute import compute_api
|
||||
from gns3server.config import Config
|
||||
from gns3server.controller.controller_error import (
|
||||
ComputeConflictError,
|
||||
ControllerBadRequestError,
|
||||
@@ -49,6 +50,7 @@ from gns3server.controller.controller_error import (
|
||||
ControllerUnauthorizedError,
|
||||
)
|
||||
from gns3server.core import tasks
|
||||
from gns3server.version import __api_version__
|
||||
|
||||
if MCP_AVAILABLE:
|
||||
from gns3server.agent import mcp
|
||||
@@ -59,7 +61,7 @@ else:
|
||||
|
||||
_mcp_router = APIRouter(prefix="/mcp", tags=["MCP"])
|
||||
|
||||
@_mcp_router.api_route("/{path:path}", methods=["GET", "POST", "DELETE", "PATCH", "PUT"])
|
||||
@_mcp_router.api_route("/{path:path}", methods=["GET", "POST", "DELETE", "PATCH", "PUT"], include_in_schema=False)
|
||||
async def mcp_not_available(path: str = ""):
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_501_NOT_IMPLEMENTED,
|
||||
@@ -84,15 +86,9 @@ def get_application() -> FastAPI:
|
||||
application = ControllerAPI(
|
||||
lifespan=tasks.lifespan,
|
||||
title="GNS3 controller API",
|
||||
description="This page describes the public controller API for GNS3.\n\n"
|
||||
"## Notification streams\n\n"
|
||||
"Notifications are available as HTTP streams of newline delimited JSON objects (`GET /v3/notifications` and "
|
||||
"`GET /v3/projects/{project_id}/notifications`) and as WebSockets sending one JSON object per text frame "
|
||||
"(`/v3/notifications/ws`, `/v3/projects/{project_id}/notifications/ws` and "
|
||||
"`/v3/projects/{project_id}/notifications/markers/ws`). "
|
||||
"OpenAPI cannot describe WebSocket routes, they carry the same `Notification` messages as the HTTP streams. "
|
||||
"Marker events (`marker.match`) are only sent on the markers WebSocket.",
|
||||
version="3.0.0",
|
||||
description="This page describes the public controller API for GNS3",
|
||||
version=__api_version__,
|
||||
servers=[{"url": "/"}],
|
||||
docs_url=None,
|
||||
redoc_url=None,
|
||||
)
|
||||
@@ -111,7 +107,12 @@ def get_application() -> FastAPI:
|
||||
application.mount("/v3/compute", compute_api, name="compute")
|
||||
|
||||
# Register MCP routes (stub returns 501 if MCP dependencies are not installed)
|
||||
application.include_router(_mcp_router, prefix="/v3", tags=["MCP"])
|
||||
application.include_router(
|
||||
_mcp_router,
|
||||
prefix="/v3",
|
||||
tags=["MCP"],
|
||||
include_in_schema=Config.instance().settings.Server.openapi_include_ai,
|
||||
)
|
||||
|
||||
return application
|
||||
|
||||
|
||||
Reference in new issue
Block a user