When you change settings of the GNS3 VM the VM is reloaded and project using it closed

Fix #644
pull/712/head
Julien Duponchelle 8 years ago
parent 5289c714f4
commit 8352ff02a1
No known key found for this signature in database
GPG Key ID: CE8B29639E07F5E8

@ -71,16 +71,7 @@ class Controller:
port=server_config.getint("port", 3080), port=server_config.getint("port", 3080),
user=server_config.get("user", ""), user=server_config.get("user", ""),
password=server_config.get("password", "")) password=server_config.get("password", ""))
if self.gns3vm.enable: yield from self.gns3vm.auto_start_vm()
yield from self.gns3vm.start()
self._computes["vm"] = Compute(compute_id="vm",
name="GNS3 VM",
controller=self,
protocol=self.gns3vm.protocol,
host=self.gns3vm.ip_address,
port=self.gns3vm.port,
user=self.gns3vm.user,
password=self.gns3vm.password)
@asyncio.coroutine @asyncio.coroutine
def stop(self): def stop(self):
@ -88,9 +79,12 @@ class Controller:
for project in self._projects.values(): for project in self._projects.values():
yield from project.close() yield from project.close()
for compute in self._computes.values(): for compute in self._computes.values():
yield from compute.close() try:
if self.gns3vm.enable and self.gns3vm.auto_stop: yield from compute.close()
yield from self.gns3vm.stop() # We don't care if a compute is down at this step
except aiohttp.errors.ClientOSError:
pass
yield from self.gns3vm.auto_stop_vm()
self._computes = {} self._computes = {}
self._projects = {} self._projects = {}
@ -212,18 +206,19 @@ class Controller:
return Config.instance().get_section_config("Server").getboolean("controller") return Config.instance().get_section_config("Server").getboolean("controller")
@asyncio.coroutine @asyncio.coroutine
def add_compute(self, compute_id=None, name=None, **kwargs): def add_compute(self, compute_id=None, name=None, force=False, **kwargs):
""" """
Add a server to the dictionary of compute servers controlled by this controller Add a server to the dictionary of compute servers controlled by this controller
:param compute_id: Compute server identifier :param compute_id: Compute server identifier
:param name: Compute name :param name: Compute name
:param force: True skip security check
: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
if compute_id == 'local' or compute_id == 'vm': if (compute_id == 'local' or compute_id == 'vm') and not force:
return None return None
for compute in self._computes.values(): for compute in self._computes.values():

@ -16,6 +16,7 @@
# 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 sys import sys
import copy
import asyncio import asyncio
from .vmware_gns3_vm import VMwareGNS3VM from .vmware_gns3_vm import VMwareGNS3VM
@ -41,7 +42,7 @@ class GNS3VM:
"enable": False, "enable": False,
"engine": "vmware" "engine": "vmware"
} }
self._settings.update(settings) self.settings = settings
def engine_list(self): def engine_list(self):
""" """
@ -77,6 +78,15 @@ class GNS3VM:
""" """
return self._current_engine().ip_address return self._current_engine().ip_address
@property
def running(self):
"""
Returns if the GNS3 VM is running.
:returns: Boolean
"""
return self._current_engine().running
@property @property
def user(self): def user(self):
""" """
@ -134,7 +144,19 @@ class GNS3VM:
@settings.setter @settings.setter
def settings(self, val): def settings(self, val):
self._settings.update(val) self._settings.update(val)
self._controller.save()
@asyncio.coroutine
def update_settings(self, settings):
"""
Update settings and will restart the VM if require
"""
new_settings = copy.copy(self._settings)
new_settings.update(settings)
if self.settings != new_settings:
yield from self._stop()
self._settings = settings
self._controller.save()
yield from self.auto_start_vm()
def _get_engine(self, engine): def _get_engine(self, engine):
""" """
@ -166,7 +188,20 @@ class GNS3VM:
return vms return vms
@asyncio.coroutine @asyncio.coroutine
def start(self): def auto_start_vm(self):
"""
Auto start the GNS3 VM if require
"""
if self.enable:
yield from self._start()
@asyncio.coroutine
def auto_stop_vm(self):
if self.enable and self.auto_stop:
yield from self._stop()
@asyncio.coroutine
def _start(self):
""" """
Start the GNS3 VM Start the GNS3 VM
""" """
@ -175,13 +210,23 @@ class GNS3VM:
log.info("Start the GNS3 VM") log.info("Start the GNS3 VM")
engine.vmname = self._settings["vmname"] engine.vmname = self._settings["vmname"]
yield from engine.start() yield from engine.start()
yield from self._controller.add_compute(compute_id="vm",
name="GNS3 VM",
protocol=self.protocol,
host=self.ip_address,
port=self.port,
user=self.user,
password=self.password,
force=True)
@asyncio.coroutine @asyncio.coroutine
def stop(self): def _stop(self):
""" """
Stop the GNS3 VM Stop the GNS3 VM
""" """
engine = self._current_engine() engine = self._current_engine()
if not engine.running: if "vm" in self._controller.computes:
yield from self._controller.delete_compute("vm")
if engine.running:
log.info("Stop the GNS3 VM") log.info("Stop the GNS3 VM")
yield from engine.stop() yield from engine.stop()

