diff --git a/gns3server/controller/link.py b/gns3server/controller/link.py index c33c834a..43ef7b79 100644 --- a/gns3server/controller/link.py +++ b/gns3server/controller/link.py @@ -164,7 +164,7 @@ class Link: @property def nodes(self): - return self._nodes + return [ node['node'] for node in self._nodes ] @property def capturing(self): @@ -181,6 +181,11 @@ class Link: else: return None + def __eq__(self, other): + if not isinstance(other, Link): + return False + return self.id == other.id + def __json__(self, topology_dump=False): """ :param topology_dump: Filter to keep only properties require for saving on disk diff --git a/gns3server/controller/node.py b/gns3server/controller/node.py index 732ba54a..221be900 100644 --- a/gns3server/controller/node.py +++ b/gns3server/controller/node.py @@ -400,6 +400,11 @@ class Node: def __repr__(self): return "".format(self._node_type, self._name) + def __eq__(self, other): + if not isinstance(other, Node): + return False + return self.id == other.id and other.project.id == self.project.id + def __json__(self, topology_dump=False): """ :param topology_dump: Filter to keep only properties require for saving on disk diff --git a/gns3server/controller/project.py b/gns3server/controller/project.py index 60630be6..55fec391 100644 --- a/gns3server/controller/project.py +++ b/gns3server/controller/project.py @@ -243,6 +243,11 @@ class Project: def delete_node(self, node_id): node = self.get_node(node_id) + + for link in list(self._links.values()): + if node in link.nodes: + yield from self.delete_link(link.id) + self.remove_allocated_node_name(node.name) del self._nodes[node.id] yield from node.destroy() diff --git a/tests/controller/test_link.py b/tests/controller/test_link.py index 29040d64..28200e6a 100644 --- a/tests/controller/test_link.py +++ b/tests/controller/test_link.py @@ -50,6 +50,12 @@ def link(async_run, project, compute): return link +def test_eq(project, link, controller): + assert link == Link(project, link_id=link.id) + assert link != "a" + assert link != Link(project) + + def test_add_node(async_run, project, compute): node1 = Node(project, compute, "node1") diff --git a/tests/controller/test_node.py b/tests/controller/test_node.py index 426a2ee8..6f4eb8c6 100644 --- a/tests/controller/test_node.py +++ b/tests/controller/test_node.py @@ -50,6 +50,13 @@ def node(compute, project): return node +def test_eq(compute, project, node, controller): + assert node == Node(project, compute, "demo", node_id=node.id) + assert node != "a" + assert node != Node(project, compute, "demo", node_id=str(uuid.uuid4())) + assert node != Node( Project(str(uuid.uuid4()), controller=controller), compute, "demo", node_id=node.id) + + def test_json(node, compute): assert node.__json__() == { "compute_id": str(compute.id), diff --git a/tests/controller/test_project.py b/tests/controller/test_project.py index 10309238..8a236ae3 100644 --- a/tests/controller/test_project.py +++ b/tests/controller/test_project.py @@ -151,6 +151,32 @@ def test_delete_node(async_run, controller): controller.notification.emit.assert_any_call("node.deleted", node.__json__()) +def test_delete_node_delete_link(async_run, controller): + """ + Delete a node delete all the node connected + """ + compute = MagicMock() + project = Project(controller=controller) + controller._notification = MagicMock() + + response = MagicMock() + response.json = {"console": 2048} + compute.post = AsyncioMagicMock(return_value=response) + + node = async_run(project.add_node(compute, "test", None, node_type="vpcs", properties={"startup_config": "test.cfg"})) + + link = async_run(project.add_link()) + async_run(link.add_node(node, 0, 0)) + + async_run(project.delete_node(node.id)) + assert node.id not in project._nodes + assert link.id not in project._links + + compute.delete.assert_any_call('/projects/{}/vpcs/nodes/{}'.format(project.id, node.id)) + controller.notification.emit.assert_any_call("node.deleted", node.__json__()) + controller.notification.emit.assert_any_call("link.deleted", link.__json__()) + + def test_getVM(async_run, controller): compute = MagicMock() project = Project(controller=controller)