Merge branch '2.0' into 2.1

pull/890/head
Julien Duponchelle 8 years ago
commit 5204cec9e6
No known key found for this signature in database
GPG Key ID: CE8B29639E07F5E8

@ -161,7 +161,7 @@ class VirtualBox(BaseManager):
continue
@asyncio.coroutine
def list_vms(self):
def list_vms(self, allow_clone=False):
"""
Gets VirtualBox VM list.
"""
@ -176,7 +176,7 @@ class VirtualBox(BaseManager):
if vmname == "<inaccessible>":
continue # ignore inaccessible VMs
extra_data = yield from self.execute("getextradata", [vmname, "GNS3/Clone"])
if len(extra_data) == 0 or not extra_data[0].strip() == "Value: yes":
if allow_clone or len(extra_data) == 0 or not extra_data[0].strip() == "Value: yes":
# get the amount of RAM
info_results = yield from self.execute("showvminfo", [vmname, "--machinereadable"])
ram = 0

@ -603,7 +603,16 @@ class VirtualBoxVM(BaseNode):
:param vmname: VirtualBox VM name
"""
if vmname == self._vmname:
return
if self.linked_clone:
if self.status == "started":
raise VirtualBoxError("You can't change the name of running VM {}".format(self._name))
# We can't rename a VM to name that already exists
vms = yield from self.manager.list_vms(allow_clone=True)
if vmname in [vm["vmname"] for vm in vms]:
raise VirtualBoxError("You can't change the name to {} it's already use in VirtualBox".format(vmname))
yield from self._modify_vm('--name "{}"'.format(vmname))
log.info("VirtualBox VM '{name}' [{id}] has set the VM name to '{vmname}'".format(name=self.name, id=self.id, vmname=vmname))

@ -260,6 +260,9 @@ class GNS3VM:
"""
engine = self.current_engine()
if not engine.running:
if self._settings["vmname"] is None:
return
log.info("Start the GNS3 VM")
engine.vmname = self._settings["vmname"]
engine.ram = self._settings["ram"]

@ -643,8 +643,11 @@ class Project:
# We don't care if a compute is down at this step
except (ComputeError, aiohttp.web.HTTPNotFound, aiohttp.web.HTTPConflict):
pass
if os.path.exists(path + ".backup"):
shutil.copy(path + ".backup", path)
try:
if os.path.exists(path + ".backup"):
shutil.copy(path + ".backup", path)
except (PermissionError, OSError):
pass
self._status = "closed"
self._loading = False
raise e

@ -112,10 +112,13 @@ class VirtualBoxHandler:
vbox_manager = VirtualBox.instance()
vm = vbox_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
if "vmname" in request.json:
vmname = request.json.pop("vmname")
if vmname != vm.vmname:
yield from vm.set_vmname(vmname)
if "name" in request.json:
name = request.json.pop("name")
vmname = request.json.pop("vmname", None)
if name != vm.name:
vm.name = name
if vm.linked_clone:
yield from vm.set_vmname(vm.name)
if "adapters" in request.json:
adapters = int(request.json.pop("adapters"))

@ -150,7 +150,7 @@ class ServerHandler:
# If something is wrong we log the info to the log and we hope the log will be include correctly to the debug export
log.error("Could not copy VMware VMX file {}".format(e), exc_info=1)
for compute in Controller.instance().computes.values():
for compute in list(Controller.instance().computes.values()):
try:
r = yield from compute.get("/debug", raw=True)
data = r.body.decode("utf-8")

@ -171,7 +171,7 @@ class Hypervisor(UBridgeHypervisor):
env=env)
log.info("ubridge started PID={}".format(self._process.pid))
except (OSError, subprocess.SubprocessError) as e:
except (OSError, PermissionError, subprocess.SubprocessError) as e:
ubridge_stdout = self.read_stdout()
log.error("Could not start ubridge: {}\n{}".format(e, ubridge_stdout))
raise UBridgeHypervisor("Could not start ubridge: {}\n{}".format(e, ubridge_stdout))

