mirror of
https://github.com/GNS3/gns3-server
synced 2024-12-29 18:28:11 +00:00
Backport auxiliary console support for Qemu, Docker and Dynamips nodes
This commit is contained in:
parent
1f09a3e6bc
commit
c41c11eb34
@ -50,14 +50,16 @@ class BaseNode:
|
|||||||
:param node_id: Node instance identifier
|
:param node_id: Node instance identifier
|
||||||
:param project: Project instance
|
:param project: Project instance
|
||||||
:param manager: parent node manager
|
:param manager: parent node manager
|
||||||
:param console: TCP console port
|
:param console: console TCP port
|
||||||
:param aux: TCP aux console port
|
:param console_type: console type
|
||||||
:param allocate_aux: Boolean if true will allocate an aux console port
|
:param aux: auxiliary console TCP port
|
||||||
|
:param aux_type: auxiliary console type
|
||||||
:param linked_clone: The node base image is duplicate/overlay (Each node data are independent)
|
:param linked_clone: The node base image is duplicate/overlay (Each node data are independent)
|
||||||
:param wrap_console: The console is wrapped using AsyncioTelnetServer
|
:param wrap_console: The console is wrapped using AsyncioTelnetServer
|
||||||
|
:param wrap_aux: The auxiliary console is wrapped using AsyncioTelnetServer
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, node_id, project, manager, console=None, console_type="telnet", aux=None, allocate_aux=False, linked_clone=True, wrap_console=False):
|
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):
|
||||||
|
|
||||||
self._name = name
|
self._name = name
|
||||||
self._usage = ""
|
self._usage = ""
|
||||||
@ -68,22 +70,25 @@ class BaseNode:
|
|||||||
self._console = console
|
self._console = console
|
||||||
self._aux = aux
|
self._aux = aux
|
||||||
self._console_type = console_type
|
self._console_type = console_type
|
||||||
|
self._aux_type = aux_type
|
||||||
self._temporary_directory = None
|
self._temporary_directory = None
|
||||||
self._hw_virtualization = False
|
self._hw_virtualization = False
|
||||||
self._ubridge_hypervisor = None
|
self._ubridge_hypervisor = None
|
||||||
self._closed = False
|
self._closed = False
|
||||||
self._node_status = "stopped"
|
self._node_status = "stopped"
|
||||||
self._command_line = ""
|
self._command_line = ""
|
||||||
self._allocate_aux = allocate_aux
|
|
||||||
self._wrap_console = wrap_console
|
self._wrap_console = wrap_console
|
||||||
self._wrapper_telnet_server = None
|
self._wrap_aux = wrap_aux
|
||||||
|
self._wrapper_telnet_servers = []
|
||||||
self._wrap_console_reader = None
|
self._wrap_console_reader = None
|
||||||
self._wrap_console_writer = None
|
self._wrap_console_writer = None
|
||||||
self._internal_console_port = None
|
self._internal_console_port = None
|
||||||
|
self._internal_aux_port = None
|
||||||
self._custom_adapters = []
|
self._custom_adapters = []
|
||||||
self._ubridge_require_privileged_access = False
|
self._ubridge_require_privileged_access = False
|
||||||
|
|
||||||
if self._console is not None:
|
if self._console is not None:
|
||||||
|
# use a previously allocated console port
|
||||||
if console_type == "vnc":
|
if console_type == "vnc":
|
||||||
vnc_console_start_port_range, vnc_console_end_port_range = self._get_vnc_console_port_range()
|
vnc_console_start_port_range, vnc_console_end_port_range = self._get_vnc_console_port_range()
|
||||||
self._console = self._manager.port_manager.reserve_tcp_port(
|
self._console = self._manager.port_manager.reserve_tcp_port(
|
||||||
@ -97,25 +102,45 @@ class BaseNode:
|
|||||||
else:
|
else:
|
||||||
self._console = self._manager.port_manager.reserve_tcp_port(self._console, self._project)
|
self._console = self._manager.port_manager.reserve_tcp_port(self._console, self._project)
|
||||||
|
|
||||||
# We need to allocate aux before giving a random console port
|
|
||||||
if self._aux is not None:
|
if self._aux is not None:
|
||||||
self._aux = self._manager.port_manager.reserve_tcp_port(self._aux, self._project)
|
# use a previously allocated auxiliary console port
|
||||||
|
if aux_type == "vnc":
|
||||||
|
# VNC is a special case and the range must be 5900-6000
|
||||||
|
self._aux = self._manager.port_manager.reserve_tcp_port(
|
||||||
|
self._aux, self._project, port_range_start=5900, port_range_end=6000
|
||||||
|
)
|
||||||
|
elif aux_type == "none":
|
||||||
|
self._aux = None
|
||||||
|
else:
|
||||||
|
self._aux = self._manager.port_manager.reserve_tcp_port(self._aux, self._project)
|
||||||
|
|
||||||
if self._console is None:
|
if self._console is None:
|
||||||
|
# allocate a new console
|
||||||
if console_type == "vnc":
|
if console_type == "vnc":
|
||||||
vnc_console_start_port_range, vnc_console_end_port_range = self._get_vnc_console_port_range()
|
vnc_console_start_port_range, vnc_console_end_port_range = self._get_vnc_console_port_range()
|
||||||
self._console = self._manager.port_manager.get_free_tcp_port(
|
self._console = self._manager.port_manager.get_free_tcp_port(
|
||||||
self._project,
|
self._project,
|
||||||
port_range_start=vnc_console_start_port_range,
|
port_range_start=vnc_console_start_port_range,
|
||||||
port_range_end=vnc_console_end_port_range)
|
port_range_end=vnc_console_end_port_range,
|
||||||
|
)
|
||||||
elif console_type != "none":
|
elif console_type != "none":
|
||||||
self._console = self._manager.port_manager.get_free_tcp_port(self._project)
|
self._console = self._manager.port_manager.get_free_tcp_port(self._project)
|
||||||
|
|
||||||
|
if self._aux is None:
|
||||||
|
# allocate a new auxiliary console
|
||||||
|
if aux_type == "vnc":
|
||||||
|
# VNC is a special case and the range must be 5900-6000
|
||||||
|
self._aux = self._manager.port_manager.get_free_tcp_port(
|
||||||
|
self._project, port_range_start=5900, port_range_end=6000
|
||||||
|
)
|
||||||
|
elif aux_type != "none":
|
||||||
|
self._aux = self._manager.port_manager.get_free_tcp_port(self._project)
|
||||||
|
|
||||||
if self._wrap_console:
|
if self._wrap_console:
|
||||||
self._internal_console_port = self._manager.port_manager.get_free_tcp_port(self._project)
|
self._internal_console_port = self._manager.port_manager.get_free_tcp_port(self._project)
|
||||||
|
|
||||||
if self._aux is None and allocate_aux:
|
if self._wrap_aux:
|
||||||
self._aux = self._manager.port_manager.get_free_tcp_port(self._project)
|
self._internal_aux_port = 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,
|
log.debug("{module}: {name} [{id}] initialized. Console port {console}".format(module=self.manager.module_name,
|
||||||
name=self.name,
|
name=self.name,
|
||||||
@ -343,6 +368,9 @@ class BaseNode:
|
|||||||
if self._aux:
|
if self._aux:
|
||||||
self._manager.port_manager.release_tcp_port(self._aux, self._project)
|
self._manager.port_manager.release_tcp_port(self._aux, self._project)
|
||||||
self._aux = None
|
self._aux = None
|
||||||
|
if self._wrap_aux:
|
||||||
|
self._manager.port_manager.release_tcp_port(self._internal_aux_port, self._project)
|
||||||
|
self._internal_aux_port = None
|
||||||
|
|
||||||
self._closed = True
|
self._closed = True
|
||||||
return True
|
return True
|
||||||
@ -366,56 +394,49 @@ class BaseNode:
|
|||||||
|
|
||||||
return vnc_console_start_port_range, vnc_console_end_port_range
|
return vnc_console_start_port_range, vnc_console_end_port_range
|
||||||
|
|
||||||
async def start_wrap_console(self):
|
async def _wrap_telnet_proxy(self, internal_port, external_port):
|
||||||
"""
|
|
||||||
Start a telnet proxy for the console allowing multiple telnet clients
|
|
||||||
to be connected at the same time
|
|
||||||
"""
|
|
||||||
|
|
||||||
if not self._wrap_console or self._console_type != "telnet":
|
|
||||||
return
|
|
||||||
remaining_trial = 60
|
remaining_trial = 60
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
(self._wrap_console_reader, self._wrap_console_writer) = await asyncio.open_connection(
|
(reader, writer) = await asyncio.open_connection(host="127.0.0.1", port=internal_port)
|
||||||
host="127.0.0.1",
|
|
||||||
port=self._internal_console_port
|
|
||||||
)
|
|
||||||
break
|
break
|
||||||
except (OSError, ConnectionRefusedError) as e:
|
except (OSError, ConnectionRefusedError) as e:
|
||||||
if remaining_trial <= 0:
|
if remaining_trial <= 0:
|
||||||
raise e
|
raise e
|
||||||
await asyncio.sleep(0.1)
|
await asyncio.sleep(0.1)
|
||||||
remaining_trial -= 1
|
remaining_trial -= 1
|
||||||
await AsyncioTelnetServer.write_client_intro(self._wrap_console_writer, echo=True)
|
await AsyncioTelnetServer.write_client_intro(writer, echo=True)
|
||||||
server = AsyncioTelnetServer(
|
server = AsyncioTelnetServer(reader=reader, writer=writer, binary=True, echo=True)
|
||||||
reader=self._wrap_console_reader,
|
|
||||||
writer=self._wrap_console_writer,
|
|
||||||
binary=True,
|
|
||||||
echo=True
|
|
||||||
)
|
|
||||||
# warning: this will raise OSError exception if there is a problem...
|
# warning: this will raise OSError exception if there is a problem...
|
||||||
self._wrapper_telnet_server = await asyncio.start_server(
|
telnet_server = await asyncio.start_server(server.run, self._manager.port_manager.console_host, external_port)
|
||||||
server.run,
|
self._wrapper_telnet_servers.append(telnet_server)
|
||||||
self._manager.port_manager.console_host,
|
|
||||||
self.console
|
async def start_wrap_console(self):
|
||||||
)
|
"""
|
||||||
|
Start a Telnet proxy servers for the console and auxiliary console allowing multiple telnet clients
|
||||||
|
to be connected at the same time
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._wrap_console and self._console_type == "telnet":
|
||||||
|
await self._wrap_telnet_proxy(self._internal_console_port, self.console)
|
||||||
|
log.info("New Telnet proxy server for console started (internal port = {}, external port = {})".format(self._internal_console_port,
|
||||||
|
self.console))
|
||||||
|
|
||||||
|
if self._wrap_aux and self._aux_type == "telnet":
|
||||||
|
await self._wrap_telnet_proxy(self._internal_aux_port, self.aux)
|
||||||
|
log.info("New Telnet proxy server for auxiliary console started (internal port = {}, external port = {})".format(self._internal_aux_port,
|
||||||
|
self.aux))
|
||||||
|
|
||||||
async def stop_wrap_console(self):
|
async def stop_wrap_console(self):
|
||||||
"""
|
"""
|
||||||
Stops the telnet proxy.
|
Stops the telnet proxy servers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if self._wrapper_telnet_server:
|
for telnet_proxy_server in self._wrapper_telnet_servers:
|
||||||
self._wrap_console_writer.close()
|
telnet_proxy_server.close()
|
||||||
if sys.version_info >= (3, 7, 0):
|
await telnet_proxy_server.wait_closed()
|
||||||
try:
|
self._wrapper_telnet_servers = []
|
||||||
await self._wrap_console_writer.wait_closed()
|
|
||||||
except ConnectionResetError:
|
|
||||||
pass
|
|
||||||
self._wrapper_telnet_server.close()
|
|
||||||
await self._wrapper_telnet_server.wait_closed()
|
|
||||||
self._wrapper_telnet_server = None
|
|
||||||
|
|
||||||
async def reset_wrap_console(self):
|
async def reset_wrap_console(self):
|
||||||
"""
|
"""
|
||||||
@ -492,22 +513,6 @@ class BaseNode:
|
|||||||
|
|
||||||
return ws
|
return ws
|
||||||
|
|
||||||
@property
|
|
||||||
def allocate_aux(self):
|
|
||||||
"""
|
|
||||||
:returns: Boolean allocate or not an aux console
|
|
||||||
"""
|
|
||||||
|
|
||||||
return self._allocate_aux
|
|
||||||
|
|
||||||
@allocate_aux.setter
|
|
||||||
def allocate_aux(self, allocate_aux):
|
|
||||||
"""
|
|
||||||
:returns: Boolean allocate or not an aux console
|
|
||||||
"""
|
|
||||||
|
|
||||||
self._allocate_aux = allocate_aux
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def aux(self):
|
def aux(self):
|
||||||
"""
|
"""
|
||||||
@ -526,18 +531,25 @@ class BaseNode:
|
|||||||
:params aux: Console port (integer) or None to free the port
|
:params aux: Console port (integer) or None to free the port
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if aux == self._aux:
|
if aux == self._aux or self._aux_type == "none":
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if self._aux_type == "vnc" and aux is not None and aux < 5900:
|
||||||
|
raise NodeError("VNC auxiliary console require a port superior or equal to 5900, current port is {}".format(aux))
|
||||||
|
|
||||||
if self._aux:
|
if self._aux:
|
||||||
self._manager.port_manager.release_tcp_port(self._aux, self._project)
|
self._manager.port_manager.release_tcp_port(self._aux, self._project)
|
||||||
self._aux = None
|
self._aux = None
|
||||||
if aux is not None:
|
if aux is not None:
|
||||||
self._aux = self._manager.port_manager.reserve_tcp_port(aux, self._project)
|
if self._aux_type == "vnc":
|
||||||
log.info("{module}: '{name}' [{id}]: aux port set to {port}".format(module=self.manager.module_name,
|
self._aux = self._manager.port_manager.reserve_tcp_port(aux, self._project, port_range_start=5900, port_range_end=6000)
|
||||||
name=self.name,
|
else:
|
||||||
id=self.id,
|
self._aux = self._manager.port_manager.reserve_tcp_port(aux, self._project)
|
||||||
port=aux))
|
|
||||||
|
log.info("{module}: '{name}' [{id}]: auxiliary console port set to {port}".format(module=self.manager.module_name,
|
||||||
|
name=self.name,
|
||||||
|
id=self.id,
|
||||||
|
port=aux))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def console(self):
|
def console(self):
|
||||||
@ -625,6 +637,43 @@ class BaseNode:
|
|||||||
console_type=console_type,
|
console_type=console_type,
|
||||||
console=self.console))
|
console=self.console))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def aux_type(self):
|
||||||
|
"""
|
||||||
|
Returns the auxiliary console type for this node.
|
||||||
|
:returns: aux type (string)
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self._aux_type
|
||||||
|
|
||||||
|
@aux_type.setter
|
||||||
|
def aux_type(self, aux_type):
|
||||||
|
"""
|
||||||
|
Sets the auxiliary console type for this node.
|
||||||
|
:param aux_type: console type (string)
|
||||||
|
"""
|
||||||
|
|
||||||
|
print("SET AUX TYPE", aux_type)
|
||||||
|
if aux_type != self._aux_type:
|
||||||
|
# get a new port if the aux type change
|
||||||
|
if self._aux:
|
||||||
|
self._manager.port_manager.release_tcp_port(self._aux, self._project)
|
||||||
|
if aux_type == "none":
|
||||||
|
# no need to allocate a port when the auxiliary console type is none
|
||||||
|
self._aux = None
|
||||||
|
elif aux_type == "vnc":
|
||||||
|
# VNC is a special case and the range must be 5900-6000
|
||||||
|
self._aux = self._manager.port_manager.get_free_tcp_port(self._project, 5900, 6000)
|
||||||
|
else:
|
||||||
|
self._aux = self._manager.port_manager.get_free_tcp_port(self._project)
|
||||||
|
|
||||||
|
self._aux_type = aux_type
|
||||||
|
log.info("{module}: '{name}' [{id}]: console type set to {aux_type} (auxiliary console port is {aux})".format(module=self.manager.module_name,
|
||||||
|
name=self.name,
|
||||||
|
id=self.id,
|
||||||
|
aux_type=aux_type,
|
||||||
|
aux=self.aux))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ubridge(self):
|
def ubridge(self):
|
||||||
"""
|
"""
|
||||||
|
@ -60,8 +60,9 @@ class DockerVM(BaseNode):
|
|||||||
:param manager: Manager instance
|
:param manager: Manager instance
|
||||||
:param image: Docker image
|
:param image: Docker image
|
||||||
:param console: TCP console port
|
:param console: TCP console port
|
||||||
:param console_type: Console type
|
:param console_type: console type
|
||||||
:param aux: TCP aux console port
|
:param aux: TCP aux console port
|
||||||
|
:param aux_type: auxiliary console type
|
||||||
:param console_resolution: Resolution of the VNC display
|
:param console_resolution: Resolution of the VNC display
|
||||||
:param console_http_port: Port to redirect HTTP queries
|
:param console_http_port: Port to redirect HTTP queries
|
||||||
:param console_http_path: Url part with the path of the web interface
|
:param console_http_path: Url part with the path of the web interface
|
||||||
@ -70,10 +71,10 @@ class DockerVM(BaseNode):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, node_id, project, manager, image, console=None, aux=None, start_command=None,
|
def __init__(self, name, node_id, project, manager, image, console=None, aux=None, start_command=None,
|
||||||
adapters=None, environment=None, console_type="telnet", console_resolution="1024x768",
|
adapters=None, environment=None, console_type="telnet", aux_type="none", console_resolution="1024x768",
|
||||||
console_http_port=80, console_http_path="/", extra_hosts=None, extra_volumes=[]):
|
console_http_port=80, console_http_path="/", extra_hosts=None, extra_volumes=[]):
|
||||||
|
|
||||||
super().__init__(name, node_id, project, manager, console=console, aux=aux, allocate_aux=True, console_type=console_type)
|
super().__init__(name, node_id, project, manager, console=console, console_type=console_type, aux=aux, aux_type=aux_type)
|
||||||
|
|
||||||
# force the latest image if no version is specified
|
# force the latest image if no version is specified
|
||||||
if ":" not in image:
|
if ":" not in image:
|
||||||
@ -129,6 +130,7 @@ class DockerVM(BaseNode):
|
|||||||
"console_http_port": self.console_http_port,
|
"console_http_port": self.console_http_port,
|
||||||
"console_http_path": self.console_http_path,
|
"console_http_path": self.console_http_path,
|
||||||
"aux": self.aux,
|
"aux": self.aux,
|
||||||
|
"aux_type": self.aux_type,
|
||||||
"start_command": self.start_command,
|
"start_command": self.start_command,
|
||||||
"status": self.status,
|
"status": self.status,
|
||||||
"environment": self.environment,
|
"environment": self.environment,
|
||||||
@ -546,7 +548,7 @@ class DockerVM(BaseNode):
|
|||||||
elif self.console_type == "http" or self.console_type == "https":
|
elif self.console_type == "http" or self.console_type == "https":
|
||||||
await self._start_http()
|
await self._start_http()
|
||||||
|
|
||||||
if self.allocate_aux:
|
if self.aux_type != "none":
|
||||||
await self._start_aux()
|
await self._start_aux()
|
||||||
|
|
||||||
self._permissions_fixed = False
|
self._permissions_fixed = False
|
||||||
|
@ -527,6 +527,10 @@ class Dynamips(BaseManager):
|
|||||||
if usage is not None and usage != vm.usage:
|
if usage is not None and usage != vm.usage:
|
||||||
vm.usage = usage
|
vm.usage = usage
|
||||||
|
|
||||||
|
aux_type = settings.get("aux_type")
|
||||||
|
if aux_type is not None and aux_type != vm.aux_type:
|
||||||
|
vm.aux_type = aux_type
|
||||||
|
|
||||||
# update the configs if needed
|
# update the configs if needed
|
||||||
await self.set_vm_configs(vm, settings)
|
await self.set_vm_configs(vm, settings)
|
||||||
|
|
||||||
|
@ -40,15 +40,17 @@ class C1700(Router):
|
|||||||
:param manager: Parent VM Manager
|
:param manager: Parent VM Manager
|
||||||
:param dynamips_id: ID to use with Dynamips
|
:param dynamips_id: ID to use with Dynamips
|
||||||
:param console: console port
|
:param console: console port
|
||||||
|
:param console_type: console type
|
||||||
:param aux: auxiliary console port
|
:param aux: auxiliary console port
|
||||||
|
:param aux_type: auxiliary console type
|
||||||
:param chassis: chassis for this router:
|
:param chassis: chassis for this router:
|
||||||
1720, 1721, 1750, 1751 or 1760 (default = 1720).
|
1720, 1721, 1750, 1751 or 1760 (default = 1720).
|
||||||
1710 is not supported.
|
1710 is not supported.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis="1720"):
|
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, aux_type="none", chassis="1720"):
|
||||||
|
|
||||||
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c1700")
|
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, aux_type, platform="c1700")
|
||||||
|
|
||||||
# Set default values for this platform (must be the same as Dynamips)
|
# Set default values for this platform (must be the same as Dynamips)
|
||||||
self._ram = 64
|
self._ram = 64
|
||||||
|
@ -42,7 +42,9 @@ class C2600(Router):
|
|||||||
:param manager: Parent VM Manager
|
:param manager: Parent VM Manager
|
||||||
:param dynamips_id: ID to use with Dynamips
|
:param dynamips_id: ID to use with Dynamips
|
||||||
:param console: console port
|
:param console: console port
|
||||||
|
:param console_type: console type
|
||||||
:param aux: auxiliary console port
|
:param aux: auxiliary console port
|
||||||
|
:param aux_type: auxiliary console type
|
||||||
:param chassis: chassis for this router:
|
:param chassis: chassis for this router:
|
||||||
2610, 2611, 2620, 2621, 2610XM, 2611XM
|
2610, 2611, 2620, 2621, 2610XM, 2611XM
|
||||||
2620XM, 2621XM, 2650XM or 2651XM (default = 2610).
|
2620XM, 2621XM, 2650XM or 2651XM (default = 2610).
|
||||||
@ -61,9 +63,9 @@ class C2600(Router):
|
|||||||
"2650XM": C2600_MB_1FE,
|
"2650XM": C2600_MB_1FE,
|
||||||
"2651XM": C2600_MB_2FE}
|
"2651XM": C2600_MB_2FE}
|
||||||
|
|
||||||
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis="2610"):
|
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, aux_type="none", chassis="2610"):
|
||||||
|
|
||||||
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c2600")
|
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, aux_type, platform="c2600")
|
||||||
|
|
||||||
# Set default values for this platform (must be the same as Dynamips)
|
# Set default values for this platform (must be the same as Dynamips)
|
||||||
self._ram = 64
|
self._ram = 64
|
||||||
|
@ -40,12 +40,14 @@ class C2691(Router):
|
|||||||
:param manager: Parent VM Manager
|
:param manager: Parent VM Manager
|
||||||
:param dynamips_id: ID to use with Dynamips
|
:param dynamips_id: ID to use with Dynamips
|
||||||
:param console: console port
|
:param console: console port
|
||||||
|
:param console_type: console type
|
||||||
:param aux: auxiliary console port
|
:param aux: auxiliary console port
|
||||||
|
:param aux_type: auxiliary console type
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis=None):
|
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, aux_type="none", chassis=None):
|
||||||
|
|
||||||
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c2691")
|
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, aux_type, platform="c2691")
|
||||||
|
|
||||||
# Set default values for this platform (must be the same as Dynamips)
|
# Set default values for this platform (must be the same as Dynamips)
|
||||||
self._ram = 128
|
self._ram = 128
|
||||||
|
@ -39,14 +39,16 @@ class C3600(Router):
|
|||||||
:param manager: Parent VM Manager
|
:param manager: Parent VM Manager
|
||||||
:param dynamips_id: ID to use with Dynamips
|
:param dynamips_id: ID to use with Dynamips
|
||||||
:param console: console port
|
:param console: console port
|
||||||
|
:param console_type: console type
|
||||||
:param aux: auxiliary console port
|
:param aux: auxiliary console port
|
||||||
|
:param aux_type: auxiliary console type
|
||||||
:param chassis: chassis for this router:
|
:param chassis: chassis for this router:
|
||||||
3620, 3640 or 3660 (default = 3640).
|
3620, 3640 or 3660 (default = 3640).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis="3640"):
|
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, aux_type="none", chassis="3640"):
|
||||||
|
|
||||||
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c3600")
|
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, aux_type, platform="c3600")
|
||||||
|
|
||||||
# Set default values for this platform (must be the same as Dynamips)
|
# Set default values for this platform (must be the same as Dynamips)
|
||||||
self._ram = 128
|
self._ram = 128
|
||||||
|
@ -40,12 +40,14 @@ class C3725(Router):
|
|||||||
:param manager: Parent VM Manager
|
:param manager: Parent VM Manager
|
||||||
:param dynamips_id: ID to use with Dynamips
|
:param dynamips_id: ID to use with Dynamips
|
||||||
:param console: console port
|
:param console: console port
|
||||||
|
:param console_type: console type
|
||||||
:param aux: auxiliary console port
|
:param aux: auxiliary console port
|
||||||
|
:param aux_type: auxiliary console type
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis=None):
|
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, aux_type="none", chassis=None):
|
||||||
|
|
||||||
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c3725")
|
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, aux_type, platform="c3725")
|
||||||
|
|
||||||
# Set default values for this platform (must be the same as Dynamips)
|
# Set default values for this platform (must be the same as Dynamips)
|
||||||
self._ram = 128
|
self._ram = 128
|
||||||
|
@ -40,12 +40,14 @@ class C3745(Router):
|
|||||||
:param manager: Parent VM Manager
|
:param manager: Parent VM Manager
|
||||||
:param dynamips_id: ID to use with Dynamips
|
:param dynamips_id: ID to use with Dynamips
|
||||||
:param console: console port
|
:param console: console port
|
||||||
|
:param console_type: console type
|
||||||
:param aux: auxiliary console port
|
:param aux: auxiliary console port
|
||||||
|
:param aux_type: auxiliary console type
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, chassis=None):
|
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, aux_type="none", chassis=None):
|
||||||
|
|
||||||
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c3745")
|
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, aux_type, platform="c3745")
|
||||||
|
|
||||||
# Set default values for this platform (must be the same as Dynamips)
|
# Set default values for this platform (must be the same as Dynamips)
|
||||||
self._ram = 128
|
self._ram = 128
|
||||||
|
@ -42,13 +42,15 @@ class C7200(Router):
|
|||||||
:param manager: Parent VM Manager
|
:param manager: Parent VM Manager
|
||||||
:param dynamips_id: ID to use with Dynamips
|
:param dynamips_id: ID to use with Dynamips
|
||||||
:param console: console port
|
:param console: console port
|
||||||
|
:param console_type: console type
|
||||||
:param aux: auxiliary console port
|
:param aux: auxiliary console port
|
||||||
|
:param aux_type: auxiliary console type
|
||||||
:param npe: Default NPE
|
:param npe: Default NPE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, npe="npe-400", chassis=None):
|
def __init__(self, name, node_id, project, manager, dynamips_id, console=None, console_type="telnet", aux=None, aux_type="none", npe="npe-400", chassis=None):
|
||||||
|
|
||||||
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, platform="c7200")
|
super().__init__(name, node_id, project, manager, dynamips_id, console, console_type, aux, aux_type, platform="c7200")
|
||||||
|
|
||||||
# Set default values for this platform (must be the same as Dynamips)
|
# Set default values for this platform (must be the same as Dynamips)
|
||||||
self._ram = 256
|
self._ram = 256
|
||||||
|
@ -52,7 +52,9 @@ class Router(BaseNode):
|
|||||||
:param manager: Parent VM Manager
|
:param manager: Parent VM Manager
|
||||||
:param dynamips_id: ID to use with Dynamips
|
:param dynamips_id: ID to use with Dynamips
|
||||||
:param console: console port
|
:param console: console port
|
||||||
|
:param console_type: console type
|
||||||
:param aux: auxiliary console port
|
:param aux: auxiliary console port
|
||||||
|
:param aux_type: auxiliary console type
|
||||||
:param platform: Platform of this router
|
:param platform: Platform of this router
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -61,9 +63,9 @@ class Router(BaseNode):
|
|||||||
2: "running",
|
2: "running",
|
||||||
3: "suspended"}
|
3: "suspended"}
|
||||||
|
|
||||||
def __init__(self, name, node_id, project, manager, dynamips_id=None, console=None, console_type="telnet", aux=None, platform="c7200", hypervisor=None, ghost_flag=False):
|
def __init__(self, name, node_id, project, manager, dynamips_id=None, console=None, console_type="telnet", aux=None, aux_type="none", platform="c7200", hypervisor=None, ghost_flag=False):
|
||||||
|
|
||||||
super().__init__(name, node_id, project, manager, console=console, console_type=console_type, aux=aux, allocate_aux=aux)
|
super().__init__(name, node_id, project, manager, console=console, console_type=console_type, aux=aux, aux_type=aux_type)
|
||||||
|
|
||||||
self._working_directory = os.path.join(self.project.module_working_directory(self.manager.module_name.lower()), self.id)
|
self._working_directory = os.path.join(self.project.module_working_directory(self.manager.module_name.lower()), self.id)
|
||||||
try:
|
try:
|
||||||
@ -166,6 +168,7 @@ class Router(BaseNode):
|
|||||||
"console": self.console,
|
"console": self.console,
|
||||||
"console_type": self.console_type,
|
"console_type": self.console_type,
|
||||||
"aux": self.aux,
|
"aux": self.aux,
|
||||||
|
"aux_type": self.aux_type,
|
||||||
"mac_addr": self._mac_addr,
|
"mac_addr": self._mac_addr,
|
||||||
"system_id": self._system_id}
|
"system_id": self._system_id}
|
||||||
|
|
||||||
@ -223,15 +226,14 @@ class Router(BaseNode):
|
|||||||
platform=self._platform,
|
platform=self._platform,
|
||||||
id=self._id))
|
id=self._id))
|
||||||
|
|
||||||
if self._console:
|
if self._console is not None:
|
||||||
await self._hypervisor.send('vm set_con_tcp_port "{name}" {console}'.format(name=self._name, console=self._console))
|
await self._hypervisor.send('vm set_con_tcp_port "{name}" {console}'.format(name=self._name, console=self._console))
|
||||||
|
|
||||||
if self.aux is not None:
|
if self.aux is not None:
|
||||||
await self._hypervisor.send('vm set_aux_tcp_port "{name}" {aux}'.format(name=self._name, aux=self.aux))
|
await self._hypervisor.send('vm set_aux_tcp_port "{name}" {aux}'.format(name=self._name, aux=self.aux))
|
||||||
|
|
||||||
# get the default base MAC address
|
# get the default base MAC address
|
||||||
mac_addr = await self._hypervisor.send('{platform} get_mac_addr "{name}"'.format(platform=self._platform,
|
mac_addr = await self._hypervisor.send('{platform} get_mac_addr "{name}"'.format(platform=self._platform, name=self._name))
|
||||||
name=self._name))
|
|
||||||
self._mac_addr = mac_addr[0]
|
self._mac_addr = mac_addr[0]
|
||||||
|
|
||||||
self._hypervisor.devices.append(self)
|
self._hypervisor.devices.append(self)
|
||||||
|
@ -76,9 +76,9 @@ class QemuVM(BaseNode):
|
|||||||
:param platform: Platform to emulate
|
:param platform: Platform to emulate
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name, node_id, project, manager, linked_clone=True, qemu_path=None, console=None, console_type="telnet", platform=None):
|
def __init__(self, name, node_id, project, manager, linked_clone=True, qemu_path=None, console=None, console_type="telnet", aux=None, aux_type="none", platform=None):
|
||||||
|
|
||||||
super().__init__(name, node_id, project, manager, console=console, console_type=console_type, linked_clone=linked_clone, wrap_console=True)
|
super().__init__(name, node_id, project, manager, console=console, console_type=console_type, linked_clone=linked_clone, aux=aux, aux_type=aux_type, wrap_console=True, wrap_aux=True)
|
||||||
server_config = manager.config.get_section_config("Server")
|
server_config = manager.config.get_section_config("Server")
|
||||||
self._host = server_config.get("host", "127.0.0.1")
|
self._host = server_config.get("host", "127.0.0.1")
|
||||||
self._monitor_host = server_config.get("monitor_host", "127.0.0.1")
|
self._monitor_host = server_config.get("monitor_host", "127.0.0.1")
|
||||||
@ -1658,24 +1658,24 @@ class QemuVM(BaseNode):
|
|||||||
|
|
||||||
super(QemuVM, QemuVM).console_type.__set__(self, new_console_type)
|
super(QemuVM, QemuVM).console_type.__set__(self, new_console_type)
|
||||||
|
|
||||||
def _serial_options(self):
|
def _serial_options(self, internal_console_port, external_console_port):
|
||||||
|
|
||||||
if self._console:
|
if external_console_port:
|
||||||
return ["-serial", "telnet:127.0.0.1:{},server,nowait".format(self._internal_console_port)]
|
return ["-serial", "telnet:127.0.0.1:{},server,nowait".format(internal_console_port)]
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def _vnc_options(self):
|
def _vnc_options(self, port):
|
||||||
|
|
||||||
if self._console:
|
if port:
|
||||||
vnc_port = self._console - 5900 # subtract by 5900 to get the display number
|
vnc_port = port - 5900 # subtract by 5900 to get the display number
|
||||||
return ["-vnc", "{}:{}".format(self._manager.port_manager.console_host, vnc_port)]
|
return ["-vnc", "{}:{}".format(self._manager.port_manager.console_host, vnc_port)]
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def _spice_options(self):
|
def _spice_options(self, port):
|
||||||
|
|
||||||
if self._console:
|
if port:
|
||||||
console_host = self._manager.port_manager.console_host
|
console_host = self._manager.port_manager.console_host
|
||||||
if console_host == "0.0.0.0":
|
if console_host == "0.0.0.0":
|
||||||
try:
|
try:
|
||||||
@ -1687,15 +1687,15 @@ class QemuVM(BaseNode):
|
|||||||
except OSError as e:
|
except OSError as e:
|
||||||
raise QemuError("Could not check if IPv6 is enabled: {}".format(e))
|
raise QemuError("Could not check if IPv6 is enabled: {}".format(e))
|
||||||
return ["-spice",
|
return ["-spice",
|
||||||
"addr={},port={},disable-ticketing".format(console_host, self._console),
|
"addr={},port={},disable-ticketing".format(console_host, port),
|
||||||
"-vga", "qxl"]
|
"-vga", "qxl"]
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def _spice_with_agent_options(self):
|
def _spice_with_agent_options(self, port):
|
||||||
|
|
||||||
spice_options = self._spice_options()
|
spice_options = self._spice_options(port)
|
||||||
if self._console:
|
if spice_options:
|
||||||
# agent options (mouse/screen)
|
# agent options (mouse/screen)
|
||||||
agent_options = ["-device", "virtio-serial",
|
agent_options = ["-device", "virtio-serial",
|
||||||
"-chardev", "spicevmc,id=vdagent,debug=0,name=vdagent",
|
"-chardev", "spicevmc,id=vdagent,debug=0,name=vdagent",
|
||||||
@ -1707,6 +1707,36 @@ class QemuVM(BaseNode):
|
|||||||
spice_options.extend(folder_sharing_options)
|
spice_options.extend(folder_sharing_options)
|
||||||
return spice_options
|
return spice_options
|
||||||
|
|
||||||
|
def _console_options(self):
|
||||||
|
|
||||||
|
if self._console_type == "telnet" and self._wrap_console:
|
||||||
|
return self._serial_options(self._internal_console_port, self.console)
|
||||||
|
elif self._console_type == "vnc":
|
||||||
|
return self._vnc_options(self.console)
|
||||||
|
elif self._console_type == "spice":
|
||||||
|
return self._spice_options(self.console)
|
||||||
|
elif self._console_type == "spice+agent":
|
||||||
|
return self._spice_with_agent_options(self.console)
|
||||||
|
elif self._console_type != "none":
|
||||||
|
raise QemuError("Console type {} is unknown".format(self._console_type))
|
||||||
|
|
||||||
|
def _aux_options(self):
|
||||||
|
|
||||||
|
if self._aux_type != "none" and self._aux_type == self._console_type:
|
||||||
|
raise QemuError("Auxiliary console type {} cannot be the same as console type".format(self._aux_type))
|
||||||
|
|
||||||
|
if self._aux_type == "telnet" and self._wrap_aux:
|
||||||
|
return self._serial_options(self._internal_aux_port, self.aux)
|
||||||
|
elif self._aux_type == "vnc":
|
||||||
|
return self._vnc_options(self.aux)
|
||||||
|
elif self._aux_type == "spice":
|
||||||
|
return self._spice_options(self.aux)
|
||||||
|
elif self._aux_type == "spice+agent":
|
||||||
|
return self._spice_with_agent_options(self.aux)
|
||||||
|
elif self._aux_type != "none":
|
||||||
|
raise QemuError("Auxiliary console type {} is unknown".format(self._aux_type))
|
||||||
|
return []
|
||||||
|
|
||||||
def _monitor_options(self):
|
def _monitor_options(self):
|
||||||
|
|
||||||
if self._monitor:
|
if self._monitor:
|
||||||
@ -2408,16 +2438,8 @@ class QemuVM(BaseNode):
|
|||||||
command.extend(self._linux_boot_options())
|
command.extend(self._linux_boot_options())
|
||||||
if "-uuid" not in additional_options:
|
if "-uuid" not in additional_options:
|
||||||
command.extend(["-uuid", self._id])
|
command.extend(["-uuid", self._id])
|
||||||
if self._console_type == "telnet":
|
command.extend(self._console_options())
|
||||||
command.extend(self._serial_options())
|
command.extend(self._aux_options())
|
||||||
elif self._console_type == "vnc":
|
|
||||||
command.extend(self._vnc_options())
|
|
||||||
elif self._console_type == "spice":
|
|
||||||
command.extend(self._spice_options())
|
|
||||||
elif self._console_type == "spice+agent":
|
|
||||||
command.extend(self._spice_with_agent_options())
|
|
||||||
elif self._console_type != "none":
|
|
||||||
raise QemuError("Console type {} is unknown".format(self._console_type))
|
|
||||||
command.extend(self._monitor_options())
|
command.extend(self._monitor_options())
|
||||||
command.extend((await self._network_options()))
|
command.extend((await self._network_options()))
|
||||||
if self.on_close != "save_vm_state":
|
if self.on_close != "save_vm_state":
|
||||||
|
@ -68,6 +68,8 @@ class Node:
|
|||||||
self.name = name
|
self.name = name
|
||||||
self._console = None
|
self._console = None
|
||||||
self._console_type = None
|
self._console_type = None
|
||||||
|
self._aux = None
|
||||||
|
self._aux_type = None
|
||||||
self._properties = None
|
self._properties = None
|
||||||
self._command_line = None
|
self._command_line = None
|
||||||
self._node_directory = None
|
self._node_directory = None
|
||||||
@ -161,6 +163,14 @@ class Node:
|
|||||||
def console(self, val):
|
def console(self, val):
|
||||||
self._console = val
|
self._console = val
|
||||||
|
|
||||||
|
@property
|
||||||
|
def aux(self):
|
||||||
|
return self._aux
|
||||||
|
|
||||||
|
@aux.setter
|
||||||
|
def aux(self, val):
|
||||||
|
self._aux = val
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def console_type(self):
|
def console_type(self):
|
||||||
return self._console_type
|
return self._console_type
|
||||||
@ -169,6 +179,14 @@ class Node:
|
|||||||
def console_type(self, val):
|
def console_type(self, val):
|
||||||
self._console_type = val
|
self._console_type = val
|
||||||
|
|
||||||
|
@property
|
||||||
|
def aux_type(self):
|
||||||
|
return self._aux_type
|
||||||
|
|
||||||
|
@aux_type.setter
|
||||||
|
def aux_type(self, val):
|
||||||
|
self._aux_type = val
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def console_auto_start(self):
|
def console_auto_start(self):
|
||||||
return self._console_auto_start
|
return self._console_auto_start
|
||||||
@ -430,6 +448,8 @@ class Node:
|
|||||||
for key, value in response.items():
|
for key, value in response.items():
|
||||||
if key == "console":
|
if key == "console":
|
||||||
self._console = value
|
self._console = value
|
||||||
|
elif key == "aux":
|
||||||
|
self._aux = value
|
||||||
elif key == "node_directory":
|
elif key == "node_directory":
|
||||||
self._node_directory = value
|
self._node_directory = value
|
||||||
elif key == "command_line":
|
elif key == "command_line":
|
||||||
@ -438,6 +458,8 @@ class Node:
|
|||||||
self._status = value
|
self._status = value
|
||||||
elif key == "console_type":
|
elif key == "console_type":
|
||||||
self._console_type = value
|
self._console_type = value
|
||||||
|
elif key == "aux_type":
|
||||||
|
self._aux_type = value
|
||||||
elif key == "name":
|
elif key == "name":
|
||||||
self.name = value
|
self.name = value
|
||||||
elif key in ["node_id", "project_id", "console_host",
|
elif key in ["node_id", "project_id", "console_host",
|
||||||
@ -480,6 +502,12 @@ class Node:
|
|||||||
if self._console_type and self._node_type not in ("cloud", "nat", "ethernet_hub", "frame_relay_switch", "atm_switch"):
|
if self._console_type and self._node_type not in ("cloud", "nat", "ethernet_hub", "frame_relay_switch", "atm_switch"):
|
||||||
# console_type is not supported by all builtin nodes excepting Ethernet switch
|
# console_type is not supported by all builtin nodes excepting Ethernet switch
|
||||||
data["console_type"] = self._console_type
|
data["console_type"] = self._console_type
|
||||||
|
if self._aux:
|
||||||
|
# aux is optional for builtin nodes
|
||||||
|
data["aux"] = self._aux
|
||||||
|
if self._aux_type and self._node_type not in ("cloud", "nat", "ethernet_switch", "ethernet_hub", "frame_relay_switch", "atm_switch"):
|
||||||
|
# aux_type is not supported by all builtin nodes
|
||||||
|
data["aux_type"] = self._aux_type
|
||||||
if self.custom_adapters:
|
if self.custom_adapters:
|
||||||
data["custom_adapters"] = self.custom_adapters
|
data["custom_adapters"] = self.custom_adapters
|
||||||
|
|
||||||
@ -709,6 +737,8 @@ class Node:
|
|||||||
"console": self._console,
|
"console": self._console,
|
||||||
"console_type": self._console_type,
|
"console_type": self._console_type,
|
||||||
"console_auto_start": self._console_auto_start,
|
"console_auto_start": self._console_auto_start,
|
||||||
|
"aux": self._aux,
|
||||||
|
"aux_type": self._aux_type,
|
||||||
"properties": self._properties,
|
"properties": self._properties,
|
||||||
"label": self._label,
|
"label": self._label,
|
||||||
"x": self._x,
|
"x": self._x,
|
||||||
@ -746,6 +776,8 @@ class Node:
|
|||||||
"console_host": console_host,
|
"console_host": console_host,
|
||||||
"console_type": self._console_type,
|
"console_type": self._console_type,
|
||||||
"console_auto_start": self._console_auto_start,
|
"console_auto_start": self._console_auto_start,
|
||||||
|
"aux": self._aux,
|
||||||
|
"aux_type": self._aux_type,
|
||||||
"command_line": self._command_line,
|
"command_line": self._command_line,
|
||||||
"properties": self._properties,
|
"properties": self._properties,
|
||||||
"status": self._status,
|
"status": self._status,
|
||||||
|
@ -48,21 +48,25 @@ class DockerHandler:
|
|||||||
output=DOCKER_OBJECT_SCHEMA)
|
output=DOCKER_OBJECT_SCHEMA)
|
||||||
async def create(request, response):
|
async def create(request, response):
|
||||||
docker_manager = Docker.instance()
|
docker_manager = Docker.instance()
|
||||||
container = await docker_manager.create_node(request.json.pop("name"),
|
container = await docker_manager.create_node(
|
||||||
request.match_info["project_id"],
|
request.json.pop("name"),
|
||||||
request.json.get("node_id"),
|
request.match_info["project_id"],
|
||||||
image=request.json.pop("image"),
|
request.json.get("node_id"),
|
||||||
start_command=request.json.get("start_command"),
|
image=request.json.pop("image"),
|
||||||
environment=request.json.get("environment"),
|
start_command=request.json.get("start_command"),
|
||||||
adapters=request.json.get("adapters"),
|
environment=request.json.get("environment"),
|
||||||
console=request.json.get("console"),
|
adapters=request.json.get("adapters"),
|
||||||
console_type=request.json.get("console_type"),
|
console=request.json.get("console"),
|
||||||
console_resolution=request.json.get("console_resolution", "1024x768"),
|
console_type=request.json.get("console_type"),
|
||||||
console_http_port=request.json.get("console_http_port", 80),
|
console_resolution=request.json.get("console_resolution", "1024x768"),
|
||||||
console_http_path=request.json.get("console_http_path", "/"),
|
console_http_port=request.json.get("console_http_port", 80),
|
||||||
aux=request.json.get("aux"),
|
console_http_path=request.json.get("console_http_path", "/"),
|
||||||
extra_hosts=request.json.get("extra_hosts"),
|
aux=request.json.get("aux"),
|
||||||
extra_volumes=request.json.get("extra_volumes"))
|
aux_type=request.json.pop("aux_type", "none"),
|
||||||
|
extra_hosts=request.json.get("extra_hosts"),
|
||||||
|
extra_volumes=request.json.get("extra_volumes")
|
||||||
|
)
|
||||||
|
|
||||||
for name, value in request.json.items():
|
for name, value in request.json.items():
|
||||||
if name != "node_id":
|
if name != "node_id":
|
||||||
if hasattr(container, name) and getattr(container, name) != value:
|
if hasattr(container, name) and getattr(container, name) != value:
|
||||||
@ -315,7 +319,7 @@ class DockerHandler:
|
|||||||
container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
|
container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
|
||||||
|
|
||||||
props = [
|
props = [
|
||||||
"name", "console", "aux", "console_type", "console_resolution",
|
"name", "console", "console_type", "aux", "aux_type", "console_resolution",
|
||||||
"console_http_port", "console_http_path", "start_command",
|
"console_http_port", "console_http_path", "start_command",
|
||||||
"environment", "adapters", "mac_address", "custom_adapters", "extra_hosts", "extra_volumes"
|
"environment", "adapters", "mac_address", "custom_adapters", "extra_hosts", "extra_volumes"
|
||||||
]
|
]
|
||||||
|
@ -69,16 +69,19 @@ class DynamipsVMHandler:
|
|||||||
default_chassis = None
|
default_chassis = None
|
||||||
if platform in DEFAULT_CHASSIS:
|
if platform in DEFAULT_CHASSIS:
|
||||||
default_chassis = DEFAULT_CHASSIS[platform]
|
default_chassis = DEFAULT_CHASSIS[platform]
|
||||||
vm = await dynamips_manager.create_node(request.json.pop("name"),
|
vm = await dynamips_manager.create_node(
|
||||||
request.match_info["project_id"],
|
request.json.pop("name"),
|
||||||
request.json.get("node_id"),
|
request.match_info["project_id"],
|
||||||
dynamips_id=request.json.get("dynamips_id"),
|
request.json.get("node_id"),
|
||||||
platform=platform,
|
dynamips_id=request.json.get("dynamips_id"),
|
||||||
console=request.json.get("console"),
|
platform=platform,
|
||||||
console_type=request.json.get("console_type", "telnet"),
|
console=request.json.get("console"),
|
||||||
aux=request.json.get("aux"),
|
console_type=request.json.get("console_type", "telnet"),
|
||||||
chassis=request.json.pop("chassis", default_chassis),
|
aux=request.json.get("aux"),
|
||||||
node_type="dynamips")
|
aux_type=request.json.get("aux_type", "none"),
|
||||||
|
chassis=request.json.pop("chassis", default_chassis),
|
||||||
|
node_type="dynamips"
|
||||||
|
)
|
||||||
await dynamips_manager.update_vm_settings(vm, request.json)
|
await dynamips_manager.update_vm_settings(vm, request.json)
|
||||||
response.set_status(201)
|
response.set_status(201)
|
||||||
response.json(vm)
|
response.json(vm)
|
||||||
|
@ -66,14 +66,18 @@ class QEMUHandler:
|
|||||||
async def create(request, response):
|
async def create(request, response):
|
||||||
|
|
||||||
qemu = Qemu.instance()
|
qemu = Qemu.instance()
|
||||||
vm = await qemu.create_node(request.json.pop("name"),
|
vm = await qemu.create_node(
|
||||||
request.match_info["project_id"],
|
request.json.pop("name"),
|
||||||
request.json.pop("node_id", None),
|
request.match_info["project_id"],
|
||||||
linked_clone=request.json.get("linked_clone", True),
|
request.json.pop("node_id", None),
|
||||||
qemu_path=request.json.pop("qemu_path", None),
|
linked_clone=request.json.get("linked_clone", True),
|
||||||
console=request.json.pop("console", None),
|
qemu_path=request.json.pop("qemu_path", None),
|
||||||
console_type=request.json.pop("console_type", "telnet"),
|
console=request.json.pop("console", None),
|
||||||
platform=request.json.pop("platform", None))
|
console_type=request.json.pop("console_type", "telnet"),
|
||||||
|
aux=request.json.pop("aux", None),
|
||||||
|
aux_type=request.json.pop("aux_type", "none"),
|
||||||
|
platform=request.json.pop("platform", None)
|
||||||
|
)
|
||||||
|
|
||||||
for name, value in request.json.items():
|
for name, value in request.json.items():
|
||||||
if hasattr(vm, name) and getattr(vm, name) != value:
|
if hasattr(vm, name) and getattr(vm, name) != value:
|
||||||
|
@ -65,6 +65,10 @@ DOCKER_CREATE_SCHEMA = {
|
|||||||
"maximum": 65535,
|
"maximum": 65535,
|
||||||
"type": ["integer", "null"]
|
"type": ["integer", "null"]
|
||||||
},
|
},
|
||||||
|
"aux_type": {
|
||||||
|
"description": "Auxiliary console type",
|
||||||
|
"enum": ["telnet", "none"]
|
||||||
|
},
|
||||||
"usage": {
|
"usage": {
|
||||||
"description": "How to use the Docker container",
|
"description": "How to use the Docker container",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -143,7 +147,7 @@ DOCKER_OBJECT_SCHEMA = {
|
|||||||
"description": "Auxiliary TCP port",
|
"description": "Auxiliary TCP port",
|
||||||
"minimum": 1,
|
"minimum": 1,
|
||||||
"maximum": 65535,
|
"maximum": 65535,
|
||||||
"type": "integer"
|
"type": ["integer", "null"]
|
||||||
},
|
},
|
||||||
"console": {
|
"console": {
|
||||||
"description": "Console TCP port",
|
"description": "Console TCP port",
|
||||||
@ -160,6 +164,10 @@ DOCKER_OBJECT_SCHEMA = {
|
|||||||
"description": "Console type",
|
"description": "Console type",
|
||||||
"enum": ["telnet", "vnc", "http", "https", "none"]
|
"enum": ["telnet", "vnc", "http", "https", "none"]
|
||||||
},
|
},
|
||||||
|
"aux_type": {
|
||||||
|
"description": "Auxiliary console type",
|
||||||
|
"enum": ["telnet", "none"]
|
||||||
|
},
|
||||||
"console_http_port": {
|
"console_http_port": {
|
||||||
"description": "Internal port in the container for the HTTP server",
|
"description": "Internal port in the container for the HTTP server",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
|
@ -67,6 +67,11 @@ DOCKER_TEMPLATE_PROPERTIES = {
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": False,
|
"default": False,
|
||||||
},
|
},
|
||||||
|
"aux_type": {
|
||||||
|
"description": "Auxiliary console type",
|
||||||
|
"enum": ["telnet", "none"],
|
||||||
|
"default": "none"
|
||||||
|
},
|
||||||
"console_http_port": {
|
"console_http_port": {
|
||||||
"description": "Internal port in the container for the HTTP server",
|
"description": "Internal port in the container for the HTTP server",
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
|
@ -120,6 +120,11 @@ DYNAMIPS_TEMPLATE_PROPERTIES = {
|
|||||||
"description": "Automatically start the console when the node has started",
|
"description": "Automatically start the console when the node has started",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": False
|
"default": False
|
||||||
|
},
|
||||||
|
"aux_type": {
|
||||||
|
"description": "Auxiliary console type",
|
||||||
|
"enum": ["telnet", "none"],
|
||||||
|
"default": "none"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +178,10 @@ VM_CREATE_SCHEMA = {
|
|||||||
"minimum": 1,
|
"minimum": 1,
|
||||||
"maximum": 65535
|
"maximum": 65535
|
||||||
},
|
},
|
||||||
|
"aux_type": {
|
||||||
|
"description": "Auxiliary console type",
|
||||||
|
"enum": ["telnet", "none"]
|
||||||
|
},
|
||||||
"mac_addr": {
|
"mac_addr": {
|
||||||
"description": "Base MAC address",
|
"description": "Base MAC address",
|
||||||
"type": ["null", "string"],
|
"type": ["null", "string"],
|
||||||
@ -400,6 +404,10 @@ VM_UPDATE_SCHEMA = {
|
|||||||
"minimum": 1,
|
"minimum": 1,
|
||||||
"maximum": 65535
|
"maximum": 65535
|
||||||
},
|
},
|
||||||
|
"aux_type": {
|
||||||
|
"description": "Auxiliary console type",
|
||||||
|
"enum": ["telnet", "none"]
|
||||||
|
},
|
||||||
"mac_addr": {
|
"mac_addr": {
|
||||||
"description": "Base MAC address",
|
"description": "Base MAC address",
|
||||||
"type": ["null", "string"],
|
"type": ["null", "string"],
|
||||||
@ -644,6 +652,10 @@ VM_OBJECT_SCHEMA = {
|
|||||||
"minimum": 1,
|
"minimum": 1,
|
||||||
"maximum": 65535
|
"maximum": 65535
|
||||||
},
|
},
|
||||||
|
"aux_type": {
|
||||||
|
"description": "Auxiliary console type",
|
||||||
|
"enum": ["telnet", "none"]
|
||||||
|
},
|
||||||
"mac_addr": {
|
"mac_addr": {
|
||||||
"description": "Base MAC address",
|
"description": "Base MAC address",
|
||||||
"type": ["null", "string"]
|
"type": ["null", "string"]
|
||||||
|
@ -159,6 +159,16 @@ NODE_OBJECT_SCHEMA = {
|
|||||||
"description": "Automatically start the console when the node has started",
|
"description": "Automatically start the console when the node has started",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"aux": {
|
||||||
|
"description": "Auxiliary console TCP port",
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": 65535,
|
||||||
|
"type": ["integer", "null"]
|
||||||
|
},
|
||||||
|
"aux_type": {
|
||||||
|
"description": "Auxiliary console type",
|
||||||
|
"enum": ["vnc", "telnet", "http", "https", "spice", "spice+agent", "none", None]
|
||||||
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"description": "Properties specific to an emulator",
|
"description": "Properties specific to an emulator",
|
||||||
"type": "object"
|
"type": "object"
|
||||||
|
@ -67,6 +67,16 @@ QEMU_CREATE_SCHEMA = {
|
|||||||
"description": "Console type",
|
"description": "Console type",
|
||||||
"enum": ["telnet", "vnc", "spice", "spice+agent", "none"]
|
"enum": ["telnet", "vnc", "spice", "spice+agent", "none"]
|
||||||
},
|
},
|
||||||
|
"aux": {
|
||||||
|
"description": "Auxiliary TCP port",
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": 65535,
|
||||||
|
"type": ["integer", "null"]
|
||||||
|
},
|
||||||
|
"aux_type": {
|
||||||
|
"description": "Auxiliary console type",
|
||||||
|
"enum": ["telnet", "vnc", "spice", "spice+agent", "none"]
|
||||||
|
},
|
||||||
"hda_disk_image": {
|
"hda_disk_image": {
|
||||||
"description": "QEMU hda disk image path",
|
"description": "QEMU hda disk image path",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -265,6 +275,16 @@ QEMU_UPDATE_SCHEMA = {
|
|||||||
"description": "Console type",
|
"description": "Console type",
|
||||||
"enum": ["telnet", "vnc", "spice", "spice+agent", "none"]
|
"enum": ["telnet", "vnc", "spice", "spice+agent", "none"]
|
||||||
},
|
},
|
||||||
|
"aux": {
|
||||||
|
"description": "Auxiliary TCP port",
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": 65535,
|
||||||
|
"type": ["integer", "null"]
|
||||||
|
},
|
||||||
|
"aux_type": {
|
||||||
|
"description": "Auxiliary console type",
|
||||||
|
"enum": ["telnet", "vnc", "spice", "spice+agent", "none"]
|
||||||
|
},
|
||||||
"linked_clone": {
|
"linked_clone": {
|
||||||
"description": "Whether the VM is a linked clone or not",
|
"description": "Whether the VM is a linked clone or not",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
@ -579,6 +599,16 @@ QEMU_OBJECT_SCHEMA = {
|
|||||||
"description": "Console type",
|
"description": "Console type",
|
||||||
"enum": ["telnet", "vnc", "spice","spice+agent", "none"]
|
"enum": ["telnet", "vnc", "spice","spice+agent", "none"]
|
||||||
},
|
},
|
||||||
|
"aux": {
|
||||||
|
"description": "Auxiliary TCP port",
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": 65535,
|
||||||
|
"type": ["integer", "null"]
|
||||||
|
},
|
||||||
|
"aux_type": {
|
||||||
|
"description": "Auxiliary console type",
|
||||||
|
"enum": ["telnet", "vnc", "spice", "spice+agent", "none"]
|
||||||
|
},
|
||||||
"initrd": {
|
"initrd": {
|
||||||
"description": "QEMU initrd path",
|
"description": "QEMU initrd path",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -659,6 +689,7 @@ QEMU_OBJECT_SCHEMA = {
|
|||||||
"qemu_path",
|
"qemu_path",
|
||||||
"platform",
|
"platform",
|
||||||
"console_type",
|
"console_type",
|
||||||
|
"aux_type",
|
||||||
"hda_disk_image",
|
"hda_disk_image",
|
||||||
"hdb_disk_image",
|
"hdb_disk_image",
|
||||||
"hdc_disk_image",
|
"hdc_disk_image",
|
||||||
@ -682,6 +713,7 @@ QEMU_OBJECT_SCHEMA = {
|
|||||||
"adapter_type",
|
"adapter_type",
|
||||||
"mac_address",
|
"mac_address",
|
||||||
"console",
|
"console",
|
||||||
|
"aux",
|
||||||
"initrd",
|
"initrd",
|
||||||
"kernel_image",
|
"kernel_image",
|
||||||
"initrd_md5sum",
|
"initrd_md5sum",
|
||||||
|
@ -103,6 +103,11 @@ QEMU_TEMPLATE_PROPERTIES = {
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": False
|
"default": False
|
||||||
},
|
},
|
||||||
|
"aux_type": {
|
||||||
|
"description": "Auxiliary console type",
|
||||||
|
"enum": ["telnet", "vnc", "spice", "spice+agent", "none"],
|
||||||
|
"default": "none"
|
||||||
|
},
|
||||||
"boot_priority": {
|
"boot_priority": {
|
||||||
"description": "QEMU boot priority",
|
"description": "QEMU boot priority",
|
||||||
"enum": ["c", "d", "n", "cn", "cd", "dn", "dc", "nc", "nd"],
|
"enum": ["c", "d", "n", "cn", "cd", "dn", "dc", "nc", "nd"],
|
||||||
|
@ -45,9 +45,8 @@ async def manager(port_manager):
|
|||||||
@pytest.fixture(scope="function")
|
@pytest.fixture(scope="function")
|
||||||
async def vm(compute_project, manager):
|
async def vm(compute_project, manager):
|
||||||
|
|
||||||
vm = DockerVM("test", str(uuid.uuid4()), compute_project, manager, "ubuntu:latest")
|
vm = DockerVM("test", str(uuid.uuid4()), compute_project, manager, "ubuntu:latest", aux_type="none")
|
||||||
vm._cid = "e90e34656842"
|
vm._cid = "e90e34656842"
|
||||||
vm.allocate_aux = False
|
|
||||||
vm.mac_address = '02:42:3d:b7:93:00'
|
vm.mac_address = '02:42:3d:b7:93:00'
|
||||||
return vm
|
return vm
|
||||||
|
|
||||||
@ -64,6 +63,7 @@ def test_json(vm, compute_project):
|
|||||||
'mac_address': '02:42:3d:b7:93:00',
|
'mac_address': '02:42:3d:b7:93:00',
|
||||||
'console': vm.console,
|
'console': vm.console,
|
||||||
'console_type': 'telnet',
|
'console_type': 'telnet',
|
||||||
|
'aux_type': 'none',
|
||||||
'console_resolution': '1024x768',
|
'console_resolution': '1024x768',
|
||||||
'console_http_port': 80,
|
'console_http_port': 80,
|
||||||
'console_http_path': '/',
|
'console_http_path': '/',
|
||||||
@ -875,7 +875,7 @@ async def test_start(vm, manager, free_console_port, tmpdir):
|
|||||||
assert vm.status != "started"
|
assert vm.status != "started"
|
||||||
vm.adapters = 1
|
vm.adapters = 1
|
||||||
|
|
||||||
vm.allocate_aux = True
|
vm.aux_type = "telnet"
|
||||||
vm._start_aux = AsyncioMagicMock()
|
vm._start_aux = AsyncioMagicMock()
|
||||||
|
|
||||||
vm._get_container_state = AsyncioMagicMock(return_value="stopped")
|
vm._get_container_state = AsyncioMagicMock(return_value="stopped")
|
||||||
@ -1428,6 +1428,7 @@ async def test_start_vnc_missing(vm):
|
|||||||
|
|
||||||
async def test_start_aux(vm):
|
async def test_start_aux(vm):
|
||||||
|
|
||||||
|
vm.aux_type = "telnet"
|
||||||
with asyncio_patch("asyncio.subprocess.create_subprocess_exec", return_value=MagicMock()) as mock_exec:
|
with asyncio_patch("asyncio.subprocess.create_subprocess_exec", return_value=MagicMock()) as mock_exec:
|
||||||
await vm._start_aux()
|
await vm._start_aux()
|
||||||
mock_exec.assert_called_with(
|
mock_exec.assert_called_with(
|
||||||
|
@ -102,7 +102,7 @@ def test_aux(compute_project, manager, port_manager):
|
|||||||
aux = port_manager.get_free_tcp_port(compute_project)
|
aux = port_manager.get_free_tcp_port(compute_project)
|
||||||
port_manager.release_tcp_port(aux, compute_project)
|
port_manager.release_tcp_port(aux, compute_project)
|
||||||
|
|
||||||
node = DockerVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, "ubuntu", aux=aux)
|
node = DockerVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, "ubuntu", aux=aux, aux_type="telnet")
|
||||||
assert node.aux == aux
|
assert node.aux == aux
|
||||||
node.aux = None
|
node.aux = None
|
||||||
assert node.aux is None
|
assert node.aux is None
|
||||||
@ -114,12 +114,13 @@ def test_allocate_aux(compute_project, manager):
|
|||||||
assert node.aux is None
|
assert node.aux is None
|
||||||
|
|
||||||
# Docker has an aux port by default
|
# Docker has an aux port by default
|
||||||
node = DockerVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, "ubuntu")
|
node = DockerVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, "ubuntu", aux_type="telnet")
|
||||||
assert node.aux is not None
|
assert node.aux is not None
|
||||||
|
|
||||||
|
|
||||||
def test_change_aux_port(node, port_manager):
|
def test_change_aux_port(compute_project, manager, port_manager):
|
||||||
|
|
||||||
|
node = DockerVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", compute_project, manager, "ubuntu", aux_type="telnet")
|
||||||
port1 = port_manager.get_free_tcp_port(node.project)
|
port1 = port_manager.get_free_tcp_port(node.project)
|
||||||
port2 = port_manager.get_free_tcp_port(node.project)
|
port2 = port_manager.get_free_tcp_port(node.project)
|
||||||
port_manager.release_tcp_port(port1, node.project)
|
port_manager.release_tcp_port(port1, node.project)
|
||||||
|
@ -121,6 +121,8 @@ def test_json(node, compute):
|
|||||||
"console": node.console,
|
"console": node.console,
|
||||||
"console_type": node.console_type,
|
"console_type": node.console_type,
|
||||||
"console_host": str(compute.console_host),
|
"console_host": str(compute.console_host),
|
||||||
|
"aux": node.aux,
|
||||||
|
"aux_type": node.aux_type,
|
||||||
"command_line": None,
|
"command_line": None,
|
||||||
"node_directory": None,
|
"node_directory": None,
|
||||||
"properties": node.properties,
|
"properties": node.properties,
|
||||||
@ -158,6 +160,8 @@ 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,
|
||||||
|
"aux": node.aux,
|
||||||
|
"aux_type": node.aux_type,
|
||||||
"properties": node.properties,
|
"properties": node.properties,
|
||||||
"x": node.x,
|
"x": node.x,
|
||||||
"y": node.y,
|
"y": node.y,
|
||||||
|
Loading…
Reference in New Issue
Block a user