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:
parent
afb7eca27a
commit
eabe4eb97e
@ -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):
|
||||||
|
@ -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", ""),
|
||||||
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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"
|
||||||
|
@ -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'))
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user