mirror of
https://github.com/GNS3/gns3-server.git
synced 2025-01-18 02:39:45 +00: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
|
||||
def http_query(self, method, path, data=None, **kwargs):
|
||||
if not self._connected:
|
||||
if self._id == "vm" and not self._controller.gns3vm.running:
|
||||
yield from self._controller.gns3vm.start()
|
||||
|
||||
yield from self.connect()
|
||||
if not self._connected:
|
||||
raise aiohttp.web.HTTPConflict(text="Can't connect to {}".format(self._name))
|
||||
|
@ -19,9 +19,11 @@ import sys
|
||||
import copy
|
||||
import asyncio
|
||||
|
||||
from ...utils.asyncio import locked_coroutine
|
||||
from .vmware_gns3_vm import VMwareGNS3VM
|
||||
from .virtualbox_gns3_vm import VirtualBoxGNS3VM
|
||||
from .remote_gns3_vm import RemoteGNS3VM
|
||||
from .gns3_vm_error import GNS3VMError
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
@ -212,8 +214,14 @@ class GNS3VM:
|
||||
Auto start the GNS3 VM if require
|
||||
"""
|
||||
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
|
||||
def auto_stop_vm(self):
|
||||
if self.enable and self.auto_stop:
|
||||
@ -222,8 +230,8 @@ class GNS3VM:
|
||||
except GNS3VMError as e:
|
||||
log.warn(str(e))
|
||||
|
||||
@asyncio.coroutine
|
||||
def _start(self):
|
||||
@locked_coroutine
|
||||
def start(self):
|
||||
"""
|
||||
Start the GNS3 VM
|
||||
"""
|
||||
@ -232,7 +240,7 @@ class GNS3VM:
|
||||
log.info("Start the GNS3 VM")
|
||||
engine.vmname = self._settings["vmname"]
|
||||
yield from engine.start()
|
||||
yield from self._controller.add_compute(compute_id="vm",
|
||||
yield from self._controller.add_compute(compute_id="vm",
|
||||
name="GNS3 VM ({})".format(engine.vmname),
|
||||
protocol=self.protocol,
|
||||
host=self.ip_address,
|
||||
@ -241,7 +249,7 @@ class GNS3VM:
|
||||
password=self.password,
|
||||
force=True)
|
||||
|
||||
@asyncio.coroutine
|
||||
@locked_coroutine
|
||||
def _stop(self):
|
||||
"""
|
||||
Stop the GNS3 VM
|
||||
|
@ -26,4 +26,4 @@ class GNS3VMError(Exception):
|
||||
return self._message
|
||||
|
||||
def __str__(self):
|
||||
return self._message
|
||||
return "GNS3VM: {}".format(self._message)
|
||||
|
@ -114,7 +114,6 @@ class VMwareGNS3VM(BaseGNS3VM):
|
||||
args.extend(["nogui"])
|
||||
yield from self._execute("start", args)
|
||||
log.info("GNS3 VM has been started")
|
||||
self.running = True
|
||||
|
||||
# check if the VMware guest tools are installed
|
||||
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)
|
||||
self.ip_address = guest_ip_address
|
||||
log.info("GNS3 VM IP address set to {}".format(guest_ip_address))
|
||||
self.running = True
|
||||
|
||||
@asyncio.coroutine
|
||||
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__())
|
||||
|
||||
|
||||
|
||||
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):
|
||||
compute._connected = False
|
||||
response = AsyncioMagicMock()
|
||||
|
@ -289,7 +289,12 @@ def test_getProject(controller, async_run):
|
||||
|
||||
|
||||
def test_start(controller, async_run):
|
||||
async_run(controller.start())
|
||||
controller.gns3vm.settings = {
|
||||
"enable": False,
|
||||
"engine": "vmware"
|
||||
}
|
||||
with asyncio_patch("gns3server.controller.compute.Compute.connect") as mock:
|
||||
async_run(controller.start())
|
||||
assert len(controller.computes) == 1 # Local compute is created
|
||||
assert controller.computes["local"].name == socket.gethostname()
|
||||
|
||||
@ -303,8 +308,9 @@ def test_start_vm(controller, async_run):
|
||||
"engine": "vmware"
|
||||
}
|
||||
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.start") as mock:
|
||||
async_run(controller.start())
|
||||
assert mock.called
|
||||
with asyncio_patch("gns3server.controller.compute.Compute.connect") as mock_connect:
|
||||
async_run(controller.start())
|
||||
assert mock.called
|
||||
assert "local" in controller.computes
|
||||
assert "vm" in controller.computes
|
||||
assert len(controller.computes) == 2 # Local compute and vm are created
|
||||
|
@ -16,9 +16,31 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
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.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):
|
||||
@ -50,3 +72,26 @@ def test_update_settings(controller, async_run):
|
||||
assert "vm" in controller.computes
|
||||
async_run(vm.update_settings({"enable": False}))
|
||||
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