diff --git a/gns3server/controller/__init__.py b/gns3server/controller/__init__.py index 3741f2a9..2b15cf75 100644 --- a/gns3server/controller/__init__.py +++ b/gns3server/controller/__init__.py @@ -77,16 +77,23 @@ class Controller: """ Save the controller configuration on disk """ - data = {"computes": [{"host": c.host, - "name": c.name, - "port": c.port, - "protocol": c.protocol, - "user": c.user, - "password": c.password, - "compute_id": c.id - } for c in self._computes.values()], - "settings": self._settings, - "version": __version__} + data = { + "computes": [], + "settings": self._settings, + "version": __version__ + } + + for c in self._computes.values(): + if c.id != "local": + data["computes"].append({ + "host": c.host, + "name": c.name, + "port": c.port, + "protocol": c.protocol, + "user": c.user, + "password": c.password, + "compute_id": c.id + }) os.makedirs(os.path.dirname(self._config_file), exist_ok=True) with open(self._config_file, 'w+') as f: json.dump(data, f, indent=4) diff --git a/gns3server/controller/compute.py b/gns3server/controller/compute.py index b7893c06..77ee6f67 100644 --- a/gns3server/controller/compute.py +++ b/gns3server/controller/compute.py @@ -96,10 +96,6 @@ class Compute: # Websocket for notifications self._ws = None - # It's a configuration issue if the compute is not configured to be local but the compute id is local - if compute_id == "local" and Config.instance().get_section_config("Server")["local"] is False: - raise ComputeError("The local compute is started without --local") - def _session(self): if self._http_session is None or self._http_session.closed is True: self._http_session = aiohttp.ClientSession() diff --git a/gns3server/handlers/api/compute/notification_handler.py b/gns3server/handlers/api/compute/notification_handler.py index f14c75ea..a2cda68c 100644 --- a/gns3server/handlers/api/compute/notification_handler.py +++ b/gns3server/handlers/api/compute/notification_handler.py @@ -35,6 +35,7 @@ def process_websocket(ws): class NotificationHandler: + @Route.get( r"/notifications/ws", description="Send notifications using Websockets") diff --git a/tests/controller/test_compute.py b/tests/controller/test_compute.py index 5687bd51..9e6e5ebe 100644 --- a/tests/controller/test_compute.py +++ b/tests/controller/test_compute.py @@ -16,8 +16,9 @@ # along with this program. If not, see . import os -import pytest import json +import pytest +import socket import aiohttp import asyncio from unittest.mock import patch, MagicMock @@ -44,27 +45,13 @@ def test_name(): assert c.name == "https://example.com:84" with patch("gns3server.config.Config.get_section_config", return_value={"local": True}): c = Compute("local", protocol="https", host="example.com", port=84, controller=MagicMock(), name=None) - assert c.name == "Local" + assert c.name == socket.gethostname() c = Compute("world", protocol="https", host="example.com", port=84, controller=MagicMock(), name="hello") assert c.name == "hello" c = Compute("world", protocol="https", host="example.com", port=84, controller=MagicMock(), user="azertyuiopqsdfghjklkm") assert c.name == "https://azertyuiopq...@example.com:84" -def test_compute_local(compute): - """ - If the compute is local but the compute id is local - it's a configuration issue - """ - - with patch("gns3server.config.Config.get_section_config", return_value={"local": False}): - with pytest.raises(ComputeError): - s = Compute("local", controller=MagicMock()) - - with patch("gns3server.config.Config.get_section_config", return_value={"local": True}): - s = Compute("test", controller=MagicMock()) - - def test_compute_httpQuery(compute, async_run): response = MagicMock() with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock: diff --git a/tests/controller/test_controller.py b/tests/controller/test_controller.py index a846cba1..79d470ae 100644 --- a/tests/controller/test_controller.py +++ b/tests/controller/test_controller.py @@ -58,7 +58,6 @@ def test_load(controller, controller_config_path, async_run): with open(controller_config_path, "w+") as f: json.dump(data, f) async_run(controller.load()) - assert len(controller.computes) == 1 assert controller.settings["IOU"] assert controller.computes["test1"].__json__() == { "compute_id": "test1", @@ -98,14 +97,14 @@ def test_import_computes(controller, controller_config_path, async_run): json.dump(gns3_gui_conf, f) async_run(controller.load()) - assert len(controller.computes) == 1 - compute = list(controller.computes.values())[0] - assert compute.host == "127.0.0.1" - assert compute.port == 3081 - assert compute.protocol == "http" - assert compute.name == "http://127.0.0.1:3081" - assert compute.user is None - assert compute.password is None + for compute in controller.computes.values(): + if compute.id != "local": + assert compute.host == "127.0.0.1" + assert compute.port == 3081 + assert compute.protocol == "http" + assert compute.name == "http://127.0.0.1:3081" + assert compute.user is None + assert compute.password is None def test_settings(controller): @@ -136,29 +135,29 @@ def test_addCompute(controller, controller_config_path, async_run): controller._notification = MagicMock() c = async_run(controller.add_compute(compute_id="test1")) controller._notification.emit.assert_called_with("compute.created", c.__json__()) - assert len(controller.computes) == 1 + assert len(controller.computes) == 2 async_run(controller.add_compute(compute_id="test1")) controller._notification.emit.assert_called_with("compute.updated", c.__json__()) - assert len(controller.computes) == 1 - async_run(controller.add_compute(compute_id="test2")) assert len(controller.computes) == 2 + async_run(controller.add_compute(compute_id="test2")) + assert len(controller.computes) == 3 def test_addDuplicateCompute(controller, controller_config_path, async_run): controller._notification = MagicMock() c = async_run(controller.add_compute(compute_id="test1", name="Test")) - assert len(controller.computes) == 1 + assert len(controller.computes) == 2 with pytest.raises(aiohttp.web.HTTPConflict): async_run(controller.add_compute(compute_id="test2", name="Test")) def test_deleteCompute(controller, controller_config_path, async_run): c = async_run(controller.add_compute(compute_id="test1")) - assert len(controller.computes) == 1 + assert len(controller.computes) == 2 controller._notification = MagicMock() c._connected = True async_run(controller.delete_compute("test1")) - assert len(controller.computes) == 0 + assert len(controller.computes) == 1 controller._notification.emit.assert_called_with("compute.deleted", c.__json__()) with open(controller_config_path) as f: data = json.load(f) @@ -168,7 +167,7 @@ def test_deleteCompute(controller, controller_config_path, async_run): def test_addComputeConfigFile(controller, controller_config_path, async_run): async_run(controller.add_compute(compute_id="test1", name="Test")) - assert len(controller.computes) == 1 + assert len(controller.computes) == 2 with open(controller_config_path) as f: data = json.load(f) assert data["computes"] == [ @@ -199,17 +198,6 @@ def test_has_compute(controller, async_run): assert not controller.has_compute("test2") -def test_initControllerLocal(controller, controller_config_path, async_run): - """ - The local node is the controller itself you can not change the informations - """ - # The default test controller is not local - assert len(controller._computes) == 0 - Config.instance().set("Server", "local", True) - c = Controller() - assert len(c._computes) == 1 - - def test_add_project(controller, async_run): uuid1 = str(uuid.uuid4()) uuid2 = str(uuid.uuid4()) diff --git a/tests/handlers/api/controller/test_compute.py b/tests/handlers/api/controller/test_compute.py index e43f79d7..f9a4f35b 100644 --- a/tests/handlers/api/controller/test_compute.py +++ b/tests/handlers/api/controller/test_compute.py @@ -35,7 +35,7 @@ def test_compute_create_without_id(http_controller, controller): assert response.json["compute_id"] is not None assert "password" not in response.json - assert len(controller.computes) == 1 + assert len(controller.computes) == 2 assert controller.computes[response.json["compute_id"]].host == "example.com" @@ -55,7 +55,7 @@ def test_compute_create_with_id(http_controller, controller): assert response.json["user"] == "julien" assert "password" not in response.json - assert len(controller.computes) == 1 + assert len(controller.computes) == 2 assert controller.computes["my_compute_id"].host == "example.com" @@ -119,19 +119,19 @@ def test_compute_list(http_controller, controller): assert "password" not in response.json response = http_controller.get("/computes", example=True) - assert response.json == [ - { - 'compute_id': 'my_compute_id', - 'connected': False, - 'host': 'example.com', - 'port': 84, - 'protocol': 'http', - 'user': 'julien', - 'name': 'My super server', - 'cpu_usage_percent': None, - 'memory_usage_percent': None - } - ] + for compute in response.json: + if compute['compute_id'] != 'local': + assert compute == { + 'compute_id': 'my_compute_id', + 'connected': False, + 'host': 'example.com', + 'port': 84, + 'protocol': 'http', + 'user': 'julien', + 'name': 'My super server', + 'cpu_usage_percent': None, + 'memory_usage_percent': None + } def test_compute_delete(http_controller, controller): @@ -148,13 +148,13 @@ def test_compute_delete(http_controller, controller): assert response.status == 201 response = http_controller.get("/computes") - assert len(response.json) == 1 + assert len(response.json) == 2 response = http_controller.delete("/computes/my_compute_id") assert response.status == 204 response = http_controller.get("/computes") - assert len(response.json) == 0 + assert len(response.json) == 1 def test_compute_list_images(http_controller, controller): diff --git a/tests/test_config.py b/tests/test_config.py index cd8e8c23..58e5b9e7 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -59,7 +59,7 @@ def test_get_section_config(tmpdir): config = load_config(tmpdir, { "Server": { - "host": "127.0.0.1" + "host": "127.0.0.1", } }) assert dict(config.get_section_config("Server")) == {"host": "127.0.0.1"}