Option to allow console connections to any local IP address when using the local server.

This commit is contained in:
Jeremy 2014-11-09 23:01:13 -07:00
parent 1982ff8100
commit f44fbd1f16
12 changed files with 50 additions and 35 deletions

View File

@ -35,6 +35,7 @@ define("port", default=8000, help="run on the given port", type=int)
define("ipc", default=False, help="use IPC for module communication", type=bool) define("ipc", default=False, help="use IPC for module communication", type=bool)
define("version", default=False, help="show the version", type=bool) define("version", default=False, help="show the version", type=bool)
define("quiet", default=False, help="do not show output on stdout", type=bool) define("quiet", default=False, help="do not show output on stdout", type=bool)
define("console_bind_to_any", default=True, help="bind console ports to any local IP address", type=bool)
def locale_check(): def locale_check():
@ -127,7 +128,7 @@ def main():
log.critical("the current working directory doesn't exist") log.critical("the current working directory doesn't exist")
return return
server = Server(options.host, options.port, options.ipc) server = Server(options.host, options.port, options.ipc, options.console_bind_to_any)
server.load_modules() server.load_modules()
server.run() server.run()

View File

@ -33,7 +33,6 @@ from gns3server.builtins.interfaces import get_windows_interfaces
from .hypervisor import Hypervisor from .hypervisor import Hypervisor
from .hypervisor_manager import HypervisorManager from .hypervisor_manager import HypervisorManager
from .dynamips_error import DynamipsError from .dynamips_error import DynamipsError
from ..attic import has_privileged_access
# Nodes # Nodes
from .nodes.router import Router from .nodes.router import Router
@ -138,6 +137,7 @@ class Dynamips(IModule):
self._tempdir = kwargs["temp_dir"] self._tempdir = kwargs["temp_dir"]
self._working_dir = self._projects_dir self._working_dir = self._projects_dir
self._host = dynamips_config.get("host", kwargs["host"]) self._host = dynamips_config.get("host", kwargs["host"])
self._console_host = dynamips_config.get("console_host", kwargs["console_host"])
if not sys.platform.startswith("win32"): if not sys.platform.startswith("win32"):
#FIXME: pickle issues Windows #FIXME: pickle issues Windows
@ -282,7 +282,7 @@ class Dynamips(IModule):
raise DynamipsError("Cannot write to working directory {}".format(workdir)) raise DynamipsError("Cannot write to working directory {}".format(workdir))
log.info("starting the hypervisor manager with Dynamips working directory set to '{}'".format(workdir)) log.info("starting the hypervisor manager with Dynamips working directory set to '{}'".format(workdir))
self._hypervisor_manager = HypervisorManager(self._dynamips, workdir, self._host) self._hypervisor_manager = HypervisorManager(self._dynamips, workdir, self._host, self._console_host)
for name, value in self._hypervisor_manager_settings.items(): for name, value in self._hypervisor_manager_settings.items():
if hasattr(self._hypervisor_manager, name) and getattr(self._hypervisor_manager, name) != value: if hasattr(self._hypervisor_manager, name) and getattr(self._hypervisor_manager, name) != value:

View File

@ -40,14 +40,16 @@ class HypervisorManager(object):
:param path: path to the Dynamips executable :param path: path to the Dynamips executable
:param working_dir: path to a working directory :param working_dir: path to a working directory
:param host: host/address for hypervisors to listen to :param host: host/address for hypervisors to listen to
:param console_host: IP address to bind for console connections
""" """
def __init__(self, path, working_dir, host='127.0.0.1'): def __init__(self, path, working_dir, host='127.0.0.1', console_host='0.0.0.0'):
self._hypervisors = [] self._hypervisors = []
self._path = path self._path = path
self._working_dir = working_dir self._working_dir = working_dir
self._host = host self._console_host = console_host
self._host = console_host # FIXME: Dynamips must be patched to bind on a different address than the one used by the hypervisor.
config = Config.instance() config = Config.instance()
dynamips_config = config.get_section_config("DYNAMIPS") dynamips_config = config.get_section_config("DYNAMIPS")

View File

