From 2f0e2260ab69f9df42fd3823facecbd3e40ef9a5 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Tue, 13 Sep 2016 09:47:22 +0200 Subject: [PATCH] Move the generation of the list of ports to the server Ref #676 --- docs/index.rst | 1 + docs/port_name_format.rst | 38 ++ gns3server/compute/builtin/nodes/cloud.py | 16 +- gns3server/compute/builtin/nodes/nat.py | 2 +- .../compute/dynamips/nodes/ethernet_hub.py | 2 +- .../compute/dynamips/nodes/ethernet_switch.py | 11 +- gns3server/compute/qemu/qemu_vm.py | 27 -- .../compute/virtualbox/virtualbox_vm.py | 32 +- gns3server/compute/vmware/vmware_vm.py | 32 +- gns3server/controller/node.py | 72 ++- gns3server/controller/ports/__init__.py | 0 gns3server/controller/ports/atm_port.py | 65 +++ gns3server/controller/ports/ethernet_port.py | 50 ++ .../controller/ports/fastethernet_port.py | 45 ++ .../controller/ports/frame_relay_port.py | 45 ++ .../controller/ports/gigabitethernet_port.py | 45 ++ gns3server/controller/ports/port.py | 51 ++ gns3server/controller/ports/port_factory.py | 189 ++++++++ gns3server/controller/ports/pos_port.py | 66 +++ gns3server/controller/ports/serial_port.py | 67 +++ gns3server/controller/topology.py | 15 +- .../handlers/api/compute/cloud_handler.py | 2 +- .../api/compute/ethernet_hub_handler.py | 6 +- .../api/compute/ethernet_switch_handler.py | 6 +- .../handlers/api/compute/nat_handler.py | 2 +- gns3server/schemas/cloud.py | 6 +- gns3server/schemas/ethernet_hub.py | 6 +- gns3server/schemas/ethernet_switch.py | 4 +- gns3server/schemas/nat.py | 2 +- gns3server/schemas/node.py | 49 ++ gns3server/schemas/qemu.py | 44 +- gns3server/schemas/topology.py | 4 +- gns3server/schemas/virtualbox.py | 26 - gns3server/schemas/vmware.py | 26 - tests/compute/builtin/nodes/test_nat.py | 2 +- tests/controller/test_node.py | 20 +- tests/controller/test_node_port_name.py | 446 ++++++++++++++++++ .../1_3_dynamips/after/1_3_dynamips.gns3 | 3 + .../1_5_builtins/after/builtins.gns3 | 16 +- .../topologies/1_5_cloud/after/1_5_cloud.gns3 | 5 +- .../after/1_5_docker_remote.gns3 | 3 + .../1_5_dynamips/after/1_5_dynamips.gns3 | 6 + tests/topologies/1_5_host/after/1_5_host.gns3 | 5 +- .../1_5_internet/after/1_5_internet.gns3 | 6 + tests/topologies/1_5_iou/after/1_5_iou.gns3 | 3 + tests/topologies/1_5_qemu/after/testqemu.gns3 | 3 + .../1_5_snapshot/after/1_5_snapshot.gns3 | 3 + .../1_5_virtualbox/after/1_5_virtualbox.gns3 | 3 + .../1_5_vmware/after/1_5_vmware.gns3 | 3 + tests/topologies/1_5_vpcs/after/1_5_vpcs.gns3 | 6 + 50 files changed, 1347 insertions(+), 240 deletions(-) create mode 100644 docs/port_name_format.rst create mode 100644 gns3server/controller/ports/__init__.py create mode 100644 gns3server/controller/ports/atm_port.py create mode 100644 gns3server/controller/ports/ethernet_port.py create mode 100644 gns3server/controller/ports/fastethernet_port.py create mode 100644 gns3server/controller/ports/frame_relay_port.py create mode 100644 gns3server/controller/ports/gigabitethernet_port.py create mode 100644 gns3server/controller/ports/port.py create mode 100644 gns3server/controller/ports/port_factory.py create mode 100644 gns3server/controller/ports/pos_port.py create mode 100644 gns3server/controller/ports/serial_port.py create mode 100644 tests/controller/test_node_port_name.py diff --git a/docs/index.rst b/docs/index.rst index de821515..5dc420bb 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -30,4 +30,5 @@ GNS3 developements .. toctree:: development file_format + port_name_format diff --git a/docs/port_name_format.rst b/docs/port_name_format.rst new file mode 100644 index 00000000..6152ccd7 --- /dev/null +++ b/docs/port_name_format.rst @@ -0,0 +1,38 @@ +Port name formatting +#################### + +Some node like qemu allow you to personnalize the name of ports in order to match the name of the interfaces inside the emulator. + +Simple syntax +============== +The first {} will be replace by the interface number + +For example: "eth{}" will give: +* eth0 +* eth1 +* eth2 + +Or more verbose "eth{port0}" and "eth{0}" will do the same. + +Use segments +============ + +Segment allow you to split your interface in multiple ports + +For example "Ethernet{segment0}/{port0}" with a segment size of 3: +* Ethernet0/0 +* Ethernet0/1 +* Ethernet0/2 +* Ethernet1/0 +* Ethernet1/1 + +You can also change the start number. + +For example "Ethernet{segment1}/{port1}" with a segment size of 3: +* Ethernet1/1 +* Ethernet1/2 +* Ethernet1/3 +* Ethernet2/1 +* Ethernet2/2 + +This work from port0 to port9 if you need a bigger range ask us. diff --git a/gns3server/compute/builtin/nodes/cloud.py b/gns3server/compute/builtin/nodes/cloud.py index 1f6fa3e4..b3349999 100644 --- a/gns3server/compute/builtin/nodes/cloud.py +++ b/gns3server/compute/builtin/nodes/cloud.py @@ -45,9 +45,9 @@ class Cloud(BaseNode): super().__init__(name, node_id, project, manager) self._nios = {} - self._ports = [] + self._ports_mapping = [] if ports: - self._ports = ports + self._ports_mapping = ports def __json__(self): @@ -60,29 +60,29 @@ class Cloud(BaseNode): return {"name": self.name, "node_id": self.id, "project_id": self.project.id, - "ports": self._ports, + "ports_mapping": self._ports_mapping, "interfaces": host_interfaces, "status": "started"} @property - def ports(self): + def ports_mapping(self): """ Ports on this cloud. :returns: ports info """ - return self._ports + return self._ports_mapping - @ports.setter - def ports(self, ports): + @ports_mapping.setter + def ports_mapping(self, ports): """ Set the ports on this cloud. :param ports: ports info """ - self._ports = ports + self._ports_mapping = ports @asyncio.coroutine def create(self): diff --git a/gns3server/compute/builtin/nodes/nat.py b/gns3server/compute/builtin/nodes/nat.py index 40af0cd1..84e14597 100644 --- a/gns3server/compute/builtin/nodes/nat.py +++ b/gns3server/compute/builtin/nodes/nat.py @@ -53,5 +53,5 @@ class Nat(Cloud): "node_id": self.id, "project_id": self.project.id, "status": "started", - "ports": self.ports + "ports_mapping": self.ports } diff --git a/gns3server/compute/dynamips/nodes/ethernet_hub.py b/gns3server/compute/dynamips/nodes/ethernet_hub.py index 1e135926..e2377b50 100644 --- a/gns3server/compute/dynamips/nodes/ethernet_hub.py +++ b/gns3server/compute/dynamips/nodes/ethernet_hub.py @@ -60,7 +60,7 @@ class EthernetHub(Bridge): return {"name": self.name, "node_id": self.id, "project_id": self.project.id, - "ports": self._ports, + "ports_mapping": self._ports, "status": "started"} @property diff --git a/gns3server/compute/dynamips/nodes/ethernet_switch.py b/gns3server/compute/dynamips/nodes/ethernet_switch.py index 07f0e522..298d718e 100644 --- a/gns3server/compute/dynamips/nodes/ethernet_switch.py +++ b/gns3server/compute/dynamips/nodes/ethernet_switch.py @@ -65,17 +65,8 @@ class EthernetSwitch(Device): ethernet_switch_info = {"name": self.name, "node_id": self.id, "project_id": self.project.id, - "ports": self._ports, + "ports_mapping": self._ports, "status": "started"} - - # ports = [] - # for port_number, settings in self._mappings.items(): - # ports.append({"port": port_number, - # "type": settings[0], - # "vlan": settings[1], - # "ethertype": settings[2] if len(settings) > 2 else ""}) - # - # ethernet_switch_info["ports"] = ports return ethernet_switch_info @property diff --git a/gns3server/compute/qemu/qemu_vm.py b/gns3server/compute/qemu/qemu_vm.py index daad2a63..17cc6d82 100644 --- a/gns3server/compute/qemu/qemu_vm.py +++ b/gns3server/compute/qemu/qemu_vm.py @@ -114,9 +114,6 @@ class QemuVM(BaseNode): self._acpi_shutdown = False self._cpu_throttling = 0 # means no CPU throttling self._process_priority = "low" - self._first_port_name = "" - self._port_segment_size = 0 - self._port_name_format = "Ethernet{0}" self.mac_address = "" # this will generate a MAC address self.adapters = 1 # creates 1 adapter by default @@ -756,30 +753,6 @@ class QemuVM(BaseNode): kernel_command_line=kernel_command_line)) self._kernel_command_line = kernel_command_line - @property - def port_name_format(self): - return self._port_name_format - - @port_name_format.setter - def port_name_format(self, val): - self._port_name_format = val - - @property - def port_segment_size(self): - return self._port_segment_size - - @port_segment_size.setter - def port_segment_size(self, val): - self._port_segment_size = val - - @property - def first_port_name(self): - return self._first_port_name - - @first_port_name.setter - def first_port_name(self, val): - self._first_port_name = val - @asyncio.coroutine def _set_process_priority(self): """ diff --git a/gns3server/compute/virtualbox/virtualbox_vm.py b/gns3server/compute/virtualbox/virtualbox_vm.py index 86eefbe8..7f172362 100644 --- a/gns3server/compute/virtualbox/virtualbox_vm.py +++ b/gns3server/compute/virtualbox/virtualbox_vm.py @@ -71,9 +71,6 @@ class VirtualBoxVM(BaseNode): self._use_any_adapter = False self._ram = 0 self._adapter_type = "Intel PRO/1000 MT Desktop (82540EM)" - self._port_name_format = "Ethernet{0}" - self._port_segment_size = 0 - self._first_port_name = None def __json__(self): @@ -90,10 +87,7 @@ class VirtualBoxVM(BaseNode): "ram": self.ram, "status": self.status, "use_any_adapter": self.use_any_adapter, - "linked_clone": self._linked_clone, - "port_name_format": self._port_name_format, - "port_segment_size": self._port_segment_size, - "first_port_name": self._first_port_name} + "linked_clone": self._linked_clone} if self._linked_clone: json["node_directory"] = self.working_dir else: @@ -684,30 +678,6 @@ class VirtualBoxVM(BaseNode): id=self.id, adapter_type=adapter_type)) - @property - def port_name_format(self): - return self._port_name_format - - @port_name_format.setter - def port_name_format(self, val): - self._port_name_format = val - - @property - def port_segment_size(self): - return self._port_segment_size - - @port_segment_size.setter - def port_segment_size(self, val): - self._port_segment_size = val - - @property - def first_port_name(self): - return self._first_port_name - - @first_port_name.setter - def first_port_name(self, val): - self._first_port_name = val - @asyncio.coroutine def _get_vm_info(self): """ diff --git a/gns3server/compute/vmware/vmware_vm.py b/gns3server/compute/vmware/vmware_vm.py index 1e14a337..bddaefb8 100644 --- a/gns3server/compute/vmware/vmware_vm.py +++ b/gns3server/compute/vmware/vmware_vm.py @@ -70,9 +70,6 @@ class VMwareVM(BaseNode): self._ethernet_adapters = {} self._adapter_type = "e1000" self._use_any_adapter = False - self._port_name_format = "Ethernet{0}" - self._port_segment_size = 0 - self._first_port_name = None if not os.path.exists(vmx_path): raise VMwareError('VMware VM "{name}" [{id}]: could not find VMX file "{vmx_path}"'.format(name=name, id=node_id, vmx_path=vmx_path)) @@ -92,10 +89,7 @@ class VMwareVM(BaseNode): "use_any_adapter": self.use_any_adapter, "status": self.status, "node_directory": self.working_dir, - "linked_clone": self._linked_clone, - "port_name_format": self._port_name_format, - "port_segment_size": self._port_segment_size, - "first_port_name": self._first_port_name} + "linked_clone": self._linked_clone} return json @property @@ -738,30 +732,6 @@ class VMwareVM(BaseNode): log.info("VMware VM '{name}' [{id}] is not allowed to use any adapter".format(name=self.name, id=self.id)) self._use_any_adapter = use_any_adapter - @property - def port_name_format(self): - return self._port_name_format - - @port_name_format.setter - def port_name_format(self, val): - self._port_name_format = val - - @property - def port_segment_size(self): - return self._port_segment_size - - @port_segment_size.setter - def port_segment_size(self, val): - self._port_segment_size = val - - @property - def first_port_name(self): - return self._first_port_name - - @first_port_name.setter - def first_port_name(self, val): - self._first_port_name = val - @asyncio.coroutine def adapter_add_nio_binding(self, adapter_number, nio): """ diff --git a/gns3server/controller/node.py b/gns3server/controller/node.py index d4de8624..d05cf626 100644 --- a/gns3server/controller/node.py +++ b/gns3server/controller/node.py @@ -23,6 +23,7 @@ import os from .compute import ComputeConflict +from .ports.port_factory import PortFactory, StandardPortFactory, DynamipsPortFactory from ..utils.images import images_directories from ..utils.qt import qt_font_to_style @@ -33,7 +34,8 @@ 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", "width", "height", "symbol", "label", "console_host"] + CONTROLLER_ONLY_PROPERTIES = ["x", "y", "z", "width", "height", "symbol", "label", "console_host", + "port_name_format", "first_port_name", "port_segment_size", "ports"] def __init__(self, project, compute, name, node_id=None, node_type=None, **kwargs): """ @@ -69,12 +71,20 @@ class Node: self._y = 0 self._z = 0 self._symbol = None - - # Update node properties with additional elements + if node_type == "iou": + self._port_name_format = "Ethernet{segment0}/{port0}" + self._port_by_adapter = 4 + self.port_segment_size = 4 + else: + self._port_name_format = "Ethernet{0}" + self._port_by_adapter = 1 + self._port_segment_size = 0 + self._first_port_name = None # This properties will be recompute ignore_properties = ("width", "height") + # Update node properties with additional elements for prop in kwargs: if prop not in ignore_properties: try: @@ -220,6 +230,30 @@ class Node: val["text"] = self._name self._label = val + @property + def port_name_format(self): + return self._port_name_format + + @port_name_format.setter + def port_name_format(self, val): + self._port_name_format = val + + @property + def port_segment_size(self): + return self._port_segment_size + + @port_segment_size.setter + def port_segment_size(self, val): + self._port_segment_size = val + + @property + def first_port_name(self): + return self._first_port_name + + @first_port_name.setter + def first_port_name(self, val): + self._first_port_name = val + @asyncio.coroutine def create(self): """ @@ -423,6 +457,27 @@ class Node: """ return (yield from self._compute.get("/projects/{}/{}/nodes/{}/idlepc_proposals".format(self._project.id, self._node_type, self._id), timeout=240)).json + def _list_ports(self): + """ + Generate the list of port display in the client + if the compute has sent a list we return it (use by + node where you can not personnalize the port naming). + """ + ports = [] + # Some special cases + if self._node_type == "atm_switch": + for adapter_number in range(0, len(self.properties["mappings"])): + ports.append(PortFactory("ATM{}".format(adapter_number), adapter_number, adapter_number, 0, "atm")) + return ports + elif self._node_type == "frame_relay_switch": + for adapter_number in range(0, len(self.properties["mappings"])): + ports.append(PortFactory("FrameRelay{}".format(adapter_number), adapter_number, adapter_number, 0, "frame_relay")) + return ports + elif self._node_type == "dynamips": + return DynamipsPortFactory(self.properties) + else: + return StandardPortFactory(self.properties, self._port_by_adapter, self._first_port_name, self._port_name_format, self._port_segment_size) + def __repr__(self): return "".format(self._node_type, self._name) @@ -450,7 +505,10 @@ class Node: "z": self._z, "width": self._width, "height": self._height, - "symbol": self._symbol + "symbol": self._symbol, + "port_name_format": self._port_name_format, + "port_segment_size": self._port_segment_size, + "first_port_name": self._first_port_name } return { "compute_id": str(self._compute.id), @@ -471,5 +529,9 @@ class Node: "z": self._z, "width": self._width, "height": self._height, - "symbol": self._symbol + "symbol": self._symbol, + "port_name_format": self._port_name_format, + "port_segment_size": self._port_segment_size, + "first_port_name": self._first_port_name, + "ports": [port.__json__() for port in self._list_ports()] } diff --git a/gns3server/controller/ports/__init__.py b/gns3server/controller/ports/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/gns3server/controller/ports/atm_port.py b/gns3server/controller/ports/atm_port.py new file mode 100644 index 00000000..fcdd03a8 --- /dev/null +++ b/gns3server/controller/ports/atm_port.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2014 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 . + +""" +ATM port for ATM link end points. +""" + +from .port import Port + + +class ATMPort(Port): + + @staticmethod + def longNameType(): + """ + Returns the long name type for this port. + + :returns: string + """ + + return "ATM" + + @staticmethod + def shortNameType(): + """ + Returns the short name type for this port. + + :returns: string + """ + + return "a" + + @staticmethod + def linkType(): + """ + Returns the link type to be used to connect this port. + + :returns: string + """ + + return "Serial" + + @staticmethod + def dataLinkTypes(): + """ + Returns the supported PCAP DLTs. + + :return: dictionary + """ + + return {"ATM": "DLT_ATM_RFC1483"} diff --git a/gns3server/controller/ports/ethernet_port.py b/gns3server/controller/ports/ethernet_port.py new file mode 100644 index 00000000..20740a3e --- /dev/null +++ b/gns3server/controller/ports/ethernet_port.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2014 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 . + +""" +Ethernet port for Ethernet link end points. +""" + + +from .port import Port + + +class EthernetPort(Port): + + """ + Ethernet port. + """ + + @staticmethod + def longNameType(): + """ + Returns the long name type for this port. + + :returns: string + """ + + return "Ethernet" + + @staticmethod + def shortNameType(): + """ + Returns the short name type for this port. + + :returns: string + """ + + return "e" diff --git a/gns3server/controller/ports/fastethernet_port.py b/gns3server/controller/ports/fastethernet_port.py new file mode 100644 index 00000000..82be8541 --- /dev/null +++ b/gns3server/controller/ports/fastethernet_port.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2014 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 . + +""" +FastEthernet port for Ethernet link end points. +""" + +from .port import Port + + +class FastEthernetPort(Port): + + @staticmethod + def longNameType(): + """ + Returns the long name type for this port. + + :returns: string + """ + + return "FastEthernet" + + @staticmethod + def shortNameType(): + """ + Returns the short name type for this port. + + :returns: string + """ + + return "f" diff --git a/gns3server/controller/ports/frame_relay_port.py b/gns3server/controller/ports/frame_relay_port.py new file mode 100644 index 00000000..b6b5b28b --- /dev/null +++ b/gns3server/controller/ports/frame_relay_port.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2014 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 . + +""" +Frame relay port for serial link end points. +""" + +from .serial_port import SerialPort + + +class FrameRelayPort(SerialPort): + + @staticmethod + def longNameType(): + """ + Returns the long name type for this port. + + :returns: string + """ + + return "FrameRelay" + + @staticmethod + def dataLinkTypes(): + """ + Returns the supported PCAP DLTs. + + :return: dictionary + """ + + return {"Frame Relay": "DLT_FRELAY"} diff --git a/gns3server/controller/ports/gigabitethernet_port.py b/gns3server/controller/ports/gigabitethernet_port.py new file mode 100644 index 00000000..3dd6df5c --- /dev/null +++ b/gns3server/controller/ports/gigabitethernet_port.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2014 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 . + +""" +GigabitEthernet port for Ethernet link end points. +""" + +from .port import Port + + +class GigabitEthernetPort(Port): + + @staticmethod + def longNameType(): + """ + Returns the long name type for this port. + + :returns: string + """ + + return "GigabitEthernet" + + @staticmethod + def shortNameType(): + """ + Returns the short name type for this port. + + :returns: string + """ + + return "g" diff --git a/gns3server/controller/ports/port.py b/gns3server/controller/ports/port.py new file mode 100644 index 00000000..e0f40aa8 --- /dev/null +++ b/gns3server/controller/ports/port.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2014 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 . + + +class Port: + """ + Base class for port objects. + """ + + def __init__(self, name, interface_number, adapter_number, port_number): + self._interface_number = interface_number + self._adapter_number = adapter_number + self._port_number = port_number + self._name = name + + @staticmethod + def dataLinkTypes(): + """ + Returns the supported PCAP DLTs. + + :return: dictionary + """ + return {"Ethernet": "DLT_EN10MB"} + + @staticmethod + def linkType(): + return "Ethernet" + + def __json__(self): + return { + "name": self._name, + "short_name": self.shortNameType() + "{}/{}".format(self._interface_number, self._port_number), + "data_link_types": self.dataLinkTypes(), + "port_number": self._port_number, + "adapter_number": self._adapter_number, + "link_type": self.linkType().lower() + } diff --git a/gns3server/controller/ports/port_factory.py b/gns3server/controller/ports/port_factory.py new file mode 100644 index 00000000..58c1c01e --- /dev/null +++ b/gns3server/controller/ports/port_factory.py @@ -0,0 +1,189 @@ +#!/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 . + +from .atm_port import ATMPort +from .frame_relay_port import FrameRelayPort +from .gigabitethernet_port import GigabitEthernetPort +from .fastethernet_port import FastEthernetPort +from .ethernet_port import EthernetPort +from .serial_port import SerialPort +from .pos_port import POSPort + +import logging +log = logging.getLogger(__name__) + +PORTS = { + 'atm': ATMPort, + 'frame_relay': FrameRelayPort, + 'fastethernet': FastEthernetPort, + 'gigabitethernet': GigabitEthernetPort, + 'ethernet': EthernetPort, + 'serial': SerialPort +} + + +class PortFactory: + """ + Factory to create an Port object based on the type + """ + + def __new__(cls, name, interface_number, adapter_number, port_number, port_type, **kwargs): + return PORTS[port_type](name, interface_number, adapter_number, port_number, **kwargs) + + +class StandardPortFactory: + """ + Create ports for standard device + """ + def __new__(cls, properties, port_by_adapter, first_port_name, port_name_format, port_segment_size): + ports = [] + interface_number = segment_number = 0 + if "serial_adapters" in properties: + for adapter_number in range(0, properties["serial_adapters"]): + for port_number in range(0, port_by_adapter): + ports.append(PortFactory("Serial{}/{}".format(adapter_number, port_number), adapter_number, adapter_number, port_number, "serial")) + + if "ethernet_adapters" in properties: + ethernet_adapters = properties["ethernet_adapters"] + else: + ethernet_adapters = properties.get("adapters", 1) + + for adapter_number in range(0, ethernet_adapters): + for port_number in range(0, port_by_adapter): + if first_port_name and adapter_number == 0: + port_name = first_port_name + else: + port_name = port_name_format.format( + interface_number, + segment_number, + adapter=adapter_number, + **cls._generate_replacement(interface_number, segment_number)) + interface_number += 1 + if port_segment_size and interface_number % port_segment_size == 0: + segment_number += 1 + interface_number = 0 + + ports.append(PortFactory(port_name, adapter_number, adapter_number, port_number, "ethernet")) + return ports + + @staticmethod + def _generate_replacement(interface_number, segment_number): + """ + This will generate replacement string for + {port0} => {port9} + {segment0} => {segment9} + """ + replacements = {} + for i in range(0, 9): + replacements["port" + str(i)] = interface_number + i + replacements["segment" + str(i)] = segment_number + i + return replacements + + +class DynamipsPortFactory: + """ + Create port for dynamips devices + """ + ADAPTER_MATRIX = { + "C1700-MB-1FE": {"nb_ports": 1, + "port": FastEthernetPort}, + "C1700-MB-WIC1": {"nb_ports": 0, + "port": None}, + "C2600-MB-1E": {"nb_ports": 1, + "port": EthernetPort}, + "C2600-MB-1FE": {"nb_ports": 1, + "port": FastEthernetPort}, + "C2600-MB-2E": {"nb_ports": 2, + "port": EthernetPort}, + "C2600-MB-2FE": {"nb_ports": 2, + "port": FastEthernetPort}, + "C7200-IO-2FE": {"nb_ports": 2, + "port": FastEthernetPort}, + "C7200-IO-FE": {"nb_ports": 1, + "port": FastEthernetPort}, + "C7200-IO-GE-E": {"nb_ports": 1, + "port": GigabitEthernetPort}, + "GT96100-FE": {"nb_ports": 2, + "port": FastEthernetPort}, + "Leopard-2FE": {"nb_ports": 2, + "port": FastEthernetPort}, + "NM-16ESW": {"nb_ports": 16, + "port": FastEthernetPort}, + "NM-1E": {"nb_ports": 1, + "port": EthernetPort}, + "NM-1FE-TX": {"nb_ports": 1, + "port": FastEthernetPort}, + "NM-4E": {"nb_ports": 4, + "port": EthernetPort}, + "NM-4T": {"nb_ports": 4, + "port": SerialPort}, + "PA-2FE-TX": {"nb_ports": 2, + "port": FastEthernetPort}, + "PA-4E": {"nb_ports": 4, + "port": EthernetPort}, + "PA-4T+": {"nb_ports": 4, + "port": SerialPort}, + "PA-8E": {"nb_ports": 8, + "port": EthernetPort}, + "PA-8T": {"nb_ports": 8, + "port": SerialPort}, + "PA-A1": {"nb_ports": 1, + "port": ATMPort}, + "PA-FE-TX": {"nb_ports": 1, + "port": FastEthernetPort}, + "PA-GE": {"nb_ports": 1, + "port": GigabitEthernetPort}, + "PA-POS-OC3": {"nb_ports": 1, + "port": POSPort}, + } + + WIC_MATRIX = {"WIC-1ENET": {"nb_ports": 1, + "port": EthernetPort}, + + "WIC-1T": {"nb_ports": 1, + "port": SerialPort}, + + "WIC-2T": {"nb_ports": 2, + "port": SerialPort} + } + + def __new__(cls, properties): + ports = [] + + interface_numbers = {} + + adapter_number = 0 + wic_port_number = 16 + for name in sorted(properties.keys()): + if name.startswith("slot") and properties[name]: + port_class = cls.ADAPTER_MATRIX[properties[name]]["port"] + if port_class: + interface_numbers.setdefault(port_class, 0) + interface_number = interface_numbers[port_class] + for port_number in range(0, cls.ADAPTER_MATRIX[properties[name]]["nb_ports"]): + name = "{}{}/{}".format(port_class.longNameType(), interface_number, port_number) + ports.append(port_class(name, interface_number, adapter_number, port_number)) + interface_numbers[port_class] += 1 + adapter_number += 1 + elif name.startswith("wic") and properties[name]: + port_class = cls.WIC_MATRIX[properties[name]]["port"] + if port_class: + for port_number in range(0, cls.WIC_MATRIX[properties[name]]["nb_ports"]): + name = "{}{}/{}".format(port_class.longNameType(), 0, wic_port_number) + ports.append(port_class(name, 0, 0, wic_port_number)) + wic_port_number += 1 + return ports diff --git a/gns3server/controller/ports/pos_port.py b/gns3server/controller/ports/pos_port.py new file mode 100644 index 00000000..aca3e29a --- /dev/null +++ b/gns3server/controller/ports/pos_port.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2014 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 . + +""" +POS port for Packet over SONET link end points. +""" + +from .port import Port + + +class POSPort(Port): + + @staticmethod + def longNameType(): + """ + Returns the long name type for this port. + + :returns: string + """ + + return "POS" + + @staticmethod + def shortNameType(): + """ + Returns the short name type for this port. + + :returns: string + """ + + return "p" + + @staticmethod + def linkType(): + """ + Returns the link type to be used to connect this port. + + :returns: string + """ + + return "Serial" + + @staticmethod + def dataLinkTypes(): + """ + Returns the supported PCAP DLTs. + + :return: dictionary + """ + + # Packet capture on PoS is not supported + return {} diff --git a/gns3server/controller/ports/serial_port.py b/gns3server/controller/ports/serial_port.py new file mode 100644 index 00000000..980f3574 --- /dev/null +++ b/gns3server/controller/ports/serial_port.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2014 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 . + +""" +Serial port for serial link end points. +""" + +from .port import Port + + +class SerialPort(Port): + + @staticmethod + def longNameType(): + """ + Returns the long name type for this port. + + :returns: string + """ + + return "Serial" + + @staticmethod + def shortNameType(): + """ + Returns the short name type for this port. + + :returns: string + """ + + return "s" + + @staticmethod + def linkType(): + """ + Returns the link type to be used to connect this port. + + :returns: string + """ + + return "Serial" + + @staticmethod + def dataLinkTypes(): + """ + Returns the supported PCAP DLTs. + + :return: dictionary + """ + + return {"Frame Relay": "DLT_FRELAY", + "Cisco HDLC": "DLT_C_HDLC", + "Cisco PPP": "DLT_PPP_SERIAL"} diff --git a/gns3server/controller/topology.py b/gns3server/controller/topology.py index e3700985..ae156289 100644 --- a/gns3server/controller/topology.py +++ b/gns3server/controller/topology.py @@ -179,6 +179,9 @@ def _convert_1_3_later(topo, topo_path): node["x"] = int(old_node["x"]) node["y"] = int(old_node["y"]) node["z"] = int(old_node.get("z", 1)) + node["port_name_format"] = old_node.get("port_name_format", "Ethernet{0}") + node["port_segment_size"] = int(old_node.get("port_segment_size", "0")) + node["first_port_name"] = old_node.get("first_port_name") node["properties"] = {} @@ -196,21 +199,21 @@ def _convert_1_3_later(topo, topo_path): 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"] = [] + node["symbol"] = ":/symbols/hub.svg" + node["properties"]["ports_mapping"] = [] for port in old_node["ports"]: - node["properties"]["ports"].append({ + node["properties"]["ports_mapping"].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 + node["properties"]["ports_mapping"] = [] for port in old_node["ports"]: - node["properties"]["ports"].append({ + node["properties"]["ports_mapping"].append({ "name": "Ethernet{}".format(port["port_number"]), "port_number": port["port_number"], "type": port["type"], @@ -439,7 +442,7 @@ def _create_cloud(node, old_node, icon): } ports.append(port) - node["properties"]["ports"] = ports + node["properties"]["ports_mapping"] = ports node["properties"]["interfaces"] = [] diff --git a/gns3server/handlers/api/compute/cloud_handler.py b/gns3server/handlers/api/compute/cloud_handler.py index 07fe515e..ea0f1ec9 100644 --- a/gns3server/handlers/api/compute/cloud_handler.py +++ b/gns3server/handlers/api/compute/cloud_handler.py @@ -55,7 +55,7 @@ class CloudHandler: request.match_info["project_id"], request.json.get("node_id"), node_type="cloud", - ports=request.json.get("ports")) + ports=request.json.get("ports_mapping")) response.set_status(201) response.json(node) diff --git a/gns3server/handlers/api/compute/ethernet_hub_handler.py b/gns3server/handlers/api/compute/ethernet_hub_handler.py index b5fb63c1..1123a50d 100644 --- a/gns3server/handlers/api/compute/ethernet_hub_handler.py +++ b/gns3server/handlers/api/compute/ethernet_hub_handler.py @@ -57,7 +57,7 @@ class EthernetHubHandler: request.match_info["project_id"], request.json.get("node_id"), device_type="ethernet_hub", - ports=request.json.get("ports")) + ports=request.json.get("ports_mapping")) # On Linux, use the generic hub # builtin_manager = Builtin.instance() @@ -112,8 +112,8 @@ class EthernetHubHandler: node = dynamips_manager.get_device(request.match_info["node_id"], project_id=request.match_info["project_id"]) if "name" in request.json and node.name != request.json["name"]: yield from node.set_name(request.json["name"]) - if "ports" in request.json: - node.ports = request.json["ports"] + if "ports_mapping" in request.json: + node.ports_mapping = request.json["ports_mapping"] # builtin_manager = Builtin.instance() # node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) diff --git a/gns3server/handlers/api/compute/ethernet_switch_handler.py b/gns3server/handlers/api/compute/ethernet_switch_handler.py index 1b79ce72..f8396a1d 100644 --- a/gns3server/handlers/api/compute/ethernet_switch_handler.py +++ b/gns3server/handlers/api/compute/ethernet_switch_handler.py @@ -57,7 +57,7 @@ class EthernetSwitchHandler: request.match_info["project_id"], request.json.get("node_id"), device_type="ethernet_switch", - ports=request.json.get("ports")) + ports=request.json.get("ports_mapping")) # On Linux, use the generic switch # builtin_manager = Builtin.instance() @@ -112,8 +112,8 @@ class EthernetSwitchHandler: node = dynamips_manager.get_device(request.match_info["node_id"], project_id=request.match_info["project_id"]) if "name" in request.json and node.name != request.json["name"]: yield from node.set_name(request.json["name"]) - if "ports" in request.json: - node.ports = request.json["ports"] + if "ports_mapping" in request.json: + node.ports_mapping = request.json["ports_mapping"] # builtin_manager = Builtin.instance() # node = builtin_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"]) diff --git a/gns3server/handlers/api/compute/nat_handler.py b/gns3server/handlers/api/compute/nat_handler.py index df62930f..3e190ffa 100644 --- a/gns3server/handlers/api/compute/nat_handler.py +++ b/gns3server/handlers/api/compute/nat_handler.py @@ -55,7 +55,7 @@ class NatHandler: request.match_info["project_id"], request.json.get("node_id"), node_type="nat", - ports=request.json.get("ports")) + ports=request.json.get("ports_mapping")) response.set_status(201) response.json(node) diff --git a/gns3server/schemas/cloud.py b/gns3server/schemas/cloud.py index 70a5bb43..16978cb3 100644 --- a/gns3server/schemas/cloud.py +++ b/gns3server/schemas/cloud.py @@ -56,7 +56,7 @@ CLOUD_CREATE_SCHEMA = { "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}$"} ] }, - "ports": { + "ports_mapping": { "type": "array", "items": [ PORT_OBJECT_SCHEMA @@ -103,7 +103,7 @@ CLOUD_OBJECT_SCHEMA = { "maxLength": 36, "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}$" }, - "ports": { + "ports_mapping": { "type": "array", "items": [ PORT_OBJECT_SCHEMA @@ -124,7 +124,7 @@ CLOUD_OBJECT_SCHEMA = { }, }, "additionalProperties": False, - "required": ["name", "node_id", "project_id", "ports"] + "required": ["name", "node_id", "project_id", "ports_mapping"] } CLOUD_UPDATE_SCHEMA = CLOUD_OBJECT_SCHEMA diff --git a/gns3server/schemas/ethernet_hub.py b/gns3server/schemas/ethernet_hub.py index 5f0ac71b..52534ae7 100644 --- a/gns3server/schemas/ethernet_hub.py +++ b/gns3server/schemas/ethernet_hub.py @@ -54,7 +54,7 @@ ETHERNET_HUB_CREATE_SCHEMA = { "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}$"} ] }, - "ports": { + "ports_mapping": { "type": "array", "items": [ {"type": "object", @@ -111,7 +111,7 @@ ETHERNET_HUB_OBJECT_SCHEMA = { "maxLength": 36, "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}$" }, - "ports": { + "ports_mapping": { "type": "array", "items": [ {"type": "object", @@ -126,7 +126,7 @@ ETHERNET_HUB_OBJECT_SCHEMA = { }, }, "additionalProperties": False, - "required": ["name", "node_id", "project_id", "ports"] + "required": ["name", "node_id", "project_id", "ports_mapping"] } ETHERNET_HUB_UPDATE_SCHEMA = ETHERNET_HUB_OBJECT_SCHEMA diff --git a/gns3server/schemas/ethernet_switch.py b/gns3server/schemas/ethernet_switch.py index 83554749..6de9caa3 100644 --- a/gns3server/schemas/ethernet_switch.py +++ b/gns3server/schemas/ethernet_switch.py @@ -66,7 +66,7 @@ ETHERNET_SWITCH_CREATE_SCHEMA = { "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}$"} ] }, - "ports": { + "ports_mapping": { "type": "array", "items": [ {"type": "object", @@ -135,7 +135,7 @@ ETHERNET_SWITCH_OBJECT_SCHEMA = { "maxLength": 36, "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}$" }, - "ports": { + "ports_mapping": { "type": "array", "items": [ {"type": "object", diff --git a/gns3server/schemas/nat.py b/gns3server/schemas/nat.py index 1651c04c..b2de1cde 100644 --- a/gns3server/schemas/nat.py +++ b/gns3server/schemas/nat.py @@ -46,7 +46,7 @@ NAT_OBJECT_SCHEMA = { "description": "Node status", "enum": ["started", "stopped", "suspended"] }, - "ports": { + "ports_mapping": { "type": "array", "items": [ PORT_OBJECT_SCHEMA diff --git a/gns3server/schemas/node.py b/gns3server/schemas/node.py index 32b1e657..0536091b 100644 --- a/gns3server/schemas/node.py +++ b/gns3server/schemas/node.py @@ -168,6 +168,55 @@ NODE_OBJECT_SCHEMA = { "z": { "description": "Z position of the node", "type": "integer" + }, + "port_name_format": { + "description": "Formating for port name {0} will be replace by port number", + "type": "string" + }, + "port_segment_size": { + "description": "Size of the port segment", + "type": "integer", + "minimum": 0 + }, + "first_port_name": { + "description": "Name of the first port", + "type": ["string", "null"], + }, + "ports": { + "description": "List of node ports READ only", + "type": "array", + "items": { + "type": "object", + "description": "A node port", + "properties": { + "name": { + "type": "string", + "description": "Port name", + }, + "short_name": { + "type": "string", + "description": "Short version of port name", + }, + "adapter_number": { + "type": "integer", + "description": "Adapter slot" + }, + "port_number": { + "type": "integer", + "description": "Port slot" + }, + "link_type": { + "description": "Type of link", + "enum": ["ethernet", "serial"] + }, + "data_link_types": { + "type": "object", + "description": "Available PCAP type for capture", + "properties": {} + }, + }, + "additionalProperties": False + } } }, "additionalProperties": False, diff --git a/gns3server/schemas/qemu.py b/gns3server/schemas/qemu.py index 19ab9d92..2623dbf6 100644 --- a/gns3server/schemas/qemu.py +++ b/gns3server/schemas/qemu.py @@ -199,19 +199,6 @@ QEMU_CREATE_SCHEMA = { "options": { "description": "Additional QEMU options", "type": ["string", "null"], - }, - "port_name_format": { - "description": "Formating for port name {0} will be replace by port number", - "type": "string" - }, - "port_segment_size": { - "description": "Size of the port segment", - "type": "integer", - "minimum": 0 - }, - "first_port_name": { - "description": "Name of the first port", - "type": ["string", "null"], } }, "additionalProperties": False, @@ -389,19 +376,6 @@ QEMU_UPDATE_SCHEMA = { "options": { "description": "Additional QEMU options", "type": ["string", "null"], - }, - "port_name_format": { - "description": "Formating for port name {0} will be replace by port number", - "type": "string" - }, - "port_segment_size": { - "description": "Size of the port segment", - "type": "integer", - "minimum": 0 - }, - "first_port_name": { - "description": "Name of the first port", - "type": ["string", "null"], } }, "additionalProperties": False, @@ -595,19 +569,6 @@ QEMU_OBJECT_SCHEMA = { "command_line": { "description": "Last command line used by GNS3 to start QEMU", "type": "string" - }, - "port_name_format": { - "description": "Formating for port name {0} will be replace by port number", - "type": "string" - }, - "port_segment_size": { - "description": "Size of the port segment", - "type": "integer", - "minimum": 0 - }, - "first_port_name": { - "description": "Name of the first port", - "type": "string", } }, "additionalProperties": False, @@ -651,10 +612,7 @@ QEMU_OBJECT_SCHEMA = { "options", "node_directory", "command_line", - "status", - "port_name_format", - "first_port_name", - "port_segment_size"] + "status"] } QEMU_BINARY_FILTER_SCHEMA = { diff --git a/gns3server/schemas/topology.py b/gns3server/schemas/topology.py index db13b111..43c5acee 100644 --- a/gns3server/schemas/topology.py +++ b/gns3server/schemas/topology.py @@ -103,10 +103,12 @@ TOPOLOGY_SCHEMA = { def main(): import jsonschema + import json import sys with open(sys.argv[1]) as f: - jsonschema.validate(f.read(), TOPOLOGY_SCHEMA) + data = json.load(f) + jsonschema.validate(data, TOPOLOGY_SCHEMA) if __name__ == '__main__': diff --git a/gns3server/schemas/virtualbox.py b/gns3server/schemas/virtualbox.py index 4f326ec3..e6d7cea4 100644 --- a/gns3server/schemas/virtualbox.py +++ b/gns3server/schemas/virtualbox.py @@ -83,19 +83,6 @@ VBOX_CREATE_SCHEMA = { "acpi_shutdown": { "description": "ACPI shutdown", "type": "boolean" - }, - "port_name_format": { - "description": "Formating for port name {0} will be replace by port number", - "type": "string" - }, - "port_segment_size": { - "description": "Size of the port segment", - "type": "integer", - "minimum": 0 - }, - "first_port_name": { - "description": "Name of the first port", - "type": ["string", "null"] } }, "additionalProperties": False, @@ -182,19 +169,6 @@ VBOX_OBJECT_SCHEMA = { "linked_clone": { "description": "Whether the VM is a linked clone or not", "type": "boolean" - }, - "port_name_format": { - "description": "Formating for port name {0} will be replace by port number", - "type": "string" - }, - "port_segment_size": { - "description": "Size of the port segment", - "type": "integer", - "minimum": 0 - }, - "first_port_name": { - "description": "Name of the first port", - "type": ["string", "null"] } }, "additionalProperties": False, diff --git a/gns3server/schemas/vmware.py b/gns3server/schemas/vmware.py index d071303f..27fb7a4e 100644 --- a/gns3server/schemas/vmware.py +++ b/gns3server/schemas/vmware.py @@ -74,19 +74,6 @@ VMWARE_CREATE_SCHEMA = { "use_any_adapter": { "description": "Allow GNS3 to use any VMware adapter", "type": "boolean", - }, - "port_name_format": { - "description": "Formating for port name {0} will be replace by port number", - "type": "string" - }, - "port_segment_size": { - "description": "Size of the port segment", - "type": "integer", - "minimum": 0 - }, - "first_port_name": { - "description": "Name of the first port", - "type": ["string", "null"] } }, "additionalProperties": False, @@ -167,19 +154,6 @@ VMWARE_OBJECT_SCHEMA = { "linked_clone": { "description": "Whether the VM is a linked clone or not", "type": "boolean" - }, - "port_name_format": { - "description": "Formating for port name {0} will be replace by port number", - "type": "string" - }, - "port_segment_size": { - "description": "Size of the port segment", - "type": "integer", - "minimum": 0 - }, - "first_port_name": { - "description": "Name of the first port", - "type": ["string", "null"] } }, "additionalProperties": False diff --git a/tests/compute/builtin/nodes/test_nat.py b/tests/compute/builtin/nodes/test_nat.py index aa221f51..2c90127b 100644 --- a/tests/compute/builtin/nodes/test_nat.py +++ b/tests/compute/builtin/nodes/test_nat.py @@ -29,7 +29,7 @@ def test_json(on_gns3vm, project): "node_id": nat.id, "project_id": project.id, "status": "started", - "ports": [ + "ports_mapping": [ { "interface": "virbr0", "name": "virbr0", diff --git a/tests/controller/test_node.py b/tests/controller/test_node.py index edb7887d..4141ad9d 100644 --- a/tests/controller/test_node.py +++ b/tests/controller/test_node.py @@ -101,7 +101,20 @@ def test_json(node, compute): "width": node.width, "height": node.height, "symbol": node.symbol, - "label": node.label + "label": node.label, + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": None, + "ports": [ + { + "adapter_number": 0, + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "link_type": "ethernet", + "name": "Ethernet0", + "port_number": 0, + "short_name": "e0/0" + } + ] } assert node.__json__(topology_dump=True) == { "compute_id": str(compute.id), @@ -117,7 +130,10 @@ def test_json(node, compute): "width": node.width, "height": node.height, "symbol": node.symbol, - "label": node.label + "label": node.label, + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": None } diff --git a/tests/controller/test_node_port_name.py b/tests/controller/test_node_port_name.py new file mode 100644 index 00000000..ec43f85a --- /dev/null +++ b/tests/controller/test_node_port_name.py @@ -0,0 +1,446 @@ +#!/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 . + +import pytest +import uuid + +from tests.utils import AsyncioMagicMock + +from gns3server.controller.node import Node +from gns3server.controller.project import Project + + +@pytest.fixture +def compute(): + s = AsyncioMagicMock() + s.id = "http://test.com:42" + return s + + +@pytest.fixture +def project(controller): + return Project(str(uuid.uuid4()), controller=controller) + + +@pytest.fixture +def node(compute, project): + node = Node(project, compute, "demo", + node_id=str(uuid.uuid4()), + node_type="vpcs", + console_type="vnc", + properties={"startup_script": "echo test"}) + return node + + +def test_list_ports(node): + """ + List port by default + """ + assert node.__json__()["ports"] == [ + { + "name": "Ethernet0", + "short_name": "e0/0", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 0, + "adapter_number": 0, + "link_type": "ethernet" + } + ] + + +def test_list_ports_port_name_format(node): + """ + Support port name format + """ + node._first_port_name = None + node._port_name_format = "eth{}" + assert node.__json__()["ports"][0]["name"] == "eth0" + node._port_name_format = "eth{port0}" + assert node.__json__()["ports"][0]["name"] == "eth0" + node._port_name_format = "eth{port1}" + assert node.__json__()["ports"][0]["name"] == "eth1" + + node._first_port_name = "" + node._port_segment_size = 2 + node._port_name_format = "eth{segment0}/{port0}" + node.properties["adapters"] = 8 + assert node.__json__()["ports"][6]["name"] == "eth3/0" + assert node.__json__()["ports"][7]["name"] == "eth3/1" + + node._first_port_name = "mgnt0" + assert node.__json__()["ports"][0]["name"] == "mgnt0" + assert node.__json__()["ports"][1]["name"] == "eth0/0" + + +def test_list_ports_adapters(node): + """ + List port using adapters properties + """ + node.properties["adapters"] = 2 + assert node.__json__()["ports"] == [ + { + "name": "Ethernet0", + "short_name": "e0/0", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 0, + "adapter_number": 0, + "link_type": "ethernet" + }, + { + "name": "Ethernet1", + "short_name": "e1/0", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 0, + "adapter_number": 1, + "link_type": "ethernet" + } + ] + + +def test_list_ports_atm_switch(project, compute): + """ + List port for atm switch + """ + node = Node(project, compute, "demo", + node_id=str(uuid.uuid4()), + node_type="atm_switch") + node.properties["mappings"] = { + "1:0:100": "10:0:200" + } + + assert node.__json__()["ports"] == [ + { + "name": "ATM0", + "short_name": "a0/0", + "data_link_types": {"ATM": "DLT_ATM_RFC1483"}, + "port_number": 0, + "adapter_number": 0, + "link_type": "serial" + } + ] + + +def test_list_ports_frame_relay_switch(project, compute): + """ + List port for frame relay switch + """ + node = Node(project, compute, "demo", + node_id=str(uuid.uuid4()), + node_type="frame_relay_switch") + node.properties["mappings"] = { + "1:0:100": "10:0:200" + } + + assert node.__json__()["ports"] == [ + { + "name": "FrameRelay0", + "short_name": "s0/0", + "data_link_types": {"Frame Relay": "DLT_FRELAY"}, + "port_number": 0, + "adapter_number": 0, + "link_type": "serial" + } + ] + + +def test_list_ports_iou(compute, project): + """ + IOU has a special behavior 4 port by adapters + """ + node = Node(project, compute, "demo", + node_id=str(uuid.uuid4()), + node_type="iou") + node.properties["serial_adapters"] = 2 + node.properties["ethernet_adapters"] = 3 + assert node.__json__()["ports"] == [ + { + "name": "Serial0/0", + "short_name": "s0/0", + "data_link_types": { + "Frame Relay": "DLT_FRELAY", + "Cisco HDLC": "DLT_C_HDLC", + "Cisco PPP": "DLT_PPP_SERIAL" + }, + "port_number": 0, + "adapter_number": 0, + "link_type": "serial" + }, + { + "name": "Serial0/1", + "short_name": "s0/1", + "data_link_types": { + "Frame Relay": "DLT_FRELAY", + "Cisco HDLC": "DLT_C_HDLC", + "Cisco PPP": "DLT_PPP_SERIAL" + }, + "port_number": 1, + "adapter_number": 0, + "link_type": "serial" + }, + { + "name": "Serial0/2", + "short_name": "s0/2", + "data_link_types": { + "Frame Relay": "DLT_FRELAY", + "Cisco HDLC": "DLT_C_HDLC", + "Cisco PPP": "DLT_PPP_SERIAL" + }, + "port_number": 2, + "adapter_number": 0, + "link_type": "serial" + }, + { + "name": "Serial0/3", + "short_name": "s0/3", + "data_link_types": { + "Frame Relay": "DLT_FRELAY", + "Cisco HDLC": "DLT_C_HDLC", + "Cisco PPP": "DLT_PPP_SERIAL" + }, + "port_number": 3, + "adapter_number": 0, + "link_type": "serial" + }, + { + "name": "Serial1/0", + "short_name": "s1/0", + "data_link_types": { + "Frame Relay": "DLT_FRELAY", + "Cisco HDLC": "DLT_C_HDLC", + "Cisco PPP": "DLT_PPP_SERIAL" + }, + "port_number": 0, + "adapter_number": 1, + "link_type": "serial" + }, + { + "name": "Serial1/1", + "short_name": "s1/1", + "data_link_types": { + "Frame Relay": "DLT_FRELAY", + "Cisco HDLC": "DLT_C_HDLC", + "Cisco PPP": "DLT_PPP_SERIAL" + }, + "port_number": 1, + "adapter_number": 1, + "link_type": "serial" + }, + { + "name": "Serial1/2", + "short_name": "s1/2", + "data_link_types": { + "Frame Relay": "DLT_FRELAY", + "Cisco HDLC": "DLT_C_HDLC", + "Cisco PPP": "DLT_PPP_SERIAL" + }, + "port_number": 2, + "adapter_number": 1, + "link_type": "serial" + }, + { + "name": "Serial1/3", + "short_name": "s1/3", + "data_link_types": { + "Frame Relay": "DLT_FRELAY", + "Cisco HDLC": "DLT_C_HDLC", + "Cisco PPP": "DLT_PPP_SERIAL" + }, + "port_number": 3, + "adapter_number": 1, + "link_type": "serial" + }, + { + "name": "Ethernet0/0", + "short_name": "e0/0", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 0, + "adapter_number": 0, + "link_type": "ethernet" + }, + { + "name": "Ethernet0/1", + "short_name": "e0/1", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 1, + "adapter_number": 0, + "link_type": "ethernet" + }, + { + "name": "Ethernet0/2", + "short_name": "e0/2", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 2, + "adapter_number": 0, + "link_type": "ethernet" + }, + { + "name": "Ethernet0/3", + "short_name": "e0/3", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 3, + "adapter_number": 0, + "link_type": "ethernet" + }, + { + "name": "Ethernet1/0", + "short_name": "e1/0", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 0, + "adapter_number": 1, + "link_type": "ethernet" + }, + { + "name": "Ethernet1/1", + "short_name": "e1/1", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 1, + "adapter_number": 1, + "link_type": "ethernet" + }, + { + "name": "Ethernet1/2", + "short_name": "e1/2", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 2, + "adapter_number": 1, + "link_type": "ethernet" + }, + { + "name": "Ethernet1/3", + "short_name": "e1/3", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 3, + "adapter_number": 1, + "link_type": "ethernet" + }, + { + "name": "Ethernet2/0", + "short_name": "e2/0", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 0, + "adapter_number": 2, + "link_type": "ethernet" + }, + { + "name": "Ethernet2/1", + "short_name": "e2/1", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 1, + "adapter_number": 2, + "link_type": "ethernet" + }, + { + "name": "Ethernet2/2", + "short_name": "e2/2", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 2, + "adapter_number": 2, + "link_type": "ethernet" + }, + { + "name": "Ethernet2/3", + "short_name": "e2/3", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 3, + "adapter_number": 2, + "link_type": "ethernet" + } + ] + + +def test_list_ports_dynamips(project, compute): + """ + List port for dynamips + """ + node = Node(project, compute, "demo", + node_id=str(uuid.uuid4()), + node_type="dynamips") + node.properties["slot0"] = "C7200-IO-FE" + node.properties["slot1"] = "GT96100-FE" + node.properties["wic0"] = "WIC-2T" + node.properties["wic1"] = "WIC-2T" + + assert node.__json__()["ports"] == [ + { + "name": "FastEthernet0/0", + "short_name": "f0/0", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 0, + "adapter_number": 0, + "link_type": "ethernet" + }, + { + "name": "FastEthernet1/0", + "short_name": "f1/0", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 0, + "adapter_number": 1, + "link_type": "ethernet" + }, + { + "name": "FastEthernet1/1", + "short_name": "f1/1", + "data_link_types": {"Ethernet": "DLT_EN10MB"}, + "port_number": 1, + "adapter_number": 1, + "link_type": "ethernet" + }, + { + "name": "Serial0/16", + "short_name": "s0/16", + "data_link_types": { + "Cisco HDLC": "DLT_C_HDLC", + "Cisco PPP": "DLT_PPP_SERIAL", + "Frame Relay": "DLT_FRELAY"}, + "port_number": 16, + "adapter_number": 0, + "link_type": "serial" + }, + { + "name": "Serial0/17", + "short_name": "s0/17", + "data_link_types": { + "Cisco HDLC": "DLT_C_HDLC", + "Cisco PPP": "DLT_PPP_SERIAL", + "Frame Relay": "DLT_FRELAY"}, + "port_number": 17, + "adapter_number": 0, + "link_type": "serial" + }, + { + "name": "Serial0/18", + "short_name": "s0/18", + "data_link_types": { + "Cisco HDLC": "DLT_C_HDLC", + "Cisco PPP": "DLT_PPP_SERIAL", + "Frame Relay": "DLT_FRELAY"}, + "port_number": 18, + "adapter_number": 0, + "link_type": "serial" + }, + { + "name": "Serial0/19", + "short_name": "s0/19", + "data_link_types": { + "Cisco HDLC": "DLT_C_HDLC", + "Cisco PPP": "DLT_PPP_SERIAL", + "Frame Relay": "DLT_FRELAY"}, + "port_number": 19, + "adapter_number": 0, + "link_type": "serial" + } + ] diff --git a/tests/topologies/1_3_dynamips/after/1_3_dynamips.gns3 b/tests/topologies/1_3_dynamips/after/1_3_dynamips.gns3 index 9877b830..81491cfb 100644 --- a/tests/topologies/1_3_dynamips/after/1_3_dynamips.gns3 +++ b/tests/topologies/1_3_dynamips/after/1_3_dynamips.gns3 @@ -31,6 +31,9 @@ "name": "R1", "node_id": "0bce6ad5-c688-4d4d-a425-f21aaf3927e2", "node_type": "dynamips", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "dynamips_id": 1, "auto_delete_disks": true, diff --git a/tests/topologies/1_5_builtins/after/builtins.gns3 b/tests/topologies/1_5_builtins/after/builtins.gns3 index e132337c..0c0c5f22 100644 --- a/tests/topologies/1_5_builtins/after/builtins.gns3 +++ b/tests/topologies/1_5_builtins/after/builtins.gns3 @@ -30,6 +30,9 @@ "name": "ATM1", "node_id": "ANYUUID", "node_type": "atm_switch", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "mappings": { "1:0:100": "10:0:200" @@ -54,8 +57,11 @@ "name": "HUB1", "node_id": "ANYUUID", "node_type": "ethernet_hub", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { - "ports": [ + "ports_mapping": [ { "name": "Ethernet1", "port_number": 1 @@ -109,8 +115,11 @@ "name": "SW1", "node_id": "ANYUUID", "node_type": "ethernet_switch", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { - "ports": [ + "ports_mapping": [ { "name": "Ethernet1", "port_number": 1, @@ -180,6 +189,9 @@ "name": "FR1", "node_id": "ANYUUID", "node_type": "frame_relay_switch", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "mappings": { "1:101": "10:202" diff --git a/tests/topologies/1_5_cloud/after/1_5_cloud.gns3 b/tests/topologies/1_5_cloud/after/1_5_cloud.gns3 index 990ac9fb..c91a1eee 100644 --- a/tests/topologies/1_5_cloud/after/1_5_cloud.gns3 +++ b/tests/topologies/1_5_cloud/after/1_5_cloud.gns3 @@ -30,10 +30,13 @@ "name": "Cloud 1", "node_id": "ANYUUID", "node_type": "cloud", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "interfaces": [ ], - "ports": [ + "ports_mapping": [ { "interface": "bridge0", "name": "bridge0", 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 index c99f0c1d..d23d8a79 100644 --- 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 @@ -30,6 +30,9 @@ "name": "remote_busybox-1", "node_id": "d397ef5a-84f1-4b6b-9d44-671937ec7781", "node_type": "docker", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "adapters": 1, "aux": 6002, diff --git a/tests/topologies/1_5_dynamips/after/1_5_dynamips.gns3 b/tests/topologies/1_5_dynamips/after/1_5_dynamips.gns3 index abf4dad5..71e7d637 100644 --- a/tests/topologies/1_5_dynamips/after/1_5_dynamips.gns3 +++ b/tests/topologies/1_5_dynamips/after/1_5_dynamips.gns3 @@ -30,6 +30,9 @@ "name": "R1", "node_id": "11845dea-f175-495b-9fc5-bf20a2262016", "node_type": "dynamips", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "auto_delete_disks": true, "clock_divisor": 8, @@ -72,6 +75,9 @@ "name": "ESW1", "node_id": "4478a968-72a1-4722-9039-db7561c717c4", "node_type": "dynamips", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "auto_delete_disks": false, "chassis": "3660", diff --git a/tests/topologies/1_5_host/after/1_5_host.gns3 b/tests/topologies/1_5_host/after/1_5_host.gns3 index 5e2c72eb..fd7ee311 100644 --- a/tests/topologies/1_5_host/after/1_5_host.gns3 +++ b/tests/topologies/1_5_host/after/1_5_host.gns3 @@ -30,10 +30,13 @@ "name": "Host 1", "node_id": "ANYUUID", "node_type": "cloud", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "interfaces": [ ], - "ports": [ + "ports_mapping": [ {"interface": "bridge0", "port_number": 1, "type": "ethernet", "name": "bridge0"}, {"interface": "en0", "port_number": 2, "type": "ethernet", "name": "en0"}, {"interface": "en1", "port_number": 3, "type": "ethernet", "name": "en1"}, diff --git a/tests/topologies/1_5_internet/after/1_5_internet.gns3 b/tests/topologies/1_5_internet/after/1_5_internet.gns3 index c88fc18c..2d5c7b40 100644 --- a/tests/topologies/1_5_internet/after/1_5_internet.gns3 +++ b/tests/topologies/1_5_internet/after/1_5_internet.gns3 @@ -40,6 +40,9 @@ "name": "Internet 0.1-1", "node_id": "b8bef484-89d2-42a7-b151-6ead2eda965e", "node_type": "nat", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "ports": [ { @@ -69,6 +72,9 @@ "name": "PC1", "node_id": "761c5e9e-eded-45b5-b6db-ca367b1855e2", "node_type": "vpcs", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "startup_script_path": "startup.vpc" }, diff --git a/tests/topologies/1_5_iou/after/1_5_iou.gns3 b/tests/topologies/1_5_iou/after/1_5_iou.gns3 index 03971fde..d99786ac 100644 --- a/tests/topologies/1_5_iou/after/1_5_iou.gns3 +++ b/tests/topologies/1_5_iou/after/1_5_iou.gns3 @@ -30,6 +30,9 @@ "name": "IOU1", "node_id": "aaeb2288-a7d8-42a9-b9d8-c42ab464a390", "node_type": "iou", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "ethernet_adapters": 2, "l1_keepalives": false, diff --git a/tests/topologies/1_5_qemu/after/testqemu.gns3 b/tests/topologies/1_5_qemu/after/testqemu.gns3 index dff790e4..6c527615 100644 --- a/tests/topologies/1_5_qemu/after/testqemu.gns3 +++ b/tests/topologies/1_5_qemu/after/testqemu.gns3 @@ -30,6 +30,9 @@ "name": "MicroCore-1", "node_id": "426face4-7f73-436b-88fa-050e3ee101e9", "node_type": "qemu", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "acpi_shutdown": false, "adapter_type": "e1000", diff --git a/tests/topologies/1_5_snapshot/after/1_5_snapshot.gns3 b/tests/topologies/1_5_snapshot/after/1_5_snapshot.gns3 index dd611145..87124df0 100644 --- a/tests/topologies/1_5_snapshot/after/1_5_snapshot.gns3 +++ b/tests/topologies/1_5_snapshot/after/1_5_snapshot.gns3 @@ -14,6 +14,9 @@ "name" : "PC1", "symbol" : ":/symbols/vpcs_guest.svg", "console_type" : "telnet", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties" : { "startup_script_path" : "startup.vpc" }, diff --git a/tests/topologies/1_5_virtualbox/after/1_5_virtualbox.gns3 b/tests/topologies/1_5_virtualbox/after/1_5_virtualbox.gns3 index 640b70cc..1647677a 100644 --- a/tests/topologies/1_5_virtualbox/after/1_5_virtualbox.gns3 +++ b/tests/topologies/1_5_virtualbox/after/1_5_virtualbox.gns3 @@ -30,6 +30,9 @@ "name": "debian", "node_id": "af5fa728-85da-44f1-b17a-e99a65a7037e", "node_type": "virtualbox", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "acpi_shutdown": false, "adapter_type": "Intel PRO/1000 MT Desktop (82540EM)", diff --git a/tests/topologies/1_5_vmware/after/1_5_vmware.gns3 b/tests/topologies/1_5_vmware/after/1_5_vmware.gns3 index 4ca0e7c6..6e7bfd69 100644 --- a/tests/topologies/1_5_vmware/after/1_5_vmware.gns3 +++ b/tests/topologies/1_5_vmware/after/1_5_vmware.gns3 @@ -30,6 +30,9 @@ "name": "GNS3 VM", "node_id": "9e06d0ce-e8df-4f38-bdfa-7c83e19a91c1", "node_type": "vmware", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "acpi_shutdown": false, "adapter_type": "e1000", diff --git a/tests/topologies/1_5_vpcs/after/1_5_vpcs.gns3 b/tests/topologies/1_5_vpcs/after/1_5_vpcs.gns3 index 3a26ee51..98b19857 100644 --- a/tests/topologies/1_5_vpcs/after/1_5_vpcs.gns3 +++ b/tests/topologies/1_5_vpcs/after/1_5_vpcs.gns3 @@ -46,6 +46,9 @@ "name": "PC1", "node_id": "0fd3dd4d-dc93-4a04-a9b9-7396a9e22e8b", "node_type": "vpcs", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "startup_script_path": "startup.vpc" }, @@ -68,6 +71,9 @@ "name": "PC2", "node_id": "b570a150-c09f-47d9-8d32-9ca5b03234d6", "node_type": "vpcs", + "port_name_format": "Ethernet{0}", + "port_segment_size": 0, + "first_port_name": null, "properties": { "startup_script_path": "startup.vpc" },