[openstack-nova/f17] update to latest stable branch

Pádraig Brady pbrady at fedoraproject.org
Fri Jul 20 17:53:53 UTC 2012


commit 7c6fb50596cea672c83b932115a67897af9bec6c
Author: Pádraig Brady <P at draigBrady.com>
Date:   Fri Jul 20 18:31:24 2012 +0100

    update to latest stable branch

 ...bvirt_volume_driver-with-right-mountpoint.patch |    0
 ...e_libvirt_utils-for-libvirt-console-tests.patch |   87 ++++++++++++
 ..._allocation_ratio-based-over-subscription.patch |   87 ++++++++++++
 ...pam_lib-from-changing-the-timeout-setting.patch |    2 +-
 ...file-injection-writing-to-host-filesystem.patch |    0
 ...ish-over-quota-for-volume-size-and-number.patch |   49 ++++---
 ...pose-over-quota-exceptions-via-native-API.patch |  139 +++++++++++++++++++
 0009-repeat-fusermount-to-avoid-business.patch     |   23 ----
 0010-Fix-call-to-network_get_all_by_uuids.patch    |   30 ++++
 ...-fix-libvirt-get_memory_mb_total-with-xen.patch |   54 ++++++++
 ...e-compute_api.get_all-in-affinity-filters.patch |   64 +++++++++
 ...-qemu-img-cluster-size-in-libvirt-connect.patch |   64 +++++++++
 ...13-status-on-over-quota-in-the-native-API.patch |  140 ++++++++++++++++++++
 ...tomic-manipulation-of-libvirt-disk-images.patch |    6 +-
 ...e-don-t-access-the-net-when-building-docs.patch |    2 +-
 ...0017-fix-useexisting-deprecation-warnings.patch |    2 +-
 ...-configurable-libvirt-injection-partition.patch |    4 +-
 ...unt-guest-image-once-when-injecting-files.patch |    4 +-
 ...ect-SELinux-context-for-injected-ssh-keys.patch |    2 +-
 ...ibguestfs-has-completed-before-proceeding.patch |   43 ++++++
 0022-ensure-libguestfs-mounts-are-cleaned-up.patch |   57 ++++++++
 openstack-nova.spec                                |   52 ++++++--
 22 files changed, 842 insertions(+), 69 deletions(-)
