mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-28 11:18:11 +00:00
Fix bug and add optimizations when connecting and sending commands to QEMU monitor after starting a VM. Fixes #2336.
This commit is contained in:
parent
135bbe8825
commit
a40fdb3641
@ -90,7 +90,7 @@ class DynamipsHypervisor:
|
|||||||
if not connection_success:
|
if not connection_success:
|
||||||
raise DynamipsError("Couldn't connect to hypervisor on {}:{} :{}".format(host, self._port, last_exception))
|
raise DynamipsError("Couldn't connect to hypervisor on {}:{} :{}".format(host, self._port, last_exception))
|
||||||
else:
|
else:
|
||||||
log.info("Connected to Dynamips hypervisor after {:.4f} seconds".format(time.time() - begin))
|
log.info("Connected to Dynamips hypervisor on {}:{} after {:.4f} seconds".format(host, self._port, time.time() - begin))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
version = yield from self.send("hypervisor version")
|
version = yield from self.send("hypervisor version")
|
||||||
|
@ -30,6 +30,7 @@ import asyncio
|
|||||||
import socket
|
import socket
|
||||||
import gns3server
|
import gns3server
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import time
|
||||||
|
|
||||||
from gns3server.utils import parse_version
|
from gns3server.utils import parse_version
|
||||||
from gns3server.utils.asyncio import subprocess_check_output, cancellable_wait_run_in_executor
|
from gns3server.utils.asyncio import subprocess_check_output, cancellable_wait_run_in_executor
|
||||||
@ -956,6 +957,7 @@ class QemuVM(BaseNode):
|
|||||||
self._hw_virtualization = True
|
self._hw_virtualization = True
|
||||||
|
|
||||||
yield from self._start_ubridge()
|
yield from self._start_ubridge()
|
||||||
|
set_link_commands = []
|
||||||
for adapter_number, adapter in enumerate(self._ethernet_adapters):
|
for adapter_number, adapter in enumerate(self._ethernet_adapters):
|
||||||
nio = adapter.get_nio(0)
|
nio = adapter.get_nio(0)
|
||||||
if nio:
|
if nio:
|
||||||
@ -963,9 +965,10 @@ class QemuVM(BaseNode):
|
|||||||
self._local_udp_tunnels[adapter_number][1],
|
self._local_udp_tunnels[adapter_number][1],
|
||||||
nio)
|
nio)
|
||||||
if nio.suspend:
|
if nio.suspend:
|
||||||
yield from self._control_vm("set_link gns3-{} off".format(adapter_number))
|
set_link_commands.append("set_link gns3-{} off".format(adapter_number))
|
||||||
else:
|
else:
|
||||||
yield from self._control_vm("set_link gns3-{} off".format(adapter_number))
|
set_link_commands.append("set_link gns3-{} off".format(adapter_number))
|
||||||
|
yield from self._control_vm_commands(set_link_commands)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
yield from self.start_wrap_console()
|
yield from self.start_wrap_console()
|
||||||
@ -1020,6 +1023,37 @@ class QemuVM(BaseNode):
|
|||||||
self._stop_cpulimit()
|
self._stop_cpulimit()
|
||||||
yield from super().stop()
|
yield from super().stop()
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def _open_qemu_monitor_connection_vm(self, timeout=10):
|
||||||
|
"""
|
||||||
|
Opens a connection to the QEMU monitor.
|
||||||
|
|
||||||
|
:param timeout: timeout to connect to the monitor TCP server
|
||||||
|
:returns: The reader returned is a StreamReader instance; the writer is a StreamWriter instance
|
||||||
|
"""
|
||||||
|
|
||||||
|
begin = time.time()
|
||||||
|
connection_success = False
|
||||||
|
last_exception = None
|
||||||
|
reader = writer = None
|
||||||
|
while time.time() - begin < timeout:
|
||||||
|
yield from asyncio.sleep(0.01)
|
||||||
|
try:
|
||||||
|
log.debug("Connecting to Qemu monitor on {}:{}".format(self._monitor_host, self._monitor))
|
||||||
|
reader, writer = yield from asyncio.open_connection(self._monitor_host, self._monitor)
|
||||||
|
except (asyncio.TimeoutError, OSError) as e:
|
||||||
|
last_exception = e
|
||||||
|
continue
|
||||||
|
connection_success = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not connection_success:
|
||||||
|
log.warning("Could not connect to QEMU monitor on {}:{}: {}".format(self._monitor_host, self._monitor,
|
||||||
|
last_exception))
|
||||||
|
else:
|
||||||
|
log.info("Connected to QEMU monitor on {}:{} after {:.4f} seconds".format(self._monitor_host, self._monitor, time.time() - begin))
|
||||||
|
return reader, writer
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _control_vm(self, command, expected=None):
|
def _control_vm(self, command, expected=None):
|
||||||
"""
|
"""
|
||||||
@ -1033,13 +1067,11 @@ class QemuVM(BaseNode):
|
|||||||
|
|
||||||
result = None
|
result = None
|
||||||
if self.is_running() and self._monitor:
|
if self.is_running() and self._monitor:
|
||||||
log.debug("Execute QEMU monitor command: {}".format(command))
|
log.info("Execute QEMU monitor command: {}".format(command))
|
||||||
try:
|
reader, writer = yield from self._open_qemu_monitor_connection_vm()
|
||||||
log.debug("Connecting to Qemu monitor on {}:{}".format(self._monitor_host, self._monitor))
|
if reader is None and writer is None:
|
||||||
reader, writer = yield from asyncio.open_connection(self._monitor_host, self._monitor)
|
|
||||||
except OSError as e:
|
|
||||||
log.warning("Could not connect to QEMU monitor on {}:{}: {}".format(self._monitor_host, self._monitor, e))
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
try:
|
try:
|
||||||
writer.write(command.encode('ascii') + b"\n")
|
writer.write(command.encode('ascii') + b"\n")
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
@ -1061,6 +1093,28 @@ class QemuVM(BaseNode):
|
|||||||
writer.close()
|
writer.close()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def _control_vm_commands(self, commands):
|
||||||
|
"""
|
||||||
|
Executes commands with QEMU monitor when this VM is running.
|
||||||
|
|
||||||
|
:param commands: a list of QEMU monitor commands (e.g. info status, stop etc.)
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.is_running() and self._monitor:
|
||||||
|
|
||||||
|
reader, writer = yield from self._open_qemu_monitor_connection_vm()
|
||||||
|
if reader is None and writer is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
for command in commands:
|
||||||
|
log.info("Execute QEMU monitor command: {}".format(command))
|
||||||
|
try:
|
||||||
|
writer.write(command.encode('ascii') + b"\n")
|
||||||
|
except OSError as e:
|
||||||
|
log.warning("Could not write to QEMU monitor: {}".format(e))
|
||||||
|
writer.close()
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def close(self):
|
def close(self):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user