@ -92,6 +92,7 @@ class IOU(IModule):
self._udp_start_port_range = iou_config.get("udp_start_port_range", 30001) self._udp_start_port_range = iou_config.get("udp_start_port_range", 30001)
self._udp_end_port_range = iou_config.get("udp_end_port_range", 35000) self._udp_end_port_range = iou_config.get("udp_end_port_range", 35000)
self._host = iou_config.get("host", kwargs["host"]) self._host = iou_config.get("host", kwargs["host"])
self._console_host = iou_config.get("console_host", kwargs["console_host"])
self._projects_dir = kwargs["projects_dir"] self._projects_dir = kwargs["projects_dir"]
self._tempdir = kwargs["temp_dir"] self._tempdir = kwargs["temp_dir"]
self._working_dir = self._projects_dir self._working_dir = self._projects_dir
@ -303,9 +304,9 @@ class IOU(IModule):
iou_instance = IOUDevice(name, iou_instance = IOUDevice(name,
iou_path, iou_path,
self._working_dir, self._working_dir,
self._host,
iou_id, iou_id,
console, console,
self._console_host,
self._console_start_port_range, self._console_start_port_range,
self._console_end_port_range) self._console_end_port_range)

View File

@ -49,9 +49,9 @@ class IOUDevice(object):
:param name: name of this IOU device :param name: name of this IOU device
:param path: path to IOU executable :param path: path to IOU executable
: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 iou_id: IOU instance ID :param iou_id: IOU instance ID
:param console: TCP console port :param console: TCP console port
:param console_host: IP address to bind for console connections
:param console_start_port_range: TCP console port range start :param console_start_port_range: TCP console port range start
:param console_end_port_range: TCP console port range end :param console_end_port_range: TCP console port range end
""" """
@ -63,9 +63,9 @@ class IOUDevice(object):
name, name,
path, path,
working_dir, working_dir,
host="127.0.0.1", iou_id=None,
iou_id = None,
console=None, console=None,
console_host="0.0.0.0",
console_start_port_range=4001, console_start_port_range=4001,
console_end_port_range=4512): console_end_port_range=4512):
@ -99,8 +99,8 @@ class IOUDevice(object):
self._iouyap_stdout_file = "" self._iouyap_stdout_file = ""
self._ioucon_thead = None self._ioucon_thead = None
self._ioucon_thread_stop_event = None self._ioucon_thread_stop_event = None
self._host = host
self._started = False self._started = False
self._console_host = console_host
self._console_start_port_range = console_start_port_range self._console_start_port_range = console_start_port_range
self._console_end_port_range = console_end_port_range self._console_end_port_range = console_end_port_range
@ -127,7 +127,7 @@ class IOUDevice(object):
try: try:
self._console = find_unused_port(self._console_start_port_range, self._console = find_unused_port(self._console_start_port_range,
self._console_end_port_range, self._console_end_port_range,
self._host, self._console_host,
ignore_ports=self._allocated_console_ports) ignore_ports=self._allocated_console_ports)
except Exception as e: except Exception as e:
raise IOUError(e) raise IOUError(e)
@ -484,7 +484,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._console_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()

View File

@ -71,6 +71,7 @@ class Qemu(IModule):
self._udp_start_port_range = qemu_config.get("udp_start_port_range", 40001) self._udp_start_port_range = qemu_config.get("udp_start_port_range", 40001)
self._udp_end_port_range = qemu_config.get("udp_end_port_range", 45500) self._udp_end_port_range = qemu_config.get("udp_end_port_range", 45500)
self._host = qemu_config.get("host", kwargs["host"]) self._host = qemu_config.get("host", kwargs["host"])
self._console_host = qemu_config.get("console_host", kwargs["console_host"])
self._projects_dir = kwargs["projects_dir"] self._projects_dir = kwargs["projects_dir"]
self._tempdir = kwargs["temp_dir"] self._tempdir = kwargs["temp_dir"]
self._working_dir = self._projects_dir self._working_dir = self._projects_dir
@ -214,6 +215,7 @@ class Qemu(IModule):
self._host, self._host,
qemu_id, qemu_id,
console, console,
self._console_host,
self._console_start_port_range, self._console_start_port_range,
self._console_end_port_range) self._console_end_port_range)
@ -614,7 +616,6 @@ class Qemu(IModule):
Gets QEMU binaries list. Gets QEMU binaries list.
Response parameters: Response parameters:
- Server address/host
- List of Qemu binaries - List of Qemu binaries
""" """
@ -642,8 +643,7 @@ class Qemu(IModule):
log.warn("Could not find QEMU version for {}: {}".format(path, e)) log.warn("Could not find QEMU version for {}: {}".format(path, e))
continue continue
response = {"server": self._host, response = {"qemus": qemus}
"qemus": qemus}
self.send_response(response) self.send_response(response)
@IModule.route("qemu.echo") @IModule.route("qemu.echo")

