JSON schema for checking topologies

Support:
* IOU
* Dynamips
* VPCS
* VirtualBox
* Qemu

VMWare is not supported

Tests schema are available in:
tests/schemas

And the test suite is auto generated from this directory you
can take a look to test_topology_check

Fix #342,#392,#384
This commit is contained in:
Julien Duponchelle
2015-06-04 15:38:35 +02:00
parent e2cdff3604
commit 17471db248
17 changed files with 1499 additions and 6 deletions

View File

@@ -25,6 +25,7 @@ import json
import uuid
import glob
import shutil
import sys
from .qt import QtGui, QtSvg, QtWidgets
@@ -40,6 +41,7 @@ from .modules import MODULES
from .modules.module_error import ModuleError
from .utils.message_box import MessageBox
from .version import __version__
from .topology_check import getTopologyValidationErrors
import logging
log = logging.getLogger(__name__)
@@ -47,6 +49,8 @@ log = logging.getLogger(__name__)
# The topology version supported by client
TOPOLOGY_REVISION = 4
VALIDATION_ERROR_MESSAGE = "Validation error when dumping the topology.\nIt's probably a false positive but please send the .gns3 to developers@gns3.net.\nThanks !"
class TopologyInstance:
@@ -528,6 +532,13 @@ class Topology:
if random_id:
topology = self._randomize_id(topology)
errors = getTopologyValidationErrors(topology)
if errors:
print(errors)
print(VALIDATION_ERROR_MESSAGE)
if hasattr(sys, '_called_from_test'):
raise Exception
return topology
def _randomize_id(self, topology):
@@ -569,6 +580,13 @@ class Topology:
if "revision" in json_topology and json_topology["revision"] > TOPOLOGY_REVISION:
raise ValueError("This topology is not supported by your version of GNS3 please use GNS3 {} or later".format(json_topology["version"]))
errors = getTopologyValidationErrors(json_topology)
if errors:
print(errors)
print(VALIDATION_ERROR_MESSAGE)
if hasattr(sys, '_called_from_test'):
raise Exception
if "project_id" in json_topology:
self._project.setId(json_topology["project_id"])
self._project.setName(json_topology.get("name", "unnamed"))

62
gns3/topology_check.py Normal file
View File

@@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
import jsonschema
import json
from gns3.utils.get_resource import get_resource
def getTopologyValidationErrors(topology):
"""
Apply a JSON schema to a topology
:param topology: A dict of the topology
:returns: Return None if ok otherwise an error message
"""
with open(get_resource("topology_schema.json")) as f:
schema = json.load(f)
v = jsonschema.Draft4Validator(schema)
errors = sorted(v.iter_errors(topology), key=lambda e: e.path)
if len(errors) == 0:
return None
error_message = ""
for error in errors:
error_message += "{}\n".format(str(error))
return error_message
if __name__ == "__main__":
"""
You can test this code with:
python gns3/topology_check.py PATH_TO_TOPOLOGY.gns3
"""
import sys
if len(sys.argv) != 2:
print("You need to pass a .gns3 file as parameter")
sys.exit(1)
with open(sys.argv[1]) as f:
print(sys.argv[1])
errors = getTopologyValidationErrors(json.load(f))
if errors:
print(errors)
sys.exit(1)

View File

@@ -50,7 +50,11 @@ def get_resource(resource_name):
resource_name = os.path.join(os.path.dirname(sys.executable), "../Resources", resource_name)
if hasattr(sys, "frozen") and os.path.exists(resource_name):
resource_path = os.path.normpath(os.path.join(os.path.dirname(sys.executable), resource_name))
elif not hasattr(sys, "frozen") and pkg_resources.resource_exists("gns3", resource_name):
resource_path = pkg_resources.resource_filename("gns3", resource_name)
resource_path = os.path.normpath(resource_path)
elif not hasattr(sys, "frozen"):
if pkg_resources.resource_exists("gns3", resource_name):
resource_path = pkg_resources.resource_filename("gns3", resource_name)
resource_path = os.path.normpath(resource_path)
else:
resource_path = os.path.dirname(os.path.realpath(__file__))
resource_path = os.path.join(resource_path, "..", "..", "resources", resource_name)
return resource_path

View File

@@ -1,3 +1,4 @@
jsonschema>=2.4.0
apache-libcloud>=0.16.0
paramiko>=1.15.1
requests>=2.4.3

View File

