1
0
mirror of https://github.com/GNS3/gns3-server synced 2025-01-12 09:00:57 +00:00

New UDP and console port allocation system for IOU. Fixes duplicated

port issues.
This commit is contained in:
grossmj 2014-05-06 16:58:22 -06:00
parent 62da0a5ec2
commit 51c1f15853
3 changed files with 67 additions and 36 deletions

View File

@ -111,6 +111,12 @@ def main():
# (UNIX/Linux only) # (UNIX/Linux only)
locale_check() locale_check()
try:
os.getcwd()
except FileNotFoundError:
log.critical("the current working directory doesn't exist")
return
server = Server(options.host, server = Server(options.host,
options.port, options.port,
ipc=options.ipc) ipc=options.ipc)

View File

@ -91,11 +91,9 @@ class IOU(IModule):
self._iou_instances = {} self._iou_instances = {}
self._console_start_port_range = 4001 self._console_start_port_range = 4001
self._console_end_port_range = 4512 self._console_end_port_range = 4512
self._allocated_console_ports = [] self._allocated_udp_ports = []
self._current_console_port = self._console_start_port_range
self._udp_start_port_range = 30001 self._udp_start_port_range = 30001
self._udp_end_port_range = 40001 self._udp_end_port_range = 40001
self._current_udp_port = self._udp_start_port_range
self._host = kwargs["host"] self._host = kwargs["host"]
self._projects_dir = kwargs["projects_dir"] self._projects_dir = kwargs["projects_dir"]
self._tempdir = kwargs["temp_dir"] self._tempdir = kwargs["temp_dir"]
@ -179,9 +177,7 @@ class IOU(IModule):
IOUDevice.reset() IOUDevice.reset()
self._iou_instances.clear() self._iou_instances.clear()
self._remote_server = False self._allocated_udp_ports.clear()
self._current_console_port = self._console_start_port_range
self._current_udp_port = self._udp_start_port_range
if self._iourc and os.path.isfile(self._iourc): if self._iourc and os.path.isfile(self._iourc):
try: try:
@ -323,15 +319,13 @@ class IOU(IModule):
except OSError as e: except OSError as e:
raise IOUError("Could not create working directory {}".format(e)) raise IOUError("Could not create working directory {}".format(e))
iou_instance = IOUDevice(iou_path, self._working_dir, host=self._host, name=name) iou_instance = IOUDevice(iou_path,
# find a console port self._working_dir,
if self._current_console_port > self._console_end_port_range: self._host,
self._current_console_port = self._console_start_port_range name,
try: self._console_start_port_range,
iou_instance.console = find_unused_port(self._current_console_port, self._console_end_port_range, self._host) self._console_end_port_range)
except Exception as e:
raise IOUError(e)
self._current_console_port += 1
except IOUError as e: except IOUError as e:
self.send_custom_error(str(e)) self.send_custom_error(str(e))
return return
@ -557,26 +551,20 @@ class IOU(IModule):
return return
try: try:
port = find_unused_port(self._udp_start_port_range,
# find a UDP port self._udp_end_port_range,
if self._current_udp_port >= self._udp_end_port_range: host=self._host,
self._current_udp_port = self._udp_start_port_range socket_type="UDP",
try: ignore_ports=self._allocated_udp_ports)
port = find_unused_port(self._current_udp_port, self._udp_end_port_range, host=self._host, socket_type="UDP") except Exception as e:
except Exception as e:
raise IOUError(e)
self._current_udp_port += 1
log.info("{} [id={}] has allocated UDP port {} with host {}".format(iou_instance.name,
iou_instance.id,
port,
self._host))
response = {"lport": port}
except IOUError as e:
self.send_custom_error(str(e)) self.send_custom_error(str(e))
return
self._allocated_udp_ports.append(port)
log.info("{} [id={}] has allocated UDP port {} with host {}".format(iou_instance.name,
iou_instance.id,
port,
self._host))
response = {"lport": port}
response["port_id"] = request["port_id"] response["port_id"] = request["port_id"]
self.send_response(response) self.send_response(response)
@ -698,7 +686,9 @@ class IOU(IModule):
slot = request["slot"] slot = request["slot"]
port = request["port"] port = request["port"]
try: try:
iou_instance.slot_remove_nio_binding(slot, port) nio = iou_instance.slot_remove_nio_binding(slot, port)
if isinstance(nio, NIO_UDP) and nio.lport in self._allocated_udp_ports:
self._allocated_udp_ports.remove(nio.lport)
except IOUError as e: except IOUError as e:
self.send_custom_error(str(e)) self.send_custom_error(str(e))
return return

View File