@ -15,6 +15,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# 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 aiohttp
import asyncio import asyncio
import copy import copy
import uuid import uuid
@ -338,7 +339,11 @@ class Node:
""" """
Stop a node Stop a node
""" """
yield from self.post("/stop") try:
yield from self.post("/stop")
# We don't care if a compute is down at this step
except aiohttp.errors.ClientOSError:
pass
@asyncio.coroutine @asyncio.coroutine
def suspend(self): def suspend(self):

@ -494,7 +494,11 @@ class Project:
def close(self, ignore_notification=False): def close(self, ignore_notification=False):
yield from self.stop_all() yield from self.stop_all()
for compute in self._project_created_on_compute: for compute in self._project_created_on_compute:
yield from compute.post("/projects/{}/close".format(self._id)) try:
yield from compute.post("/projects/{}/close".format(self._id))
# We don't care if a compute is down at this step
except aiohttp.errors.ClientOSError:
pass
self._cleanPictures() self._cleanPictures()
self._status = "closed" self._status = "closed"
if not ignore_notification: if not ignore_notification:

@ -75,6 +75,6 @@ class GNS3VMHandler:
def update(request, response): def update(request, response):
gns3_vm = Controller().instance().gns3vm gns3_vm = Controller().instance().gns3vm
gns3_vm.settings = request.json yield from gns3_vm.update_settings(request.json)
response.json(gns3_vm) response.json(gns3_vm)
response.set_status(201) response.set_status(201)

@ -301,9 +301,9 @@ def test_start_vm(controller, async_run):
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:
async_run(controller.start()) async_run(controller.start())
assert mock.called assert mock.called
assert len(controller.computes) == 2 # Local compute and vm are created
assert "local" in controller.computes assert "local" in controller.computes
assert "vm" in controller.computes assert "vm" in controller.computes
assert len(controller.computes) == 2 # Local compute and vm are created
def test_stop(controller, async_run): def test_stop(controller, async_run):
@ -322,7 +322,7 @@ def test_stop_vm(controller, async_run):
"engine": "vmware", "engine": "vmware",
"auto_stop": True "auto_stop": True
} }
controller.gns3vm.running = True controller.gns3vm._current_engine().running = True
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.stop") as mock: with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.stop") as mock:
async_run(controller.stop()) async_run(controller.stop())
assert mock.called assert mock.called

@ -37,3 +37,16 @@ def test_list(async_run, controller):
def test_json(controller): def test_json(controller):
vm = GNS3VM(controller) vm = GNS3VM(controller)
assert vm.__json__() == vm._settings assert vm.__json__() == vm._settings
def test_update_settings(controller, async_run):
vm = GNS3VM(controller)
vm.settings = {
"enable": True,
"engine": "vmware"
}
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.start"):
async_run(vm.auto_start_vm())
assert "vm" in controller.computes
async_run(vm.update_settings({"enable": False}))
assert "vm" not in controller.computes

Loading…
Cancel
Save