[openstack-glance] Rebase to latest upstream stable/diablo branch adding ~20 patches

Mark McLoughlin markmc at fedoraproject.org
Fri Jan 6 17:17:15 UTC 2012


commit 62243f94003aaad6d9a02ed13be542e803096f74
Author: Mark McLoughlin <markmc at redhat.com>
Date:   Fri Jan 6 17:17:05 2012 +0000

    Rebase to latest upstream stable/diablo branch adding ~20 patches

 ...-Point-tools-rfc.sh-at-the-correct-branch.patch |   26 ++
 0002-Fixes-LP-Bug-845788.patch                     |   96 ++++++++
 0003-Fixes-LP-Bug-850685.patch                     |  158 ++++++++++++
 ...e-remote-swift-image-streaming-functional.patch |  145 +++++++++++
 ...unctionality-of-s3-backend-to-stream-remo.patch |  253 ++++++++++++++++++++
 ...-LP-Bug-860862-Security-creds-still-shown.patch |  202 ++++++++++++++++
 ...LP-Bug-872276-small-typo-in-error-message.patch |   34 +++
 ...etter-document-using-Glance-with-Keystone.patch |  190 +++++++++++++++
 ...P-Bug-844618-SQLAlchemy-errors-not-logged.patch |  137 +++++++++++
 0010-Add-.gitreview-config-file-for-gerrit.patch   |   26 ++
 ...-0.5.0-and-replaced-with-just-mox-in-tool.patch |   35 +++
 ...ve-location-from-POST-PUT-image-responses.patch |  136 +++++++++++
 ...eystone-API-skew-issue-with-Glance-client.patch |   72 ++++++
 ...ttext-in-__init__-to-fix-_-is-not-defined.patch |   34 +++
 ...ce-show-to-print-a-valid-URI.-Fixes-bug-8.patch |   32 +++
 0016-Using-Keystone-s-new-port-number-35357.patch  |   58 +++++
 0017-Making-prefetcher-call-create_stores.patch    |   42 ++++
 0018-Add-a-LICENSE-file.patch                      |  204 ++++++++++++++++
 0019-Rename-.glance-venv-to-.venv.patch            |   79 ++++++
 ...rence-the-glance-module-from-the-package-.patch |   35 +++
 ...-Don-t-access-the-net-while-building-docs.patch |   27 ++
 openstack-glance.spec                              |   63 +++++-
 22 files changed, 2079 insertions(+), 5 deletions(-)
