From 58b998600e0b5a40b4bd7888b404cae11fda66bb Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Tue, 26 Jan 2016 16:35:00 +0100 Subject: [PATCH] Send machine stats via the notification stream Fix #252 --- gns3server/handlers/api/project_handler.py | 20 ++++++++++++++++++-- tests/handlers/api/test_project.py | 8 +++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/gns3server/handlers/api/project_handler.py b/gns3server/handlers/api/project_handler.py index 49e795cf..866fddf1 100644 --- a/gns3server/handlers/api/project_handler.py +++ b/gns3server/handlers/api/project_handler.py @@ -19,6 +19,7 @@ import aiohttp import asyncio import json import os +import psutil from ...web.route import Route from ...schemas.project import PROJECT_OBJECT_SCHEMA, PROJECT_CREATE_SCHEMA, PROJECT_UPDATE_SCHEMA, PROJECT_FILE_LIST_SCHEMA, PROJECT_LIST_SCHEMA @@ -205,7 +206,7 @@ class ProjectHandler: queue = project.get_listen_queue() ProjectHandler._notifications_listening.setdefault(project.id, 0) ProjectHandler._notifications_listening[project.id] += 1 - response.write("{\"action\": \"ping\"}\n".encode("utf-8")) + response.write("{}\n".format(json.dumps(ProjectHandler._getPingMessage())).encode("utf-8")) while True: try: (action, msg) = yield from asyncio.wait_for(queue.get(), 5) @@ -218,11 +219,26 @@ class ProjectHandler: except asyncio.futures.CancelledError as e: break except asyncio.futures.TimeoutError: - response.write("{\"action\": \"ping\"}\n".encode("utf-8")) + response.write("{}\n".format(json.dumps(ProjectHandler._getPingMessage())).encode("utf-8")) project.stop_listen_queue(queue) if project.id in ProjectHandler._notifications_listening: ProjectHandler._notifications_listening[project.id] -= 1 + @classmethod + def _getPingMessage(cls): + """ + The ping message is regulary send to the client to + keep the connection open. We send with it some informations + about server load. + + :returns: hash + """ + stats = {} + # Non blocking call in order to get cpu usage. First call will return 0 + stats["cpu_usage_percent"] = psutil.cpu_percent(interval=None) + stats["memory_usage_percent"] = psutil.virtual_memory().percent + return {"action": "ping", "event": stats} + @classmethod @Route.get( r"/projects/{project_id}/files", diff --git a/tests/handlers/api/test_project.py b/tests/handlers/api/test_project.py index 220339b5..5af3d03c 100644 --- a/tests/handlers/api/test_project.py +++ b/tests/handlers/api/test_project.py @@ -207,9 +207,9 @@ def test_notification(server, project, loop): @asyncio.coroutine def go(future): response = yield from aiohttp.request("GET", server.get_url("/projects/{project_id}/notifications".format(project_id=project.id), 1)) - response.body = yield from response.content.read(19) + response.body = yield from response.content.read(200) project.emit("vm.created", {"a": "b"}) - response.body += yield from response.content.read(47) + response.body += yield from response.content.read(50) response.close() future.set_result(response) @@ -217,7 +217,9 @@ def test_notification(server, project, loop): asyncio.async(go(future)) response = loop.run_until_complete(future) assert response.status == 200 - assert response.body == b'{"action": "ping"}\n{"action": "vm.created", "event": {"a": "b"}}\n' + assert b'"action": "ping"' in response.body + assert b'"cpu_usage_percent"' in response.body + assert b'{"action": "vm.created", "event": {"a": "b"}}\n' in response.body def test_notification_invalid_id(server):