---
diff --git a/0002-Call-libvirt_volume_driver-with-right-mountpoint.patch b/0003-Call-libvirt_volume_driver-with-right-mountpoint.patch
similarity index 100%
rename from 0002-Call-libvirt_volume_driver-with-right-mountpoint.patch
rename to 0003-Call-libvirt_volume_driver-with-right-mountpoint.patch
diff --git a/0004-Use-fake_libvirt_utils-for-libvirt-console-tests.patch b/0004-Use-fake_libvirt_utils-for-libvirt-console-tests.patch
new file mode 100644
index 0000000..554bd3b
--- /dev/null
+++ b/0004-Use-fake_libvirt_utils-for-libvirt-console-tests.patch
@@ -0,0 +1,87 @@
+From 410060f91198f1392d0810544411a53f3baa2774 Mon Sep 17 00:00:00 2001
+From: Dan Prince <dprince at redhat.com>
+Date: Thu, 3 May 2012 10:06:46 -0400
+Subject: [PATCH] Use fake_libvirt_utils for libvirt console tests.
+
+Updates test_libvirt.py so that it users fake_libvirt_utils.
+
+This resolves an issue where the previous tests required
+sudo to properly execute.
+
+Fixes LP Bug #992805.
+
+Change-Id: I9354b8facf82fb861dc2fe6da5fca102d8a33fbf
+(cherry picked from commit 82319bf69745f7a20d0f6273821745302ab711e6)
+---
+ nova/tests/fake_libvirt_utils.py |    7 ++++++-
+ nova/tests/test_libvirt.py       |   11 +++++++----
+ 2 files changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/nova/tests/fake_libvirt_utils.py b/nova/tests/fake_libvirt_utils.py
+index bdd24e4..f1d1cb7 100644
+--- a/nova/tests/fake_libvirt_utils.py
++++ b/nova/tests/fake_libvirt_utils.py
+@@ -14,6 +14,7 @@
+ #    License for the specific language governing permissions and limitations
+ #    under the License.
+ 
++import os
+ import StringIO
+ 
+ files = {}
+@@ -89,7 +90,11 @@ def file_open(path, mode=None):
+ 
+ 
+ def load_file(path):
+-    return ''
++    if os.path.exists(path):
++        with open(path, 'r+') as fp:
++            return fp.read()
++    else:
++        return ''
+ 
+ 
+ def file_delete(path):
+diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
+index af30051..afe4630 100644
+--- a/nova/tests/test_libvirt.py
++++ b/nova/tests/test_libvirt.py
+@@ -1329,7 +1329,6 @@ class LibvirtConnTestCase(test.TestCase):
+             shutil.rmtree(os.path.join(FLAGS.instances_path,
+                                        FLAGS.base_dir_name))
+ 
+-    @test.skip_if(missing_libvirt(), "Test requires libvirt")
+     def test_get_console_output_file(self):
+ 
+         with utils.tempdir() as tmpdir:
+@@ -1364,13 +1363,12 @@ class LibvirtConnTestCase(test.TestCase):
+ 
+             self.create_fake_libvirt_mock()
+             connection.LibvirtConnection._conn.lookupByName = fake_lookup
+-            connection.libvirt_utils = libvirt_utils
++            connection.libvirt_utils = fake_libvirt_utils
+ 
+             conn = connection.LibvirtConnection(False)
+             output = conn.get_console_output(instance)
+             self.assertEquals("foo", output)
+ 
+-    @test.skip_if(missing_libvirt(), "Test requires libvirt")
+     def test_get_console_output_pty(self):
+ 
+         with utils.tempdir() as tmpdir:
+@@ -1403,9 +1401,14 @@ class LibvirtConnTestCase(test.TestCase):
+             def fake_lookup(id):
+                 return FakeVirtDomain(fake_dom_xml)
+ 
++            def _fake_flush(self, fake_pty):
++                with open(fake_pty, 'r+') as fp:
++                    return fp.read()
++
+             self.create_fake_libvirt_mock()
+             connection.LibvirtConnection._conn.lookupByName = fake_lookup
+-            connection.libvirt_utils = libvirt_utils
++            connection.LibvirtConnection._flush_libvirt_console = _fake_flush
++            connection.libvirt_utils = fake_libvirt_utils
+ 
+             conn = connection.LibvirtConnection(False)
+             output = conn.get_console_output(instance)
diff --git a/0005-Fixes-ram_allocation_ratio-based-over-subscription.patch b/0005-Fixes-ram_allocation_ratio-based-over-subscription.patch
new file mode 100644
index 0000000..5f84ae4
--- /dev/null
+++ b/0005-Fixes-ram_allocation_ratio-based-over-subscription.patch
@@ -0,0 +1,87 @@
+From 5d8431b765a991b8cff4c349c3225f532d015b43 Mon Sep 17 00:00:00 2001
+From: Joe Gordon <jogo at cloudscaling.com>
+Date: Thu, 21 Jun 2012 16:41:17 -0700
+Subject: [PATCH] Fixes ram_allocation_ratio based over subscription
+
+Fix for bug 1016273
+
+Change-Id: I7f7b227e71e93b4bcded150791fb0b9e9df98e4c
+(cherry picked from commit 1b40708287808243be27b83791b7d23f8b51b194)
+---
+ doc/source/devref/filter_scheduler.rst    |    4 +++-
+ nova/scheduler/filters/ram_filter.py      |    5 ++++-
+ nova/scheduler/host_manager.py            |    2 ++
+ nova/tests/scheduler/test_host_filters.py |   16 ++++++++++++++--
+ 4 files changed, 23 insertions(+), 4 deletions(-)
+
+diff --git a/doc/source/devref/filter_scheduler.rst b/doc/source/devref/filter_scheduler.rst
+index 9f51462..92ee898 100644
+--- a/doc/source/devref/filter_scheduler.rst
++++ b/doc/source/devref/filter_scheduler.rst
+@@ -58,7 +58,9 @@ code. For example class |RamFilter| has the next realization:
+             instance_type = filter_properties.get('instance_type')
+             requested_ram = instance_type['memory_mb']
+             free_ram_mb = host_state.free_ram_mb
+-            return free_ram_mb * FLAGS.ram_allocation_ratio >= requested_ram
++            total_usable_ram_mb = host_state.total_usable_ram_mb
++            used_ram_mb = total_usable_ram_mb - free_ram_mb
++            return total_usable_ram_mb * FLAGS.ram_allocation_ratio  - used_ram_mb >= requested_ram
+ 
+ Here `ram_allocation_ratio` means the virtual RAM to physical RAM allocation
+ ratio (it is 1.5 by default). Really, nice and simple.
+diff --git a/nova/scheduler/filters/ram_filter.py b/nova/scheduler/filters/ram_filter.py
+index 65889d4..4bc84c2 100644
+--- a/nova/scheduler/filters/ram_filter.py
++++ b/nova/scheduler/filters/ram_filter.py
+@@ -37,4 +37,7 @@ class RamFilter(filters.BaseHostFilter):
+         instance_type = filter_properties.get('instance_type')
+         requested_ram = instance_type['memory_mb']
+         free_ram_mb = host_state.free_ram_mb
+-        return free_ram_mb * FLAGS.ram_allocation_ratio >= requested_ram
++        total_usable_ram_mb = host_state.total_usable_ram_mb
++        used_ram_mb = total_usable_ram_mb - free_ram_mb
++        return (total_usable_ram_mb * FLAGS.ram_allocation_ratio -
++                used_ram_mb >= requested_ram)
+diff --git a/nova/scheduler/host_manager.py b/nova/scheduler/host_manager.py
+index f5ba724..289ac27 100644
+--- a/nova/scheduler/host_manager.py
++++ b/nova/scheduler/host_manager.py
+@@ -124,7 +124,9 @@ class HostState(object):
+             all_disk_mb -= FLAGS.reserved_host_disk_mb
+         if FLAGS.reserved_host_memory_mb > 0:
+             all_ram_mb -= FLAGS.reserved_host_memory_mb
++        #NOTE(jogo) free_ram_mb can be negative
+         self.free_ram_mb = all_ram_mb
++        self.total_usable_ram_mb = all_ram_mb
+         self.free_disk_mb = all_disk_mb
+         self.vcpus_total = vcpus_total
+ 
+diff --git a/nova/tests/scheduler/test_host_filters.py b/nova/tests/scheduler/test_host_filters.py
+index f56a145..19b42fd 100644
+--- a/nova/tests/scheduler/test_host_filters.py
++++ b/nova/tests/scheduler/test_host_filters.py
+@@ -182,10 +182,22 @@ class HostFiltersTestCase(test.TestCase):
+         capabilities = {'enabled': True}
+         service = {'disabled': False}
+         host = fakes.FakeHostState('host1', 'compute',
+-                {'free_ram_mb': 1023, 'capabilities': capabilities,
+-                 'service': service})
++                {'free_ram_mb': 1023, 'total_usable_ram_mb': 1024,
++                 'capabilities': capabilities, 'service': service})
+         self.assertFalse(filt_cls.host_passes(host, filter_properties))
+ 
++    def test_ram_filter_oversubscribe(self):
++        self._stub_service_is_up(True)
++        filt_cls = self.class_map['RamFilter']()
++        self.flags(ram_allocation_ratio=2.0)
++        filter_properties = {'instance_type': {'memory_mb': 1024}}
++        capabilities = {'enabled': True}
++        service = {'disabled': False}
++        host = fakes.FakeHostState('host1', 'compute',
++                {'free_ram_mb': -1024, 'total_usable_ram_mb': 2048,
++                 'capabilities': capabilities, 'service': service})
++        self.assertTrue(filt_cls.host_passes(host, filter_properties))
++
+     def test_compute_filter_fails_on_service_disabled(self):
+         self._stub_service_is_up(True)
+         filt_cls = self.class_map['ComputeFilter']()
diff --git a/0004-Stop-nova_ipam_lib-from-changing-the-timeout-setting.patch b/0006-Stop-nova_ipam_lib-from-changing-the-timeout-setting.patch
similarity index 98%
rename from 0004-Stop-nova_ipam_lib-from-changing-the-timeout-setting.patch
rename to 0006-Stop-nova_ipam_lib-from-changing-the-timeout-setting.patch
index fd66e64..2cb9e35 100644
--- a/0004-Stop-nova_ipam_lib-from-changing-the-timeout-setting.patch
+++ b/0006-Stop-nova_ipam_lib-from-changing-the-timeout-setting.patch
@@ -1,4 +1,4 @@
-From 72c218d730736210961cf86f88543c69bf52d1fc Mon Sep 17 00:00:00 2001
+From 3cb6e57587b58864ce70e99cef9f8c87c6082882 Mon Sep 17 00:00:00 2001
 From: Vishvananda Ishaya <vishvananda at gmail.com>
 Date: Tue, 26 Jun 2012 20:37:02 +0000
 Subject: [PATCH] Stop nova_ipam_lib from changing the timeout setting
diff --git a/0003-Prevent-file-injection-writing-to-host-filesystem.patch b/0007-Prevent-file-injection-writing-to-host-filesystem.patch
similarity index 100%
rename from 0003-Prevent-file-injection-writing-to-host-filesystem.patch
rename to 0007-Prevent-file-injection-writing-to-host-filesystem.patch
diff --git a/0012-Distinguish-over-quota-for-volume-size-and-number.patch b/0008-Distinguish-over-quota-for-volume-size-and-number.patch
similarity index 86%
rename from 0012-Distinguish-over-quota-for-volume-size-and-number.patch
rename to 0008-Distinguish-over-quota-for-volume-size-and-number.patch
index ff17e86..99bab56 100644
--- a/0012-Distinguish-over-quota-for-volume-size-and-number.patch
+++ b/0008-Distinguish-over-quota-for-volume-size-and-number.patch
@@ -1,4 +1,4 @@
-From 6fb416d31517b347e9f4ce990d14d9248537cba0 Mon Sep 17 00:00:00 2001
+From 19631f3b4708443486950b602b6b95d13d6d7e74 Mon Sep 17 00:00:00 2001
 From: Eoghan Glynn <eglynn at redhat.com>
 Date: Wed, 4 Jul 2012 19:14:00 +0100
 Subject: [PATCH] Distinguish over-quota for volume size and number.
@@ -11,14 +11,14 @@ excessive space usage.
 
 Change-Id: I71ec995c77bc447bfc9221084b057bd8d69a4513
 ---
