Skip to content

Commit

Permalink
Always affect a free console port
Browse files Browse the repository at this point in the history
Instead a leaving the choice to the client this always
affect a random free console port. This should solve
issues when two users are on the same server or
you opened GNS3 twice.
  • Loading branch information
julien-duponchelle committed Dec 2, 2015
1 parent a6826fe commit e20f1f3
Show file tree
Hide file tree
Showing 20 changed files with 41 additions and 105 deletions.
1 change: 0 additions & 1 deletion gns3server/handlers/api/dynamips_vm_handler.py
Expand Up @@ -70,7 +70,6 @@ def create(request, response):
request.json.get("vm_id"),
request.json.get("dynamips_id"),
platform,
console=request.json.get("console"),
aux=request.json.get("aux"),
chassis=request.json.pop("chassis", default_chassis))

Expand Down
3 changes: 1 addition & 2 deletions gns3server/handlers/api/iou_handler.py
Expand Up @@ -55,8 +55,7 @@ def create(request, response):
iou = IOU.instance()
vm = yield from iou.create_vm(request.json.pop("name"),
request.match_info["project_id"],
request.json.get("vm_id"),
console=request.json.get("console"))
request.json.get("vm_id"))

for name, value in request.json.items():
if hasattr(vm, name) and getattr(vm, name) != value:
Expand Down
1 change: 0 additions & 1 deletion gns3server/handlers/api/qemu_handler.py
Expand Up @@ -60,7 +60,6 @@ def create(request, response):
request.json.pop("vm_id", None),
linked_clone=request.json.get("linked_clone", True),
qemu_path=request.json.pop("qemu_path", None),
console=request.json.pop("console", None),
console_type=request.json.pop("console_type", "telnet"),
platform=request.json.pop("platform", None))

Expand Down
1 change: 0 additions & 1 deletion gns3server/handlers/api/virtualbox_handler.py
Expand Up @@ -69,7 +69,6 @@ def create(request, response):
request.json.get("vm_id"),
request.json.pop("vmname"),
request.json.pop("linked_clone"),
console=request.json.get("console", None),
adapters=request.json.get("adapters", 0))

if "enable_remote_console" in request.json:
Expand Down
4 changes: 2 additions & 2 deletions gns3server/handlers/api/vmware_handler.py
Expand Up @@ -68,8 +68,8 @@ def create(request, response):
request.match_info["project_id"],
request.json.get("vm_id"),
request.json.pop("vmx_path"),
request.json.pop("linked_clone"),
console=request.json.get("console", None))
request.json.pop("linked_clone")
)

for name, value in request.json.items():
if name != "vm_id":
Expand Down
1 change: 0 additions & 1 deletion gns3server/handlers/api/vpcs_handler.py
Expand Up @@ -50,7 +50,6 @@ def create(request, response):
vm = yield from vpcs.create_vm(request.json["name"],
request.match_info["project_id"],
request.json.get("vm_id"),
console=request.json.get("console"),
startup_script=request.json.get("startup_script"))
response.set_status(201)
response.json(vm)
Expand Down
41 changes: 11 additions & 30 deletions gns3server/modules/base_vm.py
Expand Up @@ -45,28 +45,24 @@ class BaseVM:
:param console: TCP console port
"""

def __init__(self, name, vm_id, project, manager, console=None, console_type="telnet"):
def __init__(self, name, vm_id, project, manager, console_type="telnet"):

self._name = name
self._usage = ""
self._id = vm_id
self._project = project
self._manager = manager
self._console = console
self._console_type = console_type
self._temporary_directory = None
self._hw_virtualization = False
self._ubridge_hypervisor = None
self._vm_status = "stopped"

if self._console is not None:
self._console = self._manager.port_manager.reserve_tcp_port(self._console, self._project)
if console_type == "vnc":
# VNC is a special case and the range must be 5900-6000
self._console = self._manager.port_manager.get_free_tcp_port(self._project, 5900, 6000)
else:
if console_type == "vnc":
# VNC is a special case and the range must be 5900-6000
self._console = self._manager.port_manager.get_free_tcp_port(self._project, 5900, 6000)
else:
self._console = self._manager.port_manager.get_free_tcp_port(self._project)
self._console = self._manager.port_manager.get_free_tcp_port(self._project)

log.debug("{module}: {name} [{id}] initialized. Console port {console}".format(module=self.manager.module_name,
name=self.name,
Expand Down Expand Up @@ -223,7 +219,9 @@ def close(self):
Close the VM process.
"""

