summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorRick Harris <rconradharris@gmail.com>2012-07-31 22:49:13 +0000
committerRick Harris <rconradharris@gmail.com>2012-08-01 04:49:37 +0000
commit4f3291e3795460f0b8da5a029faa2e4a9271c8a9 (patch)
treeef2326cde9b818daea4aabdf1c5d9168b7afea54 /plugins
parentc577144166913d6bdbed626e06ad1fc865d3334d (diff)
downloadnova-4f3291e3795460f0b8da5a029faa2e4a9271c8a9.tar.gz
nova-4f3291e3795460f0b8da5a029faa2e4a9271c8a9.tar.xz
nova-4f3291e3795460f0b8da5a029faa2e4a9271c8a9.zip
XenAPI: Fix race-condition with cached images.
The core problem is that XenServer's `VDI.copy` call drops the destination file directly into the SR. This means that half-completed files are visible with no way to distinguish these from fully-copied files. We had some code that attempted to mitigate this issue by checking physical_utilisation against an expected value. The problem with this code is that it didn't account for VDI chaining where the physical_utilisation would not necessarily match the parent. The net effect of this was that 'cloned' VDIs would never be found because their physical_utilisation was far below what was expected. The work around is to create our own `_safe_copy_vdi` which is isolated and atomic. Long term, `VDI.copy` should be fixed so that half-completed files are never stored in the SR. Change-Id: I6eb3cb5259f9ee1c7394e58f76105a8b39bfc720
Diffstat (limited to 'plugins')
-rw-r--r--plugins/xenserver/xenapi/contrib/rpmbuild/SPECS/openstack-xen-plugins.spec1
-rwxr-xr-xplugins/xenserver/xenapi/etc/xapi.d/plugins/workarounds65
2 files changed, 66 insertions, 0 deletions
diff --git a/plugins/xenserver/xenapi/contrib/rpmbuild/SPECS/openstack-xen-plugins.spec b/plugins/xenserver/xenapi/contrib/rpmbuild/SPECS/openstack-xen-plugins.spec
index 8f4415311..63b5e71d3 100644
--- a/plugins/xenserver/xenapi/contrib/rpmbuild/SPECS/openstack-xen-plugins.spec
+++ b/plugins/xenserver/xenapi/contrib/rpmbuild/SPECS/openstack-xen-plugins.spec
@@ -33,6 +33,7 @@ rm -rf $RPM_BUILD_ROOT
/etc/xapi.d/plugins/kernel
/etc/xapi.d/plugins/migration
/etc/xapi.d/plugins/pluginlib_nova.py
+/etc/xapi.d/plugins/workarounds
/etc/xapi.d/plugins/xenhost
/etc/xapi.d/plugins/xenstore.py
/etc/xapi.d/plugins/utils.py
diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/workarounds b/plugins/xenserver/xenapi/etc/xapi.d/plugins/workarounds
new file mode 100755
index 000000000..611436539
--- /dev/null
+++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/workarounds
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2012 Openstack, LLC
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Handle the uploading and downloading of images via Glance."""
+
+import cPickle as pickle
+try:
+ import json
+except ImportError:
+ import simplejson as json
+import os
+import shutil
+
+import XenAPIPlugin
+
+import utils
+
+#FIXME(sirp): should this use pluginlib from 5.6?
+from pluginlib_nova import *
+configure_logging('hacks')
+
+
+def _copy_vdis(sr_path, staging_path, vdi_uuids):
+ seq_num = 0
+ for vdi_uuid in vdi_uuids:
+ src = os.path.join(sr_path, "%s.vhd" % vdi_uuid)
+ dst = os.path.join(staging_path, "%d.vhd" % seq_num)
+ shutil.copyfile(src, dst)
+ seq_num += 1
+
+
+def safe_copy_vdis(session, args):
+ params = pickle.loads(exists(args, 'params'))
+ sr_path = params["sr_path"]
+ vdi_uuids = params["vdi_uuids"]
+ uuid_stack = params["uuid_stack"]
+
+ staging_path = utils.make_staging_area(sr_path)
+ try:
+ _copy_vdis(sr_path, staging_path, vdi_uuids)
+ imported_vhds = utils.import_vhds(sr_path, staging_path, uuid_stack)
+ finally:
+ utils.cleanup_staging_area(staging_path)
+
+ # Right now, it's easier to return a single string via XenAPI,
+ # so we'll json encode the list of VHDs.
+ return json.dumps(imported_vhds)
+
+
+if __name__ == '__main__':
+ XenAPIPlugin.dispatch({'safe_copy_vdis': safe_copy_vdis})