mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-17 05:48:58 +00:00
Fixing race condition when starting the GNS3 VM.
This commit is contained in:
parent
5f14f8eb46
commit
f9c7c15f95
@ -405,6 +405,7 @@ class Controller:
|
|||||||
:param connect: True connect to the compute immediately
|
:param connect: True connect to the compute immediately
|
||||||
:param kwargs: See the documentation of Compute
|
:param kwargs: See the documentation of Compute
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if compute_id not in self._computes:
|
if compute_id not in self._computes:
|
||||||
|
|
||||||
# We disallow to create from the outside the local and VM server
|
# We disallow to create from the outside the local and VM server
|
||||||
|
@ -377,13 +377,13 @@ class Compute:
|
|||||||
"""
|
"""
|
||||||
:param dont_connect: If true do not reconnect if not connected
|
:param dont_connect: If true do not reconnect if not connected
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not self._connected and not dont_connect:
|
if not self._connected and not dont_connect:
|
||||||
if self._id == "vm" and not self._controller.gns3vm.running:
|
if self._id == "vm" and not self._controller.gns3vm.running:
|
||||||
yield from self._controller.gns3vm.start()
|
yield from self._controller.gns3vm.start()
|
||||||
|
|
||||||
yield from self.connect()
|
yield from self.connect()
|
||||||
if not self._connected and not dont_connect:
|
if not self._connected and not dont_connect:
|
||||||
raise ComputeError("Can't connect to {}".format(self._name))
|
raise ComputeError("Cannot connect to compute '{}' with request {} {}".format(self._name, method, path))
|
||||||
response = yield from self._run_http_query(method, path, data=data, **kwargs)
|
response = yield from self._run_http_query(method, path, data=data, **kwargs)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@ -402,20 +402,20 @@ class Compute:
|
|||||||
"""
|
"""
|
||||||
Check if remote server is accessible
|
Check if remote server is accessible
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not self._connected and not self._closed:
|
if not self._connected and not self._closed:
|
||||||
try:
|
try:
|
||||||
|
log.info("Connecting to compute '{}'".format(self._id))
|
||||||
response = yield from self._run_http_query("GET", "/capabilities")
|
response = yield from self._run_http_query("GET", "/capabilities")
|
||||||
except ComputeError:
|
except ComputeError as e:
|
||||||
# Try to reconnect after 2 seconds if server unavailable only if not during tests (otherwise we create a ressources usage bomb)
|
# Try to reconnect after 2 seconds if server unavailable only if not during tests (otherwise we create a ressources usage bomb)
|
||||||
if not hasattr(sys, "_called_from_test") or not sys._called_from_test:
|
if not hasattr(sys, "_called_from_test") or not sys._called_from_test:
|
||||||
self._connection_failure += 1
|
self._connection_failure += 1
|
||||||
# After 5 failure we close the project using the compute to avoid sync issues
|
# After 5 failure we close the project using the compute to avoid sync issues
|
||||||
if self._connection_failure == 5:
|
if self._connection_failure == 5:
|
||||||
log.warning("Can't connect to compute %s", self._id)
|
log.warning("Cannot connect to compute '{}': {}".format(self._id, e))
|
||||||
yield from self._controller.close_compute_projects(self)
|
yield from self._controller.close_compute_projects(self)
|
||||||
|
|
||||||
asyncio.get_event_loop().call_later(2, lambda: asyncio.async(self._try_reconnect()))
|
asyncio.get_event_loop().call_later(2, lambda: asyncio.async(self._try_reconnect()))
|
||||||
|
|
||||||
return
|
return
|
||||||
except aiohttp.web.HTTPNotFound:
|
except aiohttp.web.HTTPNotFound:
|
||||||
raise aiohttp.web.HTTPConflict(text="The server {} is not a GNS3 server or it's a 1.X server".format(self._id))
|
raise aiohttp.web.HTTPConflict(text="The server {} is not a GNS3 server or it's a 1.X server".format(self._id))
|
||||||
|
@ -27,6 +27,7 @@ from .virtualbox_gns3_vm import VirtualBoxGNS3VM
|
|||||||
from .remote_gns3_vm import RemoteGNS3VM
|
from .remote_gns3_vm import RemoteGNS3VM
|
||||||
from .gns3_vm_error import GNS3VMError
|
from .gns3_vm_error import GNS3VMError
|
||||||
from ...version import __version__
|
from ...version import __version__
|
||||||
|
from ..compute import ComputeError
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -281,7 +282,8 @@ class GNS3VM:
|
|||||||
compute = yield from self._controller.add_compute(compute_id="vm",
|
compute = yield from self._controller.add_compute(compute_id="vm",
|
||||||
name="GNS3 VM is starting ({})".format(engine.vmname),
|
name="GNS3 VM is starting ({})".format(engine.vmname),
|
||||||
host=None,
|
host=None,
|
||||||
force=True)
|
force=True,
|
||||||
|
connect=False)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
yield from engine.start()
|
yield from engine.start()
|
||||||
@ -290,6 +292,7 @@ class GNS3VM:
|
|||||||
log.error("Can't start the GNS3 VM: {}".format(str(e)))
|
log.error("Can't start the GNS3 VM: {}".format(str(e)))
|
||||||
yield from compute.update(name="GNS3 VM ({})".format(engine.vmname))
|
yield from compute.update(name="GNS3 VM ({})".format(engine.vmname))
|
||||||
raise e
|
raise e
|
||||||
|
yield from compute.connect() # we can connect now that the VM has started
|
||||||
yield from compute.update(name="GNS3 VM ({})".format(engine.vmname),
|
yield from compute.update(name="GNS3 VM ({})".format(engine.vmname),
|
||||||
protocol=self.protocol,
|
protocol=self.protocol,
|
||||||
host=self.ip_address,
|
host=self.ip_address,
|
||||||
@ -297,7 +300,9 @@ class GNS3VM:
|
|||||||
user=self.user,
|
user=self.user,
|
||||||
password=self.password)
|
password=self.password)
|
||||||
|
|
||||||
yield from self._check_network(compute)
|
# check if the VM is in the same subnet as the local server, start 10 seconds later to give
|
||||||
|
# some time for the compute in the VM to be ready for requests
|
||||||
|
asyncio.get_event_loop().call_later(10, lambda: asyncio.async(self._check_network(compute)))
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _check_network(self, compute):
|
def _check_network(self, compute):
|
||||||
@ -305,6 +310,7 @@ class GNS3VM:
|
|||||||
Check that the VM is in the same subnet as the local server
|
Check that the VM is in the same subnet as the local server
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
vm_interfaces = yield from compute.interfaces()
|
vm_interfaces = yield from compute.interfaces()
|
||||||
vm_interface_netmask = None
|
vm_interface_netmask = None
|
||||||
for interface in vm_interfaces:
|
for interface in vm_interfaces:
|
||||||
@ -325,8 +331,11 @@ class GNS3VM:
|
|||||||
if netmask:
|
if netmask:
|
||||||
compute_network = ipaddress.ip_interface("{}/{}".format(compute.host_ip, netmask)).network
|
compute_network = ipaddress.ip_interface("{}/{}".format(compute.host_ip, netmask)).network
|
||||||
if vm_network.compare_networks(compute_network) != 0:
|
if vm_network.compare_networks(compute_network) != 0:
|
||||||
msg = "The GNS3 VM ({}) is not on the same network as the {} server ({}), please make sure the local server binding is in the same network as the GNS3 VM".format(vm_network, compute_id, compute_network)
|
msg = "The GNS3 VM ({}) is not on the same network as the {} server ({}), please make sure the local server binding is in the same network as the GNS3 VM".format(
|
||||||
|
vm_network, compute_id, compute_network)
|
||||||
self._controller.notification.emit("log.warning", {"message": msg})
|
self._controller.notification.emit("log.warning", {"message": msg})
|
||||||
|
except ComputeError as e:
|
||||||
|
log.warning("Could not check the VM is in the same subnet as the local server: {}".format(e))
|
||||||
|
|
||||||
@locked_coroutine
|
@locked_coroutine
|
||||||
def _suspend(self):
|
def _suspend(self):
|
||||||
|
@ -171,7 +171,7 @@ class VMwareGNS3VM(BaseGNS3VM):
|
|||||||
trial -= 1
|
trial -= 1
|
||||||
# If ip not found fallback on old method
|
# If ip not found fallback on old method
|
||||||
if trial == 0:
|
if trial == 0:
|
||||||
log.warn("No IP found for the VM via readVariable fallback to getGuestIPAddress")
|
log.warning("No IP found for the VM via readVariable fallback to getGuestIPAddress")
|
||||||
guest_ip_address = yield from self._execute("getGuestIPAddress", [self._vmx_path, "-wait"], timeout=120)
|
guest_ip_address = yield from self._execute("getGuestIPAddress", [self._vmx_path, "-wait"], timeout=120)
|
||||||
break
|
break
|
||||||
yield from asyncio.sleep(1)
|
yield from asyncio.sleep(1)
|
||||||
|
Loading…
Reference in New Issue
Block a user