@@ -0,0 +1,543 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "GNS3 topology",
"definitions": {
"uuid" : {
"type": "string",
"pattern": "^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}$"
},
"optional_uuid" : {
"oneOf": [
{ "$ref": "#/definitions/uuid" },
{ "type": "null" }
]
},
"numeric_id": {
"type": "integer",
"minimum": 0
},
"mandatory_string": {
"type": "string",
"minLength": 1
},
"network_port": {
"type": "integer",
"minimum": 1,
"maximum": 65535
},
"rectangle": {
"type": "object",
"properties": {
"height": { "type": "number" },
"width": {"type": "number" },
"x": { "type": "number" },
"y": {"type": "number" }
},
"required": [
"height",
"width",
"x",
"y"
],
"additionalProperties": false
},
"ellipse": {
"type": "object",
"properties": {
"border_style": {
"type": "integer",
"minimum": 0,
"maximum": 6
},
"height": { "type": "number" },
"width": {"type": "number" },
"x": { "type": "number" },
"y": {"type": "number" }
},
"required": [
"border_style",
"height",
"width",
"x",
"y"
],
"additionalProperties": false
},
"label": {
"type": "object",
"properties": {
"color": {
"type": "string",
"pattern": "^#[0-9a-f]{8}$"
},
"font": { "$ref": "#/definitions/mandatory_string" },
"text": { "$ref": "#/definitions/mandatory_string" },
"x": { "type": "number" },
"y": {"type": "number" }
},
"required": [
"color",
"font",
"text",
"x",
"y"
],
"additionalProperties": false
},
"port": {
"type": "object",
"properties": {
"adapter_number": {
"type": "integer",
"minimum": 0
},
"description": { "$ref": "#/definitions/mandatory_string" },
"id": { "$ref": "#/definitions/numeric_id" },
"link_id": { "$ref": "#/definitions/numeric_id" },
"name": { "$ref": "#/definitions/mandatory_string" },
"nio": {
"enum": ["NIO_UDP"]
},
"port_number": {
"type": "integer",
"minimum": 0
},
"vlan": {
"type": "integer",
"minimum": 0
},
"type": {
"enum": ["access"]
}
},
"required": [
"id",
"name",
"port_number"
],
"additionalProperties": false
},
"link": {
"type": "object",
"properties": {
"description": { "$ref": "#/definitions/mandatory_string" },
"destination_node_id": { "$ref": "#/definitions/numeric_id" },
"destination_port_id": { "$ref": "#/definitions/numeric_id" },
"id": { "$ref": "#/definitions/numeric_id" },
"source_node_id": { "$ref": "#/definitions/numeric_id" },
"source_port_id": { "$ref": "#/definitions/numeric_id" }
},
"required": [
"description",
"destination_node_id",
"destination_port_id",
"id",
"source_node_id",
"source_port_id"
],
"additionalProperties": false
},
"server_http": {
"properties": {
"protocol": { "enum": ["http", "https"] },
"cloud": { "type": "boolean" },
"host": { "$ref": "#/definitions/mandatory_string" },
"id": { "$ref": "#/definitions/numeric_id" },
"local": { "type": "boolean" },
"port": { "$ref": "#/definitions/network_port" },
"user": {
"type": ["string", "null"]
}
},
"required": [
"protocol",
"cloud",
"host",
"id",
"local",
"port"
],
"additionalProperties": false
},
"server_ssh": {
"properties": {
"protocol": { "enum": ["ssh"] },
"cloud": { "type": "boolean" },
"host": { "$ref": "#/definitions/mandatory_string" },
"id": { "$ref": "#/definitions/numeric_id" },
"local": { "type": "boolean" },
"port": { "$ref": "#/definitions/network_port" },
"ssh_key": { "$ref": "#/definitions/mandatory_string" },
"ssh_port": { "$ref": "#/definitions/network_port" },
"user": { "$ref": "#/definitions/mandatory_string" }
},
"required": [
"protocol",
"cloud",
"host",
"id",
"local",
"port",
"ssh_key",
"ssh_port",
"user"
],
"additionalProperties": false
},
"node": {
"type": "object",
"properties": {
"type": {
"enum": [
"IOUDevice",
"VirtualBoxVM",
"QemuVM",
"VPCSDevice",
"EthernetHub",
"EthernetSwitch",
"ATMSwitch",
"FrameRelaySwitch",
"C1700",
"C2600",
"C2691",
"C3600",
"C3725",
"C3745",
"C7200"
]
},
"description": { "$ref": "#/definitions/mandatory_string" },
"id": { "$ref": "#/definitions/numeric_id" },
"device_id": { "$ref": "#/definitions/optional_uuid" },
"label": { "$ref": "#/definitions/label" },
"hover_symbol": { "$ref": "#/definitions/mandatory_string" },
"default_symbol": { "$ref": "#/definitions/mandatory_string" },
"ports": {
"type": "array",
"items": { "$ref": "#/definitions/port" }
},
"dynamips_id": { "$ref": "#/definitions/numeric_id" },
"server_id": { "$ref": "#/definitions/numeric_id" },
"vm_id": {
"oneOf": [
{ "$ref": "#/definitions/uuid" },
{ "type": "null" }
]
},
"linked_clone": { "type" : "boolean" },
"x": { "type": "number" },
"y": { "type": "number" },
"properties": {
"type": "object",
"oneOf": [
{ "$ref": "#/definitions/properties_vpcs" },
{ "$ref": "#/definitions/properties_dynamips" },
{ "$ref": "#/definitions/properties_qemu" },
{ "$ref": "#/definitions/properties_virtualbox" },
{ "$ref": "#/definitions/properties_iou" }
]
},
"required": [
"type",
"description",
"id",
"label",
"ports",
"server_id",
"vm_id",
"x",
"y",
"properties"
]
},
"additionalProperties": false
},
"properties_iou": {
"type": "object",
"properties": {
"console": { "$ref": "#/definitions/network_port" },
"ethernet_adapters": { "type": "integer", "minimum": 0 },
"initial_config": { "$ref": "#/definitions/mandatory_string" },
"l1_keepalives": { "type": "boolean" },
"name": { "$ref": "#/definitions/mandatory_string" },
"nvram": { "type": "integer", "minimum": 1 },
"path": { "$ref": "#/definitions/mandatory_string" },
"ram": { "type": "integer", "minimum": 1 },
"serial_adapters": { "type": "integer", "minimum": 0 },
"use_default_iou_values": { "type": "boolean" }
},
"required": [
"console",
"ethernet_adapters",
"initial_config",
"l1_keepalives",
"name",
"nvram",
"path",
"ram",
"serial_adapters",
"use_default_iou_values"
],
"additionalProperties": false
},
"properties_qemu": {
"type": "object",
"properties": {
"console": { "$ref": "#/definitions/network_port" },
"name": { "$ref": "#/definitions/mandatory_string" },
"acpi_shutdown": { "type": "boolean" },
"adapter_type": {
"enum": ["e1000", "i82551", "i82557b", "i82559er", "ne2k_pci", "pcnet", "rtl8139", "virtio"]
},
"adapters": {"type": "integer", "minimum": 1},
"cpu_throttling": {"type": "integer", "minimum": 0, "maximum": 100},
"hda_disk_image": { "type": "string" },
"hdb_disk_image": { "type": "string" },
"hdc_disk_image": { "type": "string" },
"hdd_disk_image": { "type": "string" },
"initrd": { "type": "string" },
"kernel_image": { "type": "string"},
"kernel_command_line": { "type": "string" },
"legacy_networking": { "type": "boolean" },
"mac_address": { "$ref": "#/definitions/mandatory_string" },
"options": { "type": "string" },
"process_priority": {
"enum": ["realtime", "very high", "high", "normal", "low", "very low"]
},
"qemu_path": { "type": "string" },
"ram": {"type": "integer", "minimum": 1}
},
"required": [
"name",
"adapter_type",
"adapters",
"console",
"cpu_throttling",
"legacy_networking",
"mac_address",
"options",
"process_priority",
"qemu_path",
"ram"
],
"additionalProperties": false
},
"properties_virtualbox": {
"type": "object",
"properties": {
"acpi_shutdown": { "type": "boolean" },
"adapters": { "type": "integer", "minimum": 0 },
"console": { "$ref": "#/definitions/network_port" },
"enable_remote_console": { "type": "boolean" },
"headless": { "type": "boolean" },
"name": { "$ref": "#/definitions/mandatory_string" },
"ram": { "type": "integer", "minimum": 1 },
"use_any_adapter": { "type": "boolean" },
"vmname": { "$ref": "#/definitions/mandatory_string" },
"adapter_type": {
"enum": [
"PCnet-PCI II (Am79C970A)",
"PCNet-FAST III (Am79C973)",
"Intel PRO/1000 MT Desktop (82540EM)",
"Intel PRO/1000 T Server (82543GC)",
"Intel PRO/1000 MT Server (82545EM)",
"Paravirtualized Network (virtio-net)"
]
}
},
"required": [
"adapter_type",
"adapters",
"console",
"enable_remote_console",
"headless",
"name",
"ram",
"use_any_adapter",
"vmname"
],
"additionalProperties": false
},
"properties_vpcs": {
"type": "object",
"properties": {
"console": { "$ref": "#/definitions/network_port" },
"name": { "$ref": "#/definitions/mandatory_string" },
"startup_script_path":{ "$ref": "#/definitions/mandatory_string" }
},
"required": [
"name"
],
"additionalProperties": false
},
"dynamips_slot": {
"enum": ["C2600-MB-2FE", "C2600-MB-1E", "PA-A1", "PA-8E", "C1700-MB-1FE", "PA-8T", "PA-2FE-TX", "PA-FE-TX", "PA-GE", "C2600-MB-2E", "C7200-IO-FE", "NM-4T", "C2600-MB-1FE", "C7200-IO-2FE", "PA-POS-OC3", "PA-4T+", "C1700-MB-WIC1", "NM-16ESW", "C7200-IO-GE-E", "NM-4E", "GT96100-FE", "NM-1FE-TX", "Leopard-2FE", "NM-1E", "PA-4E"]
},
"properties_dynamips": {
"type": "object",
"properties": {
"name": { "$ref": "#/definitions/mandatory_string" },
"clock_divisor": {"type": "integer", "minimum": 1},
"console": { "$ref": "#/definitions/network_port" },
"disk0": {"type": "integer", "minimum": 0},
"disk1": {"type": "integer", "minimum": 0},
"exec_area": {"type": "integer", "minimum": 1},
"idlemax": {"type": "integer", "minimum": 1},
"idlepc": {"type": "string", "pattern": "^0x[0-9a-f]{8}"},
"idlesleep": {"type": "integer", "minimum": 1},
"image": { "$ref": "#/definitions/mandatory_string" },
"mac_addr": { "$ref": "#/definitions/mandatory_string" },
"midplane": { "enum": "vxr" },
"mmap": { "type": "boolean" },
"npe": {
"enum": ["npe-100", "npe-150", "npe-175", "npe-200", "npe-225", "npe-300", "npe-400", "npe-g2"]
},
"nvram": {"type": "integer", "minimum": 1},
"platform": {
"enum": ["c1700", "c2600", "c2691", "c3725", "c3745", "c3600", "c7200"]
},
"power_supplies": {
"type": "array",
"items": {"type": "integer", "minimum": 1}
},
"ram": {"type": "integer", "minimum": 1},
"sensors": {
"type": "array",
"items": {"type": "integer", "minimum": 1}
},
"slot0": { "$ref": "#/definitions/dynamips_slot" },
"slot1": { "$ref": "#/definitions/dynamips_slot" },
"slot2": { "$ref": "#/definitions/dynamips_slot" },
"slot3": { "$ref": "#/definitions/dynamips_slot" },
"slot4": { "$ref": "#/definitions/dynamips_slot" },
"slot5": { "$ref": "#/definitions/dynamips_slot" },
"slot6": { "$ref": "#/definitions/dynamips_slot" },
"sparsemem": {"type": "boolean"},
"startup_config": { "$ref": "#/definitions/mandatory_string" },
"system_id": { "$ref": "#/definitions/mandatory_string" }
},
"required": [
"name",
"clock_divisor",
"console",
"disk0",
"disk1",
"exec_area",
"idlemax",
"idlepc",
"idlesleep",
"image",
"mac_addr",
"midplane",
"mmap",
"npe",
"nvram",
"platform",
"power_supplies",
"ram",
"sensors",
"slot0",
"sparsemem",
"startup_config",
"system_id"
],
"additionalProperties": false
},
"topology": {
"type": "object",
"properties": {
"links": {
"type": "array",
"items": {
"type": "object",
"oneOf": [
{ "$ref": "#/definitions/link" }
]
}
},
"nodes": {
"type": "array",
"items": { "$ref": "#/definitions/node" }
},
"ellipses": {
"type": "array",
"items": { "$ref": "#/definitions/ellipse" }
},
"rectangles": {
"type": "array",
"items": { "$ref": "#/definitions/rectangle" }
},
"notes": {
"type": "array",
"items": { "$ref": "#/definitions/label" }
},
"servers": {
"type": "array",
"items": {
"type": "object",
"oneOf": [
{ "$ref": "#/definitions/server_http" },
{ "$ref": "#/definitions/server_ssh" }
]
}
}
},
"additionalProperties": false
}
},
"type": "object",
"properties": {
"auto_start": {
"type": "boolean"
},
"name": { "$ref": "#/definitions/mandatory_string" },
"project_id": { "$ref": "#/definitions/optional_uuid" },
"resources_type": {
"enum": ["local"]
},
"revision": {
"type": "integer",
"minimum": 3
},
"version": {
"type": "string",
"minLength": 5
},
"type": {
"enum": ["topology"]
},
"topology": { "$ref": "#/definitions/topology" }
},
"required": [
"auto_start",
"name",
"project_id",
"resources_type",
"topology",
"type"
],
"additionalProperties": false
}

