@@ -50,14 +50,16 @@ class BaseNode:
50
50
:param node_id: Node instance identifier
51
51
:param project: Project instance
52
52
:param manager: parent node manager
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
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
56
57
:param linked_clone: The node base image is duplicate/overlay (Each node data are independent)
57
58
:param wrap_console: The console is wrapped using AsyncioTelnetServer
59
+ :param wrap_aux: The auxiliary console is wrapped using AsyncioTelnetServer
58
60
"""
59
61
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 ):
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 ):
61
63
62
64
self ._name = name
63
65
self ._usage = ""
@@ -68,22 +70,25 @@ def __init__(self, name, node_id, project, manager, console=None, console_type="
68
70
self ._console = console
69
71
self ._aux = aux
70
72
self ._console_type = console_type
73
+ self ._aux_type = aux_type
71
74
self ._temporary_directory = None
72
75
self ._hw_virtualization = False
73
76
self ._ubridge_hypervisor = None
74
77
self ._closed = False
75
78
self ._node_status = "stopped"
76
79
self ._command_line = ""
77
- self ._allocate_aux = allocate_aux
78
80
self ._wrap_console = wrap_console
79
- self ._wrapper_telnet_server = None
81
+ self ._wrap_aux = wrap_aux
82
+ self ._wrapper_telnet_servers = []
80
83
self ._wrap_console_reader = None
81
84
self ._wrap_console_writer = None
82
85
self ._internal_console_port = None
86
+ self ._internal_aux_port = None
83
87
self ._custom_adapters = []
84
88
self ._ubridge_require_privileged_access = False
85
89
86
90
if self ._console is not None :
91
+ # use a previously allocated console port
87
92
if console_type == "vnc" :
88
93
vnc_console_start_port_range , vnc_console_end_port_range = self ._get_vnc_console_port_range ()
89
94
self ._console = self ._manager .port_manager .reserve_tcp_port (
@@ -97,25 +102,45 @@ def __init__(self, name, node_id, project, manager, console=None, console_type="
97
102
else :
98
103
self ._console = self ._manager .port_manager .reserve_tcp_port (self ._console , self ._project )
99
104
100
- # We need to allocate aux before giving a random console port
101
105
if self ._aux is not None :
102
- self ._aux = self ._manager .port_manager .reserve_tcp_port (self ._aux , self ._project )
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 )
103
116
104
117
if self ._console is None :
118
+ # allocate a new console
105
119
if console_type == "vnc" :
106
120
vnc_console_start_port_range , vnc_console_end_port_range = self ._get_vnc_console_port_range ()
107
121
self ._console = self ._manager .port_manager .get_free_tcp_port (
108
122
self ._project ,
109
123
port_range_start = vnc_console_start_port_range ,
110
- port_range_end = vnc_console_end_port_range )
124
+ port_range_end = vnc_console_end_port_range ,
125
+ )
111
126
elif console_type != "none" :
112
127
self ._console = self ._manager .port_manager .get_free_tcp_port (self ._project )
113
128
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
+
114
139
if self ._wrap_console :
115
140
self ._internal_console_port = self ._manager .port_manager .get_free_tcp_port (self ._project )
116
141
117
- if self ._aux is None and allocate_aux :
118
- self ._aux = self ._manager .port_manager .get_free_tcp_port (self ._project )
142
+ if self ._wrap_aux :
143
+ self ._internal_aux_port = self ._manager .port_manager .get_free_tcp_port (self ._project )
119
144
120
145
log .debug ("{module}: {name} [{id}] initialized. Console port {console}" .format (module = self .manager .module_name ,
121
146
name = self .name ,
@@ -343,6 +368,9 @@ async def close(self):
343
368
if self ._aux :
344
369
self ._manager .port_manager .release_tcp_port (self ._aux , self ._project )
345
370
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
346
374
347
375
self ._closed = True
348
376
return True
@@ -366,56 +394,49 @@ def _get_vnc_console_port_range(self):
366
394
367
395
return vnc_console_start_port_range , vnc_console_end_port_range
368
396
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
- """
397
+ async def _wrap_telnet_proxy (self , internal_port , external_port ):
374
398
375
- if not self ._wrap_console or self ._console_type != "telnet" :
376
- return
377
399
remaining_trial = 60
378
400
while True :
379
401
try :
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
- )
402
+ (reader , writer ) = await asyncio .open_connection (host = "127.0.0.1" , port = internal_port )
384
403
break
385
404
except (OSError , ConnectionRefusedError ) as e :
386
405
if remaining_trial <= 0 :
387
406
raise e
388
407
await asyncio .sleep (0.1 )
389
408
remaining_trial -= 1
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
- )
409
+ await AsyncioTelnetServer .write_client_intro (writer , echo = True )
410
+ server = AsyncioTelnetServer (reader = reader , writer = writer , binary = True , echo = True )
397
411
# warning: this will raise OSError exception if there is a problem...
398
- self ._wrapper_telnet_server = await asyncio .start_server (
399
- server .run ,
400
- self ._manager .port_manager .console_host ,
401
- self .console
402
- )
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 ))
403
430
404
431
async def stop_wrap_console (self ):
405
432
"""
406
- Stops the telnet proxy.
433
+ Stops the telnet proxy servers .
407
434
"""
408
435
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
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 = []
419
440
420
441
async def reset_wrap_console (self ):
421
442
"""
@@ -492,22 +513,6 @@ async def telnet_forward(telnet_reader):
492
513
493
514
return ws
494
515
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
-
511
516
@property
512
517
def aux (self ):
513
518
"""
@@ -526,18 +531,25 @@ def aux(self, aux):
526
531
:params aux: Console port (integer) or None to free the port
527
532
"""
528
533
529
- if aux == self ._aux :
534
+ if aux == self ._aux or self . _aux_type == "none" :
530
535
return
531
536
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
+
532
540
if self ._aux :
533
541
self ._manager .port_manager .release_tcp_port (self ._aux , self ._project )
534
542
self ._aux = None
535
543
if aux is not None :
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 ))
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 ))
541
553
542
554
@property
543
555
def console (self ):
@@ -625,6 +637,43 @@ def console_type(self, console_type):
625
637
console_type = console_type ,
626
638
console = self .console ))
627
639
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
+ print ("SET AUX TYPE" , aux_type )
657
+ if aux_type != self ._aux_type :
658
+ # get a new port if the aux type change
659
+ if self ._aux :
660
+ self ._manager .port_manager .release_tcp_port (self ._aux , self ._project )
661
+ if aux_type == "none" :
662
+ # no need to allocate a port when the auxiliary console type is none
663
+ self ._aux = None
664
+ elif aux_type == "vnc" :
665
+ # VNC is a special case and the range must be 5900-6000
666
+ self ._aux = self ._manager .port_manager .get_free_tcp_port (self ._project , 5900 , 6000 )
667
+ else :
668
+ self ._aux = self ._manager .port_manager .get_free_tcp_port (self ._project )
669
+
670
+ self ._aux_type = aux_type
671
+ log .info ("{module}: '{name}' [{id}]: console type set to {aux_type} (auxiliary console port is {aux})" .format (module = self .manager .module_name ,
672
+ name = self .name ,
673
+ id = self .id ,
674
+ aux_type = aux_type ,
675
+ aux = self .aux ))
676
+
628
677
@property
629
678
def ubridge (self ):
630
679
"""
0 commit comments