- nova/quota.py             |   35 ++++++++++++++++++++---------
- nova/tests/test_quota.py  |   53 +++++++++++++++++++++++---------------------
- nova/tests/test_volume.py |   30 +++++++++++++++++++++++++
- nova/volume/api.py        |   23 ++++++++++++++++---
- 4 files changed, 101 insertions(+), 40 deletions(-)
+ nova/quota.py             |   35 +++++++++++++++++++---------
+ nova/tests/test_quota.py  |   55 ++++++++++++++++++++++++--------------------
+ nova/tests/test_volume.py |   30 ++++++++++++++++++++++++
+ nova/volume/api.py        |   26 ++++++++++++++++++---
+ 4 files changed, 106 insertions(+), 40 deletions(-)
 
 diff --git a/nova/quota.py b/nova/quota.py
-index 12dd146..bcdad99 100644
+index 12dd146..505dce0 100644
 --- a/nova/quota.py
 +++ b/nova/quota.py
 @@ -129,23 +129,36 @@ def allowed_instances(context, requested_instances, instance_type):
@@ -65,15 +65,15 @@ index 12dd146..bcdad99 100644
 +        allowed['volumes'] = min(allowed['volumes'],
 +                                 int(allowed['gigabytes'] // size))
 +
-+    return (overs, usages, quotas, allowed)
++    return dict(overs=overs, usages=usages, quotas=quotas, allowed=allowed)
  
  
  def allowed_floating_ips(context, requested_floating_ips):
 diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py
-index 8cc5577..69242ea 100644
+index 8cc5577..286600c 100644
 --- a/nova/tests/test_quota.py
 +++ b/nova/tests/test_quota.py
-@@ -196,31 +196,34 @@ class QuotaTestCase(test.TestCase):
+@@ -196,31 +196,36 @@ class QuotaTestCase(test.TestCase):
                                                  instance_type)
          self.assertEqual(num_instances, 101)
  
@@ -105,8 +105,10 @@ index 8cc5577..69242ea 100644
 +    def _do_test_volume_quota(self, resource):
 +
 +        def _validate(result, request, quota, allow):
-+            (overs, usages, quotas, allowed) = result
-+            print 'overs %s' % overs
++            overs = result['overs']
++            usages = result['usages']
++            quotas = result['quotas']
++            allowed = result['allowed']
 +            self.assertEquals(request > allow, resource in overs)
 +            self.assertEquals(usages[resource], 0)
 +            self.assertEquals(quotas[resource], quota)
@@ -134,7 +136,7 @@ index 8cc5577..69242ea 100644
      def test_unlimited_floating_ips(self):
          self.flags(quota_floating_ips=10)
 diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py
-index fca593c..118fd5b 100644
+index fca593c..58a6715 100644
 --- a/nova/tests/test_volume.py
 +++ b/nova/tests/test_volume.py
 @@ -81,6 +81,36 @@ class VolumeTestCase(test.TestCase):
@@ -145,10 +147,10 @@ index fca593c..118fd5b 100644
 +        """Test volume creation over quota."""
 +
 +        def fake_allowed_volumes(context, requested_volumes, size):
-+            return ([resource],
-+                    dict(gigabytes=999, volumes=9),
-+                    dict(gigabytes=1000, volumes=10),
-+                    dict(gigabytes=0, volumes=0))
++            return dict(overs=[resource],
++                        usages=dict(gigabytes=999, volumes=9),
++                        quotas=dict(gigabytes=1000, volumes=10),
++                        allowed=dict(gigabytes=0, volumes=0))
 +
 +        self.stubs.Set(nova.quota, 'allowed_volumes', fake_allowed_volumes)
 +
@@ -175,17 +177,20 @@ index fca593c..118fd5b 100644
          """Test volume survives deletion if driver reports it as busy."""
          volume = self._create_volume()
 diff --git a/nova/volume/api.py b/nova/volume/api.py
-index 76de551..08c51bb 100644
+index 76de551..c5faf4a 100644
 --- a/nova/volume/api.py
 +++ b/nova/volume/api.py
-@@ -80,11 +80,26 @@ class API(base.Base):
+@@ -80,11 +80,29 @@ class API(base.Base):
          else:
              snapshot_id = None
  
 -        if quota.allowed_volumes(context, 1, size) < 1:
-+        (overs, usages, quotas, allowed) = quota.allowed_volumes(context,
-+                                                                 1,
-+                                                                 size)
++        result = quota.allowed_volumes(context, 1, size)
++
++        overs = result['overs']
++        usages = result['usages']
++        quotas = result['quotas']
++        allowed = result['allowed']
 +
 +        if allowed['volumes'] < 1:
              pid = context.project_id
diff --git a/0009-Expose-over-quota-exceptions-via-native-API.patch b/0009-Expose-over-quota-exceptions-via-native-API.patch
new file mode 100644
index 0000000..830f13c
--- /dev/null
+++ b/0009-Expose-over-quota-exceptions-via-native-API.patch
@@ -0,0 +1,139 @@
+From 4c49df742d1730b124f81e30f12e61602966a819 Mon Sep 17 00:00:00 2001
+From: Eoghan Glynn <eglynn at redhat.com>
+Date: Fri, 6 Jul 2012 10:10:28 +0000
+Subject: [PATCH] Expose over-quota exceptions via native API.
+
+Fixes bug LP 1021373.
+
+Previously an over-quota condition would be exposed via the EC2 API,
+but hidden in the corresponding call via the native API (in the sense
+of the exception detail being replaced with a generic 500 Server Error
+response).
+
+We now report any NovaException declared to be safe. In this patch,
+the set of safe exception types includes any subclass of QuotaError,
+but in subsequent patches the net should be widened to include
+exceptions that do not expose senstive information.
+
+Change-Id: I3cc36337c7e67cf487ca49de646c437c217ae538
+---
+ nova/api/openstack/__init__.py               |   30 ++++++++++++++++++-------
+ nova/exception.py                            |    2 +
+ nova/tests/api/openstack/compute/test_api.py |   24 ++++++++++++++++++++
+ 3 files changed, 47 insertions(+), 9 deletions(-)
+
+diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py
+index 82e958a..92b4731 100644
+--- a/nova/api/openstack/__init__.py
++++ b/nova/api/openstack/__init__.py
+@@ -25,6 +25,7 @@ import webob.dec
+ import webob.exc
+ 
+ from nova.api.openstack import wsgi
++from nova import exception
+ from nova import log as logging
+ from nova import wsgi as base_wsgi
+ 
+@@ -35,20 +36,31 @@ LOG = logging.getLogger(__name__)
+ class FaultWrapper(base_wsgi.Middleware):
+     """Calls down the middleware stack, making exceptions into faults."""
+ 
++    def _error(self, inner, req, safe=False):
++        LOG.exception(_("Caught error: %s"), unicode(inner))
++        msg_dict = dict(url=req.url, status=500)
++        LOG.info(_("%(url)s returned with HTTP %(status)d") % msg_dict)
++        outer = webob.exc.HTTPInternalServerError()
++        # NOTE(johannes): We leave the explanation empty here on
++        # purpose. It could possibly have sensitive information
++        # that should not be returned back to the user. See
++        # bugs 868360 and 874472
++        # NOTE(eglynn): However, it would be over-conservative and
++        # inconsistent with the EC2 API to hide every exception,
++        # including those that are safe to expose, see bug 1021373
++        if safe:
++            outer.explanation = '%s: %s' % (inner.__class__.__name__,
++                                            unicode(inner))
++        return wsgi.Fault(outer)
++
+     @webob.dec.wsgify(RequestClass=wsgi.Request)
+     def __call__(self, req):
+         try:
+             return req.get_response(self.application)
++        except exception.NovaException as ex:
++            return self._error(ex, req, ex.safe)
+         except Exception as ex:
+-            LOG.exception(_("Caught error: %s"), unicode(ex))
+-            msg_dict = dict(url=req.url, status=500)
+-            LOG.info(_("%(url)s returned with HTTP %(status)d") % msg_dict)
+-            exc = webob.exc.HTTPInternalServerError()
+-            # NOTE(johannes): We leave the explanation empty here on
+-            # purpose. It could possibly have sensitive information
+-            # that should not be returned back to the user. See
+-            # bugs 868360 and 874472
+-            return wsgi.Fault(exc)
++            return self._error(ex, req)
+ 
+ 
+ class APIMapper(routes.Mapper):
+diff --git a/nova/exception.py b/nova/exception.py
+index da067b6..8dd6033 100644
+--- a/nova/exception.py
++++ b/nova/exception.py
+@@ -153,6 +153,7 @@ class NovaException(Exception):
+ 
+     """
+     message = _("An unknown exception occurred.")
++    safe = False
+ 
+     def __init__(self, message=None, **kwargs):
+         self.kwargs = kwargs
+@@ -952,6 +953,7 @@ class WillNotSchedule(NovaException):
+ 
+ class QuotaError(NovaException):
+     message = _("Quota exceeded") + ": code=%(code)s"
++    safe = True
+ 
+ 
+ class AggregateError(NovaException):
+diff --git a/nova/tests/api/openstack/compute/test_api.py b/nova/tests/api/openstack/compute/test_api.py
+index 99210cc..974b588 100644
+--- a/nova/tests/api/openstack/compute/test_api.py
++++ b/nova/tests/api/openstack/compute/test_api.py
+@@ -23,6 +23,7 @@ import webob.exc
+ import webob.dec
+ 
+ import nova.context
++from nova import exception
+ from nova import test
+ from nova.api import openstack as openstack_api
+ from nova.api.openstack import wsgi
+@@ -121,6 +122,29 @@ class APITest(test.TestCase):
+         self.assertTrue('<computeFault' in resp.body, resp.body)
+         self.assertEqual(resp.status_int, 500, resp.body)
+ 
++    def _do_test_exception_safety_reflected_in_faults(self, expose):
++        class ExceptionWithSafety(exception.NovaException):
++            safe = expose
++
++        @webob.dec.wsgify
++        def fail(req):
++            raise ExceptionWithSafety('some explanation')
++
++        api = self._wsgi_app(fail)
++        resp = webob.Request.blank('/').get_response(api)
++        self.assertTrue('{"computeFault' in resp.body, resp.body)
++        expected = ('ExceptionWithSafety: some explanation' if expose else
++                    'The server has either erred or is incapable '
++                    'of performing the requested operation.')
++        self.assertTrue(expected in resp.body, resp.body)
++        self.assertEqual(resp.status_int, 500, resp.body)
++
++    def test_safe_exceptions_are_described_in_faults(self):
++        self._do_test_exception_safety_reflected_in_faults(True)
++
++    def test_unsafe_exceptions_are_not_described_in_faults(self):
++        self._do_test_exception_safety_reflected_in_faults(False)
++
+     def test_request_id_in_response(self):
+         req = webob.Request.blank('/')
+         req.method = 'GET'
diff --git a/0010-Fix-call-to-network_get_all_by_uuids.patch b/0010-Fix-call-to-network_get_all_by_uuids.patch
new file mode 100644
index 0000000..f7e1664
--- /dev/null
+++ b/0010-Fix-call-to-network_get_all_by_uuids.patch
@@ -0,0 +1,30 @@
+From 00e5104b8b0160100bcd442dfcdba507a3d4a137 Mon Sep 17 00:00:00 2001
+From: Chuck Short <chuck.short at canonical.com>
+Date: Thu, 26 Apr 2012 10:26:57 -0400
+Subject: [PATCH] Fix call to network_get_all_by_uuids().
+
+Fix bug 986922
+
+This patch fixes a typo in the network manager.  This function is part
+of the db API, not a method of the network manager.
+
+(cherry picked from commit cc05a8defbb0d36ae6531acd2c5a9677c2f7ce97)
+
+Change-Id: I2b0769f69ec4f58cd22708070b5fa4037f856026
+---
+ nova/network/manager.py |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/nova/network/manager.py b/nova/network/manager.py
+index 9ecc6e2..73ac52b 100644
+--- a/nova/network/manager.py
++++ b/nova/network/manager.py
+@@ -868,7 +868,7 @@ class NetworkManager(manager.SchedulerDependentManager):
+         #                 a non-vlan instance should connect to
+         if requested_networks is not None and len(requested_networks) != 0:
+             network_uuids = [uuid for (uuid, fixed_ip) in requested_networks]
+-            networks = self.network_get_all_by_uuids(context, network_uuids)
++            networks = self.db.network_get_all_by_uuids(context, network_uuids)
+         else:
+             try:
+                 networks = self.db.network_get_all(context)
diff --git a/0011-fix-libvirt-get_memory_mb_total-with-xen.patch b/0011-fix-libvirt-get_memory_mb_total-with-xen.patch
new file mode 100644
index 0000000..cd834db
--- /dev/null
+++ b/0011-fix-libvirt-get_memory_mb_total-with-xen.patch
@@ -0,0 +1,54 @@
+From 835ba4f23eb32c69aaeb1da590a297565b60388d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady at redhat.com>
+Date: Mon, 25 Jun 2012 16:48:24 +0100
+Subject: [PATCH] fix libvirt get_memory_mb_total() with xen
+
+Fixes bug 1004298 in stable/essex.
+
+Commit 5b93a576 failed to remove the 'staticmethod'
+decorator from the method, to allow it to access
+object variables.
+
+Also there is no need to have the libvirt getInfo() call
+be xen specific.  In the LXC/QEMU/UML drivers this call
+uses GNULIB's physmem module, which is cross-OS portable.
+
+Change-Id: I565eda78f6c468cf6bd227756cfc068725069218
+(cherry picked from commit 78352b98a96946145bec9010872d8f2769691ac2)
+---
+ nova/virt/libvirt/connection.py |   16 ++--------------
+ 1 files changed, 2 insertions(+), 14 deletions(-)
+
+diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
+index 5ec029a..da44ac4 100644
+--- a/nova/virt/libvirt/connection.py
++++ b/nova/virt/libvirt/connection.py
+@@ -1703,26 +1703,14 @@ class LibvirtConnection(driver.ComputeDriver):
+                        "This error can be safely ignored for now."))
+             return 0
+ 
+-    @staticmethod
+-    def get_memory_mb_total():
++    def get_memory_mb_total(self):
+         """Get the total memory size(MB) of physical computer.
+ 
+         :returns: the total amount of memory(MB).
+ 
+         """
+ 
+-        if sys.platform.upper() not in ['LINUX2', 'LINUX3']:
+-            return 0
+-
+-        if FLAGS.libvirt_type == 'xen':
+-            meminfo = self._conn.getInfo()[1]
+-            # this is in MB
+-            return meminfo
+-        else:
+-            meminfo = open('/proc/meminfo').read().split()
+-            idx = meminfo.index('MemTotal:')
+-            # transforming KB to MB
+-            return int(meminfo[idx + 1]) / 1024
++        return self._conn.getInfo()[1]
+ 
+     @staticmethod
+     def get_local_gb_total():
diff --git a/0012-Use-compute_api.get_all-in-affinity-filters.patch b/0012-Use-compute_api.get_all-in-affinity-filters.patch
new file mode 100644
index 0000000..f30137d
--- /dev/null
+++ b/0012-Use-compute_api.get_all-in-affinity-filters.patch
@@ -0,0 +1,64 @@
+From 25f5bd31805bd21d7b7e3583c775252aa8f737e9 Mon Sep 17 00:00:00 2001
+From: Dan Prince <dprince at redhat.com>
+Date: Wed, 11 Jul 2012 10:19:05 -0400
+Subject: [PATCH] Use compute_api.get_all in affinity filters.
+
+Updates the affinity filters so they make a single compute API
+call to lookup instance host information rather than single
+lookups for each UUID.
+
+This resolves a potential performance issue which can cause a
+scheduler to hang while processing requests which contain large numbers
+of UUID's in the scheduler_hints.
+
+Fixes LP Bug #1017795.
+
+Change-Id: Ie33378a992e53002c16b2d99135699b576f3d7e3
+---
+ nova/scheduler/filters/affinity_filter.py |   19 +++++++++++--------
+ 1 files changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/nova/scheduler/filters/affinity_filter.py b/nova/scheduler/filters/affinity_filter.py
+index e6e7a11..81d9442 100644
+--- a/nova/scheduler/filters/affinity_filter.py
++++ b/nova/scheduler/filters/affinity_filter.py
+@@ -26,8 +26,11 @@ class AffinityFilter(filters.BaseHostFilter):
+     def __init__(self):
+         self.compute_api = compute.API()
+ 
+-    def _affinity_host(self, context, instance_id):
+-        return self.compute_api.get(context, instance_id)['host']
++    def _all_hosts(self, context):
++        all_hosts = {}
++        for instance in self.compute_api.get_all(context):
++            all_hosts[instance['uuid']] = instance['host']
++        return all_hosts
+ 
+ 
+ class DifferentHostFilter(AffinityFilter):
+@@ -40,9 +43,9 @@ class DifferentHostFilter(AffinityFilter):
+ 
+         affinity_uuids = scheduler_hints.get('different_host', [])
+         if affinity_uuids:
+-            return not any([i for i
+-                              in affinity_uuids
+-                              if self._affinity_host(context, i) == me])
++            all_hosts = self._all_hosts(context)
++            return not any([i for i in affinity_uuids
++                              if all_hosts.get(i) == me])
+         # With no different_host key
+         return True
+ 
+@@ -59,9 +62,9 @@ class SameHostFilter(AffinityFilter):
+ 
+         affinity_uuids = scheduler_hints.get('same_host', [])
+         if affinity_uuids:
+-            return any([i for i
+-                          in affinity_uuids
+-                          if self._affinity_host(context, i) == me])
++            all_hosts = self._all_hosts(context)
++            return any([i for i in affinity_uuids
++                          if all_hosts.get(i) == me])
+         # With no same_host key
+         return True
+ 
diff --git a/0013-Use-default-qemu-img-cluster-size-in-libvirt-connect.patch b/0013-Use-default-qemu-img-cluster-size-in-libvirt-connect.patch
new file mode 100644
index 0000000..b04eb73
--- /dev/null
+++ b/0013-Use-default-qemu-img-cluster-size-in-libvirt-connect.patch
@@ -0,0 +1,64 @@
+From 7b215ed439a7b29b8681ced133e2e5b5ad074c0c Mon Sep 17 00:00:00 2001
+From: Jim Fehlig <jfehlig at suse.com>
+Date: Thu, 10 May 2012 13:20:20 -0700
+Subject: [PATCH] Use default qemu-img cluster size in libvirt connection
+ driver
+
+The recommended cluster size [1] for qcow2 is 64k, which is the default
+when invoking 'qemu-img create ...'.  Remove the cluster_size option
+from qemu-img invocation.
+
+[1] http://www.mail-archive.com/openstack@lists.launchpad.net/msg11371.html
+
+V2: Fix test.
+
+Note: This patch is needed in the stable/essex branch too, otherwise it
+is not possible to start Xen instances that use qcow2 images.  The old
+qemu 0.10 in Xen cannot cope with cluster size > 64k.
+
+Change-Id: Iafc290720a820cb5f57ded10a2f584fdc5cd5b49
+(cherry picked from commit de5cb27e64267ec59e12a495a59880412cecb5e8)
+---
+ Authors                    |    1 +
+ nova/tests/test_libvirt.py |    2 +-
+ nova/virt/libvirt/utils.py |    2 +-
+ 3 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/Authors b/Authors
+index 2a7a82a..6a9dc98 100644
+--- a/Authors
++++ b/Authors
+@@ -84,6 +84,7 @@ Jason Koelker <jason at koelker.net>
+ Jay Pipes <jaypipes at gmail.com>
+ JC Martin <jcmartin at ebaysf.com>
+ Jesse Andrews <anotherjesse at gmail.com>
++Jim Fehlig <jfehlig at suse.com>
+ Jimmy Bergman <jimmy at sigint.se>
+ Joe Gordon <jogo at cloudscaling.com>
+ Joe Heck <heckj at mac.com>
+diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
+index 659ac63..bd13e0a 100644
+--- a/nova/tests/test_libvirt.py
++++ b/nova/tests/test_libvirt.py
+@@ -2135,7 +2135,7 @@ class LibvirtUtilsTestCase(test.TestCase):
+     def test_create_cow_image(self):
+         self.mox.StubOutWithMock(utils, 'execute')
+         utils.execute('qemu-img', 'create', '-f', 'qcow2',
+-                      '-o', 'cluster_size=2M,backing_file=/some/path',
++                      '-o', 'backing_file=/some/path',
+                       '/the/new/cow')
+         # Start test
+         self.mox.ReplayAll()
+diff --git a/nova/virt/libvirt/utils.py b/nova/virt/libvirt/utils.py
+index 977eda8..ffb7477 100644
+--- a/nova/virt/libvirt/utils.py
++++ b/nova/virt/libvirt/utils.py
+@@ -69,7 +69,7 @@ def create_cow_image(backing_file, path):
+     :param path: Desired location of the COW image
+     """
+     execute('qemu-img', 'create', '-f', 'qcow2', '-o',
+-             'cluster_size=2M,backing_file=%s' % backing_file, path)
++             'backing_file=%s' % backing_file, path)
+ 
+ 
+ def get_disk_size(path):
diff --git a/0014-Return-413-status-on-over-quota-in-the-native-API.patch b/0014-Return-413-status-on-over-quota-in-the-native-API.patch
new file mode 100644
index 0000000..483baf3
--- /dev/null
+++ b/0014-Return-413-status-on-over-quota-in-the-native-API.patch
@@ -0,0 +1,140 @@
+From 6e873bccc078e1013987698cd71c69deebf2e99f Mon Sep 17 00:00:00 2001
+From: Eoghan Glynn <eglynn at redhat.com>
+Date: Mon, 9 Jul 2012 21:09:06 +0100
+Subject: [PATCH] Return 413 status on over-quota in the native API.
+
+Related to LP 1021373.
+
+Previously, we returned a generic 500 Server Error on an over-quota
+conditions, whereas this is arguably more appropriately reported
+as a 413 status.
+
+Change-Id: I5c1cdc9db54804c512d60e4179c1faa13516d6f9
+---
+ nova/api/openstack/__init__.py               |   21 +++++++++++++++++----
+ nova/exception.py                            |    4 ++++
+ nova/tests/api/openstack/compute/test_api.py |   16 ++++++++++++++++
+ nova/utils.py                                |   13 +++++++++++++
+ 4 files changed, 50 insertions(+), 4 deletions(-)
+
+diff --git a/nova/api/openstack/__init__.py b/nova/api/openstack/__init__.py
+index 92b4731..00b3f3e 100644
+--- a/nova/api/openstack/__init__.py
++++ b/nova/api/openstack/__init__.py
+@@ -27,6 +27,7 @@ import webob.exc
+ from nova.api.openstack import wsgi
+ from nova import exception
+ from nova import log as logging
++from nova import utils
+ from nova import wsgi as base_wsgi
+ 
+ 
+@@ -36,11 +37,23 @@ LOG = logging.getLogger(__name__)
+ class FaultWrapper(base_wsgi.Middleware):
+     """Calls down the middleware stack, making exceptions into faults."""
+ 
+-    def _error(self, inner, req, safe=False):
++    _status_to_type = {}
++
++    @staticmethod
++    def status_to_type(status):
++        if not FaultWrapper._status_to_type:
++            for clazz in utils.walk_class_hierarchy(webob.exc.HTTPError):
++                FaultWrapper._status_to_type[clazz.code] = clazz
++        return FaultWrapper._status_to_type.get(
++                                  status, webob.exc.HTTPInternalServerError)()
++
++    def _error(self, inner, req, headers=None, status=500, safe=False):
+         LOG.exception(_("Caught error: %s"), unicode(inner))
+-        msg_dict = dict(url=req.url, status=500)
++        msg_dict = dict(url=req.url, status=status)
+         LOG.info(_("%(url)s returned with HTTP %(status)d") % msg_dict)
+-        outer = webob.exc.HTTPInternalServerError()
++        outer = self.status_to_type(status)
++        if headers:
++            outer.headers = headers
+         # NOTE(johannes): We leave the explanation empty here on
+         # purpose. It could possibly have sensitive information
+         # that should not be returned back to the user. See
+@@ -58,7 +71,7 @@ class FaultWrapper(base_wsgi.Middleware):
+         try:
+             return req.get_response(self.application)
+         except exception.NovaException as ex:
+-            return self._error(ex, req, ex.safe)
++            return self._error(ex, req, ex.headers, ex.code, ex.safe)
+         except Exception as ex:
+             return self._error(ex, req)
+ 
+diff --git a/nova/exception.py b/nova/exception.py
+index 8dd6033..107d926 100644
+--- a/nova/exception.py
++++ b/nova/exception.py
+@@ -153,6 +153,8 @@ class NovaException(Exception):
+ 
+     """
+     message = _("An unknown exception occurred.")
++    code = 500
++    headers = {}
+     safe = False
+ 
+     def __init__(self, message=None, **kwargs):
+@@ -953,6 +955,8 @@ class WillNotSchedule(NovaException):
+ 
+ class QuotaError(NovaException):
+     message = _("Quota exceeded") + ": code=%(code)s"
++    code = 413
++    headers = {'Retry-After': 0}
+     safe = True
+ 
+ 
+diff --git a/nova/tests/api/openstack/compute/test_api.py b/nova/tests/api/openstack/compute/test_api.py
+index 974b588..a9e186a 100644
+--- a/nova/tests/api/openstack/compute/test_api.py
++++ b/nova/tests/api/openstack/compute/test_api.py
+@@ -145,6 +145,22 @@ class APITest(test.TestCase):
+     def test_unsafe_exceptions_are_not_described_in_faults(self):
+         self._do_test_exception_safety_reflected_in_faults(False)
+ 
++    def _do_test_exception_mapping(self, exception_type):
++        @webob.dec.wsgify
++        def fail(req):
++            raise exception_type('too many used')
++
++        api = self._wsgi_app(fail)
++        resp = webob.Request.blank('/').get_response(api)
++        self.assertTrue('too many used' in resp.body, resp.body)
++        self.assertEqual(resp.status_int, exception_type.code, resp.body)
++        for (key, value) in exception_type.headers.iteritems():
++            self.assertTrue(key in resp.headers)
++            self.assertEquals(resp.headers[key], value)
++
++    def test_quota_error_mapping(self):
++        self._do_test_exception_mapping(exception.QuotaError)
++
+     def test_request_id_in_response(self):
+         req = webob.Request.blank('/')
+         req.method = 'GET'
+diff --git a/nova/utils.py b/nova/utils.py
+index 819929a..de2da9f 100644
+--- a/nova/utils.py
++++ b/nova/utils.py
+@@ -1687,6 +1687,19 @@ def strcmp_const_time(s1, s2):
+     return result == 0
+ 
+ 
++def walk_class_hierarchy(clazz, encountered=None):
++    """Walk class hierarchy, yielding most derived classes first"""
++    if not encountered:
++        encountered = []
++    for subclass in clazz.__subclasses__():
++        if subclass not in encountered:
++            encountered.append(subclass)
++            # drill down to leaves first
++            for subsubclass in walk_class_hierarchy(subclass, encountered):
++                yield subsubclass
++            yield subclass
++
++
+ class UndoManager(object):
+     """Provides a mechanism to facilitate rolling back a series of actions
+     when an exception is raised.
diff --git a/0005-ensure-atomic-manipulation-of-libvirt-disk-images.patch b/0015-ensure-atomic-manipulation-of-libvirt-disk-images.patch
similarity index 98%
rename from 0005-ensure-atomic-manipulation-of-libvirt-disk-images.patch
rename to 0015-ensure-atomic-manipulation-of-libvirt-disk-images.patch
index cc7e0a4..e2e9a3a 100644
--- a/0005-ensure-atomic-manipulation-of-libvirt-disk-images.patch
+++ b/0015-ensure-atomic-manipulation-of-libvirt-disk-images.patch
@@ -1,4 +1,4 @@
-From c765c320651a7cf029658ffb1b987e7162b5e2bf Mon Sep 17 00:00:00 2001
+From 8d21a20cb7ca568afaa5b9a759d7e61fb87bb786 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady at redhat.com>
 Date: Fri, 16 Mar 2012 03:43:49 +0000
 Subject: [PATCH] ensure atomic manipulation of libvirt disk images