View File

@@ -49,6 +49,7 @@ setup(
description="GNS3 graphical interface for the GNS3 server.",
long_description=open("README.rst", "r").read(),
install_requires=[
"jsonschema>=2.4.0",
"apache-libcloud>=0.14.1",
"requests>=2.4.3",
"paramiko>=1.15.1",

View File

@@ -0,0 +1,189 @@
{
"auto_start": false,
"name": "untitled",
"project_id": "85376bb0-3f17-4b46-ae9d-76b393f9eb65",
"resources_type": "local",
"revision": 4,
"topology": {
"nodes": [
{
"description": "Router c7200",
"dynamips_id": 1,
"id": 2,
"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": 5,
"id": 2,
"name": "Serial5/0",
"port_number": 0
},
{
"adapter_number": 5,
"id": 3,
"name": "Serial5/1",
"port_number": 1
},
{
"adapter_number": 5,
"id": 4,
"name": "Serial5/2",
"port_number": 2
},
{
"adapter_number": 5,
"id": 5,
"name": "Serial5/3",
"port_number": 3
},
{
"adapter_number": 6,
"id": 6,
"name": "Serial6/0",
"port_number": 0
},
{
"adapter_number": 6,
"id": 7,
"name": "Serial6/1",
"port_number": 1
},
{
"adapter_number": 6,
"id": 8,
"name": "Serial6/2",
"port_number": 2
},
{
"adapter_number": 6,
"id": 9,
"name": "Serial6/3",
"port_number": 3
},
{
"adapter_number": 6,
"id": 10,
"name": "Serial6/4",
"port_number": 4
},
{
"adapter_number": 6,
"id": 11,
"name": "Serial6/5",
"port_number": 5
},
{
"adapter_number": 6,
"id": 12,
"name": "Serial6/6",
"port_number": 6
},
{
"adapter_number": 6,
"id": 13,
"name": "Serial6/7",
"port_number": 7
},
{
"adapter_number": 1,
"id": 14,
"name": "ATM1/0",
"port_number": 0
},
{
"adapter_number": 3,
"id": 15,
"name": "FastEthernet3/0",
"port_number": 0
},
{
"adapter_number": 3,
"id": 16,
"name": "FastEthernet3/1",
"port_number": 1
},
{
"adapter_number": 2,
"id": 17,
"name": "FastEthernet2/0",
"port_number": 0
},
{
"adapter_number": 0,
"id": 18,
"name": "FastEthernet0/0",
"port_number": 0
},
{
"adapter_number": 4,
"id": 19,
"name": "GigabitEthernet4/0",
"port_number": 0
}
],
"properties": {
"clock_divisor": 4,
"console": 2001,
"disk0": 0,
"disk1": 0,
"exec_area": 64,
"idlemax": 500,
"idlepc": "0x606e056c",
"idlesleep": 30,
"image": "c7200-adventerprisek9-mz.124-24.T8.image",
"mac_addr": "ca01.7778.0000",
"midplane": "vxr",
"mmap": true,
"name": "R1",
"npe": "npe-400",
"nvram": 512,
"platform": "c7200",
"power_supplies": [
1,
1
],
"ram": 512,
"sensors": [
22,
22,
22,
22
],
"slot0": "C7200-IO-FE",
"slot1": "PA-A1",
"slot2": "PA-FE-TX",
"slot3": "PA-2FE-TX",
"slot4": "PA-GE",
"slot5": "PA-4T+",
"slot6": "PA-8T",
"sparsemem": true,
"startup_config": "configs/i1_startup-config.cfg",
"system_id": "FTX0945W0MY"
},
"server_id": 1,
"type": "C7200",
"vm_id": "466d182c-a6eb-4116-b8ce-9915d00a3d08",
"x": -70.0,
"y": -127.0
}
],
"servers": [
{
"cloud": false,
"host": "127.0.0.1",
"id": 1,
"local": true,
"port": 8000,
"protocol": "http"
}
]
},
"type": "topology",
"version": "1.4.0.dev1"
}

