From 14fd8104b844c3e5f7fe7444eb1837465b48fe72 Mon Sep 17 00:00:00 2001 From: Julien Duponchelle Date: Thu, 17 Nov 2016 12:21:38 +0100 Subject: [PATCH] Fix opening a project whith the same non linked VM as current project Fix https://github.com/GNS3/gns3-gui/issues/1646 --- .../compute/virtualbox/virtualbox_vm.py | 34 ++++++++++++++++--- gns3server/compute/vmware/vmware_vm.py | 34 ++++++++++++++++--- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/gns3server/compute/virtualbox/virtualbox_vm.py b/gns3server/compute/virtualbox/virtualbox_vm.py index a691bf1c..4d6b6463 100644 --- a/gns3server/compute/virtualbox/virtualbox_vm.py +++ b/gns3server/compute/virtualbox/virtualbox_vm.py @@ -66,11 +66,6 @@ class VirtualBoxVM(BaseNode): self._ethernet_adapters = {} self._headless = False self._acpi_shutdown = False - if not self.linked_clone: - for node in self.manager.nodes: - if node.vmname == vmname: - raise VirtualBoxError("Sorry a node without the linked clone setting enabled can only be used once on your server. {} is already used by {}".format(vmname, node.name)) - self._vmname = vmname self._use_any_adapter = False self._ram = 0 @@ -150,8 +145,37 @@ class VirtualBoxVM(BaseNode): args = shlex.split(params) yield from self.manager.execute("modifyvm", [self._vmname] + args) + @asyncio.coroutine + def _check_duplicate_linked_clone(self): + """ + Without linked clone two VM using the same image can't run + at the same time. + + To avoid issue like false detection when a project close + and another open we try multiple times. + """ + trial = 0 + + while True: + found = False + for node in self.manager.nodes: + if node != self and node.vmname == self.vmname: + found = True + if node.project != self.project: + if trial >= 30: + raise VirtualBoxError("Sorry a node without the linked clone setting enabled can only be used once on your server.\n{} is already used by {} in project {}".format(self.vmname, node.name, self.project.name)) + else: + if trial >= 5: + raise VirtualBoxError("Sorry a node without the linked clone setting enabled can only be used once on your server.\n{} is already used by {} in this project".format(self.vmname, node.name)) + if not found: + return + trial += 1 + yield from asyncio.sleep(1) + @asyncio.coroutine def create(self): + if not self.linked_clone: + yield from self._check_duplicate_linked_clone() yield from self._get_system_properties() if "API version" not in self._system_properties: diff --git a/gns3server/compute/vmware/vmware_vm.py b/gns3server/compute/vmware/vmware_vm.py index bbf6ac00..a9c96e58 100644 --- a/gns3server/compute/vmware/vmware_vm.py +++ b/gns3server/compute/vmware/vmware_vm.py @@ -56,11 +56,6 @@ class VMwareVM(BaseNode): self._started = False self._closed = False - if not self.linked_clone: - for node in self.manager.nodes: - if node.vmx_path == vmx_path: - raise VMwareError("Sorry a node without the linked clone setting enabled can only be used once on your server. {} is already used by {}".format(vmx_path, node.name)) - # VMware VM settings self._headless = False self._vmx_path = vmx_path @@ -133,11 +128,40 @@ class VMwareVM(BaseNode): return True return False + @asyncio.coroutine + def _check_duplicate_linked_clone(self): + """ + Without linked clone two VM using the same image can't run + at the same time. + + To avoid issue like false detection when a project close + and another open we try multiple times. + """ + trial = 0 + + while True: + found = False + for node in self.manager.nodes: + if node != self and node.vmx_path == self._vmx_path: + found = True + if node.project != self.project: + if trial >= 30: + raise VMwareError("Sorry a node without the linked clone setting enabled can only be used once on your server.\n{} is already used by {} in project {}".format(self.vmx_path, node.name, self.project.name)) + else: + if trial >= 5: + raise VMwareError("Sorry a node without the linked clone setting enabled can only be used once on your server.\n{} is already used by {} in this project".format(self.vmx_path, node.name)) + if not found: + return + trial += 1 + yield from asyncio.sleep(1) + @asyncio.coroutine def create(self): """ Creates this VM and handle linked clones. """ + if not self.linked_clone: + yield from self._check_duplicate_linked_clone() yield from self.manager.check_vmrun_version() if self.linked_clone and not os.path.exists(os.path.join(self.working_dir, os.path.basename(self._vmx_path))):