From 557924e91a6fb8b0a82da4bacb8d577a70736922 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Mon, 10 Jul 2017 20:38:28 +0200 Subject: [PATCH 1/2] Use ubridge for dynamips routers Ref #1109 --- gns3server/compute/base_node.py | 6 ++- gns3server/compute/dynamips/__init__.py | 2 +- gns3server/compute/dynamips/nios/nio_udp.py | 44 ++++++++++++++++--- .../compute/dynamips/nodes/atm_switch.py | 4 +- .../compute/dynamips/nodes/ethernet_hub.py | 4 +- .../compute/dynamips/nodes/ethernet_switch.py | 4 +- .../dynamips/nodes/frame_relay_switch.py | 4 +- gns3server/compute/dynamips/nodes/router.py | 6 ++- gns3server/compute/qemu/qemu_vm.py | 4 +- .../compute/virtualbox/virtualbox_vm.py | 4 +- gns3server/compute/vpcs/vpcs_vm.py | 4 +- 11 files changed, 62 insertions(+), 24 deletions(-) diff --git a/gns3server/compute/base_node.py b/gns3server/compute/base_node.py index 47640cf6..c80d5bea 100644 --- a/gns3server/compute/base_node.py +++ b/gns3server/compute/base_node.py @@ -475,7 +475,7 @@ class BaseNode: """ Returns the uBridge hypervisor. - :returns: path to uBridge + :returns: instance of uBridge """ if self._ubridge_hypervisor and not self._ubridge_hypervisor.is_running(): @@ -512,6 +512,8 @@ class BaseNode: :param command: command to send """ + if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running(): + yield from self._start_ubridge() if not self._ubridge_hypervisor or not self._ubridge_hypervisor.is_running(): raise NodeError("Cannot send command '{}': uBridge is not running".format(command)) try: @@ -557,7 +559,7 @@ class BaseNode: self._ubridge_hypervisor = None @asyncio.coroutine - def _add_ubridge_udp_connection(self, bridge_name, source_nio, destination_nio): + def add_ubridge_udp_connection(self, bridge_name, source_nio, destination_nio): """ Creates an UDP connection in uBridge. diff --git a/gns3server/compute/dynamips/__init__.py b/gns3server/compute/dynamips/__init__.py index 6d6bafda..50d3cb8d 100644 --- a/gns3server/compute/dynamips/__init__.py +++ b/gns3server/compute/dynamips/__init__.py @@ -351,7 +351,7 @@ class Dynamips(BaseManager): sock.connect(sa) except OSError as e: raise DynamipsError("Could not create an UDP connection to {}:{}: {}".format(rhost, rport, e)) - nio = NIOUDP(node.hypervisor, lport, rhost, rport) + nio = NIOUDP(node, lport, rhost, rport, nio_settings.get("filters", {})) elif nio_settings["type"] == "nio_generic_ethernet": ethernet_device = nio_settings["ethernet_device"] if sys.platform.startswith("win"): diff --git a/gns3server/compute/dynamips/nios/nio_udp.py b/gns3server/compute/dynamips/nios/nio_udp.py index 5b459771..2e0833c3 100644 --- a/gns3server/compute/dynamips/nios/nio_udp.py +++ b/gns3server/compute/dynamips/nios/nio_udp.py @@ -21,8 +21,11 @@ Interface for UDP NIOs. import asyncio import uuid + +from gns3server.compute.nios import nio_udp from .nio import NIO + import logging log = logging.getLogger(__name__) @@ -38,28 +41,59 @@ class NIOUDP(NIO): :param rport: remote port number """ - def __init__(self, hypervisor, lport, rhost, rport): + def __init__(self, node, lport, rhost, rport, filters): # create an unique name name = 'udp-{}'.format(uuid.uuid4()) self._lport = lport self._rhost = rhost self._rport = rport - super().__init__(name, hypervisor) + self._filters = filters + self._local_tunnel_lport = None + self._node = node + super().__init__(name, node.hypervisor) @asyncio.coroutine def create(self): if not self._hypervisor: return + # Ubridge is not supported + if not hasattr(self._node, "add_ubridge_udp_connection"): + yield from self._hypervisor.send("nio create_udp {name} {lport} {rhost} {rport}".format(name=self._name, + lport=self._lport, + rhost=self._rhost, + rport=self._rport)) + return + self._local_tunnel_lport = self._node.manager.port_manager.get_free_udp_port(self._node.project) + self._local_tunnel_rport = self._node.manager.port_manager.get_free_udp_port(self._node.project) + name = 'DYNAMIPS-{}-{}'.format(self._local_tunnel_lport, self._local_tunnel_rport) yield from self._hypervisor.send("nio create_udp {name} {lport} {rhost} {rport}".format(name=self._name, - lport=self._lport, - rhost=self._rhost, - rport=self._rport)) + lport=self._local_tunnel_lport, + rhost='127.0.0.1', + rport=self._local_tunnel_rport)) log.info("NIO UDP {name} created with lport={lport}, rhost={rhost}, rport={rport}".format(name=self._name, lport=self._lport, rhost=self._rhost, rport=self._rport)) + yield from self._node.add_ubridge_udp_connection( + name, + nio_udp.NIOUDP(self._local_tunnel_rport, + '127.0.0.1', + self._local_tunnel_lport, + self._filters), + nio_udp.NIOUDP(self._lport, + self._rhost, + self._rport, + self._filters) + ) + + @asyncio.coroutine + def close(self): + if self._local_tunnel_lport: + self._node.manager.port_manager.release_udp_port(self._local_tunnel_lport, self ._node.project) + self._node.manager.port_manager.release_udp_port(self._local_tunnel_rport, self._node.project) + self._node.manager.port_manager.release_udp_port(self._lport, self._node.project) @property def lport(self): diff --git a/gns3server/compute/dynamips/nodes/atm_switch.py b/gns3server/compute/dynamips/nodes/atm_switch.py index deda2c29..38cac774 100644 --- a/gns3server/compute/dynamips/nodes/atm_switch.py +++ b/gns3server/compute/dynamips/nodes/atm_switch.py @@ -122,8 +122,8 @@ class ATMSwitch(Device): @asyncio.coroutine def close(self): for nio in self._nios.values(): - if nio and isinstance(nio, NIOUDP): - self.manager.port_manager.release_udp_port(nio.lport, self._project) + if nio: + yield from nio.close() if self._hypervisor: try: diff --git a/gns3server/compute/dynamips/nodes/ethernet_hub.py b/gns3server/compute/dynamips/nodes/ethernet_hub.py index 969ce307..c481a8ab 100644 --- a/gns3server/compute/dynamips/nodes/ethernet_hub.py +++ b/gns3server/compute/dynamips/nodes/ethernet_hub.py @@ -120,8 +120,8 @@ class EthernetHub(Bridge): """ for nio in self._nios: - if nio and isinstance(nio, NIOUDP): - self.manager.port_manager.release_udp_port(nio.lport, self._project) + if nio: + yield from nio.close() try: yield from Bridge.delete(self) diff --git a/gns3server/compute/dynamips/nodes/ethernet_switch.py b/gns3server/compute/dynamips/nodes/ethernet_switch.py index bf4f7f7c..d45088f1 100644 --- a/gns3server/compute/dynamips/nodes/ethernet_switch.py +++ b/gns3server/compute/dynamips/nodes/ethernet_switch.py @@ -216,8 +216,8 @@ class EthernetSwitch(Device): """ for nio in self._nios.values(): - if nio and isinstance(nio, NIOUDP): - self.manager.port_manager.release_udp_port(nio.lport, self._project) + if nio: + yield from nio.close() self.manager.port_manager.release_tcp_port(self._console, self._project) if self._hypervisor: try: diff --git a/gns3server/compute/dynamips/nodes/frame_relay_switch.py b/gns3server/compute/dynamips/nodes/frame_relay_switch.py index 9bb3e357..c6dac00e 100644 --- a/gns3server/compute/dynamips/nodes/frame_relay_switch.py +++ b/gns3server/compute/dynamips/nodes/frame_relay_switch.py @@ -121,8 +121,8 @@ class FrameRelaySwitch(Device): @asyncio.coroutine def close(self): for nio in self._nios.values(): - if nio and isinstance(nio, NIOUDP): - self.manager.port_manager.release_udp_port(nio.lport, self._project) + if nio: + yield from nio.close() if self._hypervisor: try: diff --git a/gns3server/compute/dynamips/nodes/router.py b/gns3server/compute/dynamips/nodes/router.py index d6315df0..f0a87a1b 100644 --- a/gns3server/compute/dynamips/nodes/router.py +++ b/gns3server/compute/dynamips/nodes/router.py @@ -388,8 +388,10 @@ class Router(BaseNode): for adapter in self._slots: if adapter is not None: for nio in adapter.ports.values(): - if nio and isinstance(nio, NIOUDP): - self.manager.port_manager.release_udp_port(nio.lport, self._project) + if nio: + yield from nio.close() + + yield from self._stop_ubridge() if self in self._hypervisor.devices: self._hypervisor.devices.remove(self) diff --git a/gns3server/compute/qemu/qemu_vm.py b/gns3server/compute/qemu/qemu_vm.py index f820ae13..136929a6 100644 --- a/gns3server/compute/qemu/qemu_vm.py +++ b/gns3server/compute/qemu/qemu_vm.py @@ -912,7 +912,7 @@ class QemuVM(BaseNode): for adapter_number, adapter in enumerate(self._ethernet_adapters): nio = adapter.get_nio(0) if nio: - yield from self._add_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number), + yield from self.add_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number), self._local_udp_tunnels[adapter_number][1], nio) @@ -1133,7 +1133,7 @@ class QemuVM(BaseNode): if self.ubridge: try: - yield from self._add_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number), + yield from self.add_ubridge_udp_connection("QEMU-{}-{}".format(self._id, adapter_number), self._local_udp_tunnels[adapter_number][1], nio) except IndexError: diff --git a/gns3server/compute/virtualbox/virtualbox_vm.py b/gns3server/compute/virtualbox/virtualbox_vm.py index 6f13b8d6..f4dcd829 100644 --- a/gns3server/compute/virtualbox/virtualbox_vm.py +++ b/gns3server/compute/virtualbox/virtualbox_vm.py @@ -285,7 +285,7 @@ class VirtualBoxVM(BaseNode): for adapter_number in range(0, self._adapters): nio = self._ethernet_adapters[adapter_number].get_nio(0) if nio: - yield from self._add_ubridge_udp_connection("VBOX-{}-{}".format(self._id, adapter_number), + yield from self.add_ubridge_udp_connection("VBOX-{}-{}".format(self._id, adapter_number), self._local_udp_tunnels[adapter_number][1], nio) @@ -974,7 +974,7 @@ class VirtualBoxVM(BaseNode): if self.ubridge: try: - yield from self._add_ubridge_udp_connection("VBOX-{}-{}".format(self._id, adapter_number), + yield from self.add_ubridge_udp_connection("VBOX-{}-{}".format(self._id, adapter_number), self._local_udp_tunnels[adapter_number][1], nio) except KeyError: diff --git a/gns3server/compute/vpcs/vpcs_vm.py b/gns3server/compute/vpcs/vpcs_vm.py index 8de816aa..f37f397c 100644 --- a/gns3server/compute/vpcs/vpcs_vm.py +++ b/gns3server/compute/vpcs/vpcs_vm.py @@ -264,7 +264,7 @@ class VPCSVM(BaseNode): if self.use_ubridge: yield from self._start_ubridge() if nio: - yield from self._add_ubridge_udp_connection("VPCS-{}".format(self._id), self._local_udp_tunnel[1], nio) + yield from self.add_ubridge_udp_connection("VPCS-{}".format(self._id), self._local_udp_tunnel[1], nio) yield from self.start_wrap_console() @@ -379,7 +379,7 @@ class VPCSVM(BaseNode): port_number=port_number)) if self.ubridge: - yield from self._add_ubridge_udp_connection("VPCS-{}".format(self._id), self._local_udp_tunnel[1], nio) + yield from self.add_ubridge_udp_connection("VPCS-{}".format(self._id), self._local_udp_tunnel[1], nio) elif self.is_running(): raise VPCSError("Sorry, updating a link to a started VPCS instance is not supported without using uBridge.") From 5112f6fe56d31198da140fff50b4eabb0b6b1eb6 Mon Sep 17 00:00:00 2001 From: grossmj Date: Tue, 11 Jul 2017 12:36:43 +0700 Subject: [PATCH 2/2] Small changes for Dynamips NIO UDP. --- gns3server/compute/dynamips/nios/nio_udp.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gns3server/compute/dynamips/nios/nio_udp.py b/gns3server/compute/dynamips/nios/nio_udp.py index 2e0833c3..106e3836 100644 --- a/gns3server/compute/dynamips/nios/nio_udp.py +++ b/gns3server/compute/dynamips/nios/nio_udp.py @@ -50,6 +50,7 @@ class NIOUDP(NIO): self._rport = rport self._filters = filters self._local_tunnel_lport = None + self._local_tunnel_rport = None self._node = node super().__init__(name, node.hypervisor) @@ -92,6 +93,7 @@ class NIOUDP(NIO): def close(self): if self._local_tunnel_lport: self._node.manager.port_manager.release_udp_port(self._local_tunnel_lport, self ._node.project) + if self._local_tunnel_rport: self._node.manager.port_manager.release_udp_port(self._local_tunnel_rport, self._node.project) self._node.manager.port_manager.release_udp_port(self._lport, self._node.project)