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:
|
||||
raise DynamipsError("Couldn't connect to hypervisor on {}:{} :{}".format(host, self._port, last_exception))
|
||||
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:
|
||||
version = yield from self.send("hypervisor version")
|
||||
|
@ -30,6 +30,7 @@ import asyncio
|
||||
import socket
|
||||
import gns3server
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
from gns3server.utils import parse_version
|
||||
from gns3server.utils.asyncio import subprocess_check_output, cancellable_wait_run_in_executor
|
||||
@ -956,6 +957,7 @@ class QemuVM(BaseNode):
|
||||
self._hw_virtualization = True
|
||||
|
||||
yield from self._start_ubridge()
|
||||
set_link_commands = []
|
||||
for adapter_number, adapter in enumerate(self._ethernet_adapters):
|
||||
nio = adapter.get_nio(0)
|
||||
if nio:
|
||||
@ -963,9 +965,10 @@ class QemuVM(BaseNode):
|
||||
self._local_udp_tunnels[adapter_number][1],
|
||||
nio)
|
||||
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:
|
||||
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:
|
||||
yield from self.start_wrap_console()
|
||||
@ -1020,6 +1023,37 @@ class QemuVM(BaseNode):
|
||||
self._stop_cpulimit()
|
||||
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
|
||||
def _control_vm(self, command, expected=None):
|
||||
"""
|
||||
@ -1033,13 +1067,11 @@ class QemuVM(BaseNode):
|
||||
|
||||
result = None
|
||||
if self.is_running() and self._monitor:
|
||||
log.debug("Execute QEMU monitor command: {}".format(command))
|
||||
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 OSError as e:
|
||||
log.warning("Could not connect to QEMU monitor on {}:{}: {}".format(self._monitor_host, self._monitor, e))
|
||||
log.info("Execute QEMU monitor command: {}".format(command))
|
||||
reader, writer = yield from self._open_qemu_monitor_connection_vm()
|
||||
if reader is None and writer is None:
|
||||
return result
|
||||
|
||||
try:
|
||||
writer.write(command.encode('ascii') + b"\n")
|
||||
except OSError as e:
|
||||
@ -1061,6 +1093,28 @@ class QemuVM(BaseNode):
|
||||
writer.close()
|
||||
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
|
||||
def close(self):
|
||||
"""
|
||||
|
Loading…
Reference in New Issue
Block a user