View File

@@ -0,0 +1,199 @@
{
"auto_start": false,
"name": "untitled",
"project_id": "fe7ee04a-656d-462b-85b9-c6d3fe7a7420",
"resources_type": "local",
"revision": 4,
"topology": {
"nodes": [
{
"description": "Ethernet hub",
"device_id": "c5a4c951-28b6-40dc-98c5-92411ff2a77a",
"id": 1,
"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": 1,
"type": "EthernetHub",
"x": -73.0,
"y": -88.0
},
{
"description": "Ethernet switch",
"device_id": "35c8209c-2887-4cc6-8fdc-af79ad0fe961",
"id": 2,
"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": 1,
"type": "EthernetSwitch",
"x": -70.5,
"y": -269.0
},
{
"description": "Frame Relay switch",
"device_id": "71099637-1279-4b70-8fc5-c14e78c19b94",
"id": 3,
"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"
},
"server_id": 1,
"type": "FrameRelaySwitch",
"x": 13.5,
"y": -213.5
},
{
"description": "ATM switch",
"device_id": "a16673ee-93e6-443c-b86b-8d3f9a3995d5",
"id": 4,
"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"
},
"server_id": 1,
"type": "ATMSwitch",
"x": -95.5,
"y": -195.5
}
],
"servers": [
{
"cloud": false,
"host": "127.0.0.1",
"id": 1,
"local": true,
"port": 8000,
"protocol": "http"
}
]
},
"type": "topology",
"version": "1.4.0.dev1"
}

