1
0
mirror of https://github.com/GNS3/gns3-server synced 2024-12-01 04:38:12 +00:00

Improve remote server console host support when binding to 0.0.0.0

Fix https://github.com/GNS3/gns3-gui/issues/1574
This commit is contained in:
Julien Duponchelle 2016-10-26 14:43:47 +02:00
parent afb7eca27a
commit eabe4eb97e
No known key found for this signature in database
GPG Key ID: CE8B29639E07F5E8
8 changed files with 55 additions and 31 deletions

View File

@ -16,7 +16,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import socket import socket
import ipaddress
from aiohttp.web import HTTPConflict from aiohttp.web import HTTPConflict
from gns3server.config import Config from gns3server.config import Config
@ -37,10 +36,8 @@ class PortManager:
:param host: IP address to bind for console connections :param host: IP address to bind for console connections
""" """
def __init__(self, host="127.0.0.1"): def __init__(self):
self._console_host = None
self._console_host = host
# UDP host must be 0.0.0.0, reason: https://github.com/GNS3/gns3-server/issues/265 # UDP host must be 0.0.0.0, reason: https://github.com/GNS3/gns3-server/issues/265
self._udp_host = "0.0.0.0" self._udp_host = "0.0.0.0"
self._used_tcp_ports = set() self._used_tcp_ports = set()
@ -59,17 +56,6 @@ class PortManager:
self._udp_port_range = (udp_start_port_range, udp_end_port_range) self._udp_port_range = (udp_start_port_range, udp_end_port_range)
log.debug("UDP port range is {}-{}".format(udp_start_port_range, udp_end_port_range)) log.debug("UDP port range is {}-{}".format(udp_start_port_range, udp_end_port_range))
if remote_console_connections:
log.warning("Remote console connections are allowed")
if ipaddress.ip_address(host).version == 6:
self._console_host = "::"
else:
self._console_host = "0.0.0.0"
else:
self._console_host = host
PortManager._instance = self
@classmethod @classmethod
def instance(cls): def instance(cls):
""" """
@ -84,13 +70,21 @@ class PortManager:
@property @property
def console_host(self): def console_host(self):
assert self._console_host is not None
return self._console_host return self._console_host
@console_host.setter @console_host.setter
def console_host(self, new_host): def console_host(self, new_host):
"""
self._console_host = new_host If allow remote connection we need to bind console host to 0.0.0.0
"""
server_config = Config.instance().get_section_config("Server")
remote_console_connections = server_config.getboolean("allow_remote_console")
if remote_console_connections:
log.warning("Remote console connections are allowed")
self._console_host = "0.0.0.0"
else:
self._console_host = new_host
@property @property
def console_port_range(self): def console_port_range(self):

View File

