From 10c46619479e41e85b14343bd32159efda32775b Mon Sep 17 00:00:00 2001 From: Chris Behrens Date: Tue, 11 Jun 2013 19:00:02 +0000 Subject: Fix race conditions with xenstore xenapi code updates xenstore using _add_to_param_xenstore(), which has to ensure a key doesn't exist before it can add the same key. However, if you have 2 calls at the same time, this is racey. Fixes bug 1190026 Change-Id: I545b7a9fab0bc4c3749bc75387ed3f6ff27a512f --- nova/virt/xenapi/vmops.py | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index e178d08fd..feffc55ac 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -1097,6 +1097,7 @@ class VMOps(object): def inject_instance_metadata(self, instance, vm_ref): """Inject instance metadata into xenstore.""" + @utils.synchronized('xenstore-' + instance['uuid']) def store_meta(topdir, data_list): for item in data_list: key = self._sanitize_xenstore_key(item['key']) @@ -1110,9 +1111,8 @@ class VMOps(object): def change_instance_metadata(self, instance, diff): """Apply changes to instance metadata to xenstore.""" vm_ref = self._get_vm_opaque_ref(instance) - for key, change in diff.items(): - key = self._sanitize_xenstore_key(key) - location = 'vm-data/user-metadata/%s' % key + + def process_change(location, change): if change[0] == '-': self._remove_from_param_xenstore(vm_ref, location) try: @@ -1131,6 +1131,14 @@ class VMOps(object): # catch KeyError for domid if instance isn't running pass + @utils.synchronized('xenstore-' + instance['uuid']) + def update_meta(): + for key, change in diff.items(): + key = self._sanitize_xenstore_key(key) + location = 'vm-data/user-metadata/%s' % key + process_change(location, change) + update_meta() + def _find_root_vdi_ref(self, vm_ref): """Find and return the root vdi ref for a VM.""" if not vm_ref: @@ -1524,19 +1532,22 @@ class VMOps(object): vm_ref = vm_ref or self._get_vm_opaque_ref(instance) LOG.debug(_("Injecting network info to xenstore"), instance=instance) - for vif in network_info: - xs_data = self._vif_xenstore_data(vif) - location = ('vm-data/networking/%s' % - vif['address'].replace(':', '')) - self._add_to_param_xenstore(vm_ref, - location, - jsonutils.dumps(xs_data)) - try: - self._write_to_xenstore(instance, location, xs_data, - vm_ref=vm_ref) - except KeyError: - # catch KeyError for domid if instance isn't running - pass + @utils.synchronized('xenstore-' + instance['uuid']) + def update_nwinfo(): + for vif in network_info: + xs_data = self._vif_xenstore_data(vif) + location = ('vm-data/networking/%s' % + vif['address'].replace(':', '')) + self._add_to_param_xenstore(vm_ref, + location, + jsonutils.dumps(xs_data)) + try: + self._write_to_xenstore(instance, location, xs_data, + vm_ref=vm_ref) + except KeyError: + # catch KeyError for domid if instance isn't running + pass + update_nwinfo() def _create_vifs(self, vm_ref, instance, network_info): """Creates vifs for an instance.""" -- cgit