@@ -25,7 +25,7 @@ Change-Id: I81a5407665a6998128c0dee41387ef00ebddeb4d
  3 files changed, 57 insertions(+), 49 deletions(-)
 
 diff --git a/nova/utils.py b/nova/utils.py
-index 819929a..7188d98 100644
+index de2da9f..a2242e6 100644
 --- a/nova/utils.py
 +++ b/nova/utils.py
 @@ -21,6 +21,7 @@
@@ -169,7 +169,7 @@ index 1e0ae0a..626f3ff 100644
  
      return metadata
 diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
-index 5ec029a..f909886 100644
+index da44ac4..2dfe2a3 100644
 --- a/nova/virt/libvirt/connection.py
 +++ b/nova/virt/libvirt/connection.py
 @@ -1112,7 +1112,8 @@ class LibvirtConnection(driver.ComputeDriver):
diff --git a/0006-Ensure-we-don-t-access-the-net-when-building-docs.patch b/0016-Ensure-we-don-t-access-the-net-when-building-docs.patch
similarity index 94%
rename from 0006-Ensure-we-don-t-access-the-net-when-building-docs.patch
rename to 0016-Ensure-we-don-t-access-the-net-when-building-docs.patch
index 995f211..f2b7af0 100644
--- a/0006-Ensure-we-don-t-access-the-net-when-building-docs.patch
+++ b/0016-Ensure-we-don-t-access-the-net-when-building-docs.patch
@@ -1,4 +1,4 @@
-From 2f7444c4b5c8eeebdd422d45929d37aa4ccd0ec4 Mon Sep 17 00:00:00 2001
+From 8b0adec9ccc6c1117ea93ae7dad21b9780a3348f Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady at redhat.com>
 Date: Fri, 6 Jan 2012 12:16:34 +0000
 Subject: [PATCH] Ensure we don't access the net when building docs
