Skip to content

Commit d1a7474

Browse files
authored
Merge pull request #2418 from GNS3/revert-2417-backport-aux-console-support
Revert "Backport auxiliary console support for Qemu, Docker and Dynamips nodes"
2 parents f1294cf + af6f34b commit d1a7474

25 files changed

+156
-390
lines changed

gns3server/compute/base_node.py

+67-115
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,14 @@ class BaseNode:
5050
:param node_id: Node instance identifier
5151
:param project: Project instance
5252
:param manager: parent node manager
53-
:param console: console TCP port
54-
:param console_type: console type
55-
:param aux: auxiliary console TCP port
56-
:param aux_type: auxiliary console type
53+
:param console: TCP console port
54+
:param aux: TCP aux console port
55+
:param allocate_aux: Boolean if true will allocate an aux console port
5756
:param linked_clone: The node base image is duplicate/overlay (Each node data are independent)
5857
:param wrap_console: The console is wrapped using AsyncioTelnetServer
59-
:param wrap_aux: The auxiliary console is wrapped using AsyncioTelnetServer
6058
"""
6159

62-
def __init__(self, name, node_id, project, manager, console=None, console_type="telnet", aux=None, aux_type="none", linked_clone=True, wrap_console=False, wrap_aux=False):
60+
def __init__(self, name, node_id, project, manager, console=None, console_type="telnet", aux=None, allocate_aux=False, linked_clone=True, wrap_console=False):
6361

6462
self._name = name
6563
self._usage = ""
@@ -70,25 +68,22 @@ def __init__(self, name, node_id, project, manager, console=None, console_type="
7068
self._console = console
7169
self._aux = aux
7270
self._console_type = console_type
73-
self._aux_type = aux_type
7471
self._temporary_directory = None
7572
self._hw_virtualization = False
7673
self._ubridge_hypervisor = None
7774
self._closed = False
7875
self._node_status = "stopped"
7976
self._command_line = ""
77+
self._allocate_aux = allocate_aux
8078
self._wrap_console = wrap_console
81-
self._wrap_aux = wrap_aux
82-
self._wrapper_telnet_servers = []
79+
self._wrapper_telnet_server = None
8380
self._wrap_console_reader = None
8481
self._wrap_console_writer = None
8582
self._internal_console_port = None
86-
self._internal_aux_port = None
8783
self._custom_adapters = []
8884
self._ubridge_require_privileged_access = False
8985

9086
if self._console is not None:
91-
# use a previously allocated console port
9287
if console_type == "vnc":
9388
vnc_console_start_port_range, vnc_console_end_port_range = self._get_vnc_console_port_range()
9489
self._console = self._manager.port_manager.reserve_tcp_port(
@@ -102,45 +97,25 @@ def __init__(self, name, node_id, project, manager, console=None, console_type="
10297
else:
10398
self._console = self._manager.port_manager.reserve_tcp_port(self._console, self._project)
10499

100+
# We need to allocate aux before giving a random console port
105101
if self._aux is not None:
106-
# use a previously allocated auxiliary console port
107-
if aux_type == "vnc":
108-
# VNC is a special case and the range must be 5900-6000
109-
self._aux = self._manager.port_manager.reserve_tcp_port(
110-
self._aux, self._project, port_range_start=5900, port_range_end=6000
111-
)
112-
elif aux_type == "none":
113-
self._aux = None
114-
else:
115-
self._aux = self._manager.port_manager.reserve_tcp_port(self._aux, self._project)
102+
self._aux = self._manager.port_manager.reserve_tcp_port(self._aux, self._project)
116103

117104
if self._console is None:
118-
# allocate a new console
119105
if console_type == "vnc":
120106
vnc_console_start_port_range, vnc_console_end_port_range = self._get_vnc_console_port_range()
121107
self._console = self._manager.port_manager.get_free_tcp_port(
122108
self._project,
123109
port_range_start=vnc_console_start_port_range,
124-
port_range_end=vnc_console_end_port_range,
125-
)
110+
port_range_end=vnc_console_end_port_range)
126111
elif console_type != "none":
127112
self._console = self._manager.port_manager.get_free_tcp_port(self._project)
128113

129-
if self._aux is None:
130-
# allocate a new auxiliary console
131-
if aux_type == "vnc":
132-
# VNC is a special case and the range must be 5900-6000
133-
self._aux = self._manager.port_manager.get_free_tcp_port(
134-
self._project, port_range_start=5900, port_range_end=6000
135-
)
136-
elif aux_type != "none":
137-
self._aux = self._manager.port_manager.get_free_tcp_port(self._project)
138-
139114
if self._wrap_console:
140115
self._internal_console_port = self._manager.port_manager.get_free_tcp_port(self._project)
141116

142-
if self._wrap_aux:
143-
self._internal_aux_port = self._manager.port_manager.get_free_tcp_port(self._project)
117+
if self._aux is None and allocate_aux:
118+
self._aux = self._manager.port_manager.get_free_tcp_port(self._project)
144119

145120
log.debug("{module}: {name} [{id}] initialized. Console port {console}".format(module=self.manager.module_name,
146121
name=self.name,
@@ -368,9 +343,6 @@ async def close(self):
368343
if self._aux:
369344
self._manager.port_manager.release_tcp_port(self._aux, self._project)
370345
self._aux = None
371-
if self._wrap_aux:
372-
self._manager.port_manager.release_tcp_port(self._internal_aux_port, self._project)
373-
self._internal_aux_port = None
374346

375347
self._closed = True
376348
return True
@@ -394,49 +366,56 @@ def _get_vnc_console_port_range(self):
394366

395367
return vnc_console_start_port_range, vnc_console_end_port_range
396368

397-
async def _wrap_telnet_proxy(self, internal_port, external_port):
369+
async def start_wrap_console(self):
370+
"""
371+
Start a telnet proxy for the console allowing multiple telnet clients
372+
to be connected at the same time
373+
"""
398374

375+
if not self._wrap_console or self._console_type != "telnet":
376+
return
399377
remaining_trial = 60
400378
while True:
401379
try:
402-
(reader, writer) = await asyncio.open_connection(host="127.0.0.1", port=internal_port)
380+
(self._wrap_console_reader, self._wrap_console_writer) = await asyncio.open_connection(
381+
host="127.0.0.1",
382+
port=self._internal_console_port
383+
)
403384
break
404385
except (OSError, ConnectionRefusedError) as e:
405386
if remaining_trial <= 0:
406387
raise e
407388
await asyncio.sleep(0.1)
408389
remaining_trial -= 1
409-
await AsyncioTelnetServer.write_client_intro(writer, echo=True)
410-
server = AsyncioTelnetServer(reader=reader, writer=writer, binary=True, echo=True)
390+
await AsyncioTelnetServer.write_client_intro(self._wrap_console_writer, echo=True)
391+
server = AsyncioTelnetServer(
392+
reader=self._wrap_console_reader,
393+
writer=self._wrap_console_writer,
394+
binary=True,
395+
echo=True
396+
)
411397
# warning: this will raise OSError exception if there is a problem...
412-
telnet_server = await asyncio.start_server(server.run, self._manager.port_manager.console_host, external_port)
413-
self._wrapper_telnet_servers.append(telnet_server)
414-
415-
async def start_wrap_console(self):
416-
"""
417-
Start a Telnet proxy servers for the console and auxiliary console allowing multiple telnet clients
418-
to be connected at the same time
419-
"""
420-
421-
if self._wrap_console and self._console_type == "telnet":
422-
await self._wrap_telnet_proxy(self._internal_console_port, self.console)
423-
log.info("New Telnet proxy server for console started (internal port = {}, external port = {})".format(self._internal_console_port,
424-
self.console))
425-
426-
if self._wrap_aux and self._aux_type == "telnet":
427-
await self._wrap_telnet_proxy(self._internal_aux_port, self.aux)
428-
log.info("New Telnet proxy server for auxiliary console started (internal port = {}, external port = {})".format(self._internal_aux_port,
429-
self.aux))
398+
self._wrapper_telnet_server = await asyncio.start_server(
399+
server.run,
400+
self._manager.port_manager.console_host,
401+
self.console
402+
)
430403

431404
async def stop_wrap_console(self):
432405
"""
433-
Stops the telnet proxy servers.
406+
Stops the telnet proxy.
434407
"""
435408

436-
for telnet_proxy_server in self._wrapper_telnet_servers:
437-
telnet_proxy_server.close()
438-
await telnet_proxy_server.wait_closed()
439-
self._wrapper_telnet_servers = []
409+
if self._wrapper_telnet_server:
410+
self._wrap_console_writer.close()
411+
if sys.version_info >= (3, 7, 0):
412+
try:
413+
await self._wrap_console_writer.wait_closed()
414+
except ConnectionResetError:
415+
pass
416+
self._wrapper_telnet_server.close()
417+
await self._wrapper_telnet_server.wait_closed()
418+
self._wrapper_telnet_server = None
440419

441420
async def reset_wrap_console(self):
442421
"""
@@ -513,6 +492,22 @@ async def telnet_forward(telnet_reader):
513492