@ -57,12 +57,16 @@ class Controller:
yield from self.load() yield from self.load()
server_config = Config.instance().get_section_config("Server") server_config = Config.instance().get_section_config("Server")
host = server_config.get("host", "localhost") host = server_config.get("host", "localhost")
# If console_host is 0.0.0.0 client will use the ip they use
# to connect to the controller
console_host = host
if host == "0.0.0.0": if host == "0.0.0.0":
host = "127.0.0.1" host = "127.0.0.1"
yield from self.add_compute(compute_id="local", yield from self.add_compute(compute_id="local",
name=socket.gethostname(), name=socket.gethostname(),
protocol=server_config.get("protocol", "http"), protocol=server_config.get("protocol", "http"),
host=host, host=host,
console_host=console_host,
port=server_config.getint("port", 3080), port=server_config.getint("port", 3080),
user=server_config.get("user", ""), user=server_config.get("user", ""),
password=server_config.get("password", ""), password=server_config.get("password", ""),

View File

@ -73,7 +73,7 @@ class Compute:
A GNS3 compute. A GNS3 compute.
""" """
def __init__(self, compute_id, controller=None, protocol="http", host="localhost", port=3080, user=None, password=None, name=None): def __init__(self, compute_id, controller=None, protocol="http", host="localhost", port=3080, user=None, password=None, name=None, console_host=None):
self._http_session = None self._http_session = None
assert controller is not None assert controller is not None
log.info("Create compute %s", compute_id) log.info("Create compute %s", compute_id)
@ -87,6 +87,10 @@ class Compute:
self.host = host self.host = host
self.port = port self.port = port
self._user = None self._user = None
if console_host is None:
self._console_host = host
else:
self._console_host = console_host
self._password = None self._password = None
self._connected = False self._connected = False
self._closed = False # Close mean we are destroying the compute node self._closed = False # Close mean we are destroying the compute node
@ -214,6 +218,10 @@ class Compute:
def host(self, host): def host(self, host):
self._host = host self._host = host
@property
def console_host(self):
return self._console_host
@property @property
def port(self): def port(self):
""" """

View File

@ -568,7 +568,7 @@ class Node:
"node_directory": self._node_directory, "node_directory": self._node_directory,
"name": self._name, "name": self._name,
"console": self._console, "console": self._console,
"console_host": str(self._compute.host), "console_host": str(self._compute.console_host),
"console_type": self._console_type, "console_type": self._console_type,
"command_line": self._command_line, "command_line": self._command_line,
"properties": self._properties, "properties": self._properties,

View File

@ -60,7 +60,6 @@ class WebServer:
self._server = None self._server = None
self._app = None self._app = None
self._start_time = time.time() self._start_time = time.time()
self._port_manager = PortManager(host)
self._running = False self._running = False
self._closing = False self._closing = False
@ -115,11 +114,11 @@ class WebServer:
m = module.instance() m = module.instance()
yield from m.unload() yield from m.unload()
if self._port_manager.tcp_ports: if PortManager.instance().tcp_ports:
log.warning("TCP ports are still used {}".format(self._port_manager.tcp_ports)) log.warning("TCP ports are still used {}".format(PortManager.instance().tcp_ports))
if self._port_manager.udp_ports: if PortManager.instance().udp_ports:
log.warning("UDP ports are still used {}".format(self._port_manager.udp_ports)) log.warning("UDP ports are still used {}".format(PortManager.instance().udp_ports))
for task in asyncio.Task.all_tasks(): for task in asyncio.Task.all_tasks():
task.cancel() task.cancel()
@ -292,13 +291,16 @@ class WebServer:
"http://localhost:8080": aiohttp_cors.ResourceOptions(expose_headers="*", allow_headers="*"), "http://localhost:8080": aiohttp_cors.ResourceOptions(expose_headers="*", allow_headers="*"),
"http://gns3.github.io": aiohttp_cors.ResourceOptions(expose_headers="*", allow_headers="*") "http://gns3.github.io": aiohttp_cors.ResourceOptions(expose_headers="*", allow_headers="*")
}) })
PortManager.instance().console_host = self._host
for method, route, handler in Route.get_routes(): for method, route, handler in Route.get_routes():
log.debug("Adding route: {} {}".format(method, route)) log.debug("Adding route: {} {}".format(method, route))
cors.add(self._app.router.add_route(method, route, handler)) cors.add(self._app.router.add_route(method, route, handler))
for module in MODULES: for module in MODULES:
log.debug("Loading module {}".format(module.__name__)) log.debug("Loading module {}".format(module.__name__))
m = module.instance() m = module.instance()
m.port_manager = self._port_manager m.port_manager = PortManager.instance()
log.info("Starting server on {}:{}".format(self._host, self._port)) log.info("Starting server on {}:{}".format(self._host, self._port))
self._handler = self._app.make_handler(handler=RequestHandler) self._handler = self._app.make_handler(handler=RequestHandler)

View File

@ -119,3 +119,18 @@ def test_find_unused_port():
def test_find_unused_port_invalid_range(): def test_find_unused_port_invalid_range():
with pytest.raises(aiohttp.web.HTTPConflict): with pytest.raises(aiohttp.web.HTTPConflict):
p = PortManager().find_unused_port(10000, 1000) p = PortManager().find_unused_port(10000, 1000)
def test_set_console_host(config):
"""
If allow remote connection we need to bind console host
to 0.0.0.0
"""
p = PortManager()
config.set_section_config("Server", {"allow_remote_console": False})
p.console_host = "10.42.1.42"
assert p.console_host == "10.42.1.42"
p = PortManager()
config.set_section_config("Server", {"allow_remote_console": True})
p.console_host = "10.42.1.42"
assert p.console_host == "0.0.0.0"

View File

@ -145,8 +145,10 @@ def project(tmpdir):
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
def port_manager(): def port_manager():
"""An instance of port manager""" """An instance of port manager"""
PortManager._instance = None
return PortManager("127.0.0.1") p = PortManager.instance()
p.console_host = "127.0.0.1"
return p
@pytest.fixture(scope="function") @pytest.fixture(scope="function")
@ -198,7 +200,6 @@ def run_around_tests(monkeypatch, port_manager, controller, config):
for module in MODULES: for module in MODULES:
module._instance = None module._instance = None
port_manager._instance = port_manager
os.makedirs(os.path.join(tmppath, 'projects')) os.makedirs(os.path.join(tmppath, 'projects'))
config.set("Server", "projects_path", os.path.join(tmppath, 'projects')) config.set("Server", "projects_path", os.path.join(tmppath, 'projects'))
config.set("Server", "symbols_path", os.path.join(tmppath, 'symbols')) config.set("Server", "symbols_path", os.path.join(tmppath, 'symbols'))

View File

@ -92,7 +92,7 @@ def test_json(node, compute):
"name": "demo", "name": "demo",
"console": node.console, "console": node.console,
"console_type": node.console_type, "console_type": node.console_type,
"console_host": str(compute.host), "console_host": str(compute.console_host),
"command_line": None, "command_line": None,
"node_directory": None, "node_directory": None,
"properties": node.properties, "properties": node.properties,