View File

@ -44,6 +44,7 @@ class QemuVM(object):
:param host: host/address to bind for console and UDP connections :param host: host/address to bind for console and UDP connections
:param qemu_id: QEMU VM instance ID :param qemu_id: QEMU VM instance ID
:param console: TCP console port :param console: TCP console port
:param console_host: IP address to bind for console connections
:param console_start_port_range: TCP console port range start :param console_start_port_range: TCP console port range start
:param console_end_port_range: TCP console port range end :param console_end_port_range: TCP console port range end
""" """
@ -58,6 +59,7 @@ class QemuVM(object):
host="127.0.0.1", host="127.0.0.1",
qemu_id=None, qemu_id=None,
console=None, console=None,
console_host="0.0.0.0",
console_start_port_range=5001, console_start_port_range=5001,
console_end_port_range=5500): console_end_port_range=5500):
@ -84,6 +86,7 @@ class QemuVM(object):
self._started = False self._started = False
self._process = None self._process = None
self._stdout_file = "" self._stdout_file = ""
self._console_host = console_host
self._console_start_port_range = console_start_port_range self._console_start_port_range = console_start_port_range
self._console_end_port_range = console_end_port_range self._console_end_port_range = console_end_port_range
@ -113,7 +116,7 @@ class QemuVM(object):
try: try:
self._console = find_unused_port(self._console_start_port_range, self._console = find_unused_port(self._console_start_port_range,
self._console_end_port_range, self._console_end_port_range,
self._host, self._console_host,
ignore_ports=self._allocated_console_ports) ignore_ports=self._allocated_console_ports)
except Exception as e: except Exception as e:
raise QemuError(e) raise QemuError(e)
@ -681,7 +684,7 @@ class QemuVM(object):
def _serial_options(self): def _serial_options(self):
if self._console: if self._console:
return ["-serial", "telnet:{}:{},server,nowait".format(self._host, self._console)] return ["-serial", "telnet:{}:{},server,nowait".format(self._console_host, self._console)]
else: else:
return [] return []

View File

@ -96,6 +96,7 @@ class VirtualBox(IModule):
self._udp_start_port_range = vbox_config.get("udp_start_port_range", 35001) self._udp_start_port_range = vbox_config.get("udp_start_port_range", 35001)
self._udp_end_port_range = vbox_config.get("udp_end_port_range", 35500) self._udp_end_port_range = vbox_config.get("udp_end_port_range", 35500)
self._host = vbox_config.get("host", kwargs["host"]) self._host = vbox_config.get("host", kwargs["host"])
self._console_host = vbox_config.get("console_host", kwargs["console_host"])
self._projects_dir = kwargs["projects_dir"] self._projects_dir = kwargs["projects_dir"]
self._tempdir = kwargs["temp_dir"] self._tempdir = kwargs["temp_dir"]
self._working_dir = self._projects_dir self._working_dir = self._projects_dir
@ -251,9 +252,9 @@ class VirtualBox(IModule):
vmname, vmname,
linked_clone, linked_clone,
self._working_dir, self._working_dir,
self._host,
vbox_id, vbox_id,
console, console,
self._console_host,
self._console_start_port_range, self._console_start_port_range,
self._console_end_port_range) self._console_end_port_range)
@ -755,9 +756,7 @@ class VirtualBox(IModule):
if not extra_data == "Value: yes": if not extra_data == "Value: yes":
vms.append(vmname) vms.append(vmname)
response = {"server": self._host, response = {"vms": vms}
"vms": vms}
self.send_response(response) self.send_response(response)
@IModule.route("virtualbox.echo") @IModule.route("virtualbox.echo")

View File