514493
return ws
515494

495+
@property
496+
def allocate_aux(self):
497+
"""
498+
:returns: Boolean allocate or not an aux console
499+
"""
500+
501+
return self._allocate_aux
502+
503+
@allocate_aux.setter
504+
def allocate_aux(self, allocate_aux):
505+
"""
506+
:returns: Boolean allocate or not an aux console
507+
"""
508+
509+
self._allocate_aux = allocate_aux
510+
516511
@property
517512
def aux(self):
518513
"""
@@ -531,25 +526,18 @@ def aux(self, aux):
531526
:params aux: Console port (integer) or None to free the port
532527
"""
533528

534-
if aux == self._aux or self._aux_type == "none":
529+
if aux == self._aux:
535530
return
536531

537-
if self._aux_type == "vnc" and aux is not None and aux < 5900:
538-
raise NodeError("VNC auxiliary console require a port superior or equal to 5900, current port is {}".format(aux))
539-
540532
if self._aux:
541533
self._manager.port_manager.release_tcp_port(self._aux, self._project)
542534
self._aux = None
543535
if aux is not None:
544-
if self._aux_type == "vnc":
545-
self._aux = self._manager.port_manager.reserve_tcp_port(aux, self._project, port_range_start=5900, port_range_end=6000)
546-
else:
547-
self._aux = self._manager.port_manager.reserve_tcp_port(aux, self._project)
548-
549-
log.info("{module}: '{name}' [{id}]: auxiliary console port set to {port}".format(module=self.manager.module_name,
550-
name=self.name,
551-
id=self.id,
552-
port=aux))
536+
self._aux = self._manager.port_manager.reserve_tcp_port(aux, self._project)
537+
log.info("{module}: '{name}' [{id}]: aux port set to {port}".format(module=self.manager.module_name,
538+
name=self.name,
539+
id=self.id,
540+
port=aux))
553541