@ -77,8 +77,11 @@ def wait_for_process_termination(process, timeout=10):
:param timeout: Timeout in seconds
"""
if sys.version_info >= (3,5):
yield from asyncio.wait_for(process.wait(), timeout=timeout)
if sys.version_info >= (3, 5):
try:
yield from asyncio.wait_for(process.wait(), timeout=timeout)
except ProcessLookupError:
return
else:
while timeout > 0:
if process.returncode is not None:

@ -130,8 +130,11 @@ def images_directories(type):
paths = []
img_dir = os.path.expanduser(server_config.get("images_path", "~/GNS3/images"))
type_img_directory = default_images_directory(type)
os.makedirs(type_img_directory, exist_ok=True)
paths.append(type_img_directory)
try:
os.makedirs(type_img_directory, exist_ok=True)
paths.append(type_img_directory)
except (OSError, PermissionError):
pass
for directory in server_config.get("additional_images_path", "").split(";"):
paths.append(directory)
# Compatibility with old topologies we look in parent directory

@ -41,16 +41,15 @@ from ..config import Config
def parse_request(request, input_schema, raw):
"""Parse body of request and raise HTTP errors in case of problems"""
content_length = request.content_length
if content_length is not None and content_length > 0 and not raw:
request.json = {}
if not raw:
body = yield from request.read()
try:
request.json = json.loads(body.decode('utf-8'))
except ValueError as e:
request.json = {"malformed_json": body.decode('utf-8')}
raise aiohttp.web.HTTPBadRequest(text="Invalid JSON {}".format(e))
else:
request.json = {}
if body:
try:
request.json = json.loads(body.decode('utf-8'))
except ValueError as e:
request.json = {"malformed_json": body.decode('utf-8')}
raise aiohttp.web.HTTPBadRequest(text="Invalid JSON {}".format(e))
# Parse the query string
if len(request.query_string) > 0:

@ -18,7 +18,7 @@
import os
import pytest
import asyncio
from tests.utils import asyncio_patch
from tests.utils import asyncio_patch, AsyncioMagicMock
from gns3server.compute.virtualbox.virtualbox_vm import VirtualBoxVM
from gns3server.compute.virtualbox.virtualbox_error import VirtualBoxError
@ -44,6 +44,34 @@ def test_vm(project, manager):
assert vm.vmname == "test"
def test_rename_vmname(project, manager, async_run):
"""
Rename a VM is not allowed when using a running linked clone
or if the vm already exists in Vbox
"""
vm = VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "test", False)
vm.manager.list_vms = AsyncioMagicMock(return_value=[{"vmname": "Debian"}])
vm._linked_clone = True
vm._modify_vm = AsyncioMagicMock()
# Vm is running
vm._node_status = "started"
with pytest.raises(VirtualBoxError):
async_run(vm.set_vmname("Arch"))
assert not vm._modify_vm.called
vm._node_status = "stopped"
# Name already use
with pytest.raises(VirtualBoxError):
async_run(vm.set_vmname("Debian"))
assert not vm._modify_vm.called
# Work
async_run(vm.set_vmname("Arch"))
assert vm._modify_vm.called
def test_vm_valid_virtualbox_api_version(loop, project, manager):
with asyncio_patch("gns3server.compute.virtualbox.VirtualBox.execute", return_value=["API version: 4_3"]):
vm = VirtualBoxVM("test", "00010203-0405-0607-0809-0a0b0c0d0e0f", project, manager, "test", False)

@ -376,7 +376,8 @@ def test_getProject(controller, async_run):
def test_start(controller, async_run):
controller.gns3vm.settings = {
"enable": False,
"engine": "vmware"
"engine": "vmware",
"vmname": "GNS3 VM"
}
with asyncio_patch("gns3server.controller.compute.Compute.connect") as mock:
async_run(controller.start())
@ -390,7 +391,8 @@ def test_start_vm(controller, async_run):
"""
controller.gns3vm.settings = {
"enable": True,
"engine": "vmware"
"engine": "vmware",
"vmname": "GNS3 VM"
}
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.start") as mock:
with asyncio_patch("gns3server.controller.compute.Compute.connect") as mock_connect:
@ -415,7 +417,8 @@ def test_stop_vm(controller, async_run):
controller.gns3vm.settings = {
"enable": True,
"engine": "vmware",
"when_exit": "stop"
"when_exit": "stop",
"vmname": "GNS3 VM"
}
controller.gns3vm.current_engine().running = True
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.stop") as mock:
@ -430,7 +433,8 @@ def test_suspend_vm(controller, async_run):
controller.gns3vm.settings = {
"enable": True,
"engine": "vmware",
"when_exit": "suspend"
"when_exit": "suspend",
"vmname": "GNS3 VM"
}
controller.gns3vm.current_engine().running = True
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.suspend") as mock:
@ -445,7 +449,8 @@ def test_keep_vm(controller, async_run):
controller.gns3vm.settings = {
"enable": True,
"engine": "vmware",
"when_exit": "keep"
"when_exit": "keep",
"vmname": "GNS3 VM"
}
controller.gns3vm.current_engine().running = True
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.suspend") as mock:

@ -21,6 +21,7 @@ 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()
@ -65,7 +66,8 @@ def test_update_settings(controller, async_run):
vm = GNS3VM(controller)
vm.settings = {
"enable": True,
"engine": "vmware"
"engine": "vmware",
"vmname": "GNS3 VM"
}
with asyncio_patch("gns3server.controller.gns3vm.vmware_gns3_vm.VMwareGNS3VM.start"):
async_run(vm.auto_start_vm())
@ -94,4 +96,3 @@ def test_auto_start_with_error(async_run, controller, dummy_gns3vm, dummy_engine
async_run(dummy_gns3vm.auto_start_vm())
assert dummy_engine.start.called
assert controller.computes["vm"].name == "GNS3 VM (Test VM)"

Loading…
Cancel
Save