mirror of
https://github.com/GNS3/gns3-server.git
synced 2025-01-18 23:43:48 +02:00
Manage error when GNS3VM failed to start
Fix https://github.com/GNS3/gns3-gui/issues/1446
This commit is contained in:
parent
f216422d0f
commit
4bbd8938ab
@ -334,6 +334,9 @@ class Compute:
|
|||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def http_query(self, method, path, data=None, **kwargs):
|
def http_query(self, method, path, data=None, **kwargs):
|
||||||
if not self._connected:
|
if not self._connected:
|
||||||
|
if self._id == "vm" and not self._controller.gns3vm.running:
|
||||||
|
yield from self._controller.gns3vm.start()
|
||||||
|
|
||||||
yield from self.connect()
|
yield from self.connect()
|
||||||
if not self._connected:
|
if not self._connected:
|
||||||
raise aiohttp.web.HTTPConflict(text="Can't connect to {}".format(self._name))
|
raise aiohttp.web.HTTPConflict(text="Can't connect to {}".format(self._name))
|
||||||
|
@ -19,9 +19,11 @@ import sys
|
|||||||
import copy
|
import copy
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
|
from ...utils.asyncio import locked_coroutine
|
||||||
from .vmware_gns3_vm import VMwareGNS3VM
|
from .vmware_gns3_vm import VMwareGNS3VM
|
||||||
from .virtualbox_gns3_vm import VirtualBoxGNS3VM
|
from .virtualbox_gns3_vm import VirtualBoxGNS3VM
|
||||||
from .remote_gns3_vm import RemoteGNS3VM
|
from .remote_gns3_vm import RemoteGNS3VM
|
||||||
|
from .gns3_vm_error import GNS3VMError
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -212,8 +214,14 @@ class GNS3VM:
|
|||||||
Auto start the GNS3 VM if require
|
Auto start the GNS3 VM if require
|
||||||
"""
|
"""
|
||||||
if self.enable:
|
if self.enable:
|
||||||
yield from self._start()
|
try:
|
||||||
|
yield from self.start()
|
||||||
|
except GNS3VMError as e:
|
||||||
|
# User will receive the error later when they will try to use the node
|
||||||
|
yield from self._controller.add_compute(compute_id="vm",
|
||||||
|
name="GNS3 VM ({})".format(self._current_engine().vmname),
|
||||||
|
host=None,
|
||||||
|
force=True)
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def auto_stop_vm(self):
|
def auto_stop_vm(self):
|
||||||
if self.enable and self.auto_stop:
|
if self.enable and self.auto_stop:
|
||||||
@ -222,8 +230,8 @@ class GNS3VM:
|
|||||||
except GNS3VMError as e:
|
except GNS3VMError as e:
|
||||||
log.warn(str(e))
|
log.warn(str(e))
|
||||||
|
|
||||||
@asyncio.coroutine
|
@locked_coroutine
|
||||||
def _start(self):
|
def start(self):
|
||||||
"""
|
"""
|
||||||
Start the GNS3 VM
|
Start the GNS3 VM
|
||||||
"""
|
"""
|
||||||
@ -241,7 +249,7 @@ class GNS3VM:
|
|||||||
password=self.password,
|
password=self.password,
|
||||||
force=True)
|
force=True)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@locked_coroutine
|
||||||
def _stop(self):
|
def _stop(self):
|
||||||
"""
|
"""
|
||||||
Stop the GNS3 VM
|
Stop the GNS3 VM
|
||||||
|
@ -26,4 +26,4 @@ class GNS3VMError(Exception):
|
|||||||
return self._message
|
return self._message
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self._message
|
return "GNS3VM: {}".format(self._message)
|
||||||
|
@ -114,7 +114,6 @@ class VMwareGNS3VM(BaseGNS3VM):
|
|||||||
args.extend(["nogui"])
|
args.extend(["nogui"])
|
||||||
yield from self._execute("start", args)
|
yield from self._execute("start", args)
|
||||||
log.info("GNS3 VM has been started")
|
log.info("GNS3 VM has been started")
|
||||||
self.running = True
|
|
||||||
|
|
||||||
# check if the VMware guest tools are installed
|
# check if the VMware guest tools are installed
|
||||||
vmware_tools_state = yield from self._execute("checkToolsState", [self._vmx_path])
|
vmware_tools_state = yield from self._execute("checkToolsState", [self._vmx_path])
|
||||||
@ -125,6 +124,7 @@ class VMwareGNS3VM(BaseGNS3VM):
|
|||||||
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)
|
||||||
self.ip_address = guest_ip_address
|
self.ip_address = guest_ip_address
|
||||||
log.info("GNS3 VM IP address set to {}".format(guest_ip_address))
|
log.info("GNS3 VM IP address set to {}".format(guest_ip_address))
|
||||||
|
self.running = True
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
@ -92,6 +92,33 @@ def test_compute_httpQueryNotConnected(compute, controller, async_run):
|
|||||||
controller.notification.emit.assert_called_with("compute.updated", compute.__json__())
|
controller.notification.emit.assert_called_with("compute.updated", compute.__json__())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def test_compute_httpQueryNotConnectedGNS3vmNotRunning(compute, controller, async_run):
|
||||||
|
"""
|
||||||
|
We are not connected to the remote and it's a GNS3 VM. So we need to start it
|
||||||
|
"""
|
||||||
|
controller._notification = MagicMock()
|
||||||
|
controller.gns3vm = AsyncioMagicMock()
|
||||||
|
controller.gns3vm.running = False
|
||||||
|
|
||||||
|
compute._id = "vm"
|
||||||
|
compute._connected = False
|
||||||
|
response = AsyncioMagicMock()
|
||||||
|
response.read = AsyncioMagicMock(return_value=json.dumps({"version": __version__}).encode())
|
||||||
|
response.status = 200
|
||||||
|
with asyncio_patch("aiohttp.ClientSession.request", return_value=response) as mock:
|
||||||
|
async_run(compute.post("/projects", {"a": "b"}))
|
||||||
|
mock.assert_any_call("GET", "https://example.com:84/v2/compute/capabilities", headers={'content-type': 'application/json'}, data=None, auth=None, chunked=False)
|
||||||
|
mock.assert_any_call("POST", "https://example.com:84/v2/compute/projects", data='{"a": "b"}', headers={'content-type': 'application/json'}, auth=None, chunked=False)
|
||||||
|
|
||||||
|
assert controller.gns3vm.start.called
|
||||||
|
assert compute._connected
|
||||||
|
assert compute._capabilities["version"] == __version__
|
||||||
|
controller.notification.emit.assert_called_with("compute.updated", compute.__json__())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_compute_httpQueryNotConnectedInvalidVersion(compute, async_run):
|
def test_compute_httpQueryNotConnectedInvalidVersion(compute, async_run):
|
||||||
compute._connected = False
|
compute._connected = False
|
||||||
response = AsyncioMagicMock()
|
response = AsyncioMagicMock()
|
||||||
|
@ -289,6 +289,11 @@ def test_getProject(controller, async_run):
|
|||||||
|
|
||||||
|
|
||||||
def test_start(controller, async_run):
|
def test_start(controller, async_run):
|
||||||
|
controller.gns3vm.settings = {
|
||||||
|
"enable": False,
|
||||||
|
"engine": "vmware"
|
||||||
|
}
|
||||||
|
with asyncio_patch("gns3server.controller.compute.Compute.connect") as mock:
|
||||||
async_run(controller.start())
|
async_run(controller.start())
|
||||||
assert len(controller.computes) == 1 # Local compute is created
|
assert len(controller.computes) == 1 # Local compute is created
|
||||||
assert controller.computes["local"].name == socket.gethostname()
|
assert controller.computes["local"].name == socket.gethostname()
|
||||||
@ -303,6 +308,7 @@ def test_start_vm(controller, async_run):
|
|||||||
"engine": "vmware"
|
"engine": "vmware"
|
||||||
}
|
}
|
||||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.start") as mock:
|
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.start") as mock:
|
||||||
|
with asyncio_patch("gns3server.controller.compute.Compute.connect") as mock_connect:
|
||||||
async_run(controller.start())
|
async_run(controller.start())
|
||||||
assert mock.called
|
assert mock.called
|
||||||
assert "local" in controller.computes
|
assert "local" in controller.computes
|
||||||
|
@ -16,9 +16,31 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from tests.utils import asyncio_patch
|
from tests.utils import asyncio_patch, AsyncioMagicMock
|
||||||
|
|
||||||
from gns3server.controller.gns3vm import GNS3VM
|
from gns3server.controller.gns3vm import GNS3VM
|
||||||
|
from gns3server.controller.gns3vm.gns3_vm_error import GNS3VMError
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def dummy_engine():
|
||||||
|
engine = AsyncioMagicMock()
|
||||||
|
engine.running = False
|
||||||
|
engine.ip_address = "vm.local"
|
||||||
|
engine.protocol = "https"
|
||||||
|
engine.port = 8442
|
||||||
|
engine.user = "hello"
|
||||||
|
engine.password = "world"
|
||||||
|
return engine
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def dummy_gns3vm(controller, dummy_engine):
|
||||||
|
vm = GNS3VM(controller)
|
||||||
|
vm._settings["engine"] = "dummy"
|
||||||
|
vm._settings["vmname"] = "Test VM"
|
||||||
|
vm._settings["enable"] = True
|
||||||
|
vm._engines["dummy"] = dummy_engine
|
||||||
|
return vm
|
||||||
|
|
||||||
|
|
||||||
def test_list(async_run, controller):
|
def test_list(async_run, controller):
|
||||||
@ -50,3 +72,26 @@ def test_update_settings(controller, async_run):
|
|||||||
assert "vm" in controller.computes
|
assert "vm" in controller.computes
|
||||||
async_run(vm.update_settings({"enable": False}))
|
async_run(vm.update_settings({"enable": False}))
|
||||||
assert "vm" not in controller.computes
|
assert "vm" not in controller.computes
|
||||||
|
|
||||||
|
|
||||||
|
def test_auto_start(async_run, controller, dummy_gns3vm, dummy_engine):
|
||||||
|
"""
|
||||||
|
When start the compute should be add to the controller
|
||||||
|
"""
|
||||||
|
async_run(dummy_gns3vm.auto_start_vm())
|
||||||
|
assert dummy_engine.start.called
|
||||||
|
assert controller.computes["vm"].name == "GNS3 VM (Test VM)"
|
||||||
|
assert controller.computes["vm"].host == "vm.local"
|
||||||
|
assert controller.computes["vm"].port == 8442
|
||||||
|
assert controller.computes["vm"].protocol == "https"
|
||||||
|
assert controller.computes["vm"].user == "hello"
|
||||||
|
assert controller.computes["vm"].password == "world"
|
||||||
|
|
||||||
|
|
||||||
|
def test_auto_start_with_error(async_run, controller, dummy_gns3vm, dummy_engine):
|
||||||
|
dummy_engine.start.side_effect = GNS3VMError("Dummy error")
|
||||||
|
|
||||||
|
async_run(dummy_gns3vm.auto_start_vm())
|
||||||
|
assert dummy_engine.start.called
|
||||||
|
assert controller.computes["vm"].name == "GNS3 VM (Test VM)"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user