554542
@property
555543
def console(self):
@@ -637,42 +625,6 @@ def console_type(self, console_type):
637625
console_type=console_type,
638626
console=self.console))
639627

640-
@property
641-
def aux_type(self):
642-
"""
643-
Returns the auxiliary console type for this node.
644-
:returns: aux type (string)
645-
"""
646-
647-
return self._aux_type
648-
649-
@aux_type.setter
650-
def aux_type(self, aux_type):
651-
"""
652-
Sets the auxiliary console type for this node.
653-
:param aux_type: console type (string)
654-
"""
655-
656-
if aux_type != self._aux_type:
657-
# get a new port if the aux type change
658-
if self._aux:
659-
self._manager.port_manager.release_tcp_port(self._aux, self._project)
660-
if aux_type == "none":
661-
# no need to allocate a port when the auxiliary console type is none
662-
self._aux = None
663-
elif aux_type == "vnc":
664-
# VNC is a special case and the range must be 5900-6000
665-
self._aux = self._manager.port_manager.get_free_tcp_port(self._project, 5900, 6000)
666-
else:
667-
self._aux = self._manager.port_manager.get_free_tcp_port(self._project)
668-
669-
self._aux_type = aux_type
670-
log.info("{module}: '{name}' [{id}]: console type set to {aux_type} (auxiliary console port is {aux})".format(module=self.manager.module_name,
671-
name=self.name,
672-
id=self.id,
673-
aux_type=aux_type,
674-
aux=self.aux))
675-
676628
@property
677629
def ubridge(self):
678630
"""

gns3server/compute/docker/docker_vm.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,8 @@ class DockerVM(BaseNode):
6060
:param manager: Manager instance
6161
:param image: Docker image
6262
:param console: TCP console port
63-
:param console_type: console type
63+
:param console_type: Console type
6464
:param aux: TCP aux console port
65-
:param aux_type: auxiliary console type
6665
:param console_resolution: Resolution of the VNC display
6766
:param console_http_port: Port to redirect HTTP queries
6867
:param console_http_path: Url part with the path of the web interface
@@ -71,10 +70,10 @@ class DockerVM(BaseNode):
7170
"""
7271