@ -52,9 +52,9 @@ class VirtualBoxVM(object):
:param vmname: name of this VirtualBox VM in VirtualBox itself :param vmname: name of this VirtualBox VM in VirtualBox itself
:param linked_clone: flag if a linked clone must be created :param linked_clone: flag if a linked clone must be created
: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 vbox_id: VirtalBox VM instance ID :param vbox_id: VirtalBox VM instance ID
:param console: TCP console port :param console: TCP console port
:param console_host: IP address to bind for console connections
:param console_start_port_range: TCP console port range start :param console_start_port_range: TCP console port range start
:param console_end_port_range: TCP console port range end :param console_end_port_range: TCP console port range end
""" """
@ -68,9 +68,9 @@ class VirtualBoxVM(object):
vmname, vmname,
linked_clone, linked_clone,
working_dir, working_dir,
host="127.0.0.1",
vbox_id=None, vbox_id=None,
console=None, console=None,
console_host="0.0.0.0",
console_start_port_range=4512, console_start_port_range=4512,
console_end_port_range=5000): console_end_port_range=5000):
@ -93,10 +93,10 @@ class VirtualBoxVM(object):
self._name = name self._name = name
self._linked_clone = linked_clone self._linked_clone = linked_clone
self._working_dir = None self._working_dir = None
self._host = host
self._command = [] self._command = []
self._vboxmanage_path = vboxmanage_path self._vboxmanage_path = vboxmanage_path
self._started = False self._started = False
self._console_host = console_host
self._console_start_port_range = console_start_port_range self._console_start_port_range = console_start_port_range
self._console_end_port_range = console_end_port_range self._console_end_port_range = console_end_port_range
@ -125,7 +125,7 @@ class VirtualBoxVM(object):
try: try:
self._console = find_unused_port(self._console_start_port_range, self._console = find_unused_port(self._console_start_port_range,
self._console_end_port_range, self._console_end_port_range,
self._host, self._console_host,
ignore_ports=self._allocated_console_ports) ignore_ports=self._allocated_console_ports)
except Exception as e: except Exception as e:
raise VirtualBoxError(e) raise VirtualBoxError(e)
@ -810,7 +810,7 @@ class VirtualBoxVM(object):
self._serial_pipe = open(pipe_name, "a+b") self._serial_pipe = open(pipe_name, "a+b")
except OSError as e: except OSError as e:
raise VirtualBoxError("Could not open the pipe {}: {}".format(pipe_name, e)) raise VirtualBoxError("Could not open the pipe {}: {}".format(pipe_name, e))
self._telnet_server_thread = TelnetServer(self._vmname, msvcrt.get_osfhandle(self._serial_pipe.fileno()), self._host, self._console) self._telnet_server_thread = TelnetServer(self._vmname, msvcrt.get_osfhandle(self._serial_pipe.fileno()), self._console_host, self._console)
self._telnet_server_thread.start() self._telnet_server_thread.start()
else: else:
try: try:
@ -818,7 +818,7 @@ class VirtualBoxVM(object):
self._serial_pipe.connect(pipe_name) self._serial_pipe.connect(pipe_name)
except OSError as e: except OSError as e:
raise VirtualBoxError("Could not connect to the pipe {}: {}".format(pipe_name, e)) raise VirtualBoxError("Could not connect to the pipe {}: {}".format(pipe_name, e))
self._telnet_server_thread = TelnetServer(self._vmname, self._serial_pipe, self._host, self._console) self._telnet_server_thread = TelnetServer(self._vmname, self._serial_pipe, self._console_host, self._console)
self._telnet_server_thread.start() self._telnet_server_thread.start()
def stop(self): def stop(self):

View File

@ -87,6 +87,7 @@ class VPCS(IModule):
self._udp_start_port_range = vpcs_config.get("udp_start_port_range", 20501) self._udp_start_port_range = vpcs_config.get("udp_start_port_range", 20501)
self._udp_end_port_range = vpcs_config.get("udp_end_port_range", 21000) self._udp_end_port_range = vpcs_config.get("udp_end_port_range", 21000)
self._host = vpcs_config.get("host", kwargs["host"]) self._host = vpcs_config.get("host", kwargs["host"])
self._console_host = vpcs_config.get("console_host", kwargs["console_host"])
self._projects_dir = kwargs["projects_dir"] self._projects_dir = kwargs["projects_dir"]
self._tempdir = kwargs["temp_dir"] self._tempdir = kwargs["temp_dir"]
self._working_dir = self._projects_dir self._working_dir = self._projects_dir
@ -237,9 +238,9 @@ class VPCS(IModule):
vpcs_instance = VPCSDevice(name, vpcs_instance = VPCSDevice(name,
self._vpcs, self._vpcs,
self._working_dir, self._working_dir,
self._host,
vpcs_id, vpcs_id,
console, console,
self._console_host,
self._console_start_port_range, self._console_start_port_range,
self._console_end_port_range) self._console_end_port_range)