diff --git a/0007-fix-useexisting-deprecation-warnings.patch b/0017-fix-useexisting-deprecation-warnings.patch
similarity index 97%
rename from 0007-fix-useexisting-deprecation-warnings.patch
rename to 0017-fix-useexisting-deprecation-warnings.patch
index a81071f..9bd96c9 100644
--- a/0007-fix-useexisting-deprecation-warnings.patch
+++ b/0017-fix-useexisting-deprecation-warnings.patch
@@ -1,4 +1,4 @@
-From 45f00db6fe33eeb2514c1fecb2a56f4ee294bfd2 Mon Sep 17 00:00:00 2001
+From d6c56537b8ad046b1b6ffd8011226f4cbe626526 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady at redhat.com>
 Date: Thu, 8 Mar 2012 16:32:30 +0000
 Subject: [PATCH] fix useexisting deprecation warnings
diff --git a/0008-support-a-configurable-libvirt-injection-partition.patch b/0018-support-a-configurable-libvirt-injection-partition.patch
similarity index 97%
rename from 0008-support-a-configurable-libvirt-injection-partition.patch
rename to 0018-support-a-configurable-libvirt-injection-partition.patch
index 8c9fdd2..f237b33 100644
--- a/0008-support-a-configurable-libvirt-injection-partition.patch
+++ b/0018-support-a-configurable-libvirt-injection-partition.patch
@@ -1,4 +1,4 @@
-From aee4d472fc80726bc9a18d7175627d9c5d1fab5c Mon Sep 17 00:00:00 2001
+From b06d4c0c4648a25ac7605905d7559e9de4cb810a Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady at redhat.com>
 Date: Wed, 18 Apr 2012 23:27:31 +0100
 Subject: [PATCH] support a configurable libvirt injection partition