7372
def __init__(self, name, node_id, project, manager, image, console=None, aux=None, start_command=None,
74-
adapters=None, environment=None, console_type="telnet", aux_type="none", console_resolution="1024x768",
73+
adapters=None, environment=None, console_type="telnet", console_resolution="1024x768",
7574
console_http_port=80, console_http_path="/", extra_hosts=None, extra_volumes=[]):
7675

77-
super().__init__(name, node_id, project, manager, console=console, console_type=console_type, aux=aux, aux_type=aux_type)
76+
super().__init__(name, node_id, project, manager, console=console, aux=aux, allocate_aux=True, console_type=console_type)
7877

7978
# force the latest image if no version is specified
8079
if ":" not in image:
@@ -130,7 +129,6 @@ def __json__(self):
130129
"console_http_port": self.console_http_port,
131130
"console_http_path": self.console_http_path,
132131
"aux": self.aux,
133-
"aux_type": self.aux_type,
134132
"start_command": self.start_command,
135133
"status": self.status,
136134
"environment": self.environment,
@@ -548,7 +546,7 @@ async def start(self):
548546
elif self.console_type == "http" or self.console_type == "https":
549547
await self._start_http()
550548

551-
if self.aux_type != "none":
549+
if self.allocate_aux:
552550
await self._start_aux()
553551

554552
self._permissions_fixed = False

gns3server/compute/dynamips/nodes/c1700.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,15 @@ class C1700(Router):
4040
:param manager: Parent VM Manager
4141
:param dynamips_id: ID to use with Dynamips
4242
:param console: console port
43-
:param console_type: console type
4443
:param aux: auxiliary console port
45-
:param aux_type: auxiliary console type
4644
:param chassis: chassis for this router:
4745
1720, 1721, 1750, 1751 or 1760 (default = 1720).
4846
1710 is not supported.
4947
"""
5048

51-
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, aux_type="none", chassis="1720"):
49+
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis="1720"):
5250

53-
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, aux_type, platform="c1700")
51+
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c1700")
5452

5553
# Set default values for this platform (must be the same as Dynamips)
5654
self._ram = 64

gns3server/compute/dynamips/nodes/c2600.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,7 @@ class C2600(Router):
4242
:param manager: Parent VM Manager
4343
:param dynamips_id: ID to use with Dynamips
4444
:param console: console port
45-
:param console_type: console type
4645
:param aux: auxiliary console port
47-
:param aux_type: auxiliary console type
4846
:param chassis: chassis for this router:
4947
2610, 2611, 2620, 2621, 2610XM, 2611XM
5048
2620XM, 2621XM, 2650XM or 2651XM (default = 2610).
@@ -63,9 +61,9 @@ class C2600(Router):
6361
"2650XM": C2600_MB_1FE,
6462
"2651XM": C2600_MB_2FE}
6563

66-
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, aux_type="none", chassis="2610"):
64+
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis="2610"):
6765

68-
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, aux_type, platform="c2600")
66+
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c2600")
6967

7068
# Set default values for this platform (must be the same as Dynamips)
7169
self._ram = 64

gns3server/compute/dynamips/nodes/c2691.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,12 @@ class C2691(Router):
4040
:param manager: Parent VM Manager
4141
:param dynamips_id: ID to use with Dynamips
4242
:param console: console port
43-
:param console_type: console type
4443
:param aux: auxiliary console port
45-
:param aux_type: auxiliary console type
4644
"""
4745

48-
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, aux_type="none", chassis=None):
46+
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis=None):
4947

50-
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, aux_type, platform="c2691")
48+
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c2691")
5149

5250
# Set default values for this platform (must be the same as Dynamips)
5351
self._ram = 128

0 commit comments

Comments
 (0)