raise NotImplementedError
if self._console:
self._manager.port_manager.release_tcp_port(self._console, self._project)
self._console = None

@property
def console(self):
Expand All @@ -236,26 +234,9 @@ def console(self):
return self._console

@console.setter
def console(self, console):
"""
Changes the console port
:params console: Console port (integer)
"""

if console == self._console:
return

if self._console_type == "vnc" and console < 5900:
raise VMError("VNC console require a port superior or equal to 5900")

if self._console:
self._manager.port_manager.release_tcp_port(self._console, self._project)
self._console = self._manager.port_manager.reserve_tcp_port(console, self._project)
log.info("{module}: '{name}' [{id}]: console port set to {port}".format(module=self.manager.module_name,
name=self.name,
id=self.id,
port=console))
def console(self, port):
# Ignore console port for compatibility with old GNS3 version
pass

@property
def console_type(self):
Expand Down
9 changes: 3 additions & 6 deletions gns3server/modules/dynamips/nodes/router.py
Expand Up @@ -49,7 +49,6 @@ class Router(BaseVM):
:param project: Project instance
:param manager: Parent VM Manager
:param dynamips_id: ID to use with Dynamips
:param console: console port
:param aux: auxiliary console port
:param platform: Platform of this router
"""
Expand All @@ -59,9 +58,9 @@ class Router(BaseVM):
2: "running",
3: "suspended"}

def __init__(self, name, vm_id, project, manager, dynamips_id=None, console=None, aux=None, platform="c7200", hypervisor=None, ghost_flag=False):
def __init__(self, name, vm_id, project, manager, dynamips_id=None, aux=None, platform="c7200", hypervisor=None, ghost_flag=False):

super().__init__(name, vm_id, project, manager, console=console)
super().__init__(name, vm_id, project, manager)

self._hypervisor = hypervisor
self._dynamips_id = dynamips_id
Expand Down Expand Up @@ -333,9 +332,7 @@ def close(self):

log.debug('Router "{name}" [{id}] is closing'.format(name=self._name, id=self._id))

if self._console:
self._manager.port_manager.release_tcp_port(self._console, self._project)
self._console = None
super().close()

if self._aux:
self._manager.port_manager.release_tcp_port(self._aux, self._project)
Expand Down
9 changes: 3 additions & 6 deletions gns3server/modules/iou/iou_vm.py
Expand Up @@ -64,12 +64,11 @@ class IOUVM(BaseVM):
:param vm_id: IOU VM identifier
:param project: Project instance
:param manager: Manager instance
:param console: TCP console port
"""

def __init__(self, name, vm_id, project, manager, console=None):
def __init__(self, name, vm_id, project, manager):

super().__init__(name, vm_id, project, manager, console=console)
super().__init__(name, vm_id, project, manager)

self._command = []
self._iouyap_process = None
Expand Down Expand Up @@ -99,9 +98,7 @@ def close(self):

log.debug('IOU "{name}" [{id}] is closing'.format(name=self._name, id=self._id))

if self._console:
self._manager.port_manager.release_tcp_port(self._console, self._project)
self._console = None
super().close()

adapters = self._ethernet_adapters + self._serial_adapters
for adapter in adapters:
Expand Down
11 changes: 4 additions & 7 deletions gns3server/modules/qemu/qemu_vm.py
Expand Up @@ -55,15 +55,14 @@ class QemuVM(BaseVM):
:param vm_id: Qemu VM identifier
:param project: Project instance
:param manager: Manager instance
:param console: TCP console port
:param qemu_path: path to the QEMU binary
:param platform: Platform to emulate
:param console: TCP console port
"""

def __init__(self, name, vm_id, project, manager, linked_clone=True, qemu_path=None, console=None, console_type="telnet", platform=None):
def __init__(self, name, vm_id, project, manager, linked_clone=True, qemu_path=None, console_type="telnet", platform=None):

super().__init__(name, vm_id, project, manager, console=console, console_type=console_type)
super().__init__(name, vm_id, project, manager, console_type=console_type)
server_config = manager.config.get_section_config("Server")
self._host = server_config.get("host", "127.0.0.1")
self._monitor_host = server_config.get("monitor_host", "127.0.0.1")
Expand Down Expand Up @@ -973,13 +972,11 @@ def close(self):
"""

