diff --git a/gns3server/handlers/virtualbox_handler.py b/gns3server/handlers/virtualbox_handler.py index 8b7125a6..03a2e99e 100644 --- a/gns3server/handlers/virtualbox_handler.py +++ b/gns3server/handlers/virtualbox_handler.py @@ -125,3 +125,22 @@ class VirtualBoxHandler: vm = vbox_manager.get_vm(request.match_info["uuid"]) yield from vm.resume() response.set_status(204) + + @classmethod + @Route.post( + r"/virtualbox/{uuid}/reload", + parameters={ + "uuid": "VirtualBox VM instance UUID" + }, + status_codes={ + 204: "VirtualBox VM instance reloaded", + 400: "Invalid VirtualBox VM instance UUID", + 404: "VirtualBox VM instance doesn't exist" + }, + description="Reload a VirtualBox VM instance") + def suspend(request, response): + + vbox_manager = VirtualBox.instance() + vm = vbox_manager.get_vm(request.match_info["uuid"]) + yield from vm.reload() + response.set_status(204) diff --git a/gns3server/modules/base_manager.py b/gns3server/modules/base_manager.py index d40c5c7a..5c5d9de4 100644 --- a/gns3server/modules/base_manager.py +++ b/gns3server/modules/base_manager.py @@ -95,9 +95,9 @@ class BaseManager: return self._config @classmethod - @asyncio.coroutine # FIXME: why coroutine? - def destroy(cls): + def unload(cls): + # TODO: close explicitly all the VMs here? cls._instance = None def get_vm(self, uuid): @@ -152,10 +152,10 @@ class BaseManager: """ vm = self.get_vm(uuid) - if asyncio.iscoroutinefunction(vm.destroy): - yield from vm.destroy() + if asyncio.iscoroutinefunction(vm.close): + yield from vm.close() else: - vm.destroy() + vm.close() del self._vms[vm.uuid] @staticmethod diff --git a/gns3server/modules/base_vm.py b/gns3server/modules/base_vm.py index 4f13ca04..51fd0461 100644 --- a/gns3server/modules/base_vm.py +++ b/gns3server/modules/base_vm.py @@ -33,7 +33,8 @@ class BaseVM: uuid=self.uuid)) def __del__(self): - self.destroy() + + self.close() @property def project(self): @@ -120,9 +121,9 @@ class BaseVM: raise NotImplementedError - def destroy(self): + def close(self): """ - Destroy the VM process. + Close the VM process. """ raise NotImplementedError diff --git a/gns3server/modules/vpcs/vpcs_vm.py b/gns3server/modules/vpcs/vpcs_vm.py index cdfabf70..00c20847 100644 --- a/gns3server/modules/vpcs/vpcs_vm.py +++ b/gns3server/modules/vpcs/vpcs_vm.py @@ -77,7 +77,8 @@ class VPCSVM(BaseVM): else: self._console = self._manager.port_manager.get_free_console_port() - def destroy(self): + def close(self): + self._kill_process() if self._console: self._manager.port_manager.release_console_port(self._console) diff --git a/gns3server/server.py b/gns3server/server.py index 4161a917..b8a847f2 100644 --- a/gns3server/server.py +++ b/gns3server/server.py @@ -80,7 +80,7 @@ class Server: for module in MODULES: log.debug("Unloading module {}".format(module.__name__)) m = module.instance() - m.destroy() + m.unload() self._loop.stop() def _signal_handling(self): diff --git a/tests/conftest.py b/tests/conftest.py index 537b1663..cbb0a758 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -68,7 +68,7 @@ def server(request, loop, port_manager): def tear_down(): for module in MODULES: - loop.run_until_complete(module.destroy()) + loop.run_until_complete(module.unload()) srv.close() srv.wait_closed() request.addfinalizer(tear_down) diff --git a/tests/modules/vpcs/test_vpcs_vm.py b/tests/modules/vpcs/test_vpcs_vm.py index 9c1d7a40..231bf0ae 100644 --- a/tests/modules/vpcs/test_vpcs_vm.py +++ b/tests/modules/vpcs/test_vpcs_vm.py @@ -186,12 +186,12 @@ def test_change_script_file(vm, tmpdir): assert vm.script_file == path -def test_destroy(vm, port_manager): +def test_close(vm, port_manager): with asyncio_patch("gns3server.modules.vpcs.vpcs_vm.VPCSVM._check_requirements", return_value=True): with asyncio_patch("asyncio.create_subprocess_exec", return_value=MagicMock()): vm.start() port = vm.console - vm.destroy() + vm.close() # Raise an exception if the port is not free port_manager.reserve_console_port(port) assert vm.is_running() is False