10
tests/schemas/empty.gns3 Normal file
View File

@@ -0,0 +1,10 @@
{
"auto_start": false,
"name": "untitled",
"project_id": null,
"resources_type": "local",
"revision": 4,
"topology": {},
"type": "topology",
"version": "1.4.0.dev1"
}

View File

@@ -0,0 +1,28 @@
{
"auto_start": false,
"name": "untitled",
"project_id": "fe7ee04a-656d-462b-85b9-c6d3fe7a7420",
"resources_type": "local",
"revision": 4,
"topology": {
"ellipses": [
{
"border_style": 2,
"height": 200.0,
"width": 200.0,
"x": -77.0,
"y": -134.0
}
],
"rectangles": [
{
"height": 100.0,
"width": 200.0,
"x": -102.0,
"y": -278.0
}
]
},
"type": "topology",
"version": "1.4.0.dev1"
}

152
tests/schemas/iou.gns3 Normal file
View File

@@ -0,0 +1,152 @@
{
"auto_start": false,
"name": "untitled",
"project_id": "abe6eb8c-f21a-4619-b8fe-de4d0f9ad8b9",
"resources_type": "local",
"revision": 4,
"topology": {
"nodes": [
{
"default_symbol": ":/symbols/router.normal.svg",
"description": "IOU device",
"hover_symbol": ":/symbols/router.selected.svg",
"id": 1,
"label": {
"color": "#ff000000",
"font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
"text": "IOU1",
"x": 16.2578125,
"y": -25.0
},
"ports": [
{
"adapter_number": 0,
"id": 1,
"name": "Ethernet0/0",
"port_number": 0
},
{
"adapter_number": 0,
"id": 2,
"name": "Ethernet0/1",
"port_number": 1
},
{
"adapter_number": 0,
"id": 3,
"name": "Ethernet0/2",
"port_number": 2
},
{
"adapter_number": 0,
"id": 4,
"name": "Ethernet0/3",
"port_number": 3
},
{
"adapter_number": 1,
"id": 5,
"name": "Ethernet1/0",
"port_number": 0
},
{
"adapter_number": 1,
"id": 6,
"name": "Ethernet1/1",
"port_number": 1
},
{
"adapter_number": 1,
"id": 7,
"name": "Ethernet1/2",
"port_number": 2
},
{
"adapter_number": 1,
"id": 8,
"name": "Ethernet1/3",
"port_number": 3
},
{
"adapter_number": 2,
"id": 9,
"name": "Serial2/0",
"port_number": 0
},
{
"adapter_number": 2,
"id": 10,
"name": "Serial2/1",
"port_number": 1
},
{
"adapter_number": 2,
"id": 11,
"name": "Serial2/2",
"port_number": 2
},
{
"adapter_number": 2,
"id": 12,
"name": "Serial2/3",
"port_number": 3
},
{
"adapter_number": 3,
"id": 13,
"name": "Serial3/0",
"port_number": 0
},
{
"adapter_number": 3,
"id": 14,
"name": "Serial3/1",
"port_number": 1
},
{
"adapter_number": 3,
"id": 15,
"name": "Serial3/2",
"port_number": 2
},
{
"adapter_number": 3,
"id": 16,
"name": "Serial3/3",
"port_number": 3
}
],
"properties": {
"console": 6000,
"ethernet_adapters": 2,
"initial_config": "initial-config.cfg",
"l1_keepalives": false,
"name": "IOU1",
"nvram": 128,
"path": "i86bi-linux-l3-adventerprisek9-15.4.1T.bin",
"ram": 256,
"serial_adapters": 2,
"use_default_iou_values": true
},
"server_id": 2,
"type": "IOUDevice",
"vm_id": "cc932b8e-bf7d-44c6-8561-716a26810f32",
"x": -62.0,
"y": -231.0
}
],
"servers": [
{
"cloud": false,
"host": "127.0.0.1",
"id": 2,
"local": false,
"port": 8001,
"protocol": "http",
"user": ""
}
]
},
"type": "topology",
"version": "1.4.0.dev1"
}