log.debug('QEMU VM "{name}" [{id}] is closing'.format(name=self._name, id=self._id))
super().close()

self.acpi_shutdown = False
yield from self.stop()

if self._console:
self._manager.port_manager.release_tcp_port(self._console, self._project)
self._console = None

for adapter in self._ethernet_adapters:
if adapter is not None:
for nio in adapter.ports.values():
Expand Down
8 changes: 3 additions & 5 deletions gns3server/modules/virtualbox/virtualbox_vm.py
Expand Up @@ -51,9 +51,9 @@ class VirtualBoxVM(BaseVM):
VirtualBox VM implementation.
"""

def __init__(self, name, vm_id, project, manager, vmname, linked_clone, console=None, adapters=0):
def __init__(self, name, vm_id, project, manager, vmname, linked_clone, adapters=0):

super().__init__(name, vm_id, project, manager, console=console)
super().__init__(name, vm_id, project, manager)

self._maximum_adapters = 8
self._linked_clone = linked_clone
Expand Down Expand Up @@ -349,9 +349,7 @@ def close(self):
return

log.debug("VirtualBox VM '{name}' [{id}] is closing".format(name=self.name, id=self.id))
if self._console:
self._manager.port_manager.release_tcp_port(self._console, self._project)
self._console = None
super.close()

for adapter in self._ethernet_adapters.values():
if adapter is not None:
Expand Down
8 changes: 3 additions & 5 deletions gns3server/modules/vmware/vmware_vm.py
Expand Up @@ -50,9 +50,9 @@ class VMwareVM(BaseVM):
VMware VM implementation.
"""

def __init__(self, name, vm_id, project, manager, vmx_path, linked_clone, console=None):
def __init__(self, name, vm_id, project, manager, vmx_path, linked_clone):

super().__init__(name, vm_id, project, manager, console=console)
super().__init__(name, vm_id, project, manager)

self._linked_clone = linked_clone
self._vmx_pairs = OrderedDict()
Expand Down Expand Up @@ -542,9 +542,7 @@ def close(self):
return

log.debug("VMware VM '{name}' [{id}] is closing".format(name=self.name, id=self.id))
if self._console:
self._manager.port_manager.release_tcp_port(self._console, self._project)
self._console = None
super().close()

for adapter in self._ethernet_adapters.values():
if adapter is not None:
Expand Down
9 changes: 3 additions & 6 deletions gns3server/modules/vpcs/vpcs_vm.py
Expand Up @@ -52,13 +52,12 @@ class VPCSVM(BaseVM):
:param vm_id: VPCS VM identifier
:param project: Project instance
:param manager: Manager instance
:param console: TCP console port
:param startup_script: content of the startup script file
"""

def __init__(self, name, vm_id, project, manager, console=None, startup_script=None):
def __init__(self, name, vm_id, project, manager, startup_script=None):

super().__init__(name, vm_id, project, manager, console=console)
super().__init__(name, vm_id, project, manager)
self._command = []
self._process = None
self._vpcs_stdout_file = ""
Expand All @@ -77,9 +76,7 @@ def close(self):
"""

log.debug('VPCS "{name}" [{id}] is closing'.format(name=self._name, id=self._id))
if self._console:
self._manager.port_manager.release_tcp_port(self._console, self._project)
self._console = None
super().close()

nio = self._ethernet_adapter.get_nio(0)
if isinstance(nio, NIOUDP):
Expand Down
4 changes: 1 addition & 3 deletions tests/handlers/api/test_iou.py
Expand Up @@ -177,10 +177,9 @@ def test_iou_delete(server, vm):
assert response.status == 204


