From 39ddc4e8c194abf4b815ebbb354154d3e0e7e5c2 Mon Sep 17 00:00:00 2001 From: grossmj Date: Tue, 26 Jan 2016 14:23:01 -0700 Subject: [PATCH] Fixes concurrency issue when closing multiple VMware linked clone VMs. Fixes #410. --- gns3server/modules/vmware/__init__.py | 34 ++++++++++++++++++++++++++ gns3server/modules/vmware/vmware_vm.py | 26 +------------------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/gns3server/modules/vmware/__init__.py b/gns3server/modules/vmware/__init__.py index f4b3e533..8adf38b4 100644 --- a/gns3server/modules/vmware/__init__.py +++ b/gns3server/modules/vmware/__init__.py @@ -48,6 +48,7 @@ class VMware(BaseManager): super().__init__() self._execute_lock = asyncio.Lock() + self._vmware_inventory_lock = asyncio.Lock() self._vmrun_path = None self._vmnets = [] self._vmnet_start_range = 2 @@ -355,6 +356,39 @@ class VMware(BaseManager): return stdout_data.decode("utf-8", errors="ignore").splitlines() + @asyncio.coroutine + def remove_from_vmware_inventory(self, vmx_path): + """ + Removes a linked clone from the VMware inventory file. + + :param vmx_path: path of the linked clone VMX file + """ + + with (yield from self._vmware_inventory_lock): + inventory_path = self.get_vmware_inventory_path() + if os.path.exists(inventory_path): + try: + inventory_pairs = self.parse_vmware_file(inventory_path) + except OSError as e: + log.warning('Could not read VMware inventory file "{}": {}'.format(inventory_path, e)) + return + + vmlist_entry = None + for name, value in inventory_pairs.items(): + if value == vmx_path: + vmlist_entry = name.split(".", 1)[0] + break + + if vmlist_entry is not None: + for name in inventory_pairs.keys(): + if name.startswith(vmlist_entry): + del inventory_pairs[name] + + try: + self.write_vmware_file(inventory_path, inventory_pairs) + except OSError as e: + raise VMwareError('Could not write VMware inventory file "{}": {}'.format(inventory_path, e)) + @staticmethod def parse_vmware_file(path): """ diff --git a/gns3server/modules/vmware/vmware_vm.py b/gns3server/modules/vmware/vmware_vm.py index 7f25821e..8385c534 100644 --- a/gns3server/modules/vmware/vmware_vm.py +++ b/gns3server/modules/vmware/vmware_vm.py @@ -560,31 +560,7 @@ class VMwareVM(BaseVM): pass if self._linked_clone: - # clean the VMware inventory path from this linked clone - inventory_path = self.manager.get_vmware_inventory_path() - inventory_pairs = {} - if os.path.exists(inventory_path): - try: - inventory_pairs = self.manager.parse_vmware_file(inventory_path) - except OSError as e: - log.warning('Could not read VMware inventory file "{}": {}'.format(inventory_path, e)) - return - - vmlist_entry = None - for name, value in inventory_pairs.items(): - if value == self._vmx_path: - vmlist_entry = name.split(".", 1)[0] - break - - if vmlist_entry is not None: - for name in inventory_pairs.keys(): - if name.startswith(vmlist_entry): - del inventory_pairs[name] - - try: - self.manager.write_vmware_file(inventory_path, inventory_pairs) - except OSError as e: - raise VMwareError('Could not write VMware inventory file "{}": {}'.format(inventory_path, e)) + yield from self.manager.remove_from_vmware_inventory(self._vmx_path) log.info("VirtualBox VM '{name}' [{id}] closed".format(name=self.name, id=self.id)) self._closed = True