@ -34,6 +34,7 @@ from .adapters.serial_adapter import SerialAdapter
from .nios.nio_udp import NIO_UDP from .nios.nio_udp import NIO_UDP
from .nios.nio_tap import NIO_TAP from .nios.nio_tap import NIO_TAP
from .nios.nio_generic_ethernet import NIO_GenericEthernet from .nios.nio_generic_ethernet import NIO_GenericEthernet
from ..attic import find_unused_port
import logging import logging
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -47,11 +48,19 @@ class IOUDevice(object):
:param working_dir: path to a working directory :param working_dir: path to a working directory
:param host: host/address to bind for console and UDP connections :param host: host/address to bind for console and UDP connections
:param name: name of this IOU device :param name: name of this IOU device
:param console_start_port_range: TCP console port range start
:param console_end_port_range: TCP console port range end
""" """
_instances = [] _instances = []
_allocated_console_ports = []
def __init__(self, path, working_dir, host="127.0.0.1", name=None): def __init__(self, path,
working_dir,
host="127.0.0.1",
name=None,
console_start_port_range=4001,
console_end_port_range=4512):
# find an instance identifier (0 < id <= 512) # find an instance identifier (0 < id <= 512)
self._id = 0 self._id = 0
@ -82,6 +91,8 @@ class IOUDevice(object):
self._ioucon_thread_stop_event = None self._ioucon_thread_stop_event = None
self._host = host self._host = host
self._started = False self._started = False
self._console_start_port_range = console_start_port_range
self._console_end_port_range = console_end_port_range
# IOU settings # IOU settings
self._ethernet_adapters = [EthernetAdapter(), EthernetAdapter()] # one adapter = 4 interfaces self._ethernet_adapters = [EthernetAdapter(), EthernetAdapter()] # one adapter = 4 interfaces
@ -94,6 +105,16 @@ class IOUDevice(object):
# update the working directory # update the working directory
self.working_dir = working_dir self.working_dir = working_dir
# allocate a console port
try:
self._console = find_unused_port(self._console_start_port_range,
self._console_end_port_range,
self._host,
ignore_ports=self._allocated_console_ports)
except Exception as e:
raise IOUError(e)
self._allocated_console_ports.append(self._console)
log.info("IOU device {name} [id={id}] has been created".format(name=self._name, log.info("IOU device {name} [id={id}] has been created".format(name=self._name,
id=self._id)) id=self._id))
@ -132,6 +153,7 @@ class IOUDevice(object):
""" """
cls._instances.clear() cls._instances.clear()
cls._allocated_console_ports.clear()
@property @property
def name(self): def name(self):
@ -275,7 +297,12 @@ class IOUDevice(object):
:param console: console port (integer) :param console: console port (integer)
""" """
if console in self._allocated_console_ports:
raise IOUError("Console port {} is already in used by another IOU device".format(console))
self._allocated_console_ports.remove(self._console)
self._console = console self._console = console
self._allocated_console_ports.append(self._console)
log.info("IOU {name} [id={id}]: console port set to {port}".format(name=self._name, log.info("IOU {name} [id={id}]: console port set to {port}".format(name=self._name,
id=self._id, id=self._id,
port=console)) port=console))
@ -296,6 +323,10 @@ class IOUDevice(object):
self.stop() self.stop()
self._instances.remove(self._id) self._instances.remove(self._id)
if self.console:
self._allocated_console_ports.remove(self.console)
log.info("IOU device {name} [id={id}] has been deleted".format(name=self._name, log.info("IOU device {name} [id={id}] has been deleted".format(name=self._name,
id=self._id)) id=self._id))
@ -376,7 +407,7 @@ class IOUDevice(object):
""" """
if not self._ioucon_thead: if not self._ioucon_thead:
telnet_server = "{}:{}".format(self._host, self._console) telnet_server = "{}:{}".format(self._host, self.console)
log.info("starting ioucon for IOU instance {} to accept Telnet connections on {}".format(self._name, telnet_server)) log.info("starting ioucon for IOU instance {} to accept Telnet connections on {}".format(self._name, telnet_server))
args = argparse.Namespace(appl_id=str(self._id), debug=False, escape='^^', telnet_limit=0, telnet_server=telnet_server) args = argparse.Namespace(appl_id=str(self._id), debug=False, escape='^^', telnet_limit=0, telnet_server=telnet_server)
self._ioucon_thread_stop_event = threading.Event() self._ioucon_thread_stop_event = threading.Event()
@ -611,6 +642,8 @@ class IOUDevice(object):
:param slot_id: slot ID :param slot_id: slot ID
:param port_id: port ID :param port_id: port ID
:returns: NIO instance
""" """
try: try:
@ -634,6 +667,8 @@ class IOUDevice(object):
self._update_iouyap_config() self._update_iouyap_config()
os.kill(self._iouyap_process.pid, signal.SIGHUP) os.kill(self._iouyap_process.pid, signal.SIGHUP)
return nio
def _build_command(self): def _build_command(self):
""" """
Command to start the IOU process. Command to start the IOU process.