View File

@ -45,9 +45,9 @@ class VPCSDevice(object):
:param name: name of this VPCS device :param name: name of this VPCS device
:param path: path to VPCS executable :param path: path to VPCS executable
: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 vpcs_id: VPCS instance ID :param vpcs_id: VPCS instance ID
:param console: TCP console port :param console: TCP console port
:param console_host: IP address to bind for console connections
:param console_start_port_range: TCP console port range start :param console_start_port_range: TCP console port range start
:param console_end_port_range: TCP console port range end :param console_end_port_range: TCP console port range end
""" """
@ -59,9 +59,9 @@ class VPCSDevice(object):
name, name,
path, path,
working_dir, working_dir,
host="127.0.0.1",
vpcs_id=None, vpcs_id=None,
console=None, console=None,
console_host="0.0.0.0",
console_start_port_range=4512, console_start_port_range=4512,
console_end_port_range=5000): console_end_port_range=5000):
@ -89,7 +89,7 @@ class VPCSDevice(object):
self._path = path self._path = path
self._console = console self._console = console
self._working_dir = None self._working_dir = None
self._host = host self._console_host = console_host
self._command = [] self._command = []
self._process = None self._process = None
self._vpcs_stdout_file = "" self._vpcs_stdout_file = ""
@ -114,7 +114,7 @@ class VPCSDevice(object):
try: try:
self._console = find_unused_port(self._console_start_port_range, self._console = find_unused_port(self._console_start_port_range,
self._console_end_port_range, self._console_end_port_range,
self._host, self._console_host,
ignore_ports=self._allocated_console_ports) ignore_ports=self._allocated_console_ports)
except Exception as e: except Exception as e:
raise VPCSError(e) raise VPCSError(e)

View File

@ -33,7 +33,7 @@ import tornado.ioloop
import tornado.web import tornado.web
import tornado.autoreload import tornado.autoreload
import pkg_resources import pkg_resources
from os.path import expanduser import ipaddress
import base64 import base64
import uuid import uuid
@ -58,13 +58,21 @@ class Server(object):
(r"/upload", FileUploadHandler), (r"/upload", FileUploadHandler),
(r"/login", LoginHandler)] (r"/login", LoginHandler)]
def __init__(self, host, port, ipc): def __init__(self, host, port, ipc, console_bind_to_any):
self._host = host self._host = host
self._port = port self._port = port
self._router = None self._router = None
self._stream = None self._stream = None
if console_bind_to_any:
if ipaddress.ip_address(self._host).version == 6:
self._console_host = "::"
else:
self._console_host = "0.0.0.0"
else:
self._console_host = self._host
if ipc: if ipc:
self._zmq_port = 0 # this forces to use IPC for communications with the ZeroMQ server self._zmq_port = 0 # this forces to use IPC for communications with the ZeroMQ server
else: else:
@ -132,6 +140,7 @@ class Server(object):
"127.0.0.1", # ZeroMQ server address "127.0.0.1", # ZeroMQ server address
self._zmq_port, # ZeroMQ server port self._zmq_port, # ZeroMQ server port
host=self._host, # server host address host=self._host, # server host address
console_host=self._console_host,
projects_dir=self._projects_dir, projects_dir=self._projects_dir,
temp_dir=self._temp_dir) temp_dir=self._temp_dir)
@ -141,7 +150,6 @@ class Server(object):
JSONRPCWebSocket.register_destination(destination, instance.name) JSONRPCWebSocket.register_destination(destination, instance.name)
instance.start() # starts the new process instance.start() # starts the new process
def run(self): def run(self):
""" """
Starts the Tornado web server and ZeroMQ server. Starts the Tornado web server and ZeroMQ server.