diff --git a/gns3server/controller/project.py b/gns3server/controller/project.py
index 34ec7bba..961eaf97 100644
--- a/gns3server/controller/project.py
+++ b/gns3server/controller/project.py
@@ -44,11 +44,12 @@ class Project:
:param status: Status of the project (opened / closed)
"""
- def __init__(self, name=None, project_id=None, path=None, controller=None, status="opened", filename=None):
+ def __init__(self, name=None, project_id=None, path=None, controller=None, status="opened", filename=None, auto_start=False):
self._controller = controller
assert name is not None
self._name = name
+ self._auto_start = False
self._status = status
if project_id is None:
self._id = str(uuid4())
@@ -81,6 +82,10 @@ class Project:
# Create the project on demand on the compute node
self._project_created_on_compute = set()
+ @property
+ def auto_start(self):
+ return self._auto_start
+
@property
def controller(self):
return self._controller
diff --git a/gns3server/controller/topology.py b/gns3server/controller/topology.py
index 0bde0721..2deb1aa4 100644
--- a/gns3server/controller/topology.py
+++ b/gns3server/controller/topology.py
@@ -17,6 +17,8 @@
import json
import jsonschema
+import uuid
+import shutil
import aiohttp
from ..version import __version__
@@ -47,6 +49,7 @@ def project_to_topology(project):
data = {
"project_id": project.id,
"name": project.name,
+ "auto_start": project.auto_start,
"topology": {
"nodes": [],
"links": [],
@@ -77,12 +80,294 @@ def load_topology(path):
"""
Open a topology file, patch it for last GNS3 release and return it
"""
+ log.debug("Read topology %s", path)
try:
with open(path) as f:
topo = json.load(f)
except OSError as e:
raise aiohttp.web.HTTPConflict(text="Could not load topology {}: {}".format(path, str(e)))
- if topo["revision"] < GNS3_FILE_FORMAT_REVISION:
- raise aiohttp.web.HTTPConflict(text="Old GNS3 project are not yet supported")
+ if "revision" not in topo or topo["revision"] < GNS3_FILE_FORMAT_REVISION:
+ # If it's an old GNS3 file we need to convert it
+ # first we backup the file
+ shutil.copy(path, path + ".backup")
+ topo = _convert_1_3_later(topo)
+ with open(path, "w+") as f:
+ json.dump(topo, f)
+ elif topo["revision"] > GNS3_FILE_FORMAT_REVISION:
+ raise aiohttp.web.HTTPConflict(text="This project is designed for a more recent version of GNS3 please update GNS3 to version {} or later".format(topo["version"]))
_check_topology_schema(topo)
return topo
+
+
+def _convert_1_3_later(topo):
+ """
+ Convert topologies to the new file format
+
+ Look in tests/topologies/README.rst for instructions to test changes here
+ """
+ new_topo = {
+ "type": "topology",
+ "revision": GNS3_FILE_FORMAT_REVISION,
+ "version": __version__,
+ "auto_start": topo.get("auto_start", False),
+ "name": topo["name"],
+ "project_id": topo["project_id"],
+ "topology": {
+ "links": [],
+ "drawings": [],
+ "computes": [],
+ "nodes": []
+ }
+ }
+ if new_topo["project_id"] is None:
+ new_topo["project_id"] = str(uuid.uuid4()) # Could arrive for topologues with drawing only
+ if "topology" not in topo:
+ return new_topo
+ topo = topo["topology"]
+
+ # Create computes
+ server_id_to_compute_id = {}
+ for server in topo.get("servers", []):
+ compute = {
+ "host": server.get("host", "localhost"),
+ "port": server.get("port", 3080),
+ "protocol": server.get("protocol", "http")
+ }
+ if server["local"]:
+ compute["compute_id"] = "local"
+ compute["name"] = "Local"
+ elif server.get("vm", False):
+ compute["compute_id"] = "vm"
+ compute["name"] = "GNS3 VM"
+ else:
+ compute["name"] = "Remote {}".format(server["id"])
+ compute["compute_id"] = str(uuid.uuid4())
+ server_id_to_compute_id[server["id"]] = compute["compute_id"]
+ new_topo["topology"]["computes"].append(compute)
+
+ # Create nodes
+ ports = {}
+ node_id_to_node_uuid = {}
+ for old_node in topo.get("nodes", []):
+ node = {}
+ node["console"] = old_node["properties"].get("console", None)
+ node["compute_id"] = server_id_to_compute_id[old_node["server_id"]]
+ node["console_type"] = old_node["properties"].get("console_type", "telnet")
+ node["name"] = old_node["label"]["text"]
+ node["label"] = _convert_label(old_node["label"])
+ node["node_id"] = old_node.get("vm_id", str(uuid.uuid4()))
+ node["symbol"] = old_node.get("symbol", None)
+ node["x"] = int(old_node["x"])
+ node["y"] = int(old_node["y"])
+ node["z"] = int(old_node.get("z", 1))
+
+ node["properties"] = {}
+
+ if old_node["type"] == "VPCSDevice":
+ node["node_type"] = "vpcs"
+ elif old_node["type"] == "QemuVM":
+ node["node_type"] = "qemu"
+ if node["symbol"] is None:
+ node["symbol"] = ":/symbols/qemu_guest.svg"
+ elif old_node["type"] == "DockerVM":
+ node["node_type"] = "docker"
+ if node["symbol"] is None:
+ node["symbol"] = ":/symbols/docker_guest.svg"
+ elif old_node["type"] == "ATMSwitch":
+ node["node_type"] = "atm_switch"
+ node["symbol"] = ":/symbols/atm_switch.svg"
+ node["console_type"] = None
+ elif old_node["type"] == "EthernetHub":
+ node["node_type"] = "ethernet_hub"
+ node["symbol"] = ":/symbols/hub.svg"
+ node["console_type"] = None
+ node["properties"]["ports"] = []
+ for port in old_node["ports"]:
+ node["properties"]["ports"].append({
+ "name": "Ethernet{}".format(port["port_number"]),
+ "port_number": port["port_number"]
+ })
+ elif old_node["type"] == "EthernetSwitch":
+ node["node_type"] = "ethernet_switch"
+ node["symbol"] = ":/symbols/ethernet_switch.svg"
+ node["properties"]["ports"] = []
+ node["console_type"] = None
+ for port in old_node["ports"]:
+ node["properties"]["ports"].append({
+ "name": "Ethernet{}".format(port["port_number"]),
+ "port_number": port["port_number"],
+ "type": port["type"],
+ "vlan": port["vlan"]
+ })
+ elif old_node["type"] == "FrameRelaySwitch":
+ node["node_type"] = "frame_relay_switch"
+ node["symbol"] = ":/symbols/frame_relay_switch.svg"
+ node["console_type"] = None
+ elif old_node["type"] in ["C1700", "C2600", "C2691", "C3600", "C3725", "C3745", "C7200", "EtherSwitchRouter"]:
+ if node["symbol"] is None:
+ node["symbol"] = ":/symbols/router.svg"
+ node["node_type"] = "dynamips"
+ node["properties"]["dynamips_id"] = old_node["dynamips_id"]
+ elif old_node["type"] == "VMwareVM":
+ node["node_type"] = "vmware"
+ if node["symbol"] is None:
+ node["symbol"] = ":/symbols/vmware_guest.svg"
+ elif old_node["type"] == "VirtualBoxVM":
+ node["node_type"] = "virtualbox"
+ if node["symbol"] is None:
+ node["symbol"] = ":/symbols/vbox_guest.svg"
+ else:
+ raise NotImplementedError("Conversion of {} is not supported".format(old_node["type"]))
+
+ for prop in old_node["properties"]:
+ if prop not in ["console", "name", "console_type", "use_ubridge"]:
+ node["properties"][prop] = old_node["properties"][prop]
+
+ node_id_to_node_uuid[old_node["id"]] = node["node_id"]
+ for port in old_node.get("ports", []):
+ ports[port["id"]] = port
+ new_topo["topology"]["nodes"].append(node)
+
+ # Create links
+ for old_link in topo.get("links", []):
+ nodes = []
+ source_node = {
+ "adapter_number": ports[old_link["source_port_id"]].get("adapter_number", 0),
+ "port_number": ports[old_link["source_port_id"]]["port_number"],
+ "node_id": node_id_to_node_uuid[old_link["source_node_id"]]
+ }
+ nodes.append(source_node)
+
+ destination_node = {
+ "adapter_number": ports[old_link["destination_port_id"]].get("adapter_number", 0),
+ "port_number": ports[old_link["destination_port_id"]]["port_number"],
+ "node_id": node_id_to_node_uuid[old_link["destination_node_id"]]
+ }
+ nodes.append(destination_node)
+
+ link = {
+ "link_id": str(uuid.uuid4()),
+ "nodes": nodes
+ }
+ new_topo["topology"]["links"].append(link)
+
+ # Ellipse
+ for ellipse in topo.get("ellipses", []):
+ svg = ''.format(
+ height=int(ellipse["height"]),
+ width=int(ellipse["width"]),
+ cx=int(ellipse["width"] / 2),
+ cy=int(ellipse["height"] / 2),
+ rx=int(ellipse["width"] / 2),
+ ry=int(ellipse["height"] / 2),
+ fill=ellipse.get("color", "#ffffff"),
+ border_style=_convert_border_style(ellipse)
+ )
+ new_ellipse = {
+ "drawing_id": str(uuid.uuid4()),
+ "x": int(ellipse["x"]),
+ "y": int(ellipse["y"]),
+ "z": int(ellipse.get("z", 0)),
+ "rotation": int(ellipse.get("rotation", 0)),
+ "svg": svg
+ }
+ new_topo["topology"]["drawings"].append(new_ellipse)
+
+ # Notes
+ for note in topo.get("notes", []):
+ font_info = note["font"].split(",")
+
+ if font_info[4] == "75":
+ weight = "bold"
+ else:
+ weight = "normal"
+ if font_info[5] == "1":
+ style = "italic"
+ else:
+ style = "normal"
+
+ svg = ''.format(
+ height=int(font_info[1]) * 2,
+ width=int(font_info[1]) * len(note["text"]),
+ fill="#" + note["color"][-6:],
+ opacity=round(1.0 / 255 * int(note["color"][:3][-2:], base=16), 2), # Extract the alpha channel from the hexa version
+ family=font_info[0],
+ size=int(font_info[1]),
+ weight=weight,
+ style=style,
+ text=note["text"]
+ )
+ new_note = {
+ "drawing_id": str(uuid.uuid4()),
+ "x": int(note["x"]),
+ "y": int(note["y"]),
+ "z": int(note.get("z", 0)),
+ "rotation": int(ellipse.get("rotation", 0)),
+ "svg": svg
+ }
+ new_topo["topology"]["drawings"].append(new_note)
+
+ # Rectangles
+ for rectangle in topo.get("rectangles", []):
+ svg = ''.format(
+ height=int(rectangle["height"]),
+ width=int(rectangle["width"]),
+ fill=rectangle.get("color", "#ffffff"),
+ border_style=_convert_border_style(rectangle)
+ )
+ new_rectangle = {
+ "drawing_id": str(uuid.uuid4()),
+ "x": int(rectangle["x"]),
+ "y": int(rectangle["y"]),
+ "z": int(rectangle.get("z", 0)),
+ "rotation": int(ellipse.get("rotation", 0)),
+ "svg": svg
+ }
+ new_topo["topology"]["drawings"].append(new_rectangle)
+
+ return new_topo
+
+
+def _convert_border_style(element):
+ QT_DASH_TO_SVG = {
+ 2: "25, 25",
+ 3: "5, 25",
+ 4: "5, 25, 25",
+ 5: "25, 25, 5, 25, 5"
+ }
+ border_style = int(element.get("border_style", 0))
+ style = ""
+ if border_style == 1: # No border
+ return ""
+ elif border_style == 0:
+ pass # Solid line
+ else:
+ style += 'stroke-dasharray="{}" '.format(QT_DASH_TO_SVG[border_style])
+ style += 'stroke="{stroke}" stroke-width="{stroke_width}"'.format(
+ stroke=element.get("border_color", "#000000"),
+ stroke_width=element.get("border_width", 2)
+ )
+ return style
+
+
+def _convert_label(label):
+ """
+ Convert a label from 1.X to the new format
+ """
+ font_info = label["font"].split(",")
+ style = "font-family: {};font-size: {};".format(font_info[0], font_info[1])
+ if font_info[4] == "75":
+ style += "font-weight: bold;"
+ if font_info[5] == "1":
+ style += "font-style: italic;"
+ color = label["color"]
+
+ style += "fill: #" + color[-6:] + ";"
+ style += "fill-opacity: {};".format(round(1.0 / 255 * int(color[:3][-2:], base=16), 2))
+ return {
+ "text": label["text"],
+ "rotation": 0,
+ "style": style,
+ "x": int(label["x"]),
+ "y": int(label["y"])
+ }
diff --git a/gns3server/schemas/topology.py b/gns3server/schemas/topology.py
index 5a6dda8a..37025f43 100644
--- a/gns3server/schemas/topology.py
+++ b/gns3server/schemas/topology.py
@@ -41,6 +41,10 @@ TOPOLOGY_SCHEMA = {
"description": "Type of file. It's always topology",
"enum": ["topology"]
},
+ "auto_start": {
+ "description": "Start the topology when opened",
+ "type": "boolean"
+ },
"revision": {
"description": "Version of the .gns3 specification.",
"type": "integer"
diff --git a/tests/controller/test_topology.py b/tests/controller/test_topology.py
index 899c759a..db1f5af3 100644
--- a/tests/controller/test_topology.py
+++ b/tests/controller/test_topology.py
@@ -34,6 +34,7 @@ def test_project_to_topology_empty(tmpdir):
assert topo == {
"project_id": project.id,
"name": "Test",
+ "auto_start": False,
"revision": 5,
"topology": {
"nodes": [],
@@ -106,11 +107,15 @@ def test_load_topology_file_error_schema_error(tmpdir):
topo = load_topology(path)
-def test_load_old_topology(tmpdir):
+def test_load_newer_topology(tmpdir):
+ """
+ If a topology is design for a more recent GNS3 version
+ we disallow the loading.
+ """
data = {
"project_id": "69f26504-7aa3-48aa-9f29-798d44841211",
"name": "Test",
- "revision": 4,
+ "revision": 42,
"topology": {
},
"type": "topology",
diff --git a/tests/test_topologies.py b/tests/test_topologies.py
new file mode 100644
index 00000000..f3450e4b
--- /dev/null
+++ b/tests/test_topologies.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 GNS3 Technologies Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+
+#
+# This will test the conversion from old topology format to the new
+#
+# Read tests/topologies/README.rst for documentation
+
+import os
+import json
+import pytest
+import shutil
+
+
+from gns3server.controller.topology import load_topology, GNS3_FILE_FORMAT_REVISION
+
+topologies_directory = os.path.join(os.path.dirname(os.path.realpath(__file__)), "topologies")
+
+
+def topologies():
+ dirs = []
+ for directory in os.listdir(topologies_directory):
+ if os.path.isdir(os.path.join(topologies_directory, directory)):
+ dirs.append(directory)
+ return dirs
+
+
+@pytest.mark.parametrize("directory", topologies())
+def test_convert(directory, tmpdir):
+ before_directory = os.path.join(topologies_directory, directory, "before")
+ after_directory = os.path.join(topologies_directory, directory, "after")
+
+ assert os.path.exists(before_directory), "No before directory found file for {}".format(directory)
+ assert os.path.exists(after_directory), "No after directory found file for {}".format(directory)
+
+ gns3_file = None
+ for file in os.listdir(before_directory):
+ if file.endswith(".gns3"):
+ gns3_file = file
+
+ assert gns3_file, "No .gns3 found file for {}".format(before_directory)
+
+ with open(os.path.join(before_directory, gns3_file)) as f:
+ before_topology = json.load(f)
+ with open(os.path.join(after_directory, gns3_file)) as f:
+ after_topology = json.load(f)
+
+ # We use a temporary directory for conversion operation to not corrupt our files
+ work_directory = str(tmpdir / "work")
+ shutil.copytree(before_directory, work_directory)
+
+ work_topology = load_topology(os.path.join(work_directory, gns3_file))
+ assert work_topology
+
+ if "revision" not in before_topology or before_topology["revision"] < GNS3_FILE_FORMAT_REVISION:
+ assert os.path.exists(os.path.join(work_directory, gns3_file + ".backup"))
+
+ # We should have the same file in after directory and the work directory
+ for root, dirs, files in os.walk(after_directory):
+ for file in files:
+ directory = os.path.relpath(root, after_directory)
+ file_path = os.path.join(work_directory, directory, file)
+ assert os.path.exists(file_path), "{} is missing".format(os.path.join(directory, file))
+
+ # For non .gns3 file we check if the file are the same
+ if not file_path.endswith(".gns3"):
+ assert os.stat(file_path).st_size == os.stat(os.path.join(os.path.join(root, file))).st_size, "File {} is different".format(os.path.join(directory, file))
+
+ compare_dict("/", work_topology, after_topology)
+
+
+def compare_dict(path, source, reference):
+ """
+ Compare two dictionnary of a topology
+ """
+ assert isinstance(source, dict), "Source is not a dict in {}".format(path)
+ for key in source:
+ assert key in reference, "Unexcepted {} in {} it should be {}".format(key, source, reference)
+ for key in sorted(reference.keys()):
+ val = reference[key]
+ assert key in source, "{} is missing in {}".format(key, source)
+ if isinstance(val, str) or isinstance(val, float) or isinstance(val, int) or isinstance(val, bool) or val is None:
+ if val == "ANYSTR":
+ pass
+ elif val == "ANYUUID" and len(source[key]) == 36:
+ pass
+ else:
+ assert val == source[key], "Wrong value for {}: \n{}\nit should be\n{}".format(key, source[key], val)
+ elif isinstance(val, dict):
+ compare_dict(path + key + "/", source[key], val)
+ elif isinstance(val, list):
+ assert len(val) == len(source[key]), "Not enough value in {} ({}/{}) it shoud be {} not {}".format(key, len(val), len(source[key]), val, source[key])
+ for idx, element in enumerate(source[key]):
+ compare_dict(path + key + "/", element, val[idx])
+ else:
+ assert False, "Value type for {} is not supported".format(key)
diff --git a/tests/topologies/1_5_builtins/after/builtins.gns3 b/tests/topologies/1_5_builtins/after/builtins.gns3
new file mode 100644
index 00000000..79a767f6
--- /dev/null
+++ b/tests/topologies/1_5_builtins/after/builtins.gns3
@@ -0,0 +1,197 @@
+{
+ "name": "builtins",
+ "project_id": "644e3892-4a50-4457-9601-2234d4842169",
+ "revision": 5,
+ "auto_start": false,
+ "topology": {
+ "computes": [
+ {
+ "compute_id": "local",
+ "host": "127.0.0.1",
+ "name": "Local",
+ "port": 3080,
+ "protocol": "http"
+ }
+ ],
+ "drawings": [],
+ "links": [],
+ "nodes": [
+ {
+ "compute_id": "local",
+ "console": null,
+ "console_type": null,
+ "label": {
+ "rotation": 0,
+ "style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
+ "text": "ATM1",
+ "x": 6,
+ "y": -25
+ },
+ "name": "ATM1",
+ "node_id": "ANYUUID",
+ "node_type": "atm_switch",
+ "properties": {
+ "mappings": {
+ "1:0:100": "10:0:200"
+ }
+ },
+ "symbol": ":/symbols/atm_switch.svg",
+ "x": -398,
+ "y": -219,
+ "z": 1
+ },
+ {
+ "compute_id": "local",
+ "console": null,
+ "console_type": null,
+ "label": {
+ "rotation": 0,
+ "style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
+ "text": "HUB1",
+ "x": 17,
+ "y": -25
+ },
+ "name": "HUB1",
+ "node_id": "ANYUUID",
+ "node_type": "ethernet_hub",
+ "properties": {
+ "ports": [
+ {
+ "name": "Ethernet1",
+ "port_number": 1
+ },
+ {
+ "name": "Ethernet2",
+ "port_number": 2
+ },
+ {
+ "name": "Ethernet3",
+ "port_number": 3
+ },
+ {
+ "name": "Ethernet4",
+ "port_number": 4
+ },
+ {
+ "name": "Ethernet5",
+ "port_number": 5
+ },
+ {
+ "name": "Ethernet6",
+ "port_number": 6
+ },
+ {
+ "name": "Ethernet7",
+ "port_number": 7
+ },
+ {
+ "name": "Ethernet8",
+ "port_number": 8
+ }
+ ]
+ },
+ "symbol": ":/symbols/hub.svg",
+ "x": -176,
+ "y": -209,
+ "z": 1
+ },
+ {
+ "compute_id": "local",
+ "console": null,
+ "console_type": null,
+ "label": {
+ "rotation": 0,
+ "style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
+ "text": "SW1",
+ "x": 20,
+ "y": -25
+ },
+ "name": "SW1",
+ "node_id": "ANYUUID",
+ "node_type": "ethernet_switch",
+ "properties": {
+ "ports": [
+ {
+ "name": "Ethernet1",
+ "port_number": 1,
+ "type": "access",
+ "vlan": 1
+ },
+ {
+ "name": "Ethernet2",
+ "port_number": 2,
+ "type": "access",
+ "vlan": 1
+ },
+ {
+ "name": "Ethernet3",
+ "port_number": 3,
+ "type": "access",
+ "vlan": 1
+ },
+ {
+ "name": "Ethernet4",
+ "port_number": 4,
+ "type": "access",
+ "vlan": 1
+ },
+ {
+ "name": "Ethernet5",
+ "port_number": 5,
+ "type": "access",
+ "vlan": 1
+ },
+ {
+ "name": "Ethernet6",
+ "port_number": 6,
+ "type": "access",
+ "vlan": 1
+ },
+ {
+ "name": "Ethernet7",
+ "port_number": 7,
+ "type": "access",
+ "vlan": 1
+ },
+ {
+ "name": "Ethernet8",
+ "port_number": 8,
+ "type": "access",
+ "vlan": 1
+ }
+ ]
+ },
+ "symbol": ":/symbols/ethernet_switch.svg",
+ "x": 5,
+ "y": -206,
+ "z": 1
+ },
+ {
+ "compute_id": "local",
+ "console": null,
+ "console_type": null,
+ "label": {
+ "rotation": 0,
+ "style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
+ "text": "FR1",
+ "x": 11,
+ "y": -25
+ },
+ "name": "FR1",
+ "node_id": "ANYUUID",
+ "node_type": "frame_relay_switch",
+ "properties": {
+ "mappings": {
+ "1:101": "10:202"
+ }
+ },
+ "symbol": ":/symbols/frame_relay_switch.svg",
+ "x": 294,
+ "y": -209,
+ "z": 1
+ }
+ ]
+ },
+ "type": "topology",
+ "version": "2.0.0dev1"
+}
diff --git a/tests/topologies/1_5_builtins/before/builtins.gns3 b/tests/topologies/1_5_builtins/before/builtins.gns3
new file mode 100644
index 00000000..24eac2a2
--- /dev/null
+++ b/tests/topologies/1_5_builtins/before/builtins.gns3
@@ -0,0 +1,204 @@
+{
+ "auto_start": false,
+ "name": "builtins",
+ "project_id": "644e3892-4a50-4457-9601-2234d4842169",
+ "revision": 4,
+ "topology": {
+ "nodes": [
+ {
+ "description": "ATM switch",
+ "device_id": "4fed7243-cd30-4e37-bdd4-d21ed9e65c03",
+ "id": 1,
+ "label": {
+ "color": "#ff000000",
+ "font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
+ "text": "ATM1",
+ "x": 6.546875,
+ "y": -25.0
+ },
+ "properties": {
+ "name": "ATM1",
+ "mappings": {
+ "1:0:100": "10:0:200"
+ }
+ },
+ "server_id": 3,
+ "type": "ATMSwitch",
+ "x": -398.5,
+ "y": -219.5
+ },
+ {
+ "description": "Ethernet hub",
+ "device_id": "40199896-fabd-42d8-9bca-4651a73159dd",
+ "id": 2,
+ "label": {
+ "color": "#ff000000",
+ "font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
+ "text": "HUB1",
+ "x": 17.9765625,
+ "y": -25.0
+ },
+ "ports": [
+ {
+ "id": 1,
+ "name": "1",
+ "port_number": 1
+ },
+ {
+ "id": 2,
+ "name": "2",
+ "port_number": 2
+ },
+ {
+ "id": 3,
+ "name": "3",
+ "port_number": 3
+ },
+ {
+ "id": 4,
+ "name": "4",
+ "port_number": 4
+ },
+ {
+ "id": 5,
+ "name": "5",
+ "port_number": 5
+ },
+ {
+ "id": 6,
+ "name": "6",
+ "port_number": 6
+ },
+ {
+ "id": 7,
+ "name": "7",
+ "port_number": 7
+ },
+ {
+ "id": 8,
+ "name": "8",
+ "port_number": 8
+ }
+ ],
+ "properties": {
+ "name": "HUB1"
+ },
+ "server_id": 3,
+ "type": "EthernetHub",
+ "x": -176.0,
+ "y": -209.0
+ },
+ {
+ "description": "Ethernet switch",
+ "device_id": "96d18119-cc78-4129-9543-932f8b202d52",
+ "id": 3,
+ "label": {
+ "color": "#ff000000",
+ "font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
+ "text": "SW1",
+ "x": 20.8359375,
+ "y": -25.0
+ },
+ "ports": [
+ {
+ "id": 9,
+ "name": "1",
+ "port_number": 1,
+ "type": "access",
+ "vlan": 1
+ },
+ {
+ "id": 10,
+ "name": "2",
+ "port_number": 2,
+ "type": "access",
+ "vlan": 1
+ },
+ {
+ "id": 11,
+ "name": "3",
+ "port_number": 3,
+ "type": "access",
+ "vlan": 1
+ },
+ {
+ "id": 12,
+ "name": "4",
+ "port_number": 4,
+ "type": "access",
+ "vlan": 1
+ },
+ {
+ "id": 13,
+ "name": "5",
+ "port_number": 5,
+ "type": "access",
+ "vlan": 1
+ },
+ {
+ "id": 14,
+ "name": "6",
+ "port_number": 6,
+ "type": "access",
+ "vlan": 1
+ },
+ {
+ "id": 15,
+ "name": "7",
+ "port_number": 7,
+ "type": "access",
+ "vlan": 1
+ },
+ {
+ "id": 16,
+ "name": "8",
+ "port_number": 8,
+ "type": "access",
+ "vlan": 1
+ }
+ ],
+ "properties": {
+ "name": "SW1"
+ },
+ "server_id": 3,
+ "type": "EthernetSwitch",
+ "x": 5.5,
+ "y": -206.0
+ },
+ {
+ "description": "Frame Relay switch",
+ "device_id": "3bb18be3-0692-47be-a98e-213fa5f1ba73",
+ "id": 5,
+ "label": {
+ "color": "#ff000000",
+ "font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
+ "text": "FR1",
+ "x": 11.890625,
+ "y": -25.0
+ },
+ "properties": {
+ "name": "FR1",
+ "mappings": {
+ "1:101": "10:202"
+ }
+ },
+ "server_id": 3,
+ "type": "FrameRelaySwitch",
+ "x": 294.5,
+ "y": -209.5
+ }
+ ],
+ "servers": [
+ {
+ "host": "127.0.0.1",
+ "id": 3,
+ "local": true,
+ "port": 3080,
+ "protocol": "http",
+ "vm": false
+ }
+ ]
+ },
+ "type": "topology",
+ "version": "1.5.1dev1"
+}
diff --git a/tests/topologies/1_5_docker_remote/after/1_5_docker_remote.gns3 b/tests/topologies/1_5_docker_remote/after/1_5_docker_remote.gns3
new file mode 100644
index 00000000..ddb7b6e1
--- /dev/null
+++ b/tests/topologies/1_5_docker_remote/after/1_5_docker_remote.gns3
@@ -0,0 +1,50 @@
+{
+ "name": "1_5_docker_remote",
+ "project_id": "8182b710-c6bf-4e51-8e2e-213cce952797",
+ "revision": 5,
+ "auto_start": false,
+ "topology": {
+ "computes": [
+ {
+ "compute_id": "ANYUUID",
+ "host": "127.0.0.1",
+ "name": "Remote 2",
+ "port": 8001,
+ "protocol": "http"
+ }
+ ],
+ "drawings": [],
+ "links": [],
+ "nodes": [
+ {
+ "compute_id": "ANYUUID",
+ "console": 6001,
+ "console_type": "telnet",
+ "label": {
+ "rotation": 0,
+ "style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
+ "text": "remote_busybox-1",
+ "x": -20,
+ "y": -25
+ },
+ "name": "remote_busybox-1",
+ "node_id": "d397ef5a-84f1-4b6b-9d44-671937ec7781",
+ "node_type": "docker",
+ "properties": {
+ "adapters": 1,
+ "aux": 6002,
+ "console_http_path": "/",
+ "console_http_port": 80,
+ "console_resolution": "1024x768",
+ "image": "busybox:latest"
+ },
+ "symbol": ":/symbols/docker_guest.svg",
+ "x": -53,
+ "y": -69,
+ "z": 1
+ }
+ ]
+ },
+ "type": "topology",
+ "version": "2.0.0dev1"
+}
diff --git a/tests/topologies/1_5_docker_remote/before/1_5_docker_remote.gns3 b/tests/topologies/1_5_docker_remote/before/1_5_docker_remote.gns3
index 365c04c0..57e835b8 100644
--- a/tests/topologies/1_5_docker_remote/before/1_5_docker_remote.gns3
+++ b/tests/topologies/1_5_docker_remote/before/1_5_docker_remote.gns3
@@ -1,7 +1,7 @@
{
"auto_start": false,
- "name": "untitled",
- "project_id": "926e5c9e-887c-41b2-9214-fbd5fb628fe8",
+ "name": "1_5_docker_remote",
+ "project_id": "8182b710-c6bf-4e51-8e2e-213cce952797",
"revision": 4,
"topology": {
"nodes": [
@@ -55,4 +55,4 @@
},
"type": "topology",
"version": "1.5.1dev1"
-}
\ No newline at end of file
+}
diff --git a/tests/topologies/1_5_drawing/after/1_5_drawing.gns3 b/tests/topologies/1_5_drawing/after/1_5_drawing.gns3
new file mode 100644
index 00000000..f13c8b9c
--- /dev/null
+++ b/tests/topologies/1_5_drawing/after/1_5_drawing.gns3
@@ -0,0 +1,40 @@
+{
+ "auto_start": false,
+ "name": "1_5_drawing",
+ "project_id": "ANYUUID",
+ "revision": 5,
+ "topology": {
+ "computes": [
+ ],
+ "drawings": [
+ {
+ "drawing_id": "ANYUUID",
+ "rotation": 0,
+ "svg": "",
+ "x": 179,
+ "y": -44,
+ "z": 0
+ },
+ {
+ "drawing_id": "ANYUUID",
+ "rotation": 0,
+ "svg": "",
+ "x": -151,
+ "y": 93,
+ "z": 0
+ },
+ {
+ "drawing_id": "ANYUUID",
+ "rotation": 0,
+ "svg": "",
+ "x": -210,
+ "y": -108,
+ "z": 0
+ }
+ ],
+ "links": [],
+ "nodes": []
+ },
+ "type": "topology",
+ "version": "2.0.0dev1"
+}
diff --git a/tests/topologies/1_5_drawing/before/1_5_drawing.gns3 b/tests/topologies/1_5_drawing/before/1_5_drawing.gns3
new file mode 100644
index 00000000..c2a6be89
--- /dev/null
+++ b/tests/topologies/1_5_drawing/before/1_5_drawing.gns3
@@ -0,0 +1,38 @@
+{
+ "auto_start": false,
+ "name": "1_5_drawing",
+ "project_id": null,
+ "revision": 4,
+ "topology": {
+ "ellipses": [
+ {
+ "border_style": 2,
+ "height": 200.0,
+ "width": 200.0,
+ "x": 179.0,
+ "y": -44.0
+ }
+ ],
+ "notes": [
+ {
+ "color": "#ff000000",
+ "font": "TypeWriter,10,-1,5,75,1,0,0,0,0",
+ "text": "Test",
+ "x": -151.0,
+ "y": 93.0
+ }
+ ],
+ "rectangles": [
+ {
+ "border_color": "#c80000",
+ "color": "#18ffff",
+ "height": 100.0,
+ "width": 200.0,
+ "x": -210.0,
+ "y": -108.0
+ }
+ ]
+ },
+ "type": "topology",
+ "version": "1.5.1dev1"
+}
diff --git a/tests/topologies/1_5_dynamips/after/1_5_dynamips.gns3 b/tests/topologies/1_5_dynamips/after/1_5_dynamips.gns3
new file mode 100644
index 00000000..24624f99
--- /dev/null
+++ b/tests/topologies/1_5_dynamips/after/1_5_dynamips.gns3
@@ -0,0 +1,109 @@
+{
+ "auto_start": false,
+ "name": "1_5_dynamips",
+ "project_id": "62f389c0-f26d-43b7-ab29-e4d306b29c07",
+ "revision": 5,
+ "topology": {
+ "computes": [
+ {
+ "compute_id": "local",
+ "host": "127.0.0.1",
+ "name": "Local",
+ "port": 3080,
+ "protocol": "http"
+ }
+ ],
+ "drawings": [],
+ "links": [],
+ "nodes": [
+ {
+ "compute_id": "local",
+ "console": 5000,
+ "console_type": "telnet",
+ "label": {
+ "rotation": 0,
+ "style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
+ "text": "R1",
+ "x": 22,
+ "y": -25
+ },
+ "name": "R1",
+ "node_id": "11845dea-f175-495b-9fc5-bf20a2262016",
+ "node_type": "dynamips",
+ "properties": {
+ "auto_delete_disks": true,
+ "clock_divisor": 8,
+ "disk0": 0,
+ "disk1": 0,
+ "dynamips_id": 1,
+ "exec_area": 64,
+ "idlemax": 500,
+ "idlepc": "0x60aa1da0",
+ "idlesleep": 30,
+ "image": "c3745-adventerprisek9-mz.124-25d.image",
+ "image_md5sum": "ddbaf74274822b50fa9670e10c75b08f",
+ "iomem": 5,
+ "mac_addr": "c401.6b0f.0000",
+ "mmap": true,
+ "nvram": 256,
+ "platform": "c3745",
+ "ram": 256,
+ "slot0": "GT96100-FE",
+ "sparsemem": true,
+ "startup_config": "configs/i1_startup-config.cfg",
+ "system_id": "FTX0945W0MY"
+ },
+ "symbol": ":/symbols/router.svg",
+ "x": -112,
+ "y": -46,
+ "z": 1
+ },
+ {
+ "compute_id": "local",
+ "console": 5001,
+ "console_type": "telnet",
+ "label": {
+ "rotation": 0,
+ "style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
+ "text": "ESW1",
+ "x": 7,
+ "y": -25
+ },
+ "name": "ESW1",
+ "node_id": "4478a968-72a1-4722-9039-db7561c717c4",
+ "node_type": "dynamips",
+ "properties": {
+ "auto_delete_disks": false,
+ "chassis": "3660",
+ "clock_divisor": 4,
+ "disk0": 1,
+ "disk1": 0,
+ "dynamips_id": 2,
+ "exec_area": 64,
+ "idlemax": 500,
+ "idlepc": "0x6076e0b4",
+ "idlesleep": 30,
+ "image": "c3660-a3jk9s-mz.124-15.T14.image",
+ "image_md5sum": "daed99f508fd42dbaacf711e560643ed",
+ "iomem": 5,
+ "mac_addr": "cc02.6b5c.0000",
+ "mmap": true,
+ "nvram": 256,
+ "platform": "c3600",
+ "ram": 192,
+ "slot0": "Leopard-2FE",
+ "slot1": "NM-16ESW",
+ "sparsemem": true,
+ "startup_config": "configs/i2_startup-config.cfg",
+ "system_id": "FTX0945W0MY"
+ },
+ "symbol": ":/symbols/multilayer_switch.svg",
+ "x": 55,
+ "y": -76,
+ "z": 1
+ }
+ ]
+ },
+ "type": "topology",
+ "version": "2.0.0dev1"
+}
diff --git a/tests/topologies/1_5_dynamips/before/1_5_dynamips.gns3 b/tests/topologies/1_5_dynamips/before/1_5_dynamips.gns3
new file mode 100644
index 00000000..56b76f54
--- /dev/null
+++ b/tests/topologies/1_5_dynamips/before/1_5_dynamips.gns3
@@ -0,0 +1,231 @@
+{
+ "auto_start": false,
+ "name": "1_5_dynamips",
+ "project_id": "62f389c0-f26d-43b7-ab29-e4d306b29c07",
+ "revision": 4,
+ "topology": {
+ "nodes": [
+ {
+ "description": "Router c3745",
+ "dynamips_id": 1,
+ "id": 1,
+ "label": {
+ "color": "#ff000000",
+ "font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
+ "text": "R1",
+ "x": 22.2578125,
+ "y": -25.0
+ },
+ "ports": [
+ {
+ "adapter_number": 0,
+ "id": 1,
+ "name": "FastEthernet0/0",
+ "port_number": 0
+ },
+ {
+ "adapter_number": 0,
+ "id": 2,
+ "name": "FastEthernet0/1",
+ "port_number": 1
+ }
+ ],
+ "properties": {
+ "auto_delete_disks": true,
+ "clock_divisor": 8,
+ "console": 5000,
+ "disk0": 0,
+ "disk1": 0,
+ "exec_area": 64,
+ "idlemax": 500,
+ "idlepc": "0x60aa1da0",
+ "idlesleep": 30,
+ "image": "c3745-adventerprisek9-mz.124-25d.image",
+ "image_md5sum": "ddbaf74274822b50fa9670e10c75b08f",
+ "iomem": 5,
+ "mac_addr": "c401.6b0f.0000",
+ "mmap": true,
+ "name": "R1",
+ "nvram": 256,
+ "platform": "c3745",
+ "ram": 256,
+ "slot0": "GT96100-FE",
+ "sparsemem": true,
+ "startup_config": "configs/i1_startup-config.cfg",
+ "system_id": "FTX0945W0MY"
+ },
+ "server_id": 3,
+ "type": "C3745",
+ "vm_id": "11845dea-f175-495b-9fc5-bf20a2262016",
+ "x": -112.19595949289331,
+ "y": -46.04163056034261
+ },
+ {
+ "description": "Router c3600",
+ "dynamips_id": 2,
+ "id": 2,
+ "label": {
+ "color": "#ff000000",
+ "font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
+ "text": "ESW1",
+ "x": 7.8359375,
+ "y": -25.0
+ },
+ "ports": [
+ {
+ "adapter_number": 0,
+ "id": 3,
+ "name": "FastEthernet0/0",
+ "port_number": 0
+ },
+ {
+ "adapter_number": 0,
+ "id": 4,
+ "name": "FastEthernet0/1",
+ "port_number": 1
+ },
+ {
+ "adapter_number": 1,
+ "id": 5,
+ "name": "FastEthernet1/0",
+ "port_number": 0
+ },
+ {
+ "adapter_number": 1,
+ "id": 6,
+ "name": "FastEthernet1/1",
+ "port_number": 1
+ },
+ {
+ "adapter_number": 1,
+ "id": 7,
+ "name": "FastEthernet1/2",
+ "port_number": 2
+ },
+ {
+ "adapter_number": 1,
+ "id": 8,
+ "name": "FastEthernet1/3",
+ "port_number": 3
+ },
+ {
+ "adapter_number": 1,
+ "id": 9,
+ "name": "FastEthernet1/4",
+ "port_number": 4
+ },
+ {
+ "adapter_number": 1,
+ "id": 10,
+ "name": "FastEthernet1/5",
+ "port_number": 5
+ },
+ {
+ "adapter_number": 1,
+ "id": 11,
+ "name": "FastEthernet1/6",
+ "port_number": 6
+ },
+ {
+ "adapter_number": 1,
+ "id": 12,
+ "name": "FastEthernet1/7",
+ "port_number": 7
+ },
+ {
+ "adapter_number": 1,
+ "id": 13,
+ "name": "FastEthernet1/8",
+ "port_number": 8
+ },
+ {
+ "adapter_number": 1,
+ "id": 14,
+ "name": "FastEthernet1/9",
+ "port_number": 9
+ },
+ {
+ "adapter_number": 1,
+ "id": 15,
+ "name": "FastEthernet1/10",
+ "port_number": 10
+ },
+ {
+ "adapter_number": 1,
+ "id": 16,
+ "name": "FastEthernet1/11",
+ "port_number": 11
+ },
+ {
+ "adapter_number": 1,
+ "id": 17,
+ "name": "FastEthernet1/12",
+ "port_number": 12
+ },
+ {
+ "adapter_number": 1,
+ "id": 18,
+ "name": "FastEthernet1/13",
+ "port_number": 13
+ },
+ {
+ "adapter_number": 1,
+ "id": 19,
+ "name": "FastEthernet1/14",
+ "port_number": 14
+ },
+ {
+ "adapter_number": 1,
+ "id": 20,
+ "name": "FastEthernet1/15",
+ "port_number": 15
+ }
+ ],
+ "properties": {
+ "auto_delete_disks": false,
+ "chassis": "3660",
+ "clock_divisor": 4,
+ "console": 5001,
+ "disk0": 1,
+ "disk1": 0,
+ "exec_area": 64,
+ "idlemax": 500,
+ "idlepc": "0x6076e0b4",
+ "idlesleep": 30,
+ "image": "c3660-a3jk9s-mz.124-15.T14.image",
+ "image_md5sum": "daed99f508fd42dbaacf711e560643ed",
+ "iomem": 5,
+ "mac_addr": "cc02.6b5c.0000",
+ "mmap": true,
+ "name": "ESW1",
+ "nvram": 256,
+ "platform": "c3600",
+ "ram": 192,
+ "slot0": "Leopard-2FE",
+ "slot1": "NM-16ESW",
+ "sparsemem": true,
+ "startup_config": "configs/i2_startup-config.cfg",
+ "system_id": "FTX0945W0MY"
+ },
+ "server_id": 3,
+ "symbol": ":/symbols/multilayer_switch.svg",
+ "type": "C3600",
+ "vm_id": "4478a968-72a1-4722-9039-db7561c717c4",
+ "x": 55,
+ "y": -76
+ }
+ ],
+ "servers": [
+ {
+ "host": "127.0.0.1",
+ "id": 3,
+ "local": true,
+ "port": 3080,
+ "protocol": "http",
+ "vm": false
+ }
+ ]
+ },
+ "type": "topology",
+ "version": "1.5.1dev1"
+}
diff --git a/tests/topologies/1_5_qemu/after/testqemu.gns3 b/tests/topologies/1_5_qemu/after/testqemu.gns3
new file mode 100644
index 00000000..1d9bbad1
--- /dev/null
+++ b/tests/topologies/1_5_qemu/after/testqemu.gns3
@@ -0,0 +1,63 @@
+{
+ "name": "testqemu",
+ "project_id": "a3ca8a82-6b11-4c8e-b20d-c9e94286054c",
+ "revision": 5,
+ "auto_start": false,
+ "topology": {
+ "computes": [
+ {
+ "compute_id": "local",
+ "host": "127.0.0.1",
+ "name": "Local",
+ "port": 3080,
+ "protocol": "http"
+ }
+ ],
+ "drawings": [],
+ "links": [],
+ "nodes": [
+ {
+ "compute_id": "local",
+ "console": 5000,
+ "console_type": "telnet",
+ "label": {
+ "rotation": 0,
+ "style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
+ "text": "MicroCore-1",
+ "x": -4,
+ "y": -25
+ },
+ "name": "MicroCore-1",
+ "node_id": "426face4-7f73-436b-88fa-050e3ee101e9",
+ "node_type": "qemu",
+ "properties": {
+ "acpi_shutdown": false,
+ "adapter_type": "e1000",
+ "adapters": 1,
+ "boot_priority": "c",
+ "cpu_throttling": 0,
+ "cpus": 1,
+ "hda_disk_image": "core-linux-6.4-internet-0.1.img",
+ "hda_disk_image_md5sum": "8ebc5a6ec53a1c05b7aa101b5ceefe31",
+ "hda_disk_interface": "ide",
+ "hdb_disk_interface": "ide",
+ "hdc_disk_interface": "ide",
+ "hdd_disk_interface": "ide",
+ "legacy_networking": false,
+ "mac_address": "00:05:4c:01:e9:00",
+ "options": "-nographic",
+ "platform": "x86_64",
+ "process_priority": "normal",
+ "qemu_path": "/usr/local/bin/qemu-system-x86_64",
+ "ram": 256
+ },
+ "symbol": ":/symbols/qemu_guest.svg",
+ "x": -88,
+ "y": -102,
+ "z": 1
+ }
+ ]
+ },
+ "type": "topology",
+ "version": "2.0.0dev1"
+}
diff --git a/tests/topologies/1_5_qemu/before/testqemu.gns3 b/tests/topologies/1_5_qemu/before/testqemu.gns3
new file mode 100644
index 00000000..696b18b9
--- /dev/null
+++ b/tests/topologies/1_5_qemu/before/testqemu.gns3
@@ -0,0 +1,72 @@
+{
+ "auto_start": false,
+ "name": "testqemu",
+ "project_id": "a3ca8a82-6b11-4c8e-b20d-c9e94286054c",
+ "revision": 4,
+ "topology": {
+ "nodes": [
+ {
+ "description": "QEMU VM",
+ "id": 1,
+ "label": {
+ "color": "#ff000000",
+ "font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
+ "text": "MicroCore-1",
+ "x": -4.1875,
+ "y": -25.0
+ },
+ "linked_clone": true,
+ "port_name_format": "Ethernet{0}",
+ "ports": [
+ {
+ "adapter_number": 0,
+ "id": 1,
+ "name": "Ethernet0",
+ "port_number": 0
+ }
+ ],
+ "properties": {
+ "acpi_shutdown": false,
+ "adapter_type": "e1000",
+ "adapters": 1,
+ "boot_priority": "c",
+ "console": 5000,
+ "console_type": "telnet",
+ "cpu_throttling": 0,
+ "cpus": 1,
+ "hda_disk_image": "core-linux-6.4-internet-0.1.img",
+ "hda_disk_image_md5sum": "8ebc5a6ec53a1c05b7aa101b5ceefe31",
+ "hda_disk_interface": "ide",
+ "hdb_disk_interface": "ide",
+ "hdc_disk_interface": "ide",
+ "hdd_disk_interface": "ide",
+ "legacy_networking": false,
+ "mac_address": "00:05:4c:01:e9:00",
+ "name": "MicroCore-1",
+ "options": "-nographic",
+ "platform": "x86_64",
+ "process_priority": "normal",
+ "qemu_path": "/usr/local/bin/qemu-system-x86_64",
+ "ram": 256
+ },
+ "server_id": 3,
+ "type": "QemuVM",
+ "vm_id": "426face4-7f73-436b-88fa-050e3ee101e9",
+ "x": -88.5,
+ "y": -102.5
+ }
+ ],
+ "servers": [
+ {
+ "host": "127.0.0.1",
+ "id": 3,
+ "local": true,
+ "port": 3080,
+ "protocol": "http",
+ "vm": false
+ }
+ ]
+ },
+ "type": "topology",
+ "version": "1.5.1dev1"
+}
\ No newline at end of file
diff --git a/tests/topologies/1_5_virtualbox/after/1_5_virtualbox.gns3 b/tests/topologies/1_5_virtualbox/after/1_5_virtualbox.gns3
new file mode 100644
index 00000000..0dd3675b
--- /dev/null
+++ b/tests/topologies/1_5_virtualbox/after/1_5_virtualbox.gns3
@@ -0,0 +1,52 @@
+{
+ "auto_start": false,
+ "name": "1_5_virtualbox",
+ "project_id": "bf00c459-05a5-45c0-950c-3f6150a20703",
+ "revision": 5,
+ "topology": {
+ "computes": [
+ {
+ "compute_id": "local",
+ "host": "127.0.0.1",
+ "name": "Local",
+ "port": 3080,
+ "protocol": "http"
+ }
+ ],
+ "drawings": [],
+ "links": [],
+ "nodes": [
+ {
+ "compute_id": "local",
+ "console": 5000,
+ "console_type": "telnet",
+ "label": {
+ "rotation": 0,
+ "style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
+ "text": "debian",
+ "x": 11,
+ "y": -25
+ },
+ "name": "debian",
+ "node_id": "af5fa728-85da-44f1-b17a-e99a65a7037e",
+ "node_type": "virtualbox",
+ "properties": {
+ "acpi_shutdown": false,
+ "adapter_type": "Intel PRO/1000 MT Desktop (82540EM)",
+ "adapters": 1,
+ "enable_remote_console": false,
+ "headless": false,
+ "ram": 512,
+ "use_any_adapter": false,
+ "vmname": "debian"
+ },
+ "symbol": ":/symbols/vbox_guest.svg",
+ "x": -48,
+ "y": -43,
+ "z": 1
+ }
+ ]
+ },
+ "type": "topology",
+ "version": "2.0.0dev1"
+}
diff --git a/tests/topologies/1_5_virtualbox/before/1_5_virtualbox.gns3 b/tests/topologies/1_5_virtualbox/before/1_5_virtualbox.gns3
new file mode 100644
index 00000000..290fb30a
--- /dev/null
+++ b/tests/topologies/1_5_virtualbox/before/1_5_virtualbox.gns3
@@ -0,0 +1,60 @@
+{
+ "auto_start": false,
+ "name": "1_5_virtualbox",
+ "project_id": "bf00c459-05a5-45c0-950c-3f6150a20703",
+ "revision": 4,
+ "topology": {
+ "nodes": [
+ {
+ "description": "VirtualBox VM",
+ "id": 1,
+ "label": {
+ "color": "#ff000000",
+ "font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
+ "text": "debian",
+ "x": 11.1015625,
+ "y": -25.0
+ },
+ "linked_clone": false,
+ "port_name_format": "Ethernet{0}",
+ "ports": [
+ {
+ "adapter_number": 0,
+ "id": 1,
+ "name": "Ethernet0",
+ "port_number": 0
+ }
+ ],
+ "properties": {
+ "acpi_shutdown": false,
+ "adapter_type": "Intel PRO/1000 MT Desktop (82540EM)",
+ "adapters": 1,
+ "console": 5000,
+ "enable_remote_console": false,
+ "headless": false,
+ "name": "debian",
+ "ram": 512,
+ "use_any_adapter": false,
+ "vmname": "debian"
+ },
+ "server_id": 3,
+ "type": "VirtualBoxVM",
+ "vm_id": "af5fa728-85da-44f1-b17a-e99a65a7037e",
+ "x": -48.5,
+ "y": -43.5
+ }
+ ],
+ "servers": [
+ {
+ "host": "127.0.0.1",
+ "id": 3,
+ "local": true,
+ "port": 3080,
+ "protocol": "http",
+ "vm": false
+ }
+ ]
+ },
+ "type": "topology",
+ "version": "1.5.1dev1"
+}
diff --git a/tests/topologies/1_5_vmware/after/1_5_vmware.gns3 b/tests/topologies/1_5_vmware/after/1_5_vmware.gns3
new file mode 100644
index 00000000..bd75c1c8
--- /dev/null
+++ b/tests/topologies/1_5_vmware/after/1_5_vmware.gns3
@@ -0,0 +1,51 @@
+{
+ "name": "1_5_vmware",
+ "project_id": "4be1f3e5-76e5-4223-93b7-f37f4091549e",
+ "revision": 5,
+ "auto_start": false,
+ "topology": {
+ "computes": [
+ {
+ "compute_id": "local",
+ "host": "127.0.0.1",
+ "name": "Local",
+ "port": 3080,
+ "protocol": "http"
+ }
+ ],
+ "drawings": [],
+ "links": [],
+ "nodes": [
+ {
+ "compute_id": "local",
+ "console": 2000,
+ "console_type": "telnet",
+ "label": {
+ "rotation": 0,
+ "style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
+ "text": "GNS3 VM",
+ "x": 5,
+ "y": -25
+ },
+ "name": "GNS3 VM",
+ "node_id": "9e06d0ce-e8df-4f38-bdfa-7c83e19a91c1",
+ "node_type": "vmware",
+ "properties": {
+ "acpi_shutdown": false,
+ "adapter_type": "e1000",
+ "adapters": 1,
+ "enable_remote_console": false,
+ "headless": false,
+ "use_any_adapter": false,
+ "vmx_path": "/Users/bob/Documents/Virtual Machines.localized/GNS3 VM.vmwarevm/GNS3 VM.vmx"
+ },
+ "symbol": ":/symbols/vmware_guest.svg",
+ "x": 7,
+ "y": 8,
+ "z": 1
+ }
+ ]
+ },
+ "type": "topology",
+ "version": "2.0.0dev1"
+}
diff --git a/tests/topologies/1_5_vmware/before/1_5_vmware.gns3 b/tests/topologies/1_5_vmware/before/1_5_vmware.gns3
new file mode 100644
index 00000000..77c1c976
--- /dev/null
+++ b/tests/topologies/1_5_vmware/before/1_5_vmware.gns3
@@ -0,0 +1,60 @@
+{
+ "auto_start": false,
+ "name": "1_5_vmware",
+ "project_id": "4be1f3e5-76e5-4223-93b7-f37f4091549e",
+ "revision": 4,
+ "topology": {
+ "nodes": [
+ {
+ "description": "VMware VM",
+ "id": 1,
+ "label": {
+ "color": "#ff000000",
+ "font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
+ "text": "GNS3 VM",
+ "x": 5.125,
+ "y": -25.0
+ },
+ "linked_clone": false,
+ "port_name_format": "Ethernet{0}",
+ "ports": [
+ {
+ "adapter_number": 0,
+ "id": 1,
+ "name": "Ethernet0",
+ "port_number": 0
+ }
+ ],
+ "properties": {
+ "acpi_shutdown": false,
+ "adapter_type": "e1000",
+ "adapters": 1,
+ "console": 2000,
+ "enable_remote_console": false,
+ "headless": false,
+ "name": "GNS3 VM",
+ "use_any_adapter": false,
+ "use_ubridge": true,
+ "vmx_path": "/Users/bob/Documents/Virtual Machines.localized/GNS3 VM.vmwarevm/GNS3 VM.vmx"
+ },
+ "server_id": 3,
+ "type": "VMwareVM",
+ "vm_id": "9e06d0ce-e8df-4f38-bdfa-7c83e19a91c1",
+ "x": 7,
+ "y": 8
+ }
+ ],
+ "servers": [
+ {
+ "host": "127.0.0.1",
+ "id": 3,
+ "local": true,
+ "port": 3080,
+ "protocol": "http",
+ "vm": false
+ }
+ ]
+ },
+ "type": "topology",
+ "version": "1.5.1dev1"
+}
diff --git a/tests/topologies/1_5_vpcs/after/1_5_vpcs.gns3 b/tests/topologies/1_5_vpcs/after/1_5_vpcs.gns3
new file mode 100644
index 00000000..3a26ee51
--- /dev/null
+++ b/tests/topologies/1_5_vpcs/after/1_5_vpcs.gns3
@@ -0,0 +1,83 @@
+{
+ "auto_start": false,
+ "name": "1_5_vpcs",
+ "project_id": "62fc7a04-ae65-4003-a9e6-a046b1996f0e",
+ "revision": 5,
+ "topology": {
+ "computes": [
+ {
+ "compute_id": "local",
+ "host": "127.0.0.1",
+ "name": "Local",
+ "port": 3080,
+ "protocol": "http"
+ }
+ ],
+ "drawings": [],
+ "links": [
+ {
+ "link_id": "ANYUUID",
+ "nodes": [
+ {
+ "adapter_number": 0,
+ "node_id": "b570a150-c09f-47d9-8d32-9ca5b03234d6",
+ "port_number": 0
+ },
+ {
+ "adapter_number": 0,
+ "node_id": "0fd3dd4d-dc93-4a04-a9b9-7396a9e22e8b",
+ "port_number": 0
+ }
+ ]
+ }
+ ],
+ "nodes": [
+ {
+ "compute_id": "local",
+ "console": 5000,
+ "console_type": "telnet",
+ "label": {
+ "rotation": 0,
+ "style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
+ "text": "PC1",
+ "x": 18,
+ "y": -25
+ },
+ "name": "PC1",
+ "node_id": "0fd3dd4d-dc93-4a04-a9b9-7396a9e22e8b",
+ "node_type": "vpcs",
+ "properties": {
+ "startup_script_path": "startup.vpc"
+ },
+ "symbol": ":/symbols/vpcs_guest.svg",
+ "x": -87,
+ "y": -65,
+ "z": 1
+ },
+ {
+ "compute_id": "local",
+ "console": 5001,
+ "console_type": "telnet",
+ "label": {
+ "rotation": 0,
+ "style": "font-family: TypeWriter;font-size: 10;font-weight: bold;fill: #000000;fill-opacity: 1.0;",
+ "text": "PC2",
+ "x": 18,
+ "y": -25
+ },
+ "name": "PC2",
+ "node_id": "b570a150-c09f-47d9-8d32-9ca5b03234d6",
+ "node_type": "vpcs",
+ "properties": {
+ "startup_script_path": "startup.vpc"
+ },
+ "symbol": ":/symbols/vpcs_guest.svg",
+ "x": 123,
+ "y": -65,
+ "z": 1
+ }
+ ]
+ },
+ "type": "topology",
+ "version": "ANYSTR"
+}
diff --git a/tests/topologies/1_5_vpcs/after/project-files/vpcs/0fd3dd4d-dc93-4a04-a9b9-7396a9e22e8b/startup.vpc b/tests/topologies/1_5_vpcs/after/project-files/vpcs/0fd3dd4d-dc93-4a04-a9b9-7396a9e22e8b/startup.vpc
new file mode 100644
index 00000000..d46a9c6f
--- /dev/null
+++ b/tests/topologies/1_5_vpcs/after/project-files/vpcs/0fd3dd4d-dc93-4a04-a9b9-7396a9e22e8b/startup.vpc
@@ -0,0 +1 @@
+set pcname PC1
diff --git a/tests/topologies/1_5_vpcs/after/project-files/vpcs/b570a150-c09f-47d9-8d32-9ca5b03234d6/startup.vpc b/tests/topologies/1_5_vpcs/after/project-files/vpcs/b570a150-c09f-47d9-8d32-9ca5b03234d6/startup.vpc
new file mode 100644
index 00000000..062dba6a
--- /dev/null
+++ b/tests/topologies/1_5_vpcs/after/project-files/vpcs/b570a150-c09f-47d9-8d32-9ca5b03234d6/startup.vpc
@@ -0,0 +1 @@
+set pcname PC2
diff --git a/tests/topologies/1_5_vpcs/before/1_5_vpcs.gns3 b/tests/topologies/1_5_vpcs/before/1_5_vpcs.gns3
new file mode 100644
index 00000000..65652b13
--- /dev/null
+++ b/tests/topologies/1_5_vpcs/before/1_5_vpcs.gns3
@@ -0,0 +1,98 @@
+{
+ "auto_start": false,
+ "name": "1_5_vpcs",
+ "project_id": "62fc7a04-ae65-4003-a9e6-a046b1996f0e",
+ "revision": 4,
+ "topology": {
+ "links": [
+ {
+ "description": "Link from PC2 port Ethernet0 to PC1 port Ethernet0",
+ "destination_node_id": 1,
+ "destination_port_id": 1,
+ "id": 1,
+ "source_node_id": 2,
+ "source_port_id": 2
+ }
+ ],
+ "nodes": [
+ {
+ "description": "VPCS device",
+ "id": 1,
+ "label": {
+ "color": "#ff000000",
+ "font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
+ "text": "PC1",
+ "x": 18.5859375,
+ "y": -25.0
+ },
+ "ports": [
+ {
+ "adapter_number": 0,
+ "description": "connected to PC2 on port Ethernet0",
+ "id": 1,
+ "link_id": 1,
+ "name": "Ethernet0",
+ "nio": "NIO_UDP",
+ "port_number": 0
+ }
+ ],
+ "properties": {
+ "console": 5000,
+ "name": "PC1",
+ "startup_script_path": "startup.vpc"
+ },
+ "server_id": 3,
+ "symbol": ":/symbols/vpcs_guest.svg",
+ "type": "VPCSDevice",
+ "vm_id": "0fd3dd4d-dc93-4a04-a9b9-7396a9e22e8b",
+ "x": -87.5,
+ "y": -65.5
+ },
+ {
+ "description": "VPCS device",
+ "id": 2,
+ "label": {
+ "color": "#ff000000",
+ "font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
+ "text": "PC2",
+ "x": 18.5859375,
+ "y": -25.0
+ },
+ "ports": [
+ {
+ "adapter_number": 0,
+ "description": "connected to PC1 on port Ethernet0",
+ "id": 2,
+ "link_id": 1,
+ "name": "Ethernet0",
+ "nio": "NIO_UDP",
+ "port_number": 0
+ }
+ ],
+ "properties": {
+ "console": 5001,
+ "name": "PC2",
+ "startup_script_path": "startup.vpc"
+ },
+ "server_id": 3,
+ "symbol": ":/symbols/vpcs_guest.svg",
+ "type": "VPCSDevice",
+ "vm_id": "b570a150-c09f-47d9-8d32-9ca5b03234d6",
+ "x": 123.5,
+ "y": -65.5
+ }
+ ],
+ "servers": [
+ {
+ "host": "127.0.0.1",
+ "id": 3,
+ "local": true,
+ "port": 3080,
+ "protocol": "http",
+ "vm": false
+ }
+ ]
+ },
+ "type": "topology",
+ "version": "1.5.1dev1"
+}
\ No newline at end of file
diff --git a/tests/topologies/1_5_vpcs/before/project-files/vpcs/0fd3dd4d-dc93-4a04-a9b9-7396a9e22e8b/startup.vpc b/tests/topologies/1_5_vpcs/before/project-files/vpcs/0fd3dd4d-dc93-4a04-a9b9-7396a9e22e8b/startup.vpc
new file mode 100644
index 00000000..d46a9c6f
--- /dev/null
+++ b/tests/topologies/1_5_vpcs/before/project-files/vpcs/0fd3dd4d-dc93-4a04-a9b9-7396a9e22e8b/startup.vpc
@@ -0,0 +1 @@
+set pcname PC1
diff --git a/tests/topologies/1_5_vpcs/before/project-files/vpcs/b570a150-c09f-47d9-8d32-9ca5b03234d6/startup.vpc b/tests/topologies/1_5_vpcs/before/project-files/vpcs/b570a150-c09f-47d9-8d32-9ca5b03234d6/startup.vpc
new file mode 100644
index 00000000..062dba6a
--- /dev/null
+++ b/tests/topologies/1_5_vpcs/before/project-files/vpcs/b570a150-c09f-47d9-8d32-9ca5b03234d6/startup.vpc
@@ -0,0 +1 @@
+set pcname PC2
diff --git a/tests/topologies/README.rst b/tests/topologies/README.rst
new file mode 100644
index 00000000..d804f757
--- /dev/null
+++ b/tests/topologies/README.rst
@@ -0,0 +1,30 @@
+This directories contain topologies made for previous version of GNS3
+
+Each directory is a GNS3 project. You have two directory inside:
+* before
+* after
+
+Before is the state of the project before conversion and after
+is the reference for checking if conversion is a success.
+
+To check if file are the same we check the file size except
+for .gns3
+
+.gns3 check
+###########
+
+The .gns3 json is loaded and compare to the reference project.
+
+You have some special value in the after project:
+* "ANYSTR" allow for any string to match
+* "ANYUUID" allow for any uuid to match
+
+
+Run the tests
+###############
+
+You can run the tests with:
+
+.. code:: bash
+
+ py.test -vv -x tests/test_topologies.py