20
tests/schemas/note.gns3 Normal file
View File

@@ -0,0 +1,20 @@
{
"auto_start": false,
"name": "untitled",
"project_id": "fe7ee04a-656d-462b-85b9-c6d3fe7a7420",
"resources_type": "local",
"revision": 4,
"topology": {
"notes": [
{
"color": "#ff000000",
"font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
"text": "Hello",
"x": -90.0,
"y": -224.0
}
]
},
"type": "topology",
"version": "1.4.0.dev1"
}

62
tests/schemas/qemu.gns3 Normal file
View File

@@ -0,0 +1,62 @@
{
"auto_start": false,
"name": "untitled",
"project_id": "85376bb0-3f17-4b46-ae9d-76b393f9eb65",
"resources_type": "local",
"revision": 4,
"topology": {
"nodes": [
{
"description": "QEMU VM",
"id": 3,
"label": {
"color": "#ff000000",
"font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
"text": "Microcore-1",
"x": -3.2890625,
"y": -25.0
},
"ports": [
{
"adapter_number": 0,
"id": 20,
"name": "Ethernet0",
"port_number": 0
}
],
"properties": {
"acpi_shutdown": false,
"adapter_type": "e1000",
"adapters": 1,
"console": 2001,
"cpu_throttling": 0,
"hda_disk_image": "linux-microcore-3.4.1.img",
"legacy_networking": false,
"mac_address": "00:00:ab:6c:bc:00",
"name": "Microcore-1",
"options": "-nographic",
"process_priority": "normal",
"qemu_path": "/usr/local/bin/qemu-system-x86_64",
"ram": 256
},
"server_id": 1,
"type": "QemuVM",
"vm_id": "46d4334d-996c-4e9a-ad5a-81c4f5386cbc",
"x": -74.5,
"y": -169.5
}
],
"servers": [
{
"cloud": false,
"host": "127.0.0.1",
"id": 1,
"local": true,
"port": 8000,
"protocol": "http"
}
]
},
"type": "topology",
"version": "1.4.0.dev1"
}