def test_iou_update(server, vm, tmpdir, free_console_port, project):
def test_iou_update(server, vm, tmpdir, project):
params = {
"name": "test",
"console": free_console_port,
"ram": 512,
"nvram": 2048,
"ethernet_adapters": 4,
Expand All @@ -193,7 +192,6 @@ def test_iou_update(server, vm, tmpdir, free_console_port, project):
response = server.put("/projects/{project_id}/iou/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), params, example=True)
assert response.status == 200
assert response.json["name"] == "test"
assert response.json["console"] == free_console_port
assert response.json["ethernet_adapters"] == 4
assert response.json["serial_adapters"] == 0
assert response.json["ram"] == 512
Expand Down
2 changes: 0 additions & 2 deletions tests/handlers/api/test_qemu.py
Expand Up @@ -147,14 +147,12 @@ def test_qemu_delete(server, vm):
def test_qemu_update(server, vm, tmpdir, free_console_port, project, fake_qemu_vm):
params = {
"name": "test",
"console": free_console_port,
"ram": 1024,
"hdb_disk_image": "linux.img"
}
response = server.put("/projects/{project_id}/qemu/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), params, example=True)
assert response.status == 200
assert response.json["name"] == "test"
assert response.json["console"] == free_console_port
assert response.json["hdb_disk_image"] == "linux.img"
assert response.json["ram"] == 1024

Expand Down
4 changes: 1 addition & 3 deletions tests/handlers/api/test_virtualbox.py
Expand Up @@ -125,9 +125,7 @@ def test_vbox_delete_nio(server, vm):


def test_vbox_update(server, vm, free_console_port):
response = server.put("/projects/{project_id}/virtualbox/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"name": "test",
"console": free_console_port},
response = server.put("/projects/{project_id}/virtualbox/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"name": "test"},
example=True)
assert response.status == 200
assert response.json["name"] == "test"
assert response.json["console"] == free_console_port
4 changes: 1 addition & 3 deletions tests/handlers/api/test_vpcs.py
Expand Up @@ -124,12 +124,10 @@ def test_vpcs_delete(server, vm):
assert response.status == 204


def test_vpcs_update(server, vm, tmpdir, free_console_port):
def test_vpcs_update(server, vm, tmpdir):
response = server.put("/projects/{project_id}/vpcs/vms/{vm_id}".format(project_id=vm["project_id"], vm_id=vm["vm_id"]), {"name": "test",
"console": free_console_port,
"startup_script": "ip 192.168.1.1"},
example=True)
assert response.status == 200
assert response.json["name"] == "test"
assert response.json["console"] == free_console_port
assert response.json["startup_script"] == "ip 192.168.1.1"
11 changes: 3 additions & 8 deletions tests/modules/test_base_vm.py
Expand Up @@ -48,12 +48,7 @@ def test_temporary_directory(project, manager):

def test_console(project, manager):
vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
old_console = vm.console
vm.console = 2111
assert vm.console == 2111


def test_console_vnc_invalid(project, manager):
vm = VPCSVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager)
vm.console_type = "vnc"
with pytest.raises(VMError):
vm.console = 2012
# The console port should not change
assert vm.console == old_console
4 changes: 2 additions & 2 deletions tests/modules/test_manager.py
Expand Up @@ -51,10 +51,10 @@ def test_create_vm_new_topology(loop, project, vpcs):
def test_create_twice_same_vm_new_topology(loop, project, vpcs):
project._vms = set()
vm_id = str(uuid.uuid4())
vm = loop.run_until_complete(vpcs.create_vm("PC 1", project.id, vm_id, console=2222))
vm = loop.run_until_complete(vpcs.create_vm("PC 1", project.id, vm_id))
assert vm in project.vms
assert len(project.vms) == 1
vm = loop.run_until_complete(vpcs.create_vm("PC 2", project.id, vm_id, console=2222))
vm = loop.run_until_complete(vpcs.create_vm("PC 2", project.id, vm_id))
assert len(project.vms) == 1


Expand Down
11 changes: 0 additions & 11 deletions tests/modules/vpcs/test_vpcs_vm.py
Expand Up @@ -271,17 +271,6 @@ def test_get_startup_script_using_default_script(vm):
assert vm.script_file == filepath


def test_change_console_port(vm, port_manager):
port1 = port_manager.get_free_tcp_port(vm.project)
port2 = port_manager.get_free_tcp_port(vm.project)
port_manager.release_tcp_port(port1, vm.project)
port_manager.release_tcp_port(port2, vm.project)
vm.console = port1
vm.console = port2
assert vm.console == port2
port_manager.reserve_tcp_port(port1, vm.project)


def test_change_name(vm, tmpdir):
path = os.path.join(vm.working_dir, 'startup.vpc')
vm.name = "world"
Expand Down

0 comments on commit e20f1f3

Please sign in to comment.