[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