mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-24 17:28:08 +00:00
parent
cfe834afc4
commit
1412462229
@ -88,7 +88,7 @@ class Controller:
|
|||||||
# We don't care if a compute is down at this step
|
# We don't care if a compute is down at this step
|
||||||
except aiohttp.errors.ClientOSError:
|
except aiohttp.errors.ClientOSError:
|
||||||
pass
|
pass
|
||||||
yield from self.gns3vm.auto_stop_vm()
|
yield from self.gns3vm.exit_vm()
|
||||||
self._computes = {}
|
self._computes = {}
|
||||||
self._projects = {}
|
self._projects = {}
|
||||||
|
|
||||||
@ -204,10 +204,16 @@ class Controller:
|
|||||||
for compute in self._computes.values():
|
for compute in self._computes.values():
|
||||||
if compute.host == vm_settings.get("remote_vm_host") and compute.port == vm_settings.get("remote_vm_port"):
|
if compute.host == vm_settings.get("remote_vm_host") and compute.port == vm_settings.get("remote_vm_port"):
|
||||||
vmname = compute.name
|
vmname = compute.name
|
||||||
|
|
||||||
|
if vm_settings.get("auto_stop", True):
|
||||||
|
when_exit = "stop"
|
||||||
|
else:
|
||||||
|
when_exit = "keep"
|
||||||
|
|
||||||
self.gns3vm.settings = {
|
self.gns3vm.settings = {
|
||||||
"engine": engine,
|
"engine": engine,
|
||||||
"enable": vm_settings.get("auto_start", False),
|
"enable": vm_settings.get("auto_start", False),
|
||||||
"auto_stop": vm_settings.get("auto_stop", True),
|
"when_exit": when_exit,
|
||||||
"headless": vm_settings.get("headless", False),
|
"headless": vm_settings.get("headless", False),
|
||||||
"vmname": vmname
|
"vmname": vmname
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ class GNS3VM:
|
|||||||
self._engines = {}
|
self._engines = {}
|
||||||
self._settings = {
|
self._settings = {
|
||||||
"vmname": None,
|
"vmname": None,
|
||||||
"auto_stop": True,
|
"when_exit": "stop",
|
||||||
"headless": False,
|
"headless": False,
|
||||||
"enable": False,
|
"enable": False,
|
||||||
"engine": "vmware"
|
"engine": "vmware"
|
||||||
@ -54,7 +54,7 @@ class GNS3VM:
|
|||||||
vmware_informations = {
|
vmware_informations = {
|
||||||
"engine_id": "vmware",
|
"engine_id": "vmware",
|
||||||
"description": "VMware is the recommended choice for best performances.",
|
"description": "VMware is the recommended choice for best performances.",
|
||||||
"support_auto_stop": True,
|
"support_when_exit": True,
|
||||||
"support_headless": True
|
"support_headless": True
|
||||||
}
|
}
|
||||||
if sys.platform.startswith("darwin"):
|
if sys.platform.startswith("darwin"):
|
||||||
@ -66,7 +66,7 @@ class GNS3VM:
|
|||||||
"engine_id": "virtualbox",
|
"engine_id": "virtualbox",
|
||||||
"name": "VirtualBox",
|
"name": "VirtualBox",
|
||||||
"description": "VirtualBox doesn't support nested virtualization, this means running Qemu based VM could be very slow.",
|
"description": "VirtualBox doesn't support nested virtualization, this means running Qemu based VM could be very slow.",
|
||||||
"support_auto_stop": True,
|
"support_when_exit": True,
|
||||||
"support_headless": True
|
"support_headless": True
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ class GNS3VM:
|
|||||||
"engine_id": "remote",
|
"engine_id": "remote",
|
||||||
"name": "Remote",
|
"name": "Remote",
|
||||||
"description": "Use a remote GNS3 server as the GNS3 VM.",
|
"description": "Use a remote GNS3 server as the GNS3 VM.",
|
||||||
"support_auto_stop": False,
|
"support_when_exit": False,
|
||||||
"support_headless": False
|
"support_headless": False
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,11 +149,11 @@ class GNS3VM:
|
|||||||
return self._settings.get("enable", False)
|
return self._settings.get("enable", False)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def auto_stop(self):
|
def when_exit(self):
|
||||||
"""
|
"""
|
||||||
The GNSVM should auto stop
|
What should be done when exit
|
||||||
"""
|
"""
|
||||||
return self._settings["auto_stop"]
|
return self._settings["when_exit"]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def settings(self):
|
def settings(self):
|
||||||
@ -224,10 +224,13 @@ class GNS3VM:
|
|||||||
force=True)
|
force=True)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def auto_stop_vm(self):
|
def exit_vm(self):
|
||||||
if self.enable and self.auto_stop:
|
if self.enable:
|
||||||
try:
|
try:
|
||||||
|
if self._settings["when_exit"] == "stop":
|
||||||
yield from self._stop()
|
yield from self._stop()
|
||||||
|
elif self._settings["when_exit"] == "suspend":
|
||||||
|
yield from self._suspend()
|
||||||
except GNS3VMError as e:
|
except GNS3VMError as e:
|
||||||
log.warn(str(e))
|
log.warn(str(e))
|
||||||
|
|
||||||
@ -250,6 +253,18 @@ class GNS3VM:
|
|||||||
password=self.password,
|
password=self.password,
|
||||||
force=True)
|
force=True)
|
||||||
|
|
||||||
|
@locked_coroutine
|
||||||
|
def _suspend(self):
|
||||||
|
"""
|
||||||
|
Suspend the GNS3 VM
|
||||||
|
"""
|
||||||
|
engine = self._current_engine()
|
||||||
|
if "vm" in self._controller.computes:
|
||||||
|
yield from self._controller.delete_compute("vm")
|
||||||
|
if engine.running:
|
||||||
|
log.info("Suspend the GNS3 VM")
|
||||||
|
yield from engine.suspend()
|
||||||
|
|
||||||
@locked_coroutine
|
@locked_coroutine
|
||||||
def _stop(self):
|
def _stop(self):
|
||||||
"""
|
"""
|
||||||
|
@ -28,7 +28,6 @@ class BaseGNS3VM:
|
|||||||
|
|
||||||
self._controller = controller
|
self._controller = controller
|
||||||
self._vmname = None
|
self._vmname = None
|
||||||
self._auto_stop = False
|
|
||||||
self._ip_address = None
|
self._ip_address = None
|
||||||
self._port = 3080
|
self._port = 3080
|
||||||
self._headless = False
|
self._headless = False
|
||||||
@ -245,26 +244,6 @@ class BaseGNS3VM:
|
|||||||
|
|
||||||
self._ram = new_ram
|
self._ram = new_ram
|
||||||
|
|
||||||
@property
|
|
||||||
def auto_stop(self):
|
|
||||||
"""
|
|
||||||
Returns whether the VM should automatically be stopped when GNS3 quit
|
|
||||||
|
|
||||||
:returns: boolean
|
|
||||||
"""
|
|
||||||
|
|
||||||
return self._auto_start
|
|
||||||
|
|
||||||
@auto_stop.setter
|
|
||||||
def auto_stop(self, new_auto_stop):
|
|
||||||
"""
|
|
||||||
Set whether the VM should automatically be stopped when GNS3 quit
|
|
||||||
|
|
||||||
:param new_auto_stop: boolean
|
|
||||||
"""
|
|
||||||
|
|
||||||
self._auto_stop = new_auto_stop
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def engine(self):
|
def engine(self):
|
||||||
"""
|
"""
|
||||||
@ -291,6 +270,14 @@ class BaseGNS3VM:
|
|||||||
|
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def suspend(self):
|
||||||
|
"""
|
||||||
|
Suspend the GNS3 VM.
|
||||||
|
"""
|
||||||
|
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def stop(self, force=False):
|
def stop(self, force=False):
|
||||||
"""
|
"""
|
||||||
|
@ -63,6 +63,13 @@ class RemoteGNS3VM(BaseGNS3VM):
|
|||||||
return
|
return
|
||||||
raise GNS3VMError("Can't start the GNS3 VM remote VM {} not found".format(self.vmname))
|
raise GNS3VMError("Can't start the GNS3 VM remote VM {} not found".format(self.vmname))
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def suspend(self):
|
||||||
|
"""
|
||||||
|
Suspend do nothing for remote server
|
||||||
|
"""
|
||||||
|
self.running = False
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""
|
"""
|
||||||
|
@ -180,7 +180,9 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
|||||||
if self._headless:
|
if self._headless:
|
||||||
args.extend(["--type", "headless"])
|
args.extend(["--type", "headless"])
|
||||||
yield from self._execute("startvm", args)
|
yield from self._execute("startvm", args)
|
||||||
|
elif vm_state == "paused":
|
||||||
|
args = [self._vmname, "resume"]
|
||||||
|
yield from self._execute("controlvm", args)
|
||||||
ip_address = "127.0.0.1"
|
ip_address = "127.0.0.1"
|
||||||
try:
|
try:
|
||||||
# get a random port on localhost
|
# get a random port on localhost
|
||||||
@ -221,7 +223,7 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
|||||||
try:
|
try:
|
||||||
resp = None
|
resp = None
|
||||||
resp = yield from session.get('http://127.0.0.1:{}/v2/compute/network/interfaces'.format(api_port))
|
resp = yield from session.get('http://127.0.0.1:{}/v2/compute/network/interfaces'.format(api_port))
|
||||||
except OSError:
|
except (OSError, aiohttp.errors.ClientHttpProcessingError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if resp:
|
if resp:
|
||||||
@ -242,6 +244,16 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
|||||||
yield from asyncio.sleep(1)
|
yield from asyncio.sleep(1)
|
||||||
raise GNS3VMError("Could not get the GNS3 VM ip make sure the VM receive an IP from VirtualBox")
|
raise GNS3VMError("Could not get the GNS3 VM ip make sure the VM receive an IP from VirtualBox")
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def suspend(self):
|
||||||
|
"""
|
||||||
|
Suspend the GNS3 VM.
|
||||||
|
"""
|
||||||
|
|
||||||
|
yield from self._execute("controlvm", [self._vmname, "savestate"], timeout=3)
|
||||||
|
log.info("GNS3 VM has been suspend")
|
||||||
|
self.running = False
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""
|
"""
|
||||||
@ -249,7 +261,7 @@ class VirtualBoxGNS3VM(BaseGNS3VM):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
yield from self._execute("controlvm", [self._vmname, "acpipowerbutton"], timeout=3)
|
yield from self._execute("controlvm", [self._vmname, "acpipowerbutton"], timeout=3)
|
||||||
log.info("GNS3 VM hsd been stopped")
|
log.info("GNS3 VM has been stopped")
|
||||||
self.running = False
|
self.running = False
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
|
@ -126,6 +126,21 @@ class VMwareGNS3VM(BaseGNS3VM):
|
|||||||
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
|
self.running = True
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def suspend(self):
|
||||||
|
"""
|
||||||
|
Suspend the GNS3 VM.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self._vmx_path is None:
|
||||||
|
raise GNS3VMError("No VMX path configured, can't suspend the VM")
|
||||||
|
try:
|
||||||
|
yield from self._execute("suspend", [self._vmx_path])
|
||||||
|
except GNS3VMError as e:
|
||||||
|
log.warning("Error when suspending the VM: {}".format(str(e)))
|
||||||
|
log.info("GNS3 VM has been suspended")
|
||||||
|
self.running = False
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""
|
"""
|
||||||
|
@ -29,9 +29,9 @@ GNS3VM_SETTINGS_SCHEMA = {
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "The name of the VM"
|
"description": "The name of the VM"
|
||||||
},
|
},
|
||||||
"auto_stop": {
|
"when_exit": {
|
||||||
"type": "boolean",
|
"description": "What to do with the VM when GNS3 exit",
|
||||||
"description": "The VM auto stop with GNS3"
|
"enum": ["stop", "suspend", "keep"]
|
||||||
},
|
},
|
||||||
"headless": {
|
"headless": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
@ -149,7 +149,7 @@ def test_import_gns3vm_1_x(controller, controller_config_path, async_run):
|
|||||||
assert controller.gns3vm.settings["engine"] == "vmware"
|
assert controller.gns3vm.settings["engine"] == "vmware"
|
||||||
assert controller.gns3vm.settings["enable"]
|
assert controller.gns3vm.settings["enable"]
|
||||||
assert controller.gns3vm.settings["headless"]
|
assert controller.gns3vm.settings["headless"]
|
||||||
assert controller.gns3vm.settings["auto_stop"] is False
|
assert controller.gns3vm.settings["when_exit"] == "keep"
|
||||||
assert controller.gns3vm.settings["vmname"] == "GNS3 VM"
|
assert controller.gns3vm.settings["vmname"] == "GNS3 VM"
|
||||||
|
|
||||||
|
|
||||||
@ -408,12 +408,12 @@ def test_stop(controller, async_run):
|
|||||||
|
|
||||||
def test_stop_vm(controller, async_run):
|
def test_stop_vm(controller, async_run):
|
||||||
"""
|
"""
|
||||||
Start the controller with a GNS3 VM running
|
Stop GNS3 VM if configured
|
||||||
"""
|
"""
|
||||||
controller.gns3vm.settings = {
|
controller.gns3vm.settings = {
|
||||||
"enable": True,
|
"enable": True,
|
||||||
"engine": "vmware",
|
"engine": "vmware",
|
||||||
"auto_stop": True
|
"when_exit": "stop"
|
||||||
}
|
}
|
||||||
controller.gns3vm._current_engine().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:
|
||||||
@ -421,6 +421,36 @@ def test_stop_vm(controller, async_run):
|
|||||||
assert mock.called
|
assert mock.called
|
||||||
|
|
||||||
|
|
||||||
|
def test_suspend_vm(controller, async_run):
|
||||||
|
"""
|
||||||
|
Suspend GNS3 VM if configured
|
||||||
|
"""
|
||||||
|
controller.gns3vm.settings = {
|
||||||
|
"enable": True,
|
||||||
|
"engine": "vmware",
|
||||||
|
"when_exit": "suspend"
|
||||||
|
}
|
||||||
|
controller.gns3vm._current_engine().running = True
|
||||||
|
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.suspend") as mock:
|
||||||
|
async_run(controller.stop())
|
||||||
|
assert mock.called
|
||||||
|
|
||||||
|
|
||||||
|
def test_keep_vm(controller, async_run):
|
||||||
|
"""
|
||||||
|
Keep GNS3 VM if configured
|
||||||
|
"""
|
||||||
|
controller.gns3vm.settings = {
|
||||||
|
"enable": True,
|
||||||
|
"engine": "vmware",
|
||||||
|
"when_exit": "keep"
|
||||||
|
}
|
||||||
|
controller.gns3vm._current_engine().running = True
|
||||||
|
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.suspend") as mock:
|
||||||
|
async_run(controller.stop())
|
||||||
|
assert not mock.called
|
||||||
|
|
||||||
|
|
||||||
def test_get_free_project_name(controller, async_run):
|
def test_get_free_project_name(controller, async_run):
|
||||||
|
|
||||||
async_run(controller.add_project(project_id=str(uuid.uuid4()), name="Test"))
|
async_run(controller.add_project(project_id=str(uuid.uuid4()), name="Test"))
|
||||||
|
Loading…
Reference in New Issue
Block a user