Skip to content

Commit a358369

Browse files
committed
Move notifications under controller router
1 parent 5155aea commit a358369

File tree

3 files changed

+66
-95
lines changed

3 files changed

+66
-95
lines changed

gns3server/api/routes/controller/__init__.py

+10-8
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
from . import gns3vm
2424
from . import links
2525
from . import nodes
26-
from . import notifications
2726
from . import projects
2827
from . import snapshots
2928
from . import symbols
@@ -38,8 +37,16 @@
3837

3938
router = APIRouter()
4039

41-
router.include_router(controller.router, tags=["Controller"])
42-
router.include_router(users.router, prefix="/users", tags=["Users"])
40+
router.include_router(
41+
controller.router,
42+
tags=["Controller"]
43+
)
44+
45+
router.include_router(
46+
users.router,
47+
prefix="/users",
48+
tags=["Users"]
49+
)
4350

4451
router.include_router(
4552
groups.router,
@@ -110,11 +117,6 @@
110117
tags=["Computes"]
111118
)
112119

113-
router.include_router(
114-
notifications.router,
115-
prefix="/notifications",
116-
tags=["Notifications"])
117-
118120
router.include_router(
119121
appliances.router,
120122
prefix="/appliances",

gns3server/api/routes/controller/controller.py

+56-2
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@
1818
import signal
1919
import os
2020

21-
from fastapi import APIRouter, Depends, Request, Response, status
21+
from fastapi import APIRouter, Request, Depends, WebSocket, WebSocketDisconnect, status
22+
from fastapi.responses import StreamingResponse
2223
from fastapi.encoders import jsonable_encoder
2324
from fastapi.routing import Mount
25+
from websockets.exceptions import ConnectionClosed, WebSocketException
26+
2427
from typing import List
2528

2629
from gns3server.config import Config
@@ -29,7 +32,7 @@
2932
from gns3server.controller.controller_error import ControllerError, ControllerForbiddenError
3033
from gns3server import schemas
3134

32-
from .dependencies.authentication import get_current_active_user
35+
from .dependencies.authentication import get_current_active_user, get_current_active_user_from_websocket
3336

3437
import logging
3538

@@ -174,6 +177,57 @@ async def statistics() -> List[dict]:
174177
return compute_statistics
175178

176179

180+
@router.get("/notifications", dependencies=[Depends(get_current_active_user)])
181+
async def controller_http_notifications(request: Request) -> StreamingResponse:
182+
"""
183+
Receive controller notifications about the controller from HTTP stream.
184+
"""
185+
186+
from gns3server.api.server import app
187+
log.info(f"New client {request.client.host}:{request.client.port} has connected to controller HTTP "
188+
f"notification stream")
189+
190+
async def event_stream():
191+
try:
192+
with Controller.instance().notification.controller_queue() as queue:
193+
while not app.state.exiting:
194+
msg = await queue.get_json(5)
195+
yield f"{msg}\n".encode("utf-8")
196+
finally:
197+
log.info(f"Client {request.client.host}:{request.client.port} has disconnected from controller HTTP "
198+
f"notification stream")
199+
return StreamingResponse(event_stream(), media_type="application/json")
200+
201+
202+
@router.websocket("/notifications/ws")
203+
async def controller_ws_notifications(
204+
websocket: WebSocket,
205+
current_user: schemas.User = Depends(get_current_active_user_from_websocket)
206+
) -> None:
207+
"""
208+
Receive project notifications about the controller from WebSocket.
209+
"""
210+
211+
if current_user is None:
212+
return
213+
214+
log.info(f"New client {websocket.client.host}:{websocket.client.port} has connected to controller WebSocket")
215+
try:
216+
with Controller.instance().notification.controller_queue() as queue:
217+
while True:
218+
notification = await queue.get_json(5)
219+
await websocket.send_text(notification)
220+
except (ConnectionClosed, WebSocketDisconnect):
221+
log.info(f"Client {websocket.client.host}:{websocket.client.port} has disconnected from controller WebSocket")
222+
except WebSocketException as e:
223+
log.warning(f"Error while sending to controller event to WebSocket client: {e}")
224+
finally:
225+
try:
226+
await websocket.close()
227+
except OSError:
228+
pass # ignore OSError: [Errno 107] Transport endpoint is not connected
229+
230+
177231
# @Route.post(
178232
# r"/debug",
179233
# description="Dump debug information to disk (debug directory in config directory). Work only for local server",

gns3server/api/routes/controller/notifications.py

-85
This file was deleted.

0 commit comments

Comments
 (0)