View File

@@ -0,0 +1,97 @@
{
"auto_start": false,
"name": "untitled",
"project_id": "fe7ee04a-656d-462b-85b9-c6d3fe7a7420",
"resources_type": "local",
"revision": 4,
"topology": {
"links": [
{
"description": "Link from PC1 port Ethernet0 to PC2 port Ethernet0",
"destination_node_id": 2,
"destination_port_id": 2,
"id": 1,
"source_node_id": 1,
"source_port_id": 1
}
],
"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": 2001,
"name": "PC1",
"startup_script_path": "startup.vpc"
},
"server_id": 1,
"type": "VPCSDevice",
"vm_id": "120d95af-5181-4fe2-b9d1-e941e800461d",
"x": -124.5,
"y": -205.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": 2002,
"name": "PC2",
"startup_script_path": "startup.vpc"
},
"server_id": 1,
"type": "VPCSDevice",
"vm_id": "6a2ccbc4-3fec-4ad2-ab94-5b289ef9e733",
"x": 19.5,
"y": -116.5
}
],
"servers": [
{
"cloud": false,
"host": "127.0.0.1",
"id": 1,
"local": true,
"port": 8000,
"protocol": "http"
}
]
},
"type": "topology",
"version": "1.4.0.dev1"
}

View File

@@ -0,0 +1,60 @@
{
"auto_start": false,
"name": "untitled",
"project_id": "4a022469-be9f-44d2-be28-8a087b609ef8",
"resources_type": "local",
"revision": 4,
"topology": {
"nodes": [
{
"description": "VirtualBox VM",
"id": 1,
"label": {
"color": "#ff000000",
"font": "TypeWriter,10,-1,5,75,0,0,0,0,0",
"text": "Linux Microcore 4.7.1",
"x": -26.4921875,
"y": -25.0
},
"linked_clone": false,
"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": 2001,
"enable_remote_console": false,
"headless": false,
"name": "Linux Microcore 4.7.1",
"ram": 64,
"use_any_adapter": false,
"vmname": "Linux Microcore 4.7.1"
},
"server_id": 1,
"type": "VirtualBoxVM",
"vm_id": "c90c9d69-3ad1-44a5-894f-092b21c8bff2",
"x": -41.5,
"y": -152.5
}
],
"servers": [
{
"cloud": false,
"host": "127.0.0.1",
"id": 1,
"local": true,
"port": 8000,
"protocol": "http"
}
]
},
"type": "topology",
"version": "1.4.0.dev1"
}

