diff --git a/gns3server/controller/__init__.py b/gns3server/controller/__init__.py index 69399a8a..1934b2ff 100644 --- a/gns3server/controller/__init__.py +++ b/gns3server/controller/__init__.py @@ -116,7 +116,7 @@ class Controller: builtins = [] builtins.append(Appliance(uuid.uuid3(uuid.NAMESPACE_DNS, "cloud"), {"node_type": "cloud", "name": "Cloud", "category": 2, "symbol": ":/symbols/cloud.svg"}, builtin=True)) builtins.append(Appliance(uuid.uuid3(uuid.NAMESPACE_DNS, "nat"), {"node_type": "nat", "name": "NAT", "category": 2, "symbol": ":/symbols/cloud.svg"}, builtin=True)) - builtins.append(Appliance(uuid.uuid3(uuid.NAMESPACE_DNS, "vpcs"), {"node_type": "vpcs", "name": "VPCS", "category": 2, "symbol": ":/symbols/vpcs_guest.svg"}, builtin=True)) + builtins.append(Appliance(uuid.uuid3(uuid.NAMESPACE_DNS, "vpcs"), {"node_type": "vpcs", "name": "VPCS", "category": 2, "symbol": ":/symbols/vpcs_guest.svg", "properties": {"base_script_file": "vpcs_base_config.txt"}}, builtin=True)) builtins.append(Appliance(uuid.uuid3(uuid.NAMESPACE_DNS, "ethernet_switch"), {"node_type": "ethernet_switch", "name": "Ethernet switch", "category": 1, "symbol": ":/symbols/ethernet_switch.svg"}, builtin=True)) builtins.append(Appliance(uuid.uuid3(uuid.NAMESPACE_DNS, "ethernet_hub"), {"node_type": "ethernet_hub", "name": "Ethernet hub", "category": 1, "symbol": ":/symbols/hub.svg"}, builtin=True)) builtins.append(Appliance(uuid.uuid3(uuid.NAMESPACE_DNS, "frame_relay_switch"), {"node_type": "frame_relay_switch", "name": "Frame Relay switch", "category": 1, "symbol": ":/symbols/frame_relay_switch.svg"}, builtin=True)) diff --git a/gns3server/controller/appliance.py b/gns3server/controller/appliance.py index 9cfb00f0..356ae10e 100644 --- a/gns3server/controller/appliance.py +++ b/gns3server/controller/appliance.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import copy import uuid @@ -54,7 +55,7 @@ class Appliance: @property def data(self): - return self._data + return copy.deepcopy(self._data) @property def name(self): diff --git a/gns3server/controller/appliance_template.py b/gns3server/controller/appliance_template.py index 8b9a3909..de7e98c6 100644 --- a/gns3server/controller/appliance_template.py +++ b/gns3server/controller/appliance_template.py @@ -15,6 +15,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import copy import uuid @@ -43,4 +44,4 @@ class ApplianceTemplate: """ Appliance data (a hash) """ - return self._data + return copy.deepcopy(self._data) diff --git a/gns3server/controller/project.py b/gns3server/controller/project.py index d1d8935f..d2b9d7bc 100644 --- a/gns3server/controller/project.py +++ b/gns3server/controller/project.py @@ -325,11 +325,12 @@ class Project: Create a node from an appliance """ try: - template = copy.copy(self.controller.appliances[appliance_id].data) + template = self.controller.appliances[appliance_id].data except KeyError: msg = "Appliance {} doesn't exist".format(appliance_id) log.error(msg) raise aiohttp.web.HTTPNotFound(text=msg) + print(template) template["x"] = x template["y"] = y node_type = template.pop("node_type") diff --git a/tests/controller/test_controller.py b/tests/controller/test_controller.py index 9eed972b..fcae102f 100644 --- a/tests/controller/test_controller.py +++ b/tests/controller/test_controller.py @@ -483,6 +483,7 @@ def test_load_base_files(controller, config, tmpdir): def test_appliance_templates(controller, async_run): controller.load_appliances() assert len(controller.appliance_templates) > 0 + assert "Alpine Linux" in [c.__json__()["name"] for c in controller.appliance_templates.values()] def test_load_appliances(controller): @@ -498,6 +499,11 @@ def test_load_appliances(controller): controller.load_appliances() assert "Test" in [appliance.name for appliance in controller.appliances.values()] assert "Cloud" in [appliance.name for appliance in controller.appliances.values()] + assert "VPCS" in [appliance.name for appliance in controller.appliances.values()] + + for appliance in controller.appliances.values(): + if appliance.name == "VPCS": + assert appliance._data["properties"] == {"base_script_file": "vpcs_base_config.txt"} # UUID should not change when you run again the function for appliance in controller.appliances.values(): diff --git a/tests/controller/test_project.py b/tests/controller/test_project.py index c09a9e55..cbafaa51 100644 --- a/tests/controller/test_project.py +++ b/tests/controller/test_project.py @@ -193,7 +193,10 @@ def test_add_node_from_appliance(async_run, controller): "server": "local", "name": "Test", "default_name_format": "{name}-{0}", - "node_type": "vpcs" + "node_type": "vpcs", + "properties": { + "a": 1 + } }) controller._computes["local"] = compute @@ -211,11 +214,22 @@ def test_add_node_from_appliance(async_run, controller): }) compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id), data={'node_id': node.id, - 'name': 'Test-1'}, + 'name': 'Test-1', + 'a': 1, + }, timeout=120) assert compute in project._project_created_on_compute controller.notification.emit.assert_any_call("node.created", node.__json__()) + # Make sure we can call twice the node creation + node = async_run(project.add_node_from_appliance("fakeid", x=13, y=12)) + compute.post.assert_any_call('/projects/{}/vpcs/nodes'.format(project.id), + data={'node_id': node.id, + 'name': 'Test-2', + 'a': 1 + }, + timeout=120) + def test_delete_node(async_run, controller): """