---
diff --git a/0001-Point-tools-rfc.sh-at-the-correct-branch.patch b/0001-Point-tools-rfc.sh-at-the-correct-branch.patch
new file mode 100644
index 0000000..9f7b5ae
--- /dev/null
+++ b/0001-Point-tools-rfc.sh-at-the-correct-branch.patch
@@ -0,0 +1,26 @@
+From 9ec0318e72ab2caaff1b64b8ea38a9b69480d27e Mon Sep 17 00:00:00 2001
+From: Mark McLoughlin <markmc at redhat.com>
+Date: Fri, 18 Nov 2011 21:32:24 +0000
+Subject: [PATCH] Point tools/rfc.sh at the correct branch
+
+Change-Id: I204dba3060ed46dce55c5c2e8e1233daa40c195c
+---
+ tools/rfc.sh |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/tools/rfc.sh b/tools/rfc.sh
+index ed287e8..454eac9 100755
+--- a/tools/rfc.sh
++++ b/tools/rfc.sh
+@@ -20,7 +20,7 @@
+ # <http://www.gnu.org/licenses/>.
+ 
+ 
+-branch="master";
++branch="stable/diablo";
+ 
+ set_hooks_commit_msg()
+ {
+-- 
+1.7.6.5
+
diff --git a/0002-Fixes-LP-Bug-845788.patch b/0002-Fixes-LP-Bug-845788.patch
new file mode 100644
index 0000000..58b7e88
--- /dev/null
+++ b/0002-Fixes-LP-Bug-845788.patch
@@ -0,0 +1,96 @@
+From 6dff3e2b073b0e752942aa9cc6004c1ef3184614 Mon Sep 17 00:00:00 2001
+From: Jay Pipes <jaypipes at gmail.com>
+Date: Fri, 9 Sep 2011 13:03:19 -0400
+Subject: [PATCH] Fixes LP Bug#845788
+
+glance.client.image_update needed to calculate size so that Glance's Swift
+driver can do chunking properly for large objects.
+
+(cherry picked from commit 6cfff16f2dc22a870bfe3808a7895dfbbaa11369)
+
+Change-Id: Iafe8034a710cff53a0caa3ae5e9ee3a3adda19f8
+---
+ glance/client.py |   53 +++++++++++++++++++++++++++++++++++------------------
+ 1 files changed, 35 insertions(+), 18 deletions(-)
+
+diff --git a/glance/client.py b/glance/client.py
+index 74ef5f4..ac89ba2 100644
+--- a/glance/client.py
++++ b/glance/client.py
+@@ -96,6 +96,33 @@ class V1Client(base_client.BaseClient):
+         image = utils.get_image_meta_from_headers(res)
+         return image
+ 
++    def _get_image_size(self, image_data):
++        """
++        Analyzes the incoming image file and attempts to determine
++        its size.
++
++        :param image_data: The input to the client, typically a file
++                           redirected from stdin.
++        :retval The image file's size or None if it cannot be determined.
++        """
++        # For large images, we need to supply the size of the
++        # image file. See LP Bugs #827660 and #845788.
++        if hasattr(image_data, 'seek') and hasattr(image_data, 'tell'):
++            try:
++                image_data.seek(0, os.SEEK_END)
++                image_size = image_data.tell()
++                image_data.seek(0)
++                return image_size
++            except IOError, e:
++                if e.errno == errno.ESPIPE:
++                    # Illegal seek. This means the user is trying
++                    # to pipe image data to the client, e.g.
++                    # echo testdata | bin/glance add blah..., or
++                    # that stdin is empty
++                    return None
++                else:
++                    raise
++
+     def add_image(self, image_meta=None, image_data=None):
+         """
+         Tells Glance about an image's metadata as well
+@@ -114,24 +141,10 @@ class V1Client(base_client.BaseClient):
+         if image_data:
+             body = image_data
+             headers['content-type'] = 'application/octet-stream'
+-            # For large images, we need to supply the size of the
+-            # image file. See LP Bug #827660.
+-            if hasattr(image_data, 'seek') and hasattr(image_data, 'tell'):
+-                try:
+-                    image_data.seek(0, os.SEEK_END)
+-                    image_size = image_data.tell()
+-                    image_data.seek(0)
+-                    headers['x-image-meta-size'] = image_size
+-                    headers['content-length'] = image_size
+-                except IOError, e:
+-                    if e.errno == errno.ESPIPE:
+-                        # Illegal seek. This means the user is trying
+-                        # to pipe image data to the client, e.g.
+-                        # echo testdata | bin/glance add blah..., or
+-                        # that stdin is empty
+-                        pass
+-                    else:
+-                        raise
++            image_size = self._get_image_size(image_data)
++            if image_size:
++                headers['x-image-meta-size'] = image_size
++                headers['content-length'] = image_size
+         else:
+             body = None
+ 
+@@ -151,6 +164,10 @@ class V1Client(base_client.BaseClient):
+         if image_data:
+             body = image_data
+             headers['content-type'] = 'application/octet-stream'
++            image_size = self._get_image_size(image_data)
++            if image_size:
++                headers['x-image-meta-size'] = image_size
++                headers['content-length'] = image_size
+         else:
+             body = None
+ 
+-- 
+1.7.6.5
+
diff --git a/0003-Fixes-LP-Bug-850685.patch b/0003-Fixes-LP-Bug-850685.patch
new file mode 100644
index 0000000..512d499
--- /dev/null
+++ b/0003-Fixes-LP-Bug-850685.patch
@@ -0,0 +1,158 @@
+From e6aa08ceb5589448511315e4b9cacfd78d40ecf8 Mon Sep 17 00:00:00 2001
+From: Jay Pipes <jaypipes at gmail.com>
+Date: Fri, 23 Sep 2011 17:28:50 -0400
+Subject: [PATCH] Fixes LP Bug #850685
+
+Handle 300 Multiple Choices gracefully in client
+
+This patch adds a new exception MultipleChoices that
+is now raised when the client encounters a 300 from the
+server, with a helpful error message indicating the likely
+cause is that the caller has forgotten to include a version
+string in the request URI.
+
+(cherry picked from commit 1bb0600efb444fa4d8a27e876a8c002324746c1e)
+
+Change-Id: I3ccc2686bea30a770751fde605c78a3b7c5930b6
+---
+ glance/common/client.py            |    2 ++
+ glance/common/exception.py         |    6 ++++++
+ glance/tests/stubs.py              |    7 ++++++-
+ glance/tests/unit/test_clients.py  |    4 ++--
+ glance/tests/unit/test_versions.py |   23 +++++++++++++++++++++--
+ 5 files changed, 37 insertions(+), 5 deletions(-)
+
+diff --git a/glance/common/client.py b/glance/common/client.py
+index ddf7453..be3b15a 100644
+--- a/glance/common/client.py
++++ b/glance/common/client.py
+@@ -228,6 +228,8 @@ class BaseClient(object):
+                 raise exception.Duplicate(res.read())
+             elif status_code == httplib.BAD_REQUEST:
+                 raise exception.Invalid(res.read())
++            elif status_code == httplib.MULTIPLE_CHOICES:
++                raise exception.MultipleChoices(body=res.read())
+             elif status_code == httplib.INTERNAL_SERVER_ERROR:
+                 raise Exception("Internal Server error: %s" % res.read())
+             else:
+diff --git a/glance/common/exception.py b/glance/common/exception.py
+index be3523f..5d9bf19 100644
+--- a/glance/common/exception.py
++++ b/glance/common/exception.py
+@@ -152,6 +152,12 @@ class GlanceException(Exception):
+         return self._error_string
+ 
+ 
++class MultipleChoices(GlanceException):
++    message = _("The request returned a 302 Multiple Choices. This generally "
++                "means that you have not included a version indicator in a "
++                "request URI.\n\nThe body of response returned:\n%(body)s")
++
++
+ class InvalidContentType(GlanceException):
+     message = _("Invalid content type %(content_type)s")
+ 
+diff --git a/glance/tests/stubs.py b/glance/tests/stubs.py
+index e90cc48..8fa0ec7 100644
+--- a/glance/tests/stubs.py
++++ b/glance/tests/stubs.py
+@@ -33,6 +33,7 @@ from glance.common import context
+ from glance.common import exception
+ from glance.registry import server as rserver
+ from glance.api import v1 as server
++from glance.api.middleware import version_negotiation
+ import glance.store
+ import glance.store.filesystem
+ import glance.store.http
+@@ -156,11 +157,15 @@ def stub_out_registry_and_store_server(stubs):
+         def getresponse(self):
+             options = {'verbose': VERBOSE,
+                        'debug': DEBUG,
++                       'bind_host': '0.0.0.0',
++                       'bind_port': '9999999',
+                        'registry_host': '0.0.0.0',
+                        'registry_port': '9191',
+                        'default_store': 'file',
+                        'filesystem_store_datadir': FAKE_FILESYSTEM_ROOTDIR}
+-            api = context.ContextMiddleware(server.API(options), options)
++            api = version_negotiation.VersionNegotiationFilter(
++                context.ContextMiddleware(server.API(options), options),
++                options)
+             res = self.req.get_response(api)
+ 
+             # httplib.Response has a read() method...fake it out
+diff --git a/glance/tests/unit/test_clients.py b/glance/tests/unit/test_clients.py
+index 5e30358..57ee6a5 100644
+--- a/glance/tests/unit/test_clients.py
++++ b/glance/tests/unit/test_clients.py
+@@ -18,10 +18,10 @@
+ import datetime
+ import json
+ import os
+-import stubout
+ import StringIO
+ import unittest
+ 
++import stubout
+ import webob
+ 
+ from glance import client
+@@ -977,7 +977,7 @@ class TestClient(unittest.TestCase):
+         stubs.stub_out_registry_and_store_server(self.stubs)
+         stubs.stub_out_filesystem_backend()
+         db_api.configure_db(OPTIONS)
+-        self.client = client.Client("0.0.0.0", doc_root="")
++        self.client = client.Client("0.0.0.0")
+         self.FIXTURES = [
+             {'id': 1,
+              'name': 'fake image #1',
+diff --git a/glance/tests/unit/test_versions.py b/glance/tests/unit/test_versions.py
+index ce56131..cdf2591 100644
+--- a/glance/tests/unit/test_versions.py
++++ b/glance/tests/unit/test_versions.py
+@@ -18,17 +18,30 @@
+ import json
+ import unittest
+ 
++import stubout
+ import webob
+ 
++from glance import client
++from glance.common import exception
+ from glance.api import versions
++from glance.tests import stubs
+ 
+ 
+ class VersionsTest(unittest.TestCase):
++
++    """
++    Test the version information returned from
++    the API service
++    """
++
+     def setUp(self):
+-        super(VersionsTest, self).setUp()
++        """Establish a clean test environment"""
++        self.stubs = stubout.StubOutForTesting()
++        stubs.stub_out_registry_and_store_server(self.stubs)
+ 
+     def tearDown(self):
+-        super(VersionsTest, self).tearDown()
++        """Clear the test environment"""
++        self.stubs.UnsetAll()
+ 
+     def test_get_version_list(self):
+         req = webob.Request.blank('/')
+@@ -55,3 +68,9 @@ class VersionsTest(unittest.TestCase):
+                         "rel": "self",
+                         "href": "http://0.0.0.0:9292/v1/"}]}]
+         self.assertEqual(results, expected)
++
++    def test_client_handles_versions(self):
++        api_client = client.Client("0.0.0.0", doc_root="")
++
++        self.assertRaises(exception.MultipleChoices,
++                          api_client.get_images)
+-- 
+1.7.6.5
+
diff --git a/0004-Make-remote-swift-image-streaming-functional.patch b/0004-Make-remote-swift-image-streaming-functional.patch
new file mode 100644
index 0000000..eb7bccc
--- /dev/null
+++ b/0004-Make-remote-swift-image-streaming-functional.patch
@@ -0,0 +1,145 @@
+From 5a820c7b2ba8576512a69e1f6537ad7de9b1a9fb Mon Sep 17 00:00:00 2001
+From: Brian Waldon <brian.waldon at rackspace.com>
+Date: Mon, 26 Sep 2011 17:37:45 -0400
+Subject: [PATCH] Make remote swift image streaming functional
+
+Fixes lp 850425
+
+(cherry picked from commit 4847ceb59fe35481fd42ddc9369b7d3814eca721)
+
+Change-Id: I117d45f7d5b1991296736b7915857e8764aad30d
+---
+ glance/store/swift.py                 |    2 +-
+ glance/tests/functional/test_swift.py |   83 +++++++++++++++++++++++++++++++++
+ glance/tests/unit/test_swift_store.py |    4 +-
+ 3 files changed, 86 insertions(+), 3 deletions(-)
+
+diff --git a/glance/store/swift.py b/glance/store/swift.py
+index 9c93ced..e99d7be 100644
+--- a/glance/store/swift.py
++++ b/glance/store/swift.py
+@@ -260,7 +260,7 @@ class Store(glance.store.base.Store):
+         #            "Expected %s byte file, Swift has %s bytes" %
+         #            (expected_size, obj_size))
+ 
+-        return (resp_body, None)
++        return (resp_body, resp_headers.get('content-length'))
+ 
+     def _make_swift_connection(self, auth_url, user, key):
+         """
+diff --git a/glance/tests/functional/test_swift.py b/glance/tests/functional/test_swift.py
+index fc0f9aa..dbbc6f7 100644
+--- a/glance/tests/functional/test_swift.py
++++ b/glance/tests/functional/test_swift.py
+@@ -385,3 +385,86 @@ class TestSwift(test_api.TestApi):
+                          hashlib.md5("*" * FIVE_MB).hexdigest())
+ 
+         self.stop_servers()
++
++    @skip_if_disabled
++    def test_remote_image(self):
++        """
++        Ensure we can retrieve an image that was not stored by glance itself
++        """
++        self.cleanup()
++
++        self.start_servers(**self.__dict__.copy())
++
++        api_port = self.api_port
++        registry_port = self.registry_port
++
++        # POST /images with public image named Image1
++        image_data = "*" * FIVE_MB
++        headers = {'Content-Type': 'application/octet-stream',
++                   'X-Image-Meta-Name': 'Image1',
++                   'X-Image-Meta-Is-Public': 'True'}
++        path = "http://%s:%d/v1/images" % ("0.0.0.0", self.api_port)
++        http = httplib2.Http()
++        response, content = http.request(path, 'POST', headers=headers,
++                                         body=image_data)
++        self.assertEqual(response.status, 201, content)
++        data = json.loads(content)
++        self.assertEqual(data['image']['checksum'],
++                         hashlib.md5(image_data).hexdigest())
++        self.assertEqual(data['image']['size'], FIVE_MB)
++        self.assertEqual(data['image']['name'], "Image1")
++        self.assertEqual(data['image']['is_public'], True)
++
++        # GET /images/1 and make sure data was uploaded
++        path = "http://%s:%d/v1/images/1" % ("0.0.0.0", self.api_port)
++        http = httplib2.Http()
++        response, content = http.request(path, 'GET')
++        self.assertEqual(response.status, 200)
++        self.assertEqual(response['content-length'], str(FIVE_MB))
++
++        self.assertEqual(content, "*" * FIVE_MB)
++        self.assertEqual(hashlib.md5(content).hexdigest(),
++                         hashlib.md5("*" * FIVE_MB).hexdigest())
++
++        # use this header as the location for the next image
++        swift_location = response['x-image-meta-location']
++
++        # POST /images with public image named Image1 without uploading data
++        image_data = "*" * FIVE_MB
++        headers = {'Content-Type': 'application/octet-stream',
++                   'X-Image-Meta-Name': 'Image1',
++                   'X-Image-Meta-Is-Public': 'True',
++                   'X-Image-Meta-Location': swift_location}
++        path = "http://%s:%d/v1/images" % ("0.0.0.0", self.api_port)
++        http = httplib2.Http()
++        response, content = http.request(path, 'POST', headers=headers)
++        self.assertEqual(response.status, 201, content)
++        data = json.loads(content)
++        self.assertEqual(data['image']['checksum'], None)
++        self.assertEqual(data['image']['size'], 0)
++        self.assertEqual(data['image']['name'], "Image1")
++        self.assertEqual(data['image']['is_public'], True)
++
++        # GET /images/2 ensuring the data already in swift is accessible
++        path = "http://%s:%d/v1/images/2" % ("0.0.0.0", self.api_port)
++        http = httplib2.Http()
++        response, content = http.request(path, 'GET')
++        self.assertEqual(response.status, 200)
++        self.assertEqual(response['content-length'], str(FIVE_MB))
++
++        self.assertEqual(content, "*" * FIVE_MB)
++        self.assertEqual(hashlib.md5(content).hexdigest(),
++                         hashlib.md5("*" * FIVE_MB).hexdigest())
++
++        # DELETE /images/1 and /image/2
++        # Verify image and all chunks are gone...
++        path = "http://%s:%d/v1/images/1" % ("0.0.0.0", self.api_port)
++        http = httplib2.Http()
++        response, content = http.request(path, 'DELETE')
++        self.assertEqual(response.status, 200)
++        path = "http://%s:%d/v1/images/2" % ("0.0.0.0", self.api_port)
++        http = httplib2.Http()
++        response, content = http.request(path, 'DELETE')
++        self.assertEqual(response.status, 200)
++
++        self.stop_servers()
+diff --git a/glance/tests/unit/test_swift_store.py b/glance/tests/unit/test_swift_store.py
+index 036d526..36a3096 100644
+--- a/glance/tests/unit/test_swift_store.py
++++ b/glance/tests/unit/test_swift_store.py
+@@ -198,7 +198,7 @@ class TestStore(unittest.TestCase):
+         """Test a "normal" retrieval of an image in chunks"""
+         loc = get_location_from_uri("swift://user:key@auth_address/glance/2")
+         (image_swift, image_size) = self.store.get(loc)
+-        self.assertEqual(image_size, None)
++        self.assertEqual(image_size, 5120)
+ 
+         expected_data = "*" * FIVE_KB
+         data = ""
+@@ -216,7 +216,7 @@ class TestStore(unittest.TestCase):
+         loc = get_location_from_uri("swift+http://user:key@auth_address/"
+                                     "glance/2")
+         (image_swift, image_size) = self.store.get(loc)
+-        self.assertEqual(image_size, None)
++        self.assertEqual(image_size, 5120)
+ 
+         expected_data = "*" * FIVE_KB
+         data = ""
+-- 
+1.7.6.5
+
diff --git a/0005-Returning-functionality-of-s3-backend-to-stream-remo.patch b/0005-Returning-functionality-of-s3-backend-to-stream-remo.patch
new file mode 100644
index 0000000..e355e9d
--- /dev/null
+++ b/0005-Returning-functionality-of-s3-backend-to-stream-remo.patch
@@ -0,0 +1,253 @@
+From f90853082909c359459befb927767250f42be9c4 Mon Sep 17 00:00:00 2001
+From: Brian Waldon <brian.waldon at rackspace.com>
+Date: Tue, 27 Sep 2011 15:43:33 -0400
+Subject: [PATCH] Returning functionality of s3 backend to stream remote
+ images
+
+Fixes bug 860872. Also refactoring swift remote image tests to pull location data from registry now that it is unavailable from the main
+api.
+
+(Update) Fixed minor feedback for Waldon from Vek.
+
+(cherry picked from commit 47c03a348031d25fafd56ed3c74c5376f21b1cf0)
+
+Change-Id: I159958da8ed4187da2e22392fe341042eedfd056
+---
+ glance/store/s3.py                    |    2 +-
+ glance/tests/functional/test_api.py   |   18 ++++----
+ glance/tests/functional/test_s3.py    |   75 +++++++++++++++++++++++++++++++++
+ glance/tests/functional/test_swift.py |    7 ++-
+ glance/tests/unit/test_s3_store.py    |    2 +-
+ 5 files changed, 91 insertions(+), 13 deletions(-)
+
+diff --git a/glance/store/s3.py b/glance/store/s3.py
+index 8bbc72c..4603205 100644
+--- a/glance/store/s3.py
++++ b/glance/store/s3.py
+@@ -253,7 +253,7 @@ class Store(glance.store.base.Store):
+         #   raise glance.store.BackendException(msg)
+ 
+         key.BufferSize = self.CHUNKSIZE
+-        return (ChunkedFile(key), None)
++        return (ChunkedFile(key), key.size)
+ 
+     def add(self, image_id, image_file, image_size):
+         """
+diff --git a/glance/tests/functional/test_api.py b/glance/tests/functional/test_api.py
+index 1f0d76e..535266e 100644
+--- a/glance/tests/functional/test_api.py
++++ b/glance/tests/functional/test_api.py
+@@ -66,7 +66,7 @@ class TestApi(functional.FunctionalTest):
+         - Add a previously deleted property.
+         """
+         self.cleanup()
+-        self.start_servers()
++        self.start_servers(**self.__dict__.copy())
+ 
+         # 0. GET /images
+         # Verify no public images
+@@ -297,7 +297,7 @@ class TestApi(functional.FunctionalTest):
+         """
+ 
+         self.cleanup()
+-        self.start_servers()
++        self.start_servers(**self.__dict__.copy())
+ 
+         # 0. GET /images
+         # Verify no public images
+@@ -399,7 +399,7 @@ class TestApi(functional.FunctionalTest):
+         """
+ 
+         self.cleanup()
+-        self.start_servers()
++        self.start_servers(**self.__dict__.copy())
+ 
+         versions = {'versions': [{
+             "id": "v1.1",
+@@ -564,7 +564,7 @@ class TestApi(functional.FunctionalTest):
+         """
+ 
+         self.cleanup()
+-        self.start_servers()
++        self.start_servers(**self.__dict__.copy())
+ 
+         # 1. POST /images with public image named Image1
+         # attribute and a size of 5G. Use the HTTP engine with an
+@@ -603,7 +603,7 @@ class TestApi(functional.FunctionalTest):
+         :see https://bugs.launchpad.net/glance/+bug/755912
+         """
+         self.cleanup()
+-        self.start_servers()
++        self.start_servers(**self.__dict__.copy())
+ 
+         # POST /images with binary data, but not setting
+         # Content-Type to application/octet-stream, verify a
+@@ -628,7 +628,7 @@ class TestApi(functional.FunctionalTest):
+         Set up four test images and ensure each query param filter works
+         """
+         self.cleanup()
+-        self.start_servers()
++        self.start_servers(**self.__dict__.copy())
+ 
+         # 0. GET /images
+         # Verify no public images
+@@ -861,7 +861,7 @@ class TestApi(functional.FunctionalTest):
+         Ensure marker and limit query params work
+         """
+         self.cleanup()
+-        self.start_servers()
++        self.start_servers(**self.__dict__.copy())
+ 
+         # 0. GET /images
+         # Verify no public images
+@@ -950,7 +950,7 @@ class TestApi(functional.FunctionalTest):
+         Set up three test images and ensure each query param filter works
+         """
+         self.cleanup()
+-        self.start_servers()
++        self.start_servers(**self.__dict__.copy())
+ 
+         # 0. GET /images
+         # Verify no public images
+@@ -1061,7 +1061,7 @@ class TestApi(functional.FunctionalTest):
+         Upload initial image, then attempt to upload duplicate image
+         """
+         self.cleanup()
+-        self.start_servers()
++        self.start_servers(**self.__dict__.copy())
+ 
+         # 0. GET /images
+         # Verify no public images
+diff --git a/glance/tests/functional/test_s3.py b/glance/tests/functional/test_s3.py
+index 92fd469..7b192d3 100644
+--- a/glance/tests/functional/test_s3.py
++++ b/glance/tests/functional/test_s3.py
+@@ -31,15 +31,21 @@ skipped.
+ """
+ 
+ import ConfigParser
++import hashlib
+ import json
+ import os
+ import tempfile
+ import unittest
+ 
++import httplib2
++
+ from glance.tests.functional import test_api
+ from glance.tests.utils import execute, skip_if_disabled
+ 
+ 
++FIVE_KB = 5 * 1024
++
++
+ class TestS3(test_api.TestApi):
+ 
+     """Functional tests for the S3 backend"""
+@@ -145,3 +151,72 @@ class TestS3(test_api.TestApi):
+         keys = self.bucket.list()
+         for key in keys:
+             key.delete()
++
++    @skip_if_disabled
++    def test_remote_image(self):
++        """
++        """
++        self.cleanup()
++        self.start_servers(**self.__dict__.copy())
++
++        # 1. POST /images with public image named Image1
++        image_data = "*" * FIVE_KB
++        headers = {'Content-Type': 'application/octet-stream',
++                   'X-Image-Meta-Name': 'Image1',
++                   'X-Image-Meta-Is-Public': 'True'}
++        path = "http://%s:%d/v1/images" % ("0.0.0.0", self.api_port)
++        http = httplib2.Http()
++        response, content = http.request(path, 'POST', headers=headers,
++                                         body=image_data)
++        self.assertEqual(response.status, 201)
++        data = json.loads(content)
++        self.assertEqual(data['image']['checksum'],
++                         hashlib.md5(image_data).hexdigest())
++        self.assertEqual(data['image']['size'], FIVE_KB)
++
++        # 2. GET /images/1
++        # Verify all information on image we just added is correct
++        path = "http://%s:%d/v1/images/1" % ("0.0.0.0", self.api_port)
++        http = httplib2.Http()
++        response, content = http.request(path, 'GET')
++        self.assertEqual(response.status, 200)
++        self.assertEqual(response['content-length'], str(FIVE_KB))
++        self.assertEqual(content, "*" * FIVE_KB)
++
++        # 3. GET /images/1 from registry in order to find S3 location
++        path = "http://%s:%d/images/1" % ("0.0.0.0", self.registry_port)
++        http = httplib2.Http()
++        response, content = http.request(path, 'GET')
++        s3_store_location = json.loads(content)['image']['location']
++
++        # 4. POST /images using location generated by Image1
++        image_data = "*" * FIVE_KB
++        headers = {'Content-Type': 'application/octet-stream',
++                   'X-Image-Meta-Name': 'Image2',
++                   'X-Image-Meta-Is-Public': 'True',
++                   'X-Image-Meta-Location': s3_store_location}
++        path = "http://%s:%d/v1/images" % ("0.0.0.0", self.api_port)
++        http = httplib2.Http()
++        response, content = http.request(path, 'POST', headers=headers)
++        self.assertEqual(response.status, 201)
++        self.assertEqual(data['image']['size'], FIVE_KB)
++        self.assertEqual(data['image']['checksum'],
++                         hashlib.md5(image_data).hexdigest())
++
++        # 5. GET /images/2 and make sure it can stream the image
++        path = "http://%s:%d/v1/images/2" % ("0.0.0.0", self.api_port)
++        http = httplib2.Http()
++        response, content = http.request(path, 'GET')
++        self.assertEqual(response.status, 200)
++        self.assertEqual(response['content-length'], str(FIVE_KB))
++        self.assertEqual(content, "*" * FIVE_KB)
++
++        # 6. DELETE /images/1 and /images/2
++        path = "http://%s:%d/v1/images/1" % ("0.0.0.0", self.api_port)
++        http = httplib2.Http()
++        http.request(path, 'DELETE')
++        path = "http://%s:%d/v1/images/2" % ("0.0.0.0", self.api_port)
++        http = httplib2.Http()
++        http.request(path, 'DELETE')
++
++        self.stop_servers()
+diff --git a/glance/tests/functional/test_swift.py b/glance/tests/functional/test_swift.py
+index dbbc6f7..c5571f6 100644
+--- a/glance/tests/functional/test_swift.py
++++ b/glance/tests/functional/test_swift.py
+@@ -426,8 +426,11 @@ class TestSwift(test_api.TestApi):
+         self.assertEqual(hashlib.md5(content).hexdigest(),
+                          hashlib.md5("*" * FIVE_MB).hexdigest())
+ 
+-        # use this header as the location for the next image
+-        swift_location = response['x-image-meta-location']
++        # GET /images/1 from registry in order to find Swift location
++        path = "http://%s:%d/images/1" % ("0.0.0.0", self.registry_port)
++        http = httplib2.Http()
++        response, content = http.request(path, 'GET')
++        swift_location = json.loads(content)['image']['location']
+ 
+         # POST /images with public image named Image1 without uploading data
+         image_data = "*" * FIVE_MB
+diff --git a/glance/tests/unit/test_s3_store.py b/glance/tests/unit/test_s3_store.py
+index 73531aa..ce7bbfe 100644
+--- a/glance/tests/unit/test_s3_store.py
++++ b/glance/tests/unit/test_s3_store.py
+@@ -171,7 +171,7 @@ class TestStore(unittest.TestCase):
+             "s3://user:key at auth_address/glance/2")
+         (image_s3, image_size) = self.store.get(loc)
+ 
+-        self.assertEqual(image_size, None)
++        self.assertEqual(image_size, FIVE_KB)
+ 
+         expected_data = "*" * FIVE_KB
+         data = ""
+-- 
+1.7.6.5
+
diff --git a/0006-Fixes-LP-Bug-860862-Security-creds-still-shown.patch b/0006-Fixes-LP-Bug-860862-Security-creds-still-shown.patch
new file mode 100644
index 0000000..f1e8c67
--- /dev/null
+++ b/0006-Fixes-LP-Bug-860862-Security-creds-still-shown.patch
@@ -0,0 +1,202 @@
+From c308c9abe79037fee7ee42638369b553655e7c34 Mon Sep 17 00:00:00 2001
+From: Jay Pipes <jaypipes at gmail.com>
+Date: Thu, 29 Sep 2011 16:00:44 -0400
+Subject: [PATCH] Fixes LP Bug#860862 - Security creds still shown
+
+This removes the X-Image-Meta-Location entirely from
+GET /images/<ID> and HEAD /images/<ID>
+
+Previous fix only removed from GET /images and GET /images/detail.
+
+Doh.
+
+(cherry picked from commit 25e2ba4e6a60956cfd7f8ca9457698fd0f4d3747)
+
+Change-Id: Ib6c124e196688a77a3a0090bf9174a1daffb78bb
+---
+ glance/api/v1/images.py               |    5 ++++-
+ glance/tests/functional/test_swift.py |   27 ++++++++++++++++-----------
+ glance/tests/unit/test_api.py         |   30 ++++++++++++++++++++++++++++++
+ glance/tests/unit/test_clients.py     |    4 ++++
+ 4 files changed, 54 insertions(+), 12 deletions(-)
+
+diff --git a/glance/api/v1/images.py b/glance/api/v1/images.py
+index b80a164..5d177e1 100644
+--- a/glance/api/v1/images.py
++++ b/glance/api/v1/images.py
+@@ -194,8 +194,10 @@ class Controller(api.BaseController):
+ 
+         :raises HTTPNotFound if image metadata is not available to user
+         """
++        image_meta = self.get_image_meta_or_404(req, id)
++        del image_meta['location']
+         return {
+-            'image_meta': self.get_image_meta_or_404(req, id),
++            'image_meta': image_meta
+         }
+ 
+     def show(self, req, id):
+@@ -271,6 +273,7 @@ class Controller(api.BaseController):
+                          " from store"), id)
+             image_iterator = get_from_store(image)
+ 
++        del image['location']
+         return {
+             'image_iterator': image_iterator,
+             'image_meta': image,
+diff --git a/glance/tests/functional/test_swift.py b/glance/tests/functional/test_swift.py
+index c5571f6..69aba86 100644
+--- a/glance/tests/functional/test_swift.py
++++ b/glance/tests/functional/test_swift.py
+@@ -44,6 +44,7 @@ from glance.store.location import get_location_from_uri
+ from glance.tests.functional import test_api
+ from glance.tests.utils import execute, skip_if_disabled
+ 
++FIVE_KB = 5 * 1024
+ FIVE_MB = 5 * 1024 * 1024
+ 
+ 
+@@ -399,7 +400,7 @@ class TestSwift(test_api.TestApi):
+         registry_port = self.registry_port
+ 
+         # POST /images with public image named Image1
+-        image_data = "*" * FIVE_MB
++        image_data = "*" * FIVE_KB
+         headers = {'Content-Type': 'application/octet-stream',
+                    'X-Image-Meta-Name': 'Image1',
+                    'X-Image-Meta-Is-Public': 'True'}
+@@ -411,7 +412,7 @@ class TestSwift(test_api.TestApi):
+         data = json.loads(content)
+         self.assertEqual(data['image']['checksum'],
+                          hashlib.md5(image_data).hexdigest())
+-        self.assertEqual(data['image']['size'], FIVE_MB)
++        self.assertEqual(data['image']['size'], FIVE_KB)
+         self.assertEqual(data['image']['name'], "Image1")
+         self.assertEqual(data['image']['is_public'], True)
+ 
+@@ -420,20 +421,24 @@ class TestSwift(test_api.TestApi):
+         http = httplib2.Http()
+         response, content = http.request(path, 'GET')
+         self.assertEqual(response.status, 200)
+-        self.assertEqual(response['content-length'], str(FIVE_MB))
++        self.assertEqual(response['content-length'], str(FIVE_KB))
+ 
+-        self.assertEqual(content, "*" * FIVE_MB)
++        self.assertEqual(content, "*" * FIVE_KB)
+         self.assertEqual(hashlib.md5(content).hexdigest(),
+-                         hashlib.md5("*" * FIVE_MB).hexdigest())
++                         hashlib.md5("*" * FIVE_KB).hexdigest())
+ 
+-        # GET /images/1 from registry in order to find Swift location
++        # Find the location that was just added and use it as
++        # the remote image location for the next image
+         path = "http://%s:%d/images/1" % ("0.0.0.0", self.registry_port)
+         http = httplib2.Http()
+         response, content = http.request(path, 'GET')
+-        swift_location = json.loads(content)['image']['location']
++        self.assertEqual(response.status, 200)
++        data = json.loads(content)
++        self.assertTrue('location' in data['image'].keys())
++        swift_location = data['image']['location']
+ 
+         # POST /images with public image named Image1 without uploading data
+-        image_data = "*" * FIVE_MB
++        image_data = "*" * FIVE_KB
+         headers = {'Content-Type': 'application/octet-stream',
+                    'X-Image-Meta-Name': 'Image1',
+                    'X-Image-Meta-Is-Public': 'True',
+@@ -453,11 +458,11 @@ class TestSwift(test_api.TestApi):
+         http = httplib2.Http()
+         response, content = http.request(path, 'GET')
+         self.assertEqual(response.status, 200)
+-        self.assertEqual(response['content-length'], str(FIVE_MB))
++        self.assertEqual(response['content-length'], str(FIVE_KB))
+ 
+-        self.assertEqual(content, "*" * FIVE_MB)
++        self.assertEqual(content, "*" * FIVE_KB)
+         self.assertEqual(hashlib.md5(content).hexdigest(),
+-                         hashlib.md5("*" * FIVE_MB).hexdigest())
++                         hashlib.md5("*" * FIVE_KB).hexdigest())
+ 
+         # DELETE /images/1 and /image/2
+         # Verify image and all chunks are gone...
+diff --git a/glance/tests/unit/test_api.py b/glance/tests/unit/test_api.py
+index 756f07d..f867d10 100644
+--- a/glance/tests/unit/test_api.py
++++ b/glance/tests/unit/test_api.py
+@@ -1981,6 +1981,36 @@ class TestGlanceAPI(unittest.TestCase):
+         self.assertEquals(int(images[1]['id']), 2)
+         self.assertEquals(int(images[2]['id']), 4)
+ 
++    def test_store_location_not_revealed(self):
++        """
++        Test that the internal store location is NOT revealed
++        through the API server
++        """
++        # Check index and details...
++        for url in ('/images', '/images/detail'):
++            req = webob.Request.blank(url)
++            res = req.get_response(self.api)
++            self.assertEquals(res.status_int, 200)
++            res_dict = json.loads(res.body)
++
++            images = res_dict['images']
++            num_locations = sum([1 for record in images
++                                if 'location' in record.keys()])
++            self.assertEquals(0, num_locations, images)
++
++        # Check GET
++        req = webob.Request.blank("/images/2")
++        res = req.get_response(self.api)
++        self.assertEqual(res.status_int, 200)
++        self.assertFalse('X-Image-Meta-Location' in res.headers)
++
++        # Check HEAD
++        req = webob.Request.blank("/images/2")
++        req.method = 'HEAD'
++        res = req.get_response(self.api)
++        self.assertEqual(res.status_int, 200)
++        self.assertFalse('X-Image-Meta-Location' in res.headers)
++
+     def test_image_is_checksummed(self):
+         """Test that the image contents are checksummed properly"""
+         fixture_headers = {'x-image-meta-store': 'file',
+diff --git a/glance/tests/unit/test_clients.py b/glance/tests/unit/test_clients.py
+index 57ee6a5..dd2e871 100644
+--- a/glance/tests/unit/test_clients.py
++++ b/glance/tests/unit/test_clients.py
+@@ -1377,6 +1377,7 @@ class TestClient(unittest.TestCase):
+         # Test all other attributes set
+         data = self.client.get_image_meta(3)
+ 
++        del fixture['location']
+         for k, v in fixture.items():
+             self.assertEquals(v, data[k])
+ 
+@@ -1415,6 +1416,7 @@ class TestClient(unittest.TestCase):
+         # Test all other attributes set
+         data = self.client.get_image_meta(3)
+ 
++        del fixture['location']
+         for k, v in fixture.items():
+             self.assertEquals(v, data[k])
+ 
+@@ -1441,6 +1443,7 @@ class TestClient(unittest.TestCase):
+         # Test all other attributes set
+         data = self.client.get_image_meta(3)
+ 
++        del fixture['location']
+         for k, v in fixture.items():
+             self.assertEquals(v, data[k])
+ 
+@@ -1467,6 +1470,7 @@ class TestClient(unittest.TestCase):
+         # Test all other attributes set
+         data = self.client.get_image_meta(3)
+ 
++        del fixture['location']
+         for k, v in fixture.items():
+             self.assertEquals(v, data[k])
+ 
+-- 
+1.7.6.5
+
diff --git a/0007-Fixes-LP-Bug-872276-small-typo-in-error-message.patch b/0007-Fixes-LP-Bug-872276-small-typo-in-error-message.patch
new file mode 100644
index 0000000..f7f2a56
--- /dev/null
+++ b/0007-Fixes-LP-Bug-872276-small-typo-in-error-message.patch
@@ -0,0 +1,34 @@
+From 8cb2ed4145b6c742dafb9892c6f96c93421c9656 Mon Sep 17 00:00:00 2001
+From: Tomas Hancock <tom.hancock at hp.com>
+Date: Wed, 12 Oct 2011 16:08:10 +0100
+Subject: [PATCH] Fixes LP Bug#872276 - small typo in error message
+
+Add a missing s to a % formatted print statement
+Add my name to Authors file
+
+(cherry picked from commit 6aacf2388a03a138502d1ed05dce6c3bfb0502cc)
+
+Change-Id: Ib086fb9bee6f55a3bd89f3108269050c6eb0f8b9
+---
+ Authors    |    1 +
+ bin/glance |    2 +-
+ 2 files changed, 2 insertions(+), 1 deletions(-)
+
+diff --git a/Authors b/Authors
+index 673e8a3..3d2ec33 100644
+diff --git a/bin/glance b/bin/glance
+index 0cbe4a2..166b695 100755
+--- a/bin/glance
++++ b/bin/glance
+@@ -939,7 +939,7 @@ option is given, <MEMBER> will be able to further share the image."""
+         c.add_member(image_id, member_id, options.can_share)
+     else:
+         print "Dry run. We would have done the following:"
+-        print ('Add "%(member_id)" to membership of image %(image_id)s'
++        print ('Add "%(member_id)s" to membership of image %(image_id)s'
+                % locals())
+         if options.can_share:
+             print "New member would have been able to further share image."
+-- 
+1.7.6.5
+
diff --git a/0008-Better-document-using-Glance-with-Keystone.patch b/0008-Better-document-using-Glance-with-Keystone.patch
new file mode 100644
index 0000000..8d5124f
--- /dev/null
+++ b/0008-Better-document-using-Glance-with-Keystone.patch
@@ -0,0 +1,190 @@
+From a3e607bb4baea529802d343d1b401a87bea23292 Mon Sep 17 00:00:00 2001
+From: "Kevin L. Mitchell" <kevin.mitchell at rackspace.com>
+Date: Thu, 13 Oct 2011 12:02:59 -0500
+Subject: [PATCH] Better document using Glance with Keystone.
+
+Addresses bug 871803 by expounding on what configuration should
+look like.  Also fixes the example config files, which generally
+had the authentication setup completely wrong.
+
+(cherry picked from commit 5b27c663b932c30aa7e40a84e55b85223a1d9d2f)
+
+Change-Id: I44b2b8bd340ca95b5a2c2e9408797b0308000a65
+---
+ doc/source/authentication.rst |  111 +++++++++++++++++++++++++++++++++++++++++
+ etc/glance-api.conf           |    7 ++-
+ etc/glance-registry.conf      |    5 +-
+ 3 files changed, 119 insertions(+), 4 deletions(-)
+
+diff --git a/doc/source/authentication.rst b/doc/source/authentication.rst
+index e9ce451..8f3acf4 100644
+--- a/doc/source/authentication.rst
++++ b/doc/source/authentication.rst
+@@ -84,6 +84,117 @@ The final step is to verify that the `OS_AUTH_` crednetials are present::
+   OS_AUTH_URL=<THIS SHOULD POINT TO KEYSTONE>
+   OS_AUTH_STRATEGY=keystone
+ 
++Configuring the Glance servers to use Keystone
++----------------------------------------------
++
++Keystone is integrated with Glance through the use of middleware.  The
++default configuration files for both the Glance API and the Glance
++Registry use a single piece of middleware called ``context``, which
++generates a request context without any knowledge of Keystone.  In
++order to configure Glance to use Keystone, this ``context`` middleware
++must be replaced with two other pieces of middleware: the
++``authtoken`` middleware and the ``auth-context`` middleware, both of
++which may be found in the Keystone distribution.  The ``authtoken``
++middleware performs the Keystone token validation, which is the heart
++of Keystone authentication.  On the other hand, the ``auth-context``
++middleware performs the necessary tie-in between Keystone and Glance;
++it is the component which replaces the ``context`` middleware that
++Glance uses by default.
++
++One other important concept to keep in mind is the *request context*.
++In the default Glance configuration, the ``context`` middleware sets
++up a basic request context; configuring Glance to use
++``auth_context`` causes a more advanced context to be configured.  It
++is also important to note that the Glance API and the Glance Registry
++use two different context classes; this is because the registry needs
++advanced methods that are not available in the default context class.
++The implications of this will be obvious in the below example for
++configuring the Glance Registry.
++
++Configuring Glance API to use Keystone
++--------------------------------------
++
++Configuring Glance API to use Keystone is relatively straight
++forward.  The first step is to ensure that declarations for the two
++pieces of middleware exist.  Here is an example for ``authtoken``::
++
++  [filter:authtoken]
++  paste.filter_factory = keystone.middleware.auth_token:filter_factory
++  service_protocol = http
++  service_host = 127.0.0.1
++  service_port = 5000
++  auth_host = 127.0.0.1
++  auth_port = 5001
++  auth_protocol = http
++  auth_uri = http://127.0.0.1:5000/
++  admin_token = 999888777666
++
++The actual values for these variables will need to be set depending on
++your situation.  For more information, please refer to the Keystone
++documentation on the ``auth_token`` middleware, but in short:
++
++* Those variables beginning with ``service_`` are only needed if you
++  are using a proxy; they define the actual location of Glance.  That
++  said, they must be present.
++* Except for ``auth_uri``, those variables beginning with ``auth_``
++  point to the Keystone Admin service.  This information is used by
++  the middleware to actually query Keystone about the validity of the
++  authentication tokens.
++* The ``auth_uri`` variable must point to the Keystone Auth service,
++  which is the service users use to obtain Keystone tokens.  If the
++  user does not have a valid Keystone token, they will be redirected
++  to this URI to obtain one.
++* The ``admin_token`` variable specifies the administrative token that
++  Glance uses in its query to the Keystone Admin service.
++
++The other piece of middleware needed for Glance API is the
++``auth-context``::
++
++  [filter:auth_context]
++  paste.filter_factory = keystone.middleware.glance_auth_token:filter_factory
++
++Finally, to actually enable using Keystone authentication, the
++application pipeline must be modified.  By default, it looks like::
++
++  [pipeline:glance-api]
++  pipeline = versionnegotiation context apiv1app
++
++(Your particular pipeline may vary depending on other options, such as
++the image cache.)  This must be changed by replacing ``context`` with
++``authtoken`` and ``auth-context``::
++
++  [pipeline:glance-api]
++  pipeline = versionnegotiation authtoken auth-context apiv1app
++
++Configuring Glance Registry to use Keystone
++-------------------------------------------
++
++Configuring Glance Registry to use Keystone is also relatively
++straight forward.  The same pieces of middleware need to be added as
++are needed by Glance API; see above for an example of the
++``authtoken`` configuration.  There is a slight difference for the
++``auth-context`` middleware, which should look like this::
++
++  [filter:auth-context]
++  context_class = glance.registry.context.RequestContext
++  paste.filter_factory = keystone.middleware.glance_auth_token:filter_factory
++
++The ``context_class`` variable is needed to specify the
++Registry-specific request context, which contains the extra access
++checks used by the Registry.
++
++Again, to enable using Keystone authentication, the application
++pipeline must be modified.  By default, it looks like:
++
++  [pipeline:glance-registry]
++  pipeline = context registryapp
++
++This must be changed by replacing ``context`` with ``authtoken`` and
++``auth-context``::
++
++  [pipeline:glance-registry]
++  pipeline = authtoken auth-context registryapp
++
+ Sharing Images With Others
+ --------------------------
+ 
+diff --git a/etc/glance-api.conf b/etc/glance-api.conf
+index 87facb0..f3ca0da 100644
+--- a/etc/glance-api.conf
++++ b/etc/glance-api.conf
+@@ -134,12 +134,12 @@ delayed_delete = False
+ [pipeline:glance-api]
+ pipeline = versionnegotiation context apiv1app
+ # NOTE: use the following pipeline for keystone
+-# pipeline = versionnegotiation authtoken context apiv1app
++# pipeline = versionnegotiation authtoken auth-context apiv1app
+ 
+ # To enable Image Cache Management API replace pipeline with below:
+ # pipeline = versionnegotiation context imagecache apiv1app
+ # NOTE: use the following pipeline for keystone auth (with caching)
+-# pipeline = versionnegotiation authtoken context imagecache apiv1app
++# pipeline = versionnegotiation authtoken auth-context imagecache apiv1app
+ 
+ [pipeline:versions]
+ pipeline = versionsapp
+@@ -169,3 +169,6 @@ auth_port = 5001
+ auth_protocol = http
+ auth_uri = http://127.0.0.1:5000/
+ admin_token = 999888777666
++
++[filter:auth-context]
++paste.filter_factory = keystone.middleware.glance_auth_token:filter_factory
+diff --git a/etc/glance-registry.conf b/etc/glance-registry.conf
+index 2a648ea..c81e1a4 100644
+--- a/etc/glance-registry.conf
++++ b/etc/glance-registry.conf
+@@ -43,7 +43,7 @@ limit_param_default = 25
+ [pipeline:glance-registry]
+ pipeline = context registryapp
+ # NOTE: use the following pipeline for keystone
+-# pipeline = authtoken keystone_shim context registryapp
++# pipeline = authtoken auth-context registryapp
+ 
+ [app:registryapp]
+ paste.app_factory = glance.registry.server:app_factory
+@@ -63,5 +63,6 @@ auth_protocol = http
+ auth_uri = http://127.0.0.1:5000/
+ admin_token = 999888777666
+ 
+-[filter:keystone_shim]
++[filter:auth-context]
++context_class = glance.registry.context.RequestContext
+ paste.filter_factory = keystone.middleware.glance_auth_token:filter_factory
+-- 
+1.7.6.5
+
diff --git a/0009-Fixes-LP-Bug-844618-SQLAlchemy-errors-not-logged.patch b/0009-Fixes-LP-Bug-844618-SQLAlchemy-errors-not-logged.patch
new file mode 100644
index 0000000..3f6753f
--- /dev/null
+++ b/0009-Fixes-LP-Bug-844618-SQLAlchemy-errors-not-logged.patch
@@ -0,0 +1,137 @@
+From bfa9b97b37d2aa1a7a64734311381bb959560b91 Mon Sep 17 00:00:00 2001
+From: Jay Pipes <jaypipes at gmail.com>
+Date: Thu, 13 Oct 2011 11:56:19 -0400
+Subject: [PATCH] Fixes LP Bug#844618 - SQLAlchemy errors not logged
+
+Logs any import errors or SQLAlchemy connection failures
+to the glance registry log so that there is some indication
+that a driver module is not installed or there is a problem
+with the sql_connection configuration string.
+
+Adds test case that verifies log output and error raised.
+
+(cherry picked from commit 56e15f6993e85376eb6e3fb4928b0cb8f6df1fda)
+
+Change-Id: Ib86c353350530d6de62e577df57602d1762879f9
+---
+ glance/registry/db/api.py     |   24 ++++++++++++++-------
+ glance/tests/unit/test_api.py |   45 +++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 61 insertions(+), 8 deletions(-)
+
+diff --git a/glance/registry/db/api.py b/glance/registry/db/api.py
+index 9c85465..5c8bf79 100644
+--- a/glance/registry/db/api.py
++++ b/glance/registry/db/api.py
+@@ -39,7 +39,8 @@ from glance.registry.db import models
+ _ENGINE = None
+ _MAKER = None
+ BASE = models.BASE
+-logger = None
++sa_logger = None
++logger = logging.getLogger(__name__)
+ 
+ # attributes common to all models
+ BASE_MODEL_ATTRS = set(['id', 'created_at', 'updated_at', 'deleted_at',
+@@ -64,8 +65,7 @@ def configure_db(options):
+ 
+     :param options: Mapping of configuration options
+     """
+-    global _ENGINE
+-    global logger
++    global _ENGINE, sa_logger, logger
+     if not _ENGINE:
+         debug = config.get_option(
+             options, 'debug', type='bool', default=False)
+@@ -73,13 +73,21 @@ def configure_db(options):
+             options, 'verbose', type='bool', default=False)
+         timeout = config.get_option(
+             options, 'sql_idle_timeout', type='int', default=3600)
+-        _ENGINE = create_engine(options['sql_connection'],
+-                                pool_recycle=timeout)
+-        logger = logging.getLogger('sqlalchemy.engine')
++        sql_connection = config.get_option(options, 'sql_connection')
++        try:
++            _ENGINE = create_engine(sql_connection, pool_recycle=timeout)
++        except Exception, err:
++            msg = _("Error configuring registry database with supplied "
++                    "sql_connection '%(sql_connection)s'. "
++                    "Got error:\n%(err)s") % locals()
++            logger.error(msg)
++            raise
++
++        sa_logger = logging.getLogger('sqlalchemy.engine')
+         if debug:
+-            logger.setLevel(logging.DEBUG)
++            sa_logger.setLevel(logging.DEBUG)
+         elif verbose:
+-            logger.setLevel(logging.INFO)
++            sa_logger.setLevel(logging.INFO)
+ 
+         models.register_models(_ENGINE)
+ 
+diff --git a/glance/tests/unit/test_api.py b/glance/tests/unit/test_api.py
+index f867d10..5da679d 100644
+--- a/glance/tests/unit/test_api.py
++++ b/glance/tests/unit/test_api.py
+@@ -18,6 +18,7 @@
+ import datetime
+ import hashlib
+ import httplib
++import logging
+ import os
+ import json
+ import unittest
+@@ -43,6 +44,50 @@ OPTIONS = {'sql_connection': 'sqlite://',
+            'context_class': 'glance.registry.context.RequestContext'}
+ 
+ 
++class TestRegistryDb(unittest.TestCase):
++
++    def setUp(self):
++        """Establish a clean test environment"""
++        self.stubs = stubout.StubOutForTesting()
++
++    def test_bad_sql_connection(self):
++        """
++        Test that a bad sql_connection option supplied to the registry
++        API controller results in a) an Exception being thrown and b)
++        a message being logged to the registry log file...
++        """
++        bad_options = {'verbose': True,
++                       'debug': True,
++                       'sql_connection': 'baddriver:///'}
++        # We set this to None to trigger a reconfigure, otherwise
++        # other modules may have already correctly configured the DB
++        orig_engine = db_api._ENGINE
++        db_api._ENGINE = None
++        self.assertRaises(ImportError, db_api.configure_db,
++                          bad_options)
++        exc_raised = False
++        self.log_written = False
++
++        def fake_log_error(msg):
++            if 'Error configuring registry database' in msg:
++                self.log_written = True
++
++        self.stubs.Set(db_api.logger, 'error', fake_log_error)
++        try:
++            api_obj = rserver.API(bad_options)
++        except ImportError:
++            exc_raised = True
++        finally:
++            db_api._ENGINE = orig_engine
++
++        self.assertTrue(exc_raised)
++        self.assertTrue(self.log_written)
++
++    def tearDown(self):
++        """Clear the test environment"""
++        self.stubs.UnsetAll()
++
++
+ class TestRegistryAPI(unittest.TestCase):
+     def setUp(self):
+         """Establish a clean test environment"""
+-- 
+1.7.6.5
+
diff --git a/0010-Add-.gitreview-config-file-for-gerrit.patch b/0010-Add-.gitreview-config-file-for-gerrit.patch
new file mode 100644
index 0000000..c337e7f
--- /dev/null
+++ b/0010-Add-.gitreview-config-file-for-gerrit.patch
@@ -0,0 +1,26 @@
+From 9620d00097f131d2babd64cef77e6dd2c2daeaba Mon Sep 17 00:00:00 2001
+From: "James E. Blair" <james.blair at rackspace.com>
+Date: Thu, 20 Oct 2011 13:44:58 -0400
+Subject: [PATCH] Add .gitreview config file for gerrit.
+
+(cherry picked from commit 17b79b0220ab5de9e8ba4911764fe0d59d843a5f)
+
+Change-Id: I61524c310738b77df8809495ce5b7822e76562f1
+---
+ .gitreview |    4 ++++
+ 1 files changed, 4 insertions(+), 0 deletions(-)
+ create mode 100644 .gitreview
+
+diff --git a/.gitreview b/.gitreview
+new file mode 100644
+index 0000000..31aa568
+--- /dev/null
++++ b/.gitreview
+@@ -0,0 +1,4 @@
++[gerrit]
++host=review.openstack.org
++port=29418
++project=openstack/glance.git
+-- 
+1.7.6.5
+
diff --git a/0011-Removed-mox-0.5.0-and-replaced-with-just-mox-in-tool.patch b/0011-Removed-mox-0.5.0-and-replaced-with-just-mox-in-tool.patch
new file mode 100644
index 0000000..6468fb6
--- /dev/null
+++ b/0011-Removed-mox-0.5.0-and-replaced-with-just-mox-in-tool.patch
@@ -0,0 +1,35 @@
+From 9edd6634647c5c7076cdf90402f7603527eb7f4d Mon Sep 17 00:00:00 2001
+From: Brian Lamar <brian.lamar at rackspace.com>
+Date: Mon, 24 Oct 2011 16:25:21 -0500
+Subject: [PATCH] Removed 'mox==0.5.0' and replaced with just 'mox' in
+ tools/pip-requires.
+
+I was getting an error from pip stating: Could not find a version that
+satisfies the requirement mox==0.5.0 (from versions: ).
+
+Potentially pip is messed up, but all tests seem to run with the latest
+version of mox (0.5.3).
+
+(cherry picked from commit d521d6529e0d0cdd1138823e0ee5be0e5d87e21c)
+
+Change-Id: Id6a38766290a20d752177e8d272284b7b632156b
+---
+ tools/pip-requires |    2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/tools/pip-requires b/tools/pip-requires
+index f928299..e439219 100644
+--- a/tools/pip-requires
++++ b/tools/pip-requires
+@@ -12,7 +12,7 @@ nose
+ nose-exclude
+ sphinx
+ argparse
+-mox==0.5.0
++mox
+ boto
+ swift
+ -f http://pymox.googlecode.com/files/mox-0.5.0.tar.gz
+-- 
+1.7.6.5
+
diff --git a/0012-Remove-location-from-POST-PUT-image-responses.patch b/0012-Remove-location-from-POST-PUT-image-responses.patch
new file mode 100644
index 0000000..be2916e
--- /dev/null
+++ b/0012-Remove-location-from-POST-PUT-image-responses.patch
@@ -0,0 +1,136 @@
+From dd1c45b6b5c4f5b71f3922af728fdcd73a263aa9 Mon Sep 17 00:00:00 2001
+From: Brian Waldon <brian.waldon at rackspace.com>
+Date: Tue, 25 Oct 2011 22:41:42 -0400
+Subject: [PATCH] Remove 'location' from POST/PUT image responses
+
+The 'location' field is already removed from GET calls, so we should
+also remove it from POST/PUT operations. Partially fixes bug 880910.
+
+(cherry picked from commit 258aa1356ca0e3e6de0b1cdd54b3736e592d3995)
+
+Change-Id: I4f7d8d0309c8a3e10d0c2a99573ca0fa808c93be
+---
+ glance/api/v1/images.py           |    8 ++++++++
+ glance/tests/unit/test_api.py     |   29 +++++++++++++++++++++++------
+ glance/tests/unit/test_clients.py |    4 +---
+ 3 files changed, 32 insertions(+), 9 deletions(-)
+
+diff --git a/glance/api/v1/images.py b/glance/api/v1/images.py
+index 5d177e1..34efd5f 100644
+--- a/glance/api/v1/images.py
++++ b/glance/api/v1/images.py
+@@ -540,6 +540,10 @@ class Controller(api.BaseController):
+             if location:
+                 image_meta = self._activate(req, image_id, location)
+ 
++        # Prevent client from learning the location, as it
++        # could contain security credentials
++        image_meta.pop('location', None)
++
+         return {'image_meta': image_meta}
+ 
+     def update(self, req, id, image_meta, image_data):
+@@ -585,6 +589,10 @@ class Controller(api.BaseController):
+         else:
+             self.notifier.info('image.update', image_meta)
+ 
++        # Prevent client from learning the location, as it
++        # could contain security credentials
++        image_meta.pop('location', None)
++
+         return {'image_meta': image_meta}
+ 
+     def delete(self, req, id):
+diff --git a/glance/tests/unit/test_api.py b/glance/tests/unit/test_api.py
+index 5da679d..94bcd59 100644
+--- a/glance/tests/unit/test_api.py
++++ b/glance/tests/unit/test_api.py
+@@ -1975,10 +1975,6 @@ class TestGlanceAPI(unittest.TestCase):
+         res = req.get_response(self.api)
+         self.assertEquals(res.status_int, httplib.CREATED)
+ 
+-        res_body = json.loads(res.body)['image']
+-        self.assertEquals(res_body['location'],
+-                          'file:///tmp/glance-tests/3')
+-
+         # Test that the Location: header is set to the URI to
+         # edit the newly-created image, as required by APP.
+         # See LP Bug #719825
+@@ -2056,6 +2052,29 @@ class TestGlanceAPI(unittest.TestCase):
+         self.assertEqual(res.status_int, 200)
+         self.assertFalse('X-Image-Meta-Location' in res.headers)
+ 
++        # Check PUT
++        req = webob.Request.blank("/images/2")
++        req.body = res.body
++        req.method = 'PUT'
++        res = req.get_response(self.api)
++        self.assertEqual(res.status_int, 200)
++        res_body = json.loads(res.body)
++        self.assertFalse('location' in res_body['image'])
++
++        # Check POST
++        req = webob.Request.blank("/images")
++        headers = {'x-image-meta-location': 'http://localhost',
++                   'x-image-meta-disk-format': 'vhd',
++                   'x-image-meta-container-format': 'ovf',
++                   'x-image-meta-name': 'fake image #3'}
++        for k, v in headers.iteritems():
++            req.headers[k] = v
++        req.method = 'POST'
++        res = req.get_response(self.api)
++        self.assertEqual(res.status_int, 201)
++        res_body = json.loads(res.body)
++        self.assertFalse('location' in res_body['image'])
++
+     def test_image_is_checksummed(self):
+         """Test that the image contents are checksummed properly"""
+         fixture_headers = {'x-image-meta-store': 'file',
+@@ -2076,8 +2095,6 @@ class TestGlanceAPI(unittest.TestCase):
+         self.assertEquals(res.status_int, httplib.CREATED)
+ 
+         res_body = json.loads(res.body)['image']
+-        self.assertEquals(res_body['location'],
+-                          'file:///tmp/glance-tests/3')
+         self.assertEquals(image_checksum, res_body['checksum'],
+                           "Mismatched checksum. Expected %s, got %s" %
+                           (image_checksum, res_body['checksum']))
+diff --git a/glance/tests/unit/test_clients.py b/glance/tests/unit/test_clients.py
+index dd2e871..a7c4b1b 100644
+--- a/glance/tests/unit/test_clients.py
++++ b/glance/tests/unit/test_clients.py
+@@ -560,7 +560,6 @@ class TestRegistryClient(unittest.TestCase):
+                    'container_format': 'ovf',
+                    'status': 'active',
+                    'size': 19,
+-                   'location': "file:///tmp/glance-tests/2",
+                    'properties': {}}
+ 
+         images = self.client.get_images_detailed()
+@@ -787,7 +786,6 @@ class TestRegistryClient(unittest.TestCase):
+                    'container_format': 'ami',
+                    'status': 'active',
+                    'size': 13,
+-                   'location': "swift://user:passwd@acct/container/obj.tar.0",
+                    'properties': {'type': 'kernel'}}
+ 
+         data = self.client.get_image(1)
+@@ -811,7 +809,6 @@ class TestRegistryClient(unittest.TestCase):
+                    'disk_format': 'vmdk',
+                    'container_format': 'ovf',
+                    'size': 19,
+-                   'location': "file:///tmp/glance-tests/acct/3.gz.0",
+                   }
+ 
+         new_image = self.client.add_image(fixture)
+@@ -844,6 +841,7 @@ class TestRegistryClient(unittest.TestCase):
+         # Test ID auto-assigned properly
+         self.assertEquals(3, new_image['id'])
+ 
++        del fixture['location']
+         for k, v in fixture.items():
+             self.assertEquals(v, new_image[k])
+ 
+-- 
+1.7.6.5
+
diff --git a/0013-Fix-Keystone-API-skew-issue-with-Glance-client.patch b/0013-Fix-Keystone-API-skew-issue-with-Glance-client.patch
new file mode 100644
index 0000000..9543571
--- /dev/null
+++ b/0013-Fix-Keystone-API-skew-issue-with-Glance-client.patch
@@ -0,0 +1,72 @@
+From 692b066c4a4b43f1e06325eb85e870c06c28d4ec Mon Sep 17 00:00:00 2001
+From: "Kevin L. Mitchell" <kevin.mitchell at rackspace.com>
+Date: Wed, 2 Nov 2011 11:18:16 -0500
+Subject: [PATCH] Fix Keystone API skew issue with Glance client.
+
+Fixes bug 878927 by applying Roman Sokolkov's patch.
+
+(cherry picked from commit bc7aeb4a0a1295f90f7ea8824a1c8bf5313fafb7)
+
+Change-Id: I9877131c7df65a58e75e6be47f29e9b0a0c2705e
+---
+ glance/common/auth.py      |   21 ++++++++++++++++-----
+ glance/common/exception.py |    4 ++++
+ 2 files changed, 20 insertions(+), 5 deletions(-)
+
+diff --git a/glance/common/auth.py b/glance/common/auth.py
+index 3f0e483..02cfee6 100644
+--- a/glance/common/auth.py
++++ b/glance/common/auth.py
+@@ -148,8 +148,15 @@ class KeystoneStrategy(BaseStrategy):
+     def _v2_auth(self, token_url):
+         creds = self.creds
+ 
+-        creds = {"passwordCredentials": {"username": creds['username'],
+-                                         "password": creds['password']}}
++        creds = {
++            "auth": {
++                "tenantName": creds['tenant'],
++                "passwordCredentials": {
++                    "username": creds['username'],
++                    "password": creds['password']
++                    }
++                }
++            }
+ 
+         tenant = creds.get('tenant')
+         if tenant:
+@@ -163,12 +170,16 @@ class KeystoneStrategy(BaseStrategy):
+                 token_url, 'POST', headers=headers, body=req_body)
+ 
+         if resp.status == 200:
+-            resp_auth = json.loads(resp_body)['auth']
++            resp_auth = json.loads(resp_body)['access']
+ 
+             # FIXME(sirp): for now just using the first endpoint we get back
+             # from the service catalog for glance, and using the public url.
+-            glance_info = resp_auth['serviceCatalog']['glance']
+-            glance_endpoint = glance_info[0]['publicURL']
++            for service in resp_auth['serviceCatalog']:
++                if service['name'] == 'glance':
++                    glance_endpoint = service['endpoints'][0]['publicURL']
++                    break
++            else:
++                raise exception.NoServiceEndpoint()
+ 
+             self.management_url = glance_endpoint
+             self.auth_token = resp_auth['token']['id']
+diff --git a/glance/common/exception.py b/glance/common/exception.py
+index 5d9bf19..d5d20ae 100644
+--- a/glance/common/exception.py
++++ b/glance/common/exception.py
+@@ -178,3 +178,7 @@ class StoreAddDisabled(GlanceException):
+ 
+ class InvalidNotifierStrategy(GlanceException):
+     message = "'%(strategy)s' is not an available notifier strategy."
++
++
++class NoServiceEndpoint(GlanceException):
++    message = _("Response from Keystone does not contain a Glance endpoint.")
+-- 
+1.7.6.5
+
diff --git a/0014-load-gettext-in-__init__-to-fix-_-is-not-defined.patch b/0014-load-gettext-in-__init__-to-fix-_-is-not-defined.patch
new file mode 100644
index 0000000..ca787af
--- /dev/null
+++ b/0014-load-gettext-in-__init__-to-fix-_-is-not-defined.patch
@@ -0,0 +1,34 @@
+From 33ecb7a9da19b2865922ebaade096c2a4e443e14 Mon Sep 17 00:00:00 2001
+From: Mike Lundy <mike at pistoncloud.com>
+Date: Tue, 8 Nov 2011 10:57:27 -0800
+Subject: [PATCH] load gettext in __init__ to fix '_ is not defined'
+
+gettext.install needs to be run on every potential entrypoint; this
+resolves bug #885529 (the python standard library includes a noop
+gettext library for this purpose). This is also how nova does it.
+
+(cherry picked from commit 8f122d954bb35d18f0afb38aa2822cd1741f05f0)
+
+Change-Id: I4ceaa4782461ebf6d27836336f288d79ba15cf2d
+---
+ Authors            |    1 +
+ glance/__init__.py |    4 ++++
+ 2 files changed, 5 insertions(+), 0 deletions(-)
+
+diff --git a/Authors b/Authors
+index 3d2ec33..7993d0b 100644
+diff --git a/glance/__init__.py b/glance/__init__.py
+index b606957..b6d314b 100644
+--- a/glance/__init__.py
++++ b/glance/__init__.py
+@@ -14,3 +14,7 @@
+ #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ #    License for the specific language governing permissions and limitations
+ #    under the License.
++
++import gettext
++
++gettext.install('glance', unicode=1)
+-- 
+1.7.6.5
+
diff --git a/0015-Update-glance-show-to-print-a-valid-URI.-Fixes-bug-8.patch b/0015-Update-glance-show-to-print-a-valid-URI.-Fixes-bug-8.patch
new file mode 100644
index 0000000..1ae6fd8
--- /dev/null
+++ b/0015-Update-glance-show-to-print-a-valid-URI.-Fixes-bug-8.patch
@@ -0,0 +1,32 @@
+From 0037b0cef230abb171808fdbc1067bb1935bd650 Mon Sep 17 00:00:00 2001
+From: Dan Prince <dan.prince at rackspace.com>
+Date: Wed, 9 Nov 2011 20:47:27 -0500
+Subject: [PATCH] Update 'glance show' to print a valid URI. Fixes bug
+ #888370.
+
+(cherry picked from commit 98cefb7fc8430ad92b002d2300fd2085c71c9750)
+
+Change-Id: Ibe8d7974eb2dfca79953b473b904df55daafa748
+---
+ bin/glance |    4 +++-
+ 1 files changed, 3 insertions(+), 1 deletions(-)
+
+diff --git a/bin/glance b/bin/glance
+index 166b695..1008ef6 100755
+--- a/bin/glance
++++ b/bin/glance
+@@ -131,8 +131,10 @@ def print_image_formatted(client, image):
+     :param client: The Glance client object
+     :param image: The image metadata
+     """
+-    print "URI: %s://%s/images/%s" % (client.use_ssl and "https" or "http",
++    print "URI: %s://%s:%s/v1/images/%s" % (
++                                      client.use_ssl and "https" or "http",
+                                       client.host,
++                                      client.port,
+                                       image['id'])
+     print "Id: %s" % image['id']
+     print "Public: " + (image['is_public'] and "Yes" or "No")
+-- 
+1.7.6.5
+
diff --git a/0016-Using-Keystone-s-new-port-number-35357.patch b/0016-Using-Keystone-s-new-port-number-35357.patch
new file mode 100644
index 0000000..1b55db1
--- /dev/null
+++ b/0016-Using-Keystone-s-new-port-number-35357.patch
@@ -0,0 +1,58 @@
+From a1c88691d4d9b0877da6e902d787d737262dd33d Mon Sep 17 00:00:00 2001
+From: Rick Harris <rconradharris at gmail.com>
+Date: Thu, 10 Nov 2011 23:33:45 +0000
+Subject: [PATCH] Using Keystone's new port number 35357.
+
+Fixes bug 888753
+
+(cherry picked from commit 94dcf3acd0b3ef7adcb61b90bf4bdcc733cf61ac)
+
+Change-Id: I22894a31ee54edd6d00ac3458ea4a2f8842aa4a0
+---
+ doc/source/authentication.rst |    2 +-
+ etc/glance-api.conf           |    2 +-
+ etc/glance-registry.conf      |    2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/doc/source/authentication.rst b/doc/source/authentication.rst
+index 8f3acf4..2d3810d 100644
+--- a/doc/source/authentication.rst
++++ b/doc/source/authentication.rst
+@@ -124,7 +124,7 @@ pieces of middleware exist.  Here is an example for ``authtoken``::
+   service_host = 127.0.0.1
+   service_port = 5000
+   auth_host = 127.0.0.1
+-  auth_port = 5001
++  auth_port = 35357
+   auth_protocol = http
+   auth_uri = http://127.0.0.1:5000/
+   admin_token = 999888777666
+diff --git a/etc/glance-api.conf b/etc/glance-api.conf
+index f3ca0da..5e6956d 100644
+--- a/etc/glance-api.conf
++++ b/etc/glance-api.conf
+@@ -165,7 +165,7 @@ service_protocol = http
+ service_host = 127.0.0.1
+ service_port = 5000
+ auth_host = 127.0.0.1
+-auth_port = 5001
++auth_port = 35357
+ auth_protocol = http
+ auth_uri = http://127.0.0.1:5000/
+ admin_token = 999888777666
+diff --git a/etc/glance-registry.conf b/etc/glance-registry.conf
+index c81e1a4..5f21702 100644
+--- a/etc/glance-registry.conf
++++ b/etc/glance-registry.conf
+@@ -58,7 +58,7 @@ service_protocol = http
+ service_host = 127.0.0.1
+ service_port = 5000
+ auth_host = 127.0.0.1
+-auth_port = 5001
++auth_port = 35357
+ auth_protocol = http
+ auth_uri = http://127.0.0.1:5000/
+ admin_token = 999888777666
+-- 
+1.7.6.5
+
diff --git a/0017-Making-prefetcher-call-create_stores.patch b/0017-Making-prefetcher-call-create_stores.patch
new file mode 100644
index 0000000..646aebc
--- /dev/null
+++ b/0017-Making-prefetcher-call-create_stores.patch
@@ -0,0 +1,42 @@
+From 0795367c41dc4096ee45af6b4ebc6e79d5f2b41e Mon Sep 17 00:00:00 2001
+From: Rick Harris <rconradharris at gmail.com>
+Date: Fri, 11 Nov 2011 18:39:31 +0000
+Subject: [PATCH] Making prefetcher call create_stores.
+
+Fixes bug 888383
+
+(cherry picked from commit f394327f3869b8b820f1fdd345c7e6073dd82820)
+
+Change-Id: Ia3adc6a30f16f889cd344f8cb3fca4a071871fe4
+---
+ glance/image_cache/prefetcher.py |    7 +++++++
+ 1 files changed, 7 insertions(+), 0 deletions(-)
+
+diff --git a/glance/image_cache/prefetcher.py b/glance/image_cache/prefetcher.py
+index dba7f9c..4895f32 100644
+--- a/glance/image_cache/prefetcher.py
++++ b/glance/image_cache/prefetcher.py
+@@ -27,6 +27,12 @@ from glance.common import config
+ from glance.common import context
+ from glance.image_cache import ImageCache
+ from glance import registry
++import glance.store
++import glance.store.filesystem
++import glance.store.http
++import glance.store.rbd
++import glance.store.s3
++import glance.store.swift
+ from glance.store import get_from_backend
+ 
+ 
+@@ -36,6 +42,7 @@ logger = logging.getLogger('glance.image_cache.prefetcher')
+ class Prefetcher(object):
+     def __init__(self, options):
+         self.options = options
++        glance.store.create_stores(options)
+         self.cache = ImageCache(options)
+ 
+     def fetch_image_into_cache(self, image_id):
+-- 
+1.7.6.5
+
diff --git a/0018-Add-a-LICENSE-file.patch b/0018-Add-a-LICENSE-file.patch
new file mode 100644
index 0000000..83eae56
--- /dev/null
+++ b/0018-Add-a-LICENSE-file.patch
@@ -0,0 +1,204 @@
+From 49350e3f01718aee0e29486024c81d54829e23c1 Mon Sep 17 00:00:00 2001
+From: Russell Bryant <rbryant at redhat.com>
+Date: Tue, 3 Jan 2012 09:31:23 -0500
+Subject: [PATCH] Add a LICENSE file.
+
+The license file was missing in glance. The LICENSE file added here is
+copied in from nova.
+
+(cherry picked from commit db2942166de266412ed1f9ccc9127afe32b5cdd4)
+
+Change-Id: Ifae7610ea2c4d0db9cb4fc58a5639850f2b3e195
+---
+ Authors |    1 +
+ LICENSE |  176 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 177 insertions(+), 0 deletions(-)
+ create mode 100644 LICENSE
+
+diff --git a/Authors b/Authors
+index 7993d0b..36234ce 100644
+diff --git a/LICENSE b/LICENSE
+new file mode 100644
+index 0000000..68c771a
+--- /dev/null
++++ b/LICENSE
+@@ -0,0 +1,176 @@
++
++                                 Apache License
++                           Version 2.0, January 2004
++                        http://www.apache.org/licenses/
++
++   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
++
++   1. Definitions.
++
++      "License" shall mean the terms and conditions for use, reproduction,
++      and distribution as defined by Sections 1 through 9 of this document.
++
++      "Licensor" shall mean the copyright owner or entity authorized by
++      the copyright owner that is granting the License.
++
++      "Legal Entity" shall mean the union of the acting entity and all
++      other entities that control, are controlled by, or are under common
++      control with that entity. For the purposes of this definition,
++      "control" means (i) the power, direct or indirect, to cause the
++      direction or management of such entity, whether by contract or
++      otherwise, or (ii) ownership of fifty percent (50%) or more of the
++      outstanding shares, or (iii) beneficial ownership of such entity.
++
++      "You" (or "Your") shall mean an individual or Legal Entity
++      exercising permissions granted by this License.
++
++      "Source" form shall mean the preferred form for making modifications,
++      including but not limited to software source code, documentation
++      source, and configuration files.
++
++      "Object" form shall mean any form resulting from mechanical
++      transformation or translation of a Source form, including but
++      not limited to compiled object code, generated documentation,
++      and conversions to other media types.
++
++      "Work" shall mean the work of authorship, whether in Source or
++      Object form, made available under the License, as indicated by a
++      copyright notice that is included in or attached to the work
++      (an example is provided in the Appendix below).
++
++      "Derivative Works" shall mean any work, whether in Source or Object
++      form, that is based on (or derived from) the Work and for which the
++      editorial revisions, annotations, elaborations, or other modifications
++      represent, as a whole, an original work of authorship. For the purposes
++      of this License, Derivative Works shall not include works that remain
++      separable from, or merely link (or bind by name) to the interfaces of,
++      the Work and Derivative Works thereof.
++
++      "Contribution" shall mean any work of authorship, including
++      the original version of the Work and any modifications or additions
++      to that Work or Derivative Works thereof, that is intentionally
++      submitted to Licensor for inclusion in the Work by the copyright owner
++      or by an individual or Legal Entity authorized to submit on behalf of
++      the copyright owner. For the purposes of this definition, "submitted"
++      means any form of electronic, verbal, or written communication sent
++      to the Licensor or its representatives, including but not limited to
++      communication on electronic mailing lists, source code control systems,
++      and issue tracking systems that are managed by, or on behalf of, the
++      Licensor for the purpose of discussing and improving the Work, but
++      excluding communication that is conspicuously marked or otherwise
++      designated in writing by the copyright owner as "Not a Contribution."
++
++      "Contributor" shall mean Licensor and any individual or Legal Entity
++      on behalf of whom a Contribution has been received by Licensor and
++      subsequently incorporated within the Work.
++
++   2. Grant of Copyright License. Subject to the terms and conditions of
++      this License, each Contributor hereby grants to You a perpetual,
++      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
++      copyright license to reproduce, prepare Derivative Works of,
++      publicly display, publicly perform, sublicense, and distribute the
++      Work and such Derivative Works in Source or Object form.
++
++   3. Grant of Patent License. Subject to the terms and conditions of
++      this License, each Contributor hereby grants to You a perpetual,
++      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
++      (except as stated in this section) patent license to make, have made,
++      use, offer to sell, sell, import, and otherwise transfer the Work,
++      where such license applies only to those patent claims licensable
++      by such Contributor that are necessarily infringed by their
++      Contribution(s) alone or by combination of their Contribution(s)
++      with the Work to which such Contribution(s) was submitted. If You
++      institute patent litigation against any entity (including a
++      cross-claim or counterclaim in a lawsuit) alleging that the Work
++      or a Contribution incorporated within the Work constitutes direct
++      or contributory patent infringement, then any patent licenses
++      granted to You under this License for that Work shall terminate
++      as of the date such litigation is filed.
++
++   4. Redistribution. You may reproduce and distribute copies of the
++      Work or Derivative Works thereof in any medium, with or without
++      modifications, and in Source or Object form, provided that You
++      meet the following conditions:
++
++      (a) You must give any other recipients of the Work or
++          Derivative Works a copy of this License; and
++
++      (b) You must cause any modified files to carry prominent notices
++          stating that You changed the files; and
++
++      (c) You must retain, in the Source form of any Derivative Works
++          that You distribute, all copyright, patent, trademark, and
++          attribution notices from the Source form of the Work,
++          excluding those notices that do not pertain to any part of
++          the Derivative Works; and
++
++      (d) If the Work includes a "NOTICE" text file as part of its
++          distribution, then any Derivative Works that You distribute must
++          include a readable copy of the attribution notices contained
++          within such NOTICE file, excluding those notices that do not
++          pertain to any part of the Derivative Works, in at least one
++          of the following places: within a NOTICE text file distributed
++          as part of the Derivative Works; within the Source form or
++          documentation, if provided along with the Derivative Works; or,
++          within a display generated by the Derivative Works, if and
++          wherever such third-party notices normally appear. The contents
++          of the NOTICE file are for informational purposes only and
++          do not modify the License. You may add Your own attribution
++          notices within Derivative Works that You distribute, alongside
++          or as an addendum to the NOTICE text from the Work, provided
++          that such additional attribution notices cannot be construed
++          as modifying the License.
++
++      You may add Your own copyright statement to Your modifications and
++      may provide additional or different license terms and conditions
++      for use, reproduction, or distribution of Your modifications, or
++      for any such Derivative Works as a whole, provided Your use,
++      reproduction, and distribution of the Work otherwise complies with
++      the conditions stated in this License.
++
++   5. Submission of Contributions. Unless You explicitly state otherwise,
++      any Contribution intentionally submitted for inclusion in the Work
++      by You to the Licensor shall be under the terms and conditions of
++      this License, without any additional terms or conditions.
++      Notwithstanding the above, nothing herein shall supersede or modify
++      the terms of any separate license agreement you may have executed
++      with Licensor regarding such Contributions.
++
++   6. Trademarks. This License does not grant permission to use the trade
++      names, trademarks, service marks, or product names of the Licensor,
++      except as required for reasonable and customary use in describing the
++      origin of the Work and reproducing the content of the NOTICE file.
++
++   7. Disclaimer of Warranty. Unless required by applicable law or
++      agreed to in writing, Licensor provides the Work (and each
++      Contributor provides its Contributions) on an "AS IS" BASIS,
++      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
++      implied, including, without limitation, any warranties or conditions
++      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
++      PARTICULAR PURPOSE. You are solely responsible for determining the
++      appropriateness of using or redistributing the Work and assume any
++      risks associated with Your exercise of permissions under this License.
++
++   8. Limitation of Liability. In no event and under no legal theory,
++      whether in tort (including negligence), contract, or otherwise,
++      unless required by applicable law (such as deliberate and grossly
++      negligent acts) or agreed to in writing, shall any Contributor be
++      liable to You for damages, including any direct, indirect, special,
++      incidental, or consequential damages of any character arising as a
++      result of this License or out of the use or inability to use the
++      Work (including but not limited to damages for loss of goodwill,
++      work stoppage, computer failure or malfunction, or any and all
++      other commercial damages or losses), even if such Contributor
++      has been advised of the possibility of such damages.
++
++   9. Accepting Warranty or Additional Liability. While redistributing
++      the Work or Derivative Works thereof, You may choose to offer,
++      and charge a fee for, acceptance of support, warranty, indemnity,
++      or other liability obligations and/or rights consistent with this
++      License. However, in accepting such obligations, You may act only
++      on Your own behalf and on Your sole responsibility, not on behalf
++      of any other Contributor, and only if You agree to indemnify,
++      defend, and hold each Contributor harmless for any liability
++      incurred by, or claims asserted against, such Contributor by reason
++      of your accepting any such warranty or additional liability.
++
+-- 
+1.7.6.5
+
diff --git a/0019-Rename-.glance-venv-to-.venv.patch b/0019-Rename-.glance-venv-to-.venv.patch
new file mode 100644
index 0000000..07e5c19
--- /dev/null
+++ b/0019-Rename-.glance-venv-to-.venv.patch
@@ -0,0 +1,79 @@
+From 017a53fca98e90e12f45ffe419ff60476e6d02b1 Mon Sep 17 00:00:00 2001
+From: "James E. Blair" <jeblair at hp.com>
+Date: Mon, 5 Dec 2011 11:23:40 -0800
+Subject: [PATCH] Rename .glance-venv to .venv.
+
+This simplifies a number of Jenkins jobs which currently, other
+than directory names, could be the same for all OpenStack
+projects.  By renaming the virtualenv directory, the redundant
+Jenkins virtualenv build and copy jobs can be eliminated.
+
+(cherry picked from commit 37fc2b00c0a8dd67221d83697609913aa78d89c7)
+
+Change-Id: I7916783d863e5184bad8293c3aed5ba119e374a9
+---
+ .bzrignore            |    1 +
+ .gitignore            |    1 +
+ .mailmap              |    2 ++
+ Authors               |    1 +
+ run_tests.sh          |    2 +-
+ tools/install_venv.py |    4 ++--
+ tools/with_venv.sh    |    2 +-
+ 7 files changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/.bzrignore b/.bzrignore
+index 0dc1ca0..3c39f0b 100644
+diff --git a/.gitignore b/.gitignore
+index 410f8fc..b181715 100644
+diff --git a/.mailmap b/.mailmap
+index 0293555..8467e9b 100644
+diff --git a/Authors b/Authors
+index 36234ce..2e8e0b7 100644
+diff --git a/run_tests.sh b/run_tests.sh
+index eec2ac1..e1fbb7b 100755
+--- a/run_tests.sh
++++ b/run_tests.sh
+@@ -29,7 +29,7 @@ function process_option {
+   esac
+ }
+ 
+-venv=.glance-venv
++venv=.venv
+ with_venv=tools/with_venv.sh
+ always_venv=0
+ never_venv=0
+diff --git a/tools/install_venv.py b/tools/install_venv.py
+index 5c0f71a..7a9473a 100644
+--- a/tools/install_venv.py
++++ b/tools/install_venv.py
+@@ -28,7 +28,7 @@ import sys
+ 
+ 
+ ROOT = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
+-VENV = os.path.join(ROOT, '.glance-venv')
++VENV = os.path.join(ROOT, '.venv')
+ PIP_REQUIRES = os.path.join(ROOT, 'tools', 'pip-requires')
+ 
+ 
+@@ -124,7 +124,7 @@ def print_help():
+  To activate the Glance virtualenv for the extent of your current shell session
+  you can run:
+ 
+- $ source .glance-venv/bin/activate
++ $ source .venv/bin/activate
+ 
+  Or, if you prefer, you can run commands in the virtualenv on a case by case
+  basis by running:
+diff --git a/tools/with_venv.sh b/tools/with_venv.sh
+index fc5ed77..c8d2940 100755
+--- a/tools/with_venv.sh
++++ b/tools/with_venv.sh
+@@ -1,4 +1,4 @@
+ #!/bin/bash
+ TOOLS=`dirname $0`
+-VENV=$TOOLS/../.glance-venv
++VENV=$TOOLS/../.venv
+ source $VENV/bin/activate && $@
+-- 
+1.7.6.5
+
diff --git a/0020-Always-reference-the-glance-module-from-the-package-.patch b/0020-Always-reference-the-glance-module-from-the-package-.patch
new file mode 100644
index 0000000..04524b9
--- /dev/null
+++ b/0020-Always-reference-the-glance-module-from-the-package-.patch
@@ -0,0 +1,35 @@
+From 2ad33c2b49116a4765325e42ed5c8b8a9d07ea10 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady at redhat.com>
+Date: Fri, 6 Jan 2012 17:11:12 +0000
+Subject: [PATCH] Always reference the glance module from the package we're
+ building
+
+(Note this hasn't been sent upstream)
+
+Change-Id: Id0be3fb4459226113121ce5f3b2984fba94260bb
+---
+ doc/source/conf.py |    8 ++++----
+ 1 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/doc/source/conf.py b/doc/source/conf.py
+index f058b52..3ecbb03 100644
+--- a/doc/source/conf.py
++++ b/doc/source/conf.py
+@@ -33,10 +33,10 @@ import sys
+ # If extensions (or modules to document with autodoc) are in another directory,
+ # add these directories to sys.path here. If the directory is relative to the
+ # documentation root, use os.path.abspath to make it absolute, like shown here.
+-sys.path.append([os.path.abspath('../glance'),
+-    os.path.abspath('..'),
+-    os.path.abspath('../bin')
+-    ])
++sys.path = [os.path.abspath('../../glance'),
++    os.path.abspath('../..'),
++    os.path.abspath('../../bin')
++    ] + sys.path
+ 
+ # -- General configuration ---------------------------------------------------
+ 
+-- 
+1.7.6.5
+
diff --git a/0021-Don-t-access-the-net-while-building-docs.patch b/0021-Don-t-access-the-net-while-building-docs.patch
new file mode 100644
index 0000000..f069ea8
--- /dev/null
+++ b/0021-Don-t-access-the-net-while-building-docs.patch
@@ -0,0 +1,27 @@
+From 8a1b6b0825d3f9124644cb91fee53e3151c1a933 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?P=C3=A1draig=20Brady?= <pbrady at redhat.com>
+Date: Fri, 6 Jan 2012 17:12:54 +0000
+Subject: [PATCH] Don't access the net while building docs
+
+(Note this hasn't been submitted upstream)
+
+Change-Id: I42c6e3a5062db209a0abe00cebc04d383c79cbcb
+---
+ doc/source/conf.py |    1 -
+ 1 files changed, 0 insertions(+), 1 deletions(-)
+
+diff --git a/doc/source/conf.py b/doc/source/conf.py
+index 3ecbb03..98c6bba 100644
+--- a/doc/source/conf.py
++++ b/doc/source/conf.py
+@@ -45,7 +45,6 @@ sys.path = [os.path.abspath('../../glance'),
+ extensions = ['sphinx.ext.autodoc',
+               'sphinx.ext.coverage',
+               'sphinx.ext.ifconfig',
+-              'sphinx.ext.intersphinx',
+               'sphinx.ext.pngmath',
+               'sphinx.ext.graphviz',
+               'sphinx.ext.todo']
+-- 
+1.7.6.5
+
diff --git a/openstack-glance.spec b/openstack-glance.spec
index 7f6a291..1f51c99 100644
--- a/openstack-glance.spec
+++ b/openstack-glance.spec
@@ -1,7 +1,7 @@
 
 Name:             openstack-glance
 Version:          2011.3
-Release:          3%{?dist}
+Release:          4%{?dist}
 Summary:          OpenStack Image Service
 
 Group:            Applications/System
@@ -11,8 +11,38 @@ Source0:          http://launchpad.net/glance/diablo/%{version}/+download/glance
 Source1:          openstack-glance-api.service
 Source2:          openstack-glance-registry.service
 Source3:          openstack-glance.logrotate
-Patch0:           openstack-glance-docmod.patch
-Patch1:           openstack-glance-nonet.patch
+
+#
+# Patches managed here: https://github.com/markmc/glance/tree/fedora-patches
+#
+#   $> git format-patch -N 2011.3
+#   $> for p in 00*.patch; do filterdiff -x '*/.gitignore' -x '*/.mailmap' -x '*/Authors' -x '*/.bzrignore' $p | sponge $p; done
+#   $> for p in 00*.patch; do echo "Patch${p:2:2}:          $p"; done
+#   $> for p in 00*.patch; do echo "%patch${p:2:2} -p1"; done
+#
+
+# These are from stable/diablo
+Patch01:          0001-Point-tools-rfc.sh-at-the-correct-branch.patch
+Patch02:          0002-Fixes-LP-Bug-845788.patch
+Patch03:          0003-Fixes-LP-Bug-850685.patch
+Patch04:          0004-Make-remote-swift-image-streaming-functional.patch
+Patch05:          0005-Returning-functionality-of-s3-backend-to-stream-remo.patch
+Patch06:          0006-Fixes-LP-Bug-860862-Security-creds-still-shown.patch
+Patch07:          0007-Fixes-LP-Bug-872276-small-typo-in-error-message.patch
+Patch08:          0008-Better-document-using-Glance-with-Keystone.patch
+Patch09:          0009-Fixes-LP-Bug-844618-SQLAlchemy-errors-not-logged.patch
+Patch10:          0010-Add-.gitreview-config-file-for-gerrit.patch
+Patch11:          0011-Removed-mox-0.5.0-and-replaced-with-just-mox-in-tool.patch
+Patch12:          0012-Remove-location-from-POST-PUT-image-responses.patch
+Patch13:          0013-Fix-Keystone-API-skew-issue-with-Glance-client.patch
+Patch14:          0014-load-gettext-in-__init__-to-fix-_-is-not-defined.patch
+Patch15:          0015-Update-glance-show-to-print-a-valid-URI.-Fixes-bug-8.patch
+Patch16:          0016-Using-Keystone-s-new-port-number-35357.patch
+Patch17:          0017-Making-prefetcher-call-create_stores.patch
+Patch18:          0018-Add-a-LICENSE-file.patch
+Patch19:          0019-Rename-.glance-venv-to-.venv.patch
+Patch20:          0020-Always-reference-the-glance-module-from-the-package-.patch
+Patch21:          0021-Don-t-access-the-net-while-building-docs.patch
 
 BuildArch:        noarch
 BuildRequires:    python2-devel
@@ -91,8 +121,28 @@ This package contains documentation files for glance.
 
 %prep
 %setup -q -n glance-%{version}
-%patch0 -p1 -b .docmod
-%patch1 -p1 -b .nonet
+
+%patch01 -p1
+%patch02 -p1
+%patch03 -p1
+%patch04 -p1
+%patch05 -p1
+%patch06 -p1
+%patch07 -p1
+%patch08 -p1
+%patch09 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
+%patch14 -p1
+%patch15 -p1
+%patch16 -p1
+%patch17 -p1
+%patch18 -p1
+%patch19 -p1
+%patch20 -p1
+%patch21 -p1
 
 sed -i 's|\(sql_connection = sqlite:///\)\(glance.sqlite\)|\1%{_sharedstatedir}/glance/\2|' etc/glance-registry.conf
 
@@ -205,6 +255,9 @@ fi
 %doc doc/build/html
 
 %changelog
+* Fri Jan  6 2012 Mark McLoughlin <markmc at redhat.com> - 2011.3-4
+- Rebase to latest upstream stable/diablo branch adding ~20 patches
+
 * Tue Dec 20 2011 David Busby <oneiroi at fedoraproject.org> - 2011.3-3
 - Depend on python-httplib2
 


More information about the scm-commits mailing list