View File

@@ -115,7 +115,7 @@ def test_randomize_id(project, tmpdir):
assert top["topology"]["nodes"][0]["vm_id"] != vm_uuid1
assert not os.path.exists(str(tmpdir / "project-files" / "vpcs" / vm_uuid1 / "test.log"))
assert os.path.exists(str(tmpdir / "project-files" / "vpcs" / top["topology"]["nodes"][0]["vm_id"] / "test.log"))
assert os.path.exists(str(tmpdir / "project-files" / "vpcs" / top["topology"]["nodes"][0]["vm_id"] / "test.log"))
assert top["topology"]["nodes"][1]["vm_id"] != vm_uuid2
assert top["topology"]["nodes"][0]["vm_id"] != top["topology"]["nodes"][1]["vm_id"]
@@ -177,7 +177,7 @@ def test_loadFile(tmpdir):
os.makedirs(str(tmpdir / "test"))
with open(topo, 'w+') as f:
f.write('{"name": "test", "resources_type": "local"}')
f.write('{"name": "test", "resources_type": "local", "type": "topology", "auto_start": false, "project_id": null, "topology": {}}')
with patch("gns3.topology.Topology._load") as mock:
project = Project()
@@ -185,7 +185,7 @@ def test_loadFile(tmpdir):
assert mock.called
args, kwargs = mock.call_args
assert args[0] == {"name": "test", "resources_type": "local"}
assert args[0] == {"name": "test", "resources_type": "local", "auto_start": False, "project_id": None, "topology": {}, "type": "topology"}
assert topology._project.filesDir() == str(tmpdir / "test")
assert topology._project.name() == "test"
assert topology._project.type() == "local"

View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2015 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 <http://www.gnu.org/licenses/>.
import pytest
import os
import json
from gns3.topology_check import getTopologyValidationErrors
schemas_directory = os.path.join(os.path.dirname(os.path.realpath(__file__)), "schemas")
@pytest.mark.parametrize("file", os.listdir(schemas_directory))
def test_load(file):
with open(os.path.join(schemas_directory, file)) as f:
topology = json.load(f)
errors = getTopologyValidationErrors(topology)
assert errors is None, errors
@pytest.mark.parametrize("file", os.listdir(schemas_directory))
def test_load_invalid(file):
with open(os.path.join(schemas_directory, file)) as f:
topology = json.load(f)
if len(topology["topology"].get("nodes", [])) > 0:
# Simulate an error
del topology["topology"]["nodes"][0]["properties"]["name"]
errors = getTopologyValidationErrors(topology)
assert errors is not None, errors