@@ -47,7 +47,7 @@ index 4fb5dda..11959b2 100644
              else:
                  self.mapped_device = map_path
 diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
-index f909886..ad084b2 100644
+index 2dfe2a3..10d8caa 100644
 --- a/nova/virt/libvirt/connection.py
 +++ b/nova/virt/libvirt/connection.py
 @@ -108,6 +108,11 @@ libvirt_opts = [
diff --git a/0010-only-mount-guest-image-once-when-injecting-files.patch b/0019-only-mount-guest-image-once-when-injecting-files.patch
similarity index 98%
rename from 0010-only-mount-guest-image-once-when-injecting-files.patch
rename to 0019-only-mount-guest-image-once-when-injecting-files.patch
index 8ae6d8f..4d9fcd4 100644
--- a/0010-only-mount-guest-image-once-when-injecting-files.patch
+++ b/0019-only-mount-guest-image-once-when-injecting-files.patch
@@ -1,4 +1,4 @@
-From 8843f1e61d5b648306398f6e8b8448c1442f58bf Mon Sep 17 00:00:00 2001
+From 74f89b8fd765e713bdff4823210ccfa3c342cad9 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady at redhat.com>
 Date: Mon, 25 Jun 2012 13:52:46 +0100
 Subject: [PATCH] only mount guest image once when injecting files
@@ -111,7 +111,7 @@ index 04feb76..d6d6007 100644
  
      admin_password is a root password
 diff --git a/nova/virt/libvirt/connection.py b/nova/virt/libvirt/connection.py
-index ad084b2..9f85419 100644
+index 10d8caa..50ebbed 100644
 --- a/nova/virt/libvirt/connection.py
 +++ b/nova/virt/libvirt/connection.py
 @@ -970,12 +970,6 @@ class LibvirtConnection(driver.ComputeDriver):
diff --git a/0011-set-correct-SELinux-context-for-injected-ssh-keys.patch b/0020-set-correct-SELinux-context-for-injected-ssh-keys.patch
similarity index 98%
rename from 0011-set-correct-SELinux-context-for-injected-ssh-keys.patch
rename to 0020-set-correct-SELinux-context-for-injected-ssh-keys.patch
index 282e1f8..5667547 100644
--- a/0011-set-correct-SELinux-context-for-injected-ssh-keys.patch
+++ b/0020-set-correct-SELinux-context-for-injected-ssh-keys.patch
@@ -1,4 +1,4 @@
-From 0cb4c982d353089b1396b9cfaf5d2cdc53496a6f Mon Sep 17 00:00:00 2001
+From da96aac3cfcef22f03a2d3962b5fc0e15a934658 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady at redhat.com>
 Date: Wed, 27 Jun 2012 10:29:57 +0100
 Subject: [PATCH] set correct SELinux context for injected ssh keys
diff --git a/0021-ensure-libguestfs-has-completed-before-proceeding.patch b/0021-ensure-libguestfs-has-completed-before-proceeding.patch
new file mode 100644
index 0000000..e975238
--- /dev/null
+++ b/0021-ensure-libguestfs-has-completed-before-proceeding.patch
@@ -0,0 +1,43 @@
+From 7656d036b559b5337bf36f3a6676d75edb52d8ab Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady at redhat.com>
+Date: Tue, 10 Jul 2012 15:22:39 +0100
+Subject: [PATCH] ensure libguestfs has completed before proceeding
+
+This avoids a FUSE issue referenced here:
+http://code.google.com/p/s3ql/issues/detail?id=159
+which in turn references this thread on the subject from 2006:
+http://thread.gmane.org/gmane.comp.file-systems.fuse.devel/3903
+And another case from 2008:
+http://permalink.gmane.org/gmane.comp.file-systems.fuse.devel/6502
+
+The vast majority of this work was reproducing and classifying
+done by David Naori and Richard W.M. Jones at:
+https://bugzilla.redhat.com/show_bug.cgi?id=835466
+
+Fixes bug: 1013689
+Change-Id: I36fd11d5f01562f65a6b6f07e759ea066490b067
+---
+ nova/virt/disk/guestfs.py |   12 ++++++++++++
+ 1 files changed, 12 insertions(+), 0 deletions(-)
+
+diff --git a/nova/virt/disk/guestfs.py b/nova/virt/disk/guestfs.py
+index 20e3eda..f2ff3c3 100644
+--- a/nova/virt/disk/guestfs.py
++++ b/nova/virt/disk/guestfs.py
+@@ -91,4 +91,16 @@ class Mount(mount.Mount):
+         # root users don't need a specific unmnt_dev()
+         # but ordinary users do
+         utils.execute('fusermount', '-u', self.mount_dir, run_as_root=True)
++
++        # Unfortunately FUSE has an issue where it doesn't wait
++        # for processes associated with the mount to terminate.
++        # Therefore we do this manually here.  Note later versions
++        # of guestmount have the --pid-file option to help with this.
++        # Here we check every .2 seconds whether guestmount is finished
++        # but do this for at most 10 seconds.
++        wait_cmd = 'until ! ps -C guestmount -o args= | grep -qF "%s"; '
++        wait_cmd += 'do sleep .2; done'
++        wait_cmd %= self.mount_dir
++        utils.execute('timeout', '10s', 'sh', '-c', wait_cmd)
++
+         self.mounted = False
diff --git a/0022-ensure-libguestfs-mounts-are-cleaned-up.patch b/0022-ensure-libguestfs-mounts-are-cleaned-up.patch
new file mode 100644
index 0000000..84b2748
--- /dev/null
+++ b/0022-ensure-libguestfs-mounts-are-cleaned-up.patch
@@ -0,0 +1,57 @@
+From 3e48d95cc79e77c1e51ed1fbc00b9fe46d800f73 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady at redhat.com>
+Date: Wed, 11 Jul 2012 23:45:28 +0100
+Subject: [PATCH] ensure libguestfs mounts are cleaned up
+
+Make a few attempts to umount the libguestfs
+mounts, in case other processes are accessing
+the mounts (like udev etc.)
+
+If we still can't umount after 5 attempts
+(with average delay of about 1s between each),
+then initiate a lazy umount so that the mounts
+might be automatically cleaned up at some stage.
+We wait a further 10s after initiating the lazy
+umount, before raising an exception.
+
+Addresses the original issue in bug 1013689
+
+Change-Id: Ib5ede9f705c833825a19308c140f99c5bf3a776f
+---
+ nova/virt/disk/guestfs.py |   16 +++++++++++++---
+ 1 files changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/nova/virt/disk/guestfs.py b/nova/virt/disk/guestfs.py
+index f2ff3c3..c44158d 100644
+--- a/nova/virt/disk/guestfs.py
++++ b/nova/virt/disk/guestfs.py
+@@ -17,6 +17,7 @@
+ 
+ import os
+ 
++from nova import exception
+ from nova import utils
+ from nova.virt.disk import mount
+ 
+@@ -88,9 +89,18 @@ class Mount(mount.Mount):
+     def unmnt_dev(self):
+         if not self.mounted:
+             return
+-        # root users don't need a specific unmnt_dev()
+-        # but ordinary users do
+-        utils.execute('fusermount', '-u', self.mount_dir, run_as_root=True)
++        umount_cmd = ['fusermount', '-u', self.mount_dir]
++        try:
++            # We make a few attempts to work around other
++            # processes temporarily scanning the mount_dir etc.
++            utils.execute(*umount_cmd, attempts=5, run_as_root=True)
++        except exception.ProcessExecutionError:
++            # If we still can't umount, then do a lazy umount
++            # (in the background), so that mounts might eventually
++            # be cleaned up. Note we'll wait 10s below for the umount to
++            # complete, after which we'll raise an exception.
++            umount_cmd.insert(1, '-z')
++            utils.execute(*umount_cmd, run_as_root=True)
+ 
+         # Unfortunately FUSE has an issue where it doesn't wait
+         # for processes associated with the mount to terminate.
diff --git a/openstack-nova.spec b/openstack-nova.spec
index 0e04c85..189d57a 100644
--- a/openstack-nova.spec
+++ b/openstack-nova.spec
@@ -32,17 +32,26 @@ Source24:         nova-sudoers
 #
 # patches_base=2012.1.1
 #
-Patch0002: 0002-Call-libvirt_volume_driver-with-right-mountpoint.patch
-Patch0003: 0003-Prevent-file-injection-writing-to-host-filesystem.patch
-Patch0004: 0004-Stop-nova_ipam_lib-from-changing-the-timeout-setting.patch
-Patch0005: 0005-ensure-atomic-manipulation-of-libvirt-disk-images.patch
-Patch0006: 0006-Ensure-we-don-t-access-the-net-when-building-docs.patch
-Patch0007: 0007-fix-useexisting-deprecation-warnings.patch
-Patch0008: 0008-support-a-configurable-libvirt-injection-partition.patch
-Patch0009: 0009-repeat-fusermount-to-avoid-business.patch
-Patch0010: 0010-only-mount-guest-image-once-when-injecting-files.patch
-Patch0011: 0011-set-correct-SELinux-context-for-injected-ssh-keys.patch
-Patch0012: 0012-Distinguish-over-quota-for-volume-size-and-number.patch
+Patch0003: 0003-Call-libvirt_volume_driver-with-right-mountpoint.patch
+Patch0004: 0004-Use-fake_libvirt_utils-for-libvirt-console-tests.patch
+Patch0005: 0005-Fixes-ram_allocation_ratio-based-over-subscription.patch
+Patch0006: 0006-Stop-nova_ipam_lib-from-changing-the-timeout-setting.patch
+Patch0007: 0007-Prevent-file-injection-writing-to-host-filesystem.patch
+Patch0008: 0008-Distinguish-over-quota-for-volume-size-and-number.patch
+Patch0009: 0009-Expose-over-quota-exceptions-via-native-API.patch
+Patch0010: 0010-Fix-call-to-network_get_all_by_uuids.patch
+Patch0011: 0011-fix-libvirt-get_memory_mb_total-with-xen.patch
+Patch0012: 0012-Use-compute_api.get_all-in-affinity-filters.patch
+Patch0013: 0013-Use-default-qemu-img-cluster-size-in-libvirt-connect.patch
+Patch0014: 0014-Return-413-status-on-over-quota-in-the-native-API.patch
+Patch0015: 0015-ensure-atomic-manipulation-of-libvirt-disk-images.patch
+Patch0016: 0016-Ensure-we-don-t-access-the-net-when-building-docs.patch
+Patch0017: 0017-fix-useexisting-deprecation-warnings.patch
+Patch0018: 0018-support-a-configurable-libvirt-injection-partition.patch
+Patch0019: 0019-only-mount-guest-image-once-when-injecting-files.patch
+Patch0020: 0020-set-correct-SELinux-context-for-injected-ssh-keys.patch
+Patch0021: 0021-ensure-libguestfs-has-completed-before-proceeding.patch
+Patch0022: 0022-ensure-libguestfs-mounts-are-cleaned-up.patch
 
 BuildArch:        noarch
 BuildRequires:    intltool
@@ -160,7 +169,6 @@ This package contains documentation files for nova.
 %prep
 %setup -q -n nova-%{version}
 
-%patch0002 -p1
 %patch0003 -p1
 %patch0004 -p1
 %patch0005 -p1
@@ -171,6 +179,16 @@ This package contains documentation files for nova.
 %patch0010 -p1
 %patch0011 -p1
 %patch0012 -p1
+%patch0013 -p1
+%patch0014 -p1
+%patch0015 -p1
+%patch0016 -p1
+%patch0017 -p1
+%patch0018 -p1
+%patch0019 -p1
+%patch0020 -p1
+%patch0021 -p1
+%patch0022 -p1
 
 find . \( -name .gitignore -o -name .placeholder \) -delete
 
@@ -368,8 +386,16 @@ fi
 %endif
 
 %changelog
-* Wed Jul 18 2012 Pádraig Brady <P at draigBrady.com> - 2012.1.1-4
+* Fri Jul 20 2012 Pádraig Brady <P at draigBrady.com> - 2012.1.1-4
 - Enable auto cleanup of old cached instance images
+- Fix ram_allocation_ratio based over subscription
+- Expose over quota exceptions via native API
+- Return 413 status on over quota in the native API
+- Fix call to network_get_all_by_uuids
+- Fix libvirt get_memory_mb_total with xen
+- Use compute_api.get_all in affinity filters (CVE-2012-3371)
+- Use default qemu img cluster size in libvirt connect
+- Ensure libguestfs has completed before proceeding
 
 * Thu Jul  5 2012 Pádraig Brady <P at draigBrady.com> - 2012.1.1-3
 - Distinguish volume overlimit exceptions


More information about the scm-commits mailing list