From f82527e253821f2e0cf1fccbc4fdee920b704b05 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Wed, 17 Aug 2016 11:58:19 +0200 Subject: [PATCH] Compute node size on server Fix #620 --- gns3server/controller/node.py | 37 +++++++++++++++++--------------- gns3server/controller/symbols.py | 12 +++++++++++ gns3server/schemas/node.py | 4 ++-- tests/controller/test_node.py | 14 ++++++++++++ tests/controller/test_symbols.py | 5 +++++ 5 files changed, 53 insertions(+), 19 deletions(-) diff --git a/gns3server/controller/node.py b/gns3server/controller/node.py index 476d69bb..24751a97 100644 --- a/gns3server/controller/node.py +++ b/gns3server/controller/node.py @@ -31,7 +31,7 @@ log = logging.getLogger(__name__) class Node: # This properties are used only on controller and are not forwarded to the compute - CONTROLLER_ONLY_PROPERTIES = ["x", "y", "z", "symbol", "label", "console_host"] + CONTROLLER_ONLY_PROPERTIES = ["x", "y", "z", "width", "height", "symbol", "label", "console_host"] def __init__(self, project, compute, name, node_id=None, node_type=None, **kwargs): """ @@ -69,20 +69,26 @@ class Node: self._command_line = None self._node_directory = None self._status = "stopped" - self._width = 70 - self._height = 70 self._x = 0 self._y = 0 self._z = 0 - self._symbol = ":/symbols/computer.svg" + self._symbol = None # Update node properties with additional elements + + # This properties will be recompute + ignore_properties = ("width", "height") + for prop in kwargs: - try: - setattr(self, prop, kwargs[prop]) - except AttributeError as e: - log.critical("Can't set attribute %s", prop) - raise e + if prop not in ignore_properties: + try: + setattr(self, prop, kwargs[prop]) + except AttributeError as e: + log.critical("Can't set attribute %s", prop) + raise e + + if self._symbol is None: + self.symbol = ":/symbols/computer.svg" @property def id(self): @@ -173,18 +179,10 @@ class Node: def width(self): return self._width - @width.setter - def width(self, val): - self._width = val - @property def height(self): return self._height - @height.setter - def height(self, val): - self._height = val - @property def symbol(self): return self._symbol @@ -192,6 +190,11 @@ class Node: @symbol.setter def symbol(self, val): self._symbol = val + try: + self._width, self._height, filetype = self._project.controller.symbols.get_size(val) + # If symbol is invalid we replace it by default + except (ValueError, OSError): + self.symbol = ":/symbols/computer.svg" @property def label(self): diff --git a/gns3server/controller/symbols.py b/gns3server/controller/symbols.py index 894f4b8b..f3979adc 100644 --- a/gns3server/controller/symbols.py +++ b/gns3server/controller/symbols.py @@ -19,6 +19,7 @@ import os from ..utils.get_resource import get_resource +from ..utils.picture import get_size from ..config import Config @@ -29,6 +30,8 @@ class Symbols: def __init__(self): self.list() + # Keep a cache of symbols size + self._symbol_size_cache = {} def list(self): self._symbols_path = {} @@ -68,3 +71,12 @@ class Symbols: def get_path(self, symbol_id): return self._symbols_path[symbol_id] + + def get_size(self, symbol_id): + try: + return self._symbol_size_cache[symbol_id] + except KeyError: + with open(self.get_path(symbol_id), "rb") as f: + res = get_size(f.read()) + self._symbol_size_cache[symbol_id] = res + return res diff --git a/gns3server/schemas/node.py b/gns3server/schemas/node.py index c75aaa90..d4868852 100644 --- a/gns3server/schemas/node.py +++ b/gns3server/schemas/node.py @@ -145,11 +145,11 @@ NODE_OBJECT_SCHEMA = { "minLength": 1 }, "width": { - "description": "Width of the node", + "description": "Width of the node (Read only)", "type": "integer" }, "height": { - "description": "Height of the node", + "description": "Height of the node (Read only)", "type": "integer" }, "x": { diff --git a/tests/controller/test_node.py b/tests/controller/test_node.py index 5b0c2eae..f33c0485 100644 --- a/tests/controller/test_node.py +++ b/tests/controller/test_node.py @@ -171,6 +171,20 @@ def test_create_image_missing(node, compute, project, async_run): node._upload_missing_image.called is True +def test_symbol(node): + """ + Change symbol should change the node size + """ + node.symbol = ":/symbols/dslam.svg" + assert node.symbol == ":/symbols/dslam.svg" + assert node.width == 50 + assert node.height == 53 + node.symbol = ":/symbols/cloud.svg" + assert node.symbol == ":/symbols/cloud.svg" + assert node.width == 159 + assert node.height == 71 + + def test_update(node, compute, project, async_run, controller): response = MagicMock() response.json = {"console": 2048} diff --git a/tests/controller/test_symbols.py b/tests/controller/test_symbols.py index 30a91faa..c4344342 100644 --- a/tests/controller/test_symbols.py +++ b/tests/controller/test_symbols.py @@ -44,3 +44,8 @@ def test_list(symbols_dir): def test_get_path(): symbols = Symbols() assert symbols.get_path(':/symbols/firewall.svg') == get_resource("symbols/firewall.svg") + + +def test_get_size(): + symbols = Symbols() + assert symbols.get_size(':/symbols/firewall.svg') == (66, 45, 'svg')