diff options
author | Matthew Thode <prometheanfire@gentoo.org> | 2015-02-08 01:51:57 +0000 |
---|---|---|
committer | Matthew Thode <prometheanfire@gentoo.org> | 2015-02-08 01:51:57 +0000 |
commit | 4d2f7c4e3d15c4dd96bf9697666997a75aede7e2 (patch) | |
tree | 361598ca90e8cb9b483289a2be1dc7aafca436b9 /app-admin/glance | |
parent | signing (diff) | |
download | gentoo-2-4d2f7c4e3d15c4dd96bf9697666997a75aede7e2.tar.gz gentoo-2-4d2f7c4e3d15c4dd96bf9697666997a75aede7e2.tar.bz2 gentoo-2-4d2f7c4e3d15c4dd96bf9697666997a75aede7e2.zip |
bumping :D
(Portage version: 2.2.14/cvs/Linux x86_64, signed Manifest commit with key 0x33ED3FD25AFC78BA)
Diffstat (limited to 'app-admin/glance')
-rw-r--r-- | app-admin/glance/ChangeLog | 12 | ||||
-rw-r--r-- | app-admin/glance/files/0001-Prevent-file-swift-config-and-filesystem-schemes.patch | 119 | ||||
-rw-r--r-- | app-admin/glance/files/0001-To-prevent-client-use-v2-patch-api-to-handle-file-an.patch | 702 | ||||
-rw-r--r-- | app-admin/glance/files/glance-CVE-2014-9623.patch | 542 | ||||
-rw-r--r-- | app-admin/glance/glance-2014.2.2.ebuild | 162 | ||||
-rw-r--r-- | app-admin/glance/glance-2014.2.9999.ebuild | 99 | ||||
-rw-r--r-- | app-admin/glance/glance-9999.ebuild | 139 |
7 files changed, 215 insertions, 1560 deletions
diff --git a/app-admin/glance/ChangeLog b/app-admin/glance/ChangeLog index 053b821e95ab..a75e5352ed94 100644 --- a/app-admin/glance/ChangeLog +++ b/app-admin/glance/ChangeLog @@ -1,6 +1,16 @@ # ChangeLog for app-admin/glance # Copyright 1999-2015 Gentoo Foundation; Distributed under the GPL v2 -# $Header: /var/cvsroot/gentoo-x86/app-admin/glance/ChangeLog,v 1.58 2015/01/29 05:39:38 prometheanfire Exp $ +# $Header: /var/cvsroot/gentoo-x86/app-admin/glance/ChangeLog,v 1.59 2015/02/08 01:51:56 prometheanfire Exp $ + +*glance-2014.2.2 (08 Feb 2015) + + 08 Feb 2015; Matthew Thode <prometheanfire@gentoo.org> + +glance-2014.2.2.ebuild, + -files/0001-Prevent-file-swift-config-and-filesystem-schemes.patch, + -files/0001-To-prevent-client-use-v2-patch-api-to-handle-file-an.patch, + -files/glance-CVE-2014-9623.patch, -glance-9999.ebuild, + glance-2014.2.9999.ebuild: + bumping :D *glance-2014.2.1-r2 (29 Jan 2015) diff --git a/app-admin/glance/files/0001-Prevent-file-swift-config-and-filesystem-schemes.patch b/app-admin/glance/files/0001-Prevent-file-swift-config-and-filesystem-schemes.patch deleted file mode 100644 index 4cb999bd1279..000000000000 --- a/app-admin/glance/files/0001-Prevent-file-swift-config-and-filesystem-schemes.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 5191ed1879c5fd5b2694f922bcedec232f461088 Mon Sep 17 00:00:00 2001 -From: Grant Murphy <grant.murphy@hp.com> -Date: Wed, 7 Jan 2015 16:09:38 -0800 -Subject: [PATCH] Prevent file, swift+config and filesystem schemes - -This change ensures that 'file', 'filesystem', and 'swift+config' URI -schemes are not allowed when setting the location field. A previous -fix to CVE-2014-9493 attempted to address this issue but did not -include 'filesystem', a URI scheme allowed by the glance_store. - -Without this fix in place it is possible for a client to access any file -the glance-api server has read permissions for. - -Change-Id: I02cd099a8634b9c7e3cf8f172bcbd33f8edcbc83 -Closes-Bug: #1408663 -(cherry picked from commit a2d986b976e9325a272e2d422465165315d19fe6) ---- - glance/common/store_utils.py | 11 ++++++----- - glance/tests/unit/test_store_location.py | 3 +++ - glance/tests/unit/v1/test_api.py | 32 ++++++++++++-------------------- - 3 files changed, 21 insertions(+), 25 deletions(-) - -diff --git a/glance/common/store_utils.py b/glance/common/store_utils.py -index b7537ce..64cfa87 100644 ---- a/glance/common/store_utils.py -+++ b/glance/common/store_utils.py -@@ -38,6 +38,8 @@ store_utils_opts = [ - CONF = cfg.CONF - CONF.register_opts(store_utils_opts) - -+RESTRICTED_URI_SCHEMAS = frozenset(['file', 'filesystem', 'swift+config']) -+ - - def safe_delete_from_backend(context, image_id, location): - """ -@@ -136,8 +138,7 @@ def validate_external_location(uri): - """ - - # TODO(zhiyan): This function could be moved to glance_store. -- -- pieces = urlparse.urlparse(uri) -- valid_schemes = [scheme for scheme in store_api.get_known_schemes() -- if scheme != 'file' and scheme != 'swift+config'] -- return pieces.scheme in valid_schemes -+ # TODO(gm): Use a whitelist of allowed schemes -+ scheme = urlparse.urlparse(uri).scheme -+ return (scheme in store_api.get_known_schemes() and -+ scheme not in RESTRICTED_URI_SCHEMAS) -diff --git a/glance/tests/unit/test_store_location.py b/glance/tests/unit/test_store_location.py -index c9ee44c..efaecd8 100644 ---- a/glance/tests/unit/test_store_location.py -+++ b/glance/tests/unit/test_store_location.py -@@ -69,12 +69,15 @@ class TestStoreLocation(base.StoreClearingUnitTest): - - loc1 = {'url': 'file:///fake1.img.tar.gz', 'metadata': {}} - loc2 = {'url': 'swift+config:///xxx', 'metadata': {}} -+ loc3 = {'url': 'filesystem:///foo.img.tar.gz', 'metadata': {}} - - # Test for insert location - image1 = TestStoreLocation.FakeImageProxy() - locations = glance.location.StoreLocations(image1, []) - self.assertRaises(exception.BadStoreUri, locations.insert, 0, loc1) -+ self.assertRaises(exception.BadStoreUri, locations.insert, 0, loc3) - self.assertNotIn(loc1, locations) -+ self.assertNotIn(loc3, locations) - - # Test for set_attr of _locations_proxy - image2 = TestStoreLocation.FakeImageProxy() -diff --git a/glance/tests/unit/v1/test_api.py b/glance/tests/unit/v1/test_api.py -index 4ec136d..39e9a44 100644 ---- a/glance/tests/unit/v1/test_api.py -+++ b/glance/tests/unit/v1/test_api.py -@@ -1071,31 +1071,23 @@ class TestGlanceAPI(base.IsolatedUnitTest): - - def test_add_copy_from_with_restricted_sources(self): - """Tests creates an image from copy-from with restricted sources""" -- fixture_headers = {'x-image-meta-store': 'file', -+ header_template = {'x-image-meta-store': 'file', - 'x-image-meta-disk-format': 'vhd', -- 'x-glance-api-copy-from': 'file:///etc/passwd', - 'x-image-meta-container-format': 'ovf', - 'x-image-meta-name': 'fake image #F'} - -- req = webob.Request.blank("/images") -- req.method = 'POST' -- for k, v in six.iteritems(fixture_headers): -- req.headers[k] = v -- res = req.get_response(self.api) -- self.assertEqual(400, res.status_int) -+ schemas = ["file:///etc/passwd", -+ "swift+config:///xxx", -+ "filesystem:///etc/passwd"] - -- fixture_headers = {'x-image-meta-store': 'file', -- 'x-image-meta-disk-format': 'vhd', -- 'x-glance-api-copy-from': 'swift+config://xxx', -- 'x-image-meta-container-format': 'ovf', -- 'x-image-meta-name': 'fake image #F'} -- -- req = webob.Request.blank("/images") -- req.method = 'POST' -- for k, v in six.iteritems(fixture_headers): -- req.headers[k] = v -- res = req.get_response(self.api) -- self.assertEqual(400, res.status_int) -+ for schema in schemas: -+ req = webob.Request.blank("/images") -+ req.method = 'POST' -+ for k, v in six.iteritems(header_template): -+ req.headers[k] = v -+ req.headers['x-glance-api-copy-from'] = schema -+ res = req.get_response(self.api) -+ self.assertEqual(400, res.status_int) - - def test_add_copy_from_upload_image_unauthorized_with_body(self): - rules = {"upload_image": '!', "modify_image": '@', --- -2.0.5 - diff --git a/app-admin/glance/files/0001-To-prevent-client-use-v2-patch-api-to-handle-file-an.patch b/app-admin/glance/files/0001-To-prevent-client-use-v2-patch-api-to-handle-file-an.patch deleted file mode 100644 index 15b3d9a3a790..000000000000 --- a/app-admin/glance/files/0001-To-prevent-client-use-v2-patch-api-to-handle-file-an.patch +++ /dev/null @@ -1,702 +0,0 @@ -From d9a928eac360add67477e29f516af868adfe0d5e Mon Sep 17 00:00:00 2001 -From: Zhi Yan Liu <zhiyanl@cn.ibm.com> -Date: Mon, 15 Dec 2014 12:29:55 +0800 -Subject: [PATCH] To prevent client use v2 patch api to handle file and swift - location - -The change will be used to restrict client to download and delete any -file in glance-api server. The same resone and logic as what we did in -v1: -https://github.com/openstack/glance/blob/master/glance/api/v1/images.py#L429 - -Closes-Bug: bug/1400966 -DocImpact - -Note: Even this change could fully resolve the problem for Glance, but -we still need to fix this issue from glance_store perspective -separatelly due to other projects can use the lib directly. - -Conflicts: - glance/api/v1/images.py - glance/location.py - glance/tests/functional/v2/test_images.py - glance/tests/unit/test_store_location.py - glance/tests/unit/v1/test_api.py - -(cherry-picked from 4afdb017aa1ccef01482f117cb8d0736a6da38ed) -Signed-off-by: Zhi Yan Liu <zhiyanl@cn.ibm.com> -Change-Id: I72dbead3cb2dcb87f52658ddb880e26880cc229b ---- - glance/api/v1/images.py | 31 ++--- - glance/common/store_utils.py | 22 ++++ - glance/location.py | 30 +++-- - glance/tests/functional/v1/test_copy_to_file.py | 4 +- - glance/tests/functional/v2/test_images.py | 158 ++++++++++-------------- - glance/tests/unit/test_store_image.py | 3 +- - glance/tests/unit/test_store_location.py | 33 ++++- - glance/tests/unit/utils.py | 9 +- - glance/tests/unit/v1/test_api.py | 62 +++++++++- - 9 files changed, 221 insertions(+), 131 deletions(-) - -diff --git a/glance/api/v1/images.py b/glance/api/v1/images.py -index c85b301..746f8cd 100644 ---- a/glance/api/v1/images.py -+++ b/glance/api/v1/images.py -@@ -23,7 +23,6 @@ import eventlet - import glance_store as store - import glance_store.location - from oslo.config import cfg --import six.moves.urllib.parse as urlparse - from webob.exc import HTTPBadRequest - from webob.exc import HTTPConflict - from webob.exc import HTTPForbidden -@@ -40,6 +39,7 @@ from glance.api.v1 import filters - from glance.api.v1 import upload_utils - from glance.common import exception - from glance.common import property_utils -+from glance.common import store_utils - from glance.common import utils - from glance.common import wsgi - from glance.i18n import _LE -@@ -415,26 +415,19 @@ class Controller(controller.BaseController): - @staticmethod - def _validate_source(source, req): - """ -- External sources (as specified via the location or copy-from headers) -- are supported only over non-local store types, i.e. S3, Swift, HTTP. -- Note the absence of 'file://' for security reasons, see LP bug #942118. -- 'swift+config://' is also absent for security reasons, see LP bug -- #1334196. -- If the above constraint is violated, we reject with 400 "Bad Request". -+ To validate if external sources (as specified via the location -+ or copy-from headers) are supported. Otherwise we reject -+ with 400 "Bad Request". - """ - if source: -- pieces = urlparse.urlparse(source) -- schemes = [scheme for scheme in store.get_known_schemes() -- if scheme != 'file' and scheme != 'swift+config'] -- for scheme in schemes: -- if pieces.scheme == scheme: -- return source -- msg = ("External sourcing not supported for " -- "store '%s'" % pieces.scheme) -- LOG.debug(msg) -- raise HTTPBadRequest(explanation=msg, -- request=req, -- content_type="text/plain") -+ if store_utils.validate_external_location(source): -+ return source -+ else: -+ msg = _("External source are not supported: '%s'") % source -+ LOG.debug(msg) -+ raise HTTPBadRequest(explanation=msg, -+ request=req, -+ content_type="text/plain") - - @staticmethod - def _copy_from(req): -diff --git a/glance/common/store_utils.py b/glance/common/store_utils.py -index 8f04d39..b7537ce 100644 ---- a/glance/common/store_utils.py -+++ b/glance/common/store_utils.py -@@ -16,6 +16,7 @@ import sys - - import glance_store as store_api - from oslo.config import cfg -+import six.moves.urllib.parse as urlparse - - from glance.common import utils - import glance.db as db_api -@@ -119,3 +120,24 @@ def delete_image_location_from_backend(context, image_id, location): - # such as uploading process failure then we can't use - # location status mechanism to support image pending delete. - safe_delete_from_backend(context, image_id, location) -+ -+ -+def validate_external_location(uri): -+ """ -+ Validate if URI of external location are supported. -+ -+ Only over non-local store types are OK, i.e. S3, Swift, -+ HTTP. Note the absence of 'file://' for security reasons, -+ see LP bug #942118, 1400966, 'swift+config://' is also -+ absent for security reasons, see LP bug #1334196. -+ -+ :param uri: The URI of external image location. -+ :return: Whether given URI of external image location are OK. -+ """ -+ -+ # TODO(zhiyan): This function could be moved to glance_store. -+ -+ pieces = urlparse.urlparse(uri) -+ valid_schemes = [scheme for scheme in store_api.get_known_schemes() -+ if scheme != 'file' and scheme != 'swift+config'] -+ return pieces.scheme in valid_schemes -diff --git a/glance/location.py b/glance/location.py -index fcdba0a..f83fa7a 100644 ---- a/glance/location.py -+++ b/glance/location.py -@@ -66,18 +66,20 @@ class ImageRepoProxy(glance.domain.proxy.Repo): - return result - - --def _check_location_uri(context, store_api, uri): -+def _check_location_uri(context, store_api, store_utils, uri): - """Check if an image location is valid. - - :param context: Glance request context - :param store_api: store API module -+ :param store_utils: store utils module - :param uri: location's uri string - """ -+ - is_ok = True - try: -- size = store_api.get_size_from_backend(uri, context=context) - # NOTE(zhiyan): Some stores return zero when it catch exception -- is_ok = size > 0 -+ is_ok = (store_utils.validate_external_location(uri) and -+ store_api.get_size_from_backend(uri, context=context) > 0) - except (store.UnknownScheme, store.NotFound): - is_ok = False - if not is_ok: -@@ -85,8 +87,8 @@ def _check_location_uri(context, store_api, uri): - raise exception.BadStoreUri(message=reason) - - --def _check_image_location(context, store_api, location): -- _check_location_uri(context, store_api, location['url']) -+def _check_image_location(context, store_api, store_utils, location): -+ _check_location_uri(context, store_api, store_utils, location['url']) - store_api.check_location_metadata(location['metadata']) - - -@@ -122,6 +124,7 @@ class ImageFactoryProxy(glance.domain.proxy.ImageFactory): - def __init__(self, factory, context, store_api, store_utils): - self.context = context - self.store_api = store_api -+ self.store_utils = store_utils - proxy_kwargs = {'context': context, 'store_api': store_api, - 'store_utils': store_utils} - super(ImageFactoryProxy, self).__init__(factory, -@@ -131,7 +134,10 @@ class ImageFactoryProxy(glance.domain.proxy.ImageFactory): - def new_image(self, **kwargs): - locations = kwargs.get('locations', []) - for loc in locations: -- _check_image_location(self.context, self.store_api, loc) -+ _check_image_location(self.context, -+ self.store_api, -+ self.store_utils, -+ loc) - loc['status'] = 'active' - if _count_duplicated_locations(locations, loc) > 1: - raise exception.DuplicateLocation(location=loc['url']) -@@ -169,7 +175,9 @@ class StoreLocations(collections.MutableSequence): - - def insert(self, i, location): - _check_image_location(self.image_proxy.context, -- self.image_proxy.store_api, location) -+ self.image_proxy.store_api, -+ self.image_proxy.store_utils, -+ location) - location['status'] = 'active' - if _count_duplicated_locations(self.value, location) > 0: - raise exception.DuplicateLocation(location=location['url']) -@@ -214,7 +222,9 @@ class StoreLocations(collections.MutableSequence): - - def __setitem__(self, i, location): - _check_image_location(self.image_proxy.context, -- self.image_proxy.store_api, location) -+ self.image_proxy.store_api, -+ self.image_proxy.store_utils, -+ location) - location['status'] = 'active' - self.value.__setitem__(i, location) - _set_image_size(self.image_proxy.context, -@@ -303,7 +313,9 @@ def _locations_proxy(target, attr): - '%s') % ori_value) - # NOTE(zhiyan): Check locations are all valid. - for location in value: -- _check_image_location(self.context, self.store_api, -+ _check_image_location(self.context, -+ self.store_api, -+ self.store_utils, - location) - location['status'] = 'active' - if _count_duplicated_locations(value, location) > 1: -diff --git a/glance/tests/functional/v1/test_copy_to_file.py b/glance/tests/functional/v1/test_copy_to_file.py -index 15bb708..b64eac6 100644 ---- a/glance/tests/functional/v1/test_copy_to_file.py -+++ b/glance/tests/functional/v1/test_copy_to_file.py -@@ -250,7 +250,7 @@ class TestCopyToFile(functional.FunctionalTest): - response, content = http.request(path, 'POST', headers=headers) - self.assertEqual(response.status, 400, content) - -- expected = 'External sourcing not supported for store \'file\'' -+ expected = 'External source are not supported: \'%s\'' % copy_from - msg = 'expected "%s" in "%s"' % (expected, content) - self.assertTrue(expected in content, msg) - -@@ -276,7 +276,7 @@ class TestCopyToFile(functional.FunctionalTest): - response, content = http.request(path, 'POST', headers=headers) - self.assertEqual(response.status, 400, content) - -- expected = 'External sourcing not supported for store \'swift+config\'' -+ expected = 'External source are not supported: \'swift+config://xxx\'' - msg = 'expected "%s" in "%s"' % (expected, content) - self.assertTrue(expected in content, msg) - -diff --git a/glance/tests/functional/v2/test_images.py b/glance/tests/functional/v2/test_images.py -index 14fe3c7..4c32375 100644 ---- a/glance/tests/functional/v2/test_images.py -+++ b/glance/tests/functional/v2/test_images.py -@@ -16,7 +16,6 @@ - import BaseHTTPServer - import os - import signal --import tempfile - import uuid - - import requests -@@ -47,7 +46,7 @@ def get_handler_class(fixture): - self.end_headers() - return - -- def log_message(*args, **kwargs): -+ def log_message(self, *args, **kwargs): - # Override this method to prevent debug output from going - # to stderr during testing - return -@@ -75,6 +74,18 @@ class TestImages(functional.FunctionalTest): - self.cleanup() - self.api_server.deployment_flavor = 'noauth' - self.api_server.data_api = 'glance.db.sqlalchemy.api' -+ for i in range(3): -+ ret = http_server("foo_image_id%d" % i, "foo_image%d" % i) -+ setattr(self, 'http_server%d_pid' % i, ret[0]) -+ setattr(self, 'http_port%d' % i, ret[1]) -+ -+ def tearDown(self): -+ for i in range(3): -+ pid = getattr(self, 'http_server%d_pid' % i, None) -+ if pid: -+ os.kill(pid, signal.SIGKILL) -+ -+ super(TestImages, self).tearDown() - - def _url(self, path): - return 'http://127.0.0.1:%d%s' % (self.api_port, path) -@@ -329,21 +340,15 @@ class TestImages(functional.FunctionalTest): - self.assertEqual(413, response.status_code, response.text) - - # Adding 3 image locations should fail since configured limit is 2 -- for i in range(3): -- file_path = os.path.join(self.test_dir, 'fake_image_%i' % i) -- with open(file_path, 'w') as fap: -- fap.write('glance') -- - path = self._url('/v2/images/%s' % image_id) - media_type = 'application/openstack-images-v2.1-json-patch' - headers = self._headers({'content-type': media_type}) - changes = [] - for i in range(3): -+ url = ('http://127.0.0.1:%s/foo_image' % -+ getattr(self, 'http_port%d' % i)) - changes.append({'op': 'add', 'path': '/locations/-', -- 'value': {'url': 'file://{0}'.format( -- os.path.join(self.test_dir, -- 'fake_image_%i' % i)), -- 'metadata': {}}, -+ 'value': {'url': url, 'metadata': {}}, - }) - - data = jsonutils.dumps(changes) -@@ -2176,17 +2181,14 @@ class TestImages(functional.FunctionalTest): - self.assertNotIn('size', image) - self.assertNotIn('virtual_size', image) - -- file_path = os.path.join(self.test_dir, 'fake_image') -- with open(file_path, 'w') as fap: -- fap.write('glance') -- - # Update locations for the queued image - path = self._url('/v2/images/%s' % image_id) - media_type = 'application/openstack-images-v2.1-json-patch' - headers = self._headers({'content-type': media_type}) -+ url = 'http://127.0.0.1:%s/foo_image' % self.http_port0 - data = jsonutils.dumps([{'op': 'replace', 'path': '/locations', -- 'value': [{'url': 'file://' + file_path, -- 'metadata': {}}]}]) -+ 'value': [{'url': url, 'metadata': {}}] -+ }]) - response = requests.patch(path, headers=headers, data=data) - self.assertEqual(200, response.status_code, response.text) - -@@ -2195,7 +2197,42 @@ class TestImages(functional.FunctionalTest): - response = requests.get(path, headers=headers) - self.assertEqual(200, response.status_code) - image = jsonutils.loads(response.text) -- self.assertEqual(image['size'], 6) -+ self.assertEqual(image['size'], 10) -+ -+ def test_update_locations_with_restricted_sources(self): -+ self.start_servers(**self.__dict__.copy()) -+ # Create an image -+ path = self._url('/v2/images') -+ headers = self._headers({'content-type': 'application/json'}) -+ data = jsonutils.dumps({'name': 'image-1', 'disk_format': 'aki', -+ 'container_format': 'aki'}) -+ response = requests.post(path, headers=headers, data=data) -+ self.assertEqual(201, response.status_code) -+ -+ # Returned image entity should have a generated id and status -+ image = jsonutils.loads(response.text) -+ image_id = image['id'] -+ self.assertEqual('queued', image['status']) -+ self.assertNotIn('size', image) -+ self.assertNotIn('virtual_size', image) -+ -+ # Update locations for the queued image -+ path = self._url('/v2/images/%s' % image_id) -+ media_type = 'application/openstack-images-v2.1-json-patch' -+ headers = self._headers({'content-type': media_type}) -+ data = jsonutils.dumps([{'op': 'replace', 'path': '/locations', -+ 'value': [{'url': 'file:///foo_image', -+ 'metadata': {}}] -+ }]) -+ response = requests.patch(path, headers=headers, data=data) -+ self.assertEqual(400, response.status_code, response.text) -+ -+ data = jsonutils.dumps([{'op': 'replace', 'path': '/locations', -+ 'value': [{'url': 'swift+config:///foo_image', -+ 'metadata': {}}] -+ }]) -+ response = requests.patch(path, headers=headers, data=data) -+ self.assertEqual(400, response.status_code, response.text) - - - class TestImagesWithRegistry(TestImages): -@@ -2421,16 +2458,16 @@ class TestImageLocationSelectionStrategy(functional.FunctionalTest): - super(TestImageLocationSelectionStrategy, self).setUp() - self.cleanup() - self.api_server.deployment_flavor = 'noauth' -- self.foo_image_file = tempfile.NamedTemporaryFile() -- self.foo_image_file.write("foo image file") -- self.foo_image_file.flush() -- self.addCleanup(self.foo_image_file.close) -- ret = http_server("foo_image_id", "foo_image") -- self.http_server_pid, self.http_port = ret -+ for i in range(3): -+ ret = http_server("foo_image_id%d" % i, "foo_image%d" % i) -+ setattr(self, 'http_server%d_pid' % i, ret[0]) -+ setattr(self, 'http_port%d' % i, ret[1]) - - def tearDown(self): -- if self.http_server_pid is not None: -- os.kill(self.http_server_pid, signal.SIGKILL) -+ for i in range(3): -+ pid = getattr(self, 'http_server%d_pid' % i, None) -+ if pid: -+ os.kill(pid, signal.SIGKILL) - - super(TestImageLocationSelectionStrategy, self).tearDown() - -@@ -2483,69 +2520,10 @@ class TestImageLocationSelectionStrategy(functional.FunctionalTest): - path = self._url('/v2/images/%s' % image_id) - media_type = 'application/openstack-images-v2.1-json-patch' - headers = self._headers({'content-type': media_type}) -- values = [{'url': 'file://%s' % self.foo_image_file.name, -- 'metadata': {'idx': '1'}}, -- {'url': 'http://127.0.0.1:%s/foo_image' % self.http_port, -- 'metadata': {'idx': '0'}}] -- doc = [{'op': 'replace', -- 'path': '/locations', -- 'value': values}] -- data = jsonutils.dumps(doc) -- response = requests.patch(path, headers=headers, data=data) -- self.assertEqual(200, response.status_code) -- -- # Image locations should be visible -- path = self._url('/v2/images/%s' % image_id) -- headers = self._headers({'Content-Type': 'application/json'}) -- response = requests.get(path, headers=headers) -- self.assertEqual(200, response.status_code) -- image = jsonutils.loads(response.text) -- self.assertTrue('locations' in image) -- self.assertEqual(image['locations'], values) -- self.assertTrue('direct_url' in image) -- self.assertEqual(image['direct_url'], values[0]['url']) -- -- self.stop_servers() -- -- def test_image_locatons_with_store_type_strategy(self): -- self.api_server.show_image_direct_url = True -- self.api_server.show_multiple_locations = True -- self.image_location_quota = 10 -- self.api_server.location_strategy = 'store_type' -- preference = "http, swift, filesystem" -- self.api_server.store_type_location_strategy_preference = preference -- self.start_servers(**self.__dict__.copy()) -- -- # Create an image -- path = self._url('/v2/images') -- headers = self._headers({'content-type': 'application/json'}) -- data = jsonutils.dumps({'name': 'image-1', 'type': 'kernel', -- 'foo': 'bar', 'disk_format': 'aki', -- 'container_format': 'aki'}) -- response = requests.post(path, headers=headers, data=data) -- self.assertEqual(201, response.status_code) -- -- # Get the image id -- image = jsonutils.loads(response.text) -- image_id = image['id'] -- -- # Image locations should not be visible before location is set -- path = self._url('/v2/images/%s' % image_id) -- headers = self._headers({'Content-Type': 'application/json'}) -- response = requests.get(path, headers=headers) -- self.assertEqual(200, response.status_code) -- image = jsonutils.loads(response.text) -- self.assertTrue('locations' in image) -- self.assertTrue(image["locations"] == []) -- -- # Update image locations via PATCH -- path = self._url('/v2/images/%s' % image_id) -- media_type = 'application/openstack-images-v2.1-json-patch' -- headers = self._headers({'content-type': media_type}) -- values = [{'url': 'file://%s' % self.foo_image_file.name, -- 'metadata': {'idx': '1'}}, -- {'url': 'http://127.0.0.1:%s/foo_image' % self.http_port, -- 'metadata': {'idx': '0'}}] -+ values = [{'url': 'http://127.0.0.1:%s/foo_image' % self.http_port0, -+ 'metadata': {}}, -+ {'url': 'http://127.0.0.1:%s/foo_image' % self.http_port1, -+ 'metadata': {}}] - doc = [{'op': 'replace', - 'path': '/locations', - 'value': values}] -@@ -2553,8 +2531,6 @@ class TestImageLocationSelectionStrategy(functional.FunctionalTest): - response = requests.patch(path, headers=headers, data=data) - self.assertEqual(200, response.status_code) - -- values.sort(key=lambda loc: int(loc['metadata']['idx'])) -- - # Image locations should be visible - path = self._url('/v2/images/%s' % image_id) - headers = self._headers({'Content-Type': 'application/json'}) -diff --git a/glance/tests/unit/test_store_image.py b/glance/tests/unit/test_store_image.py -index 665f126..8b334ab 100644 ---- a/glance/tests/unit/test_store_image.py -+++ b/glance/tests/unit/test_store_image.py -@@ -18,6 +18,7 @@ import glance_store - - from glance.common import exception - import glance.location -+from glance.tests.unit import base as unit_test_base - from glance.tests.unit import utils as unit_test_utils - from glance.tests import utils - -@@ -759,7 +760,7 @@ class TestStoreImageRepo(utils.BaseTestCase): - self.assertEqual(acls['read'], [TENANT2]) - - --class TestImageFactory(utils.BaseTestCase): -+class TestImageFactory(unit_test_base.StoreClearingUnitTest): - - def setUp(self): - super(TestImageFactory, self).setUp() -diff --git a/glance/tests/unit/test_store_location.py b/glance/tests/unit/test_store_location.py -index 884221b..c9ee44c 100644 ---- a/glance/tests/unit/test_store_location.py -+++ b/glance/tests/unit/test_store_location.py -@@ -17,6 +17,8 @@ import mock - - import glance_store - -+from glance.common import exception -+from glance.common import store_utils - import glance.location - from glance.tests.unit import base - -@@ -32,11 +34,13 @@ CONF = {'default_store': 'file', - - class TestStoreLocation(base.StoreClearingUnitTest): - -+ class FakeImageProxy(): -+ size = None -+ context = None -+ store_api = mock.Mock() -+ store_utils = store_utils -+ - def test_add_location_for_image_without_size(self): -- class FakeImageProxy(): -- size = None -- context = None -- store_api = mock.Mock() - - def fake_get_size_from_backend(uri, context=None): - return 1 -@@ -49,14 +53,31 @@ class TestStoreLocation(base.StoreClearingUnitTest): - loc2 = {'url': 'file:///fake2.img.tar.gz', 'metadata': {}} - - # Test for insert location -- image1 = FakeImageProxy() -+ image1 = TestStoreLocation.FakeImageProxy() - locations = glance.location.StoreLocations(image1, []) - locations.insert(0, loc2) - self.assertEqual(image1.size, 1) - - # Test for set_attr of _locations_proxy -- image2 = FakeImageProxy() -+ image2 = TestStoreLocation.FakeImageProxy() - locations = glance.location.StoreLocations(image2, [loc1]) - locations[0] = loc2 - self.assertIn(loc2, locations) - self.assertEqual(image2.size, 1) -+ -+ def test_add_location_with_restricted_sources(self): -+ -+ loc1 = {'url': 'file:///fake1.img.tar.gz', 'metadata': {}} -+ loc2 = {'url': 'swift+config:///xxx', 'metadata': {}} -+ -+ # Test for insert location -+ image1 = TestStoreLocation.FakeImageProxy() -+ locations = glance.location.StoreLocations(image1, []) -+ self.assertRaises(exception.BadStoreUri, locations.insert, 0, loc1) -+ self.assertNotIn(loc1, locations) -+ -+ # Test for set_attr of _locations_proxy -+ image2 = TestStoreLocation.FakeImageProxy() -+ locations = glance.location.StoreLocations(image2, [loc1]) -+ self.assertRaises(exception.BadStoreUri, locations.insert, 0, loc2) -+ self.assertNotIn(loc2, locations) -diff --git a/glance/tests/unit/utils.py b/glance/tests/unit/utils.py -index df59160..f7c8d56 100644 ---- a/glance/tests/unit/utils.py -+++ b/glance/tests/unit/utils.py -@@ -14,12 +14,13 @@ - # under the License. - - import urllib --import urlparse - - import glance_store as store - from oslo.config import cfg -+import six.moves.urllib.parse as urlparse - - from glance.common import exception -+from glance.common import store_utils - from glance.common import wsgi - import glance.context - import glance.db.simple.api as simple_db -@@ -135,6 +136,12 @@ class FakeStoreUtils(object): - else: - self.safe_delete_from_backend(context, image_id, location) - -+ def validate_external_location(self, uri): -+ if uri and urlparse.urlparse(uri).scheme: -+ return store_utils.validate_external_location(uri) -+ else: -+ return True -+ - - class FakeStoreAPI(object): - def __init__(self, store_metadata=None): -diff --git a/glance/tests/unit/v1/test_api.py b/glance/tests/unit/v1/test_api.py -index bd2182e..4ec136d 100644 ---- a/glance/tests/unit/v1/test_api.py -+++ b/glance/tests/unit/v1/test_api.py -@@ -419,7 +419,7 @@ class TestGlanceAPI(base.IsolatedUnitTest): - - res = req.get_response(self.api) - self.assertEqual(res.status_int, 400) -- self.assertIn('External sourcing not supported', res.body) -+ self.assertIn('External source are not supported', res.body) - - def test_create_with_location_bad_store_uri(self): - fixture_headers = { -@@ -1006,7 +1006,7 @@ class TestGlanceAPI(base.IsolatedUnitTest): - res = req.get_response(self.api) - self.assertEqual(res.status_int, 409) - -- def test_add_location_with_invalid_location(self): -+ def test_add_location_with_invalid_location_on_conflict_image_size(self): - """Tests creates an image from location and conflict image size""" - fixture_headers = {'x-image-meta-store': 'file', - 'x-image-meta-disk-format': 'vhd', -@@ -1023,6 +1023,36 @@ class TestGlanceAPI(base.IsolatedUnitTest): - res = req.get_response(self.api) - self.assertEqual(res.status_int, 400) - -+ def test_add_location_with_invalid_location_on_restricted_sources(self): -+ """Tests creates an image from location and restricted sources""" -+ fixture_headers = {'x-image-meta-store': 'file', -+ 'x-image-meta-disk-format': 'vhd', -+ 'x-image-meta-location': 'file:///etc/passwd', -+ 'x-image-meta-container-format': 'ovf', -+ 'x-image-meta-name': 'fake image #F'} -+ -+ req = webob.Request.blank("/images") -+ req.headers['Content-Type'] = 'application/octet-stream' -+ req.method = 'POST' -+ for k, v in fixture_headers.iteritems(): -+ req.headers[k] = v -+ res = req.get_response(self.api) -+ self.assertEqual(400, res.status_int) -+ -+ fixture_headers = {'x-image-meta-store': 'file', -+ 'x-image-meta-disk-format': 'vhd', -+ 'x-image-meta-location': 'swift+config://xxx', -+ 'x-image-meta-container-format': 'ovf', -+ 'x-image-meta-name': 'fake image #F'} -+ -+ req = webob.Request.blank("/images") -+ req.headers['Content-Type'] = 'application/octet-stream' -+ req.method = 'POST' -+ for k, v in fixture_headers.iteritems(): -+ req.headers[k] = v -+ res = req.get_response(self.api) -+ self.assertEqual(400, res.status_int) -+ - def test_add_copy_from_with_location(self): - """Tests creates an image from copy-from and location""" - fixture_headers = {'x-image-meta-store': 'file', -@@ -1039,6 +1069,34 @@ class TestGlanceAPI(base.IsolatedUnitTest): - res = req.get_response(self.api) - self.assertEqual(res.status_int, 400) - -+ def test_add_copy_from_with_restricted_sources(self): -+ """Tests creates an image from copy-from with restricted sources""" -+ fixture_headers = {'x-image-meta-store': 'file', -+ 'x-image-meta-disk-format': 'vhd', -+ 'x-glance-api-copy-from': 'file:///etc/passwd', -+ 'x-image-meta-container-format': 'ovf', -+ 'x-image-meta-name': 'fake image #F'} -+ -+ req = webob.Request.blank("/images") -+ req.method = 'POST' -+ for k, v in six.iteritems(fixture_headers): -+ req.headers[k] = v -+ res = req.get_response(self.api) -+ self.assertEqual(400, res.status_int) -+ -+ fixture_headers = {'x-image-meta-store': 'file', -+ 'x-image-meta-disk-format': 'vhd', -+ 'x-glance-api-copy-from': 'swift+config://xxx', -+ 'x-image-meta-container-format': 'ovf', -+ 'x-image-meta-name': 'fake image #F'} -+ -+ req = webob.Request.blank("/images") -+ req.method = 'POST' -+ for k, v in six.iteritems(fixture_headers): -+ req.headers[k] = v -+ res = req.get_response(self.api) -+ self.assertEqual(400, res.status_int) -+ - def test_add_copy_from_upload_image_unauthorized_with_body(self): - rules = {"upload_image": '!', "modify_image": '@', - "add_image": '@'} --- -2.0.5 - diff --git a/app-admin/glance/files/glance-CVE-2014-9623.patch b/app-admin/glance/files/glance-CVE-2014-9623.patch deleted file mode 100644 index a9cc123f9ceb..000000000000 --- a/app-admin/glance/files/glance-CVE-2014-9623.patch +++ /dev/null @@ -1,542 +0,0 @@ -From 7d5d8657fd70b20518610b3c6f8e41e16c72fa31 Mon Sep 17 00:00:00 2001 -From: Zhi Yan Liu <zhiyanl@cn.ibm.com> -Date: Tue, 30 Dec 2014 22:25:50 +0800 -Subject: [PATCH] Cleanup chunks for deleted image that was 'saving' - -Currently image data cannot be removed synchronously for an image that -is in saving state. And when, the upload operation for such an image is -completed the operator configured quota can be exceeded. - -This patch fixes the issue of left over chunks for an image which was -deleted from saving status. However, by the limitation of the design we -cannot enforce a global quota check for the image in saving status. - -This change introduces a inconsonance between http response codes of -v1 and v2 APIs. The status codes which we will now see after the upload -process completes on an image which was deleted mid way are: - -v1: 412 Precondition Failed -v2: 410 Gone - -SecurityImpact -UpgradeImpact -APIImpact - -Closes-Bug: 1383973 -Closes-Bug: 1398830 -Closes-Bug: 1188532 - -Conflicts: - glance/api/v1/upload_utils.py - glance/api/v2/image_data.py - glance/tests/unit/test_domain_proxy.py - glance/tests/unit/v1/test_api.py - -Change-Id: I47229b366c25367ec1bd48aec684e0880f3dfe60 -Signed-off-by: Zhi Yan Liu <zhiyanl@cn.ibm.com> -(cherry picked from commit 0dc8fbb3479a53c5bba8475d14f4c7206904c5ea) ---- - glance/api/authorization.py | 4 +- - glance/api/policy.py | 8 ++-- - glance/api/v1/upload_utils.py | 19 +++++--- - glance/api/v2/image_data.py | 8 +++- - glance/db/__init__.py | 7 +-- - glance/domain/proxy.py | 4 +- - glance/location.py | 4 +- - glance/notifier.py | 4 +- - glance/quota/__init__.py | 4 +- - glance/tests/unit/test_domain_proxy.py | 14 +++--- - glance/tests/unit/test_policy.py | 2 +- - glance/tests/unit/test_quota.py | 17 ++++--- - glance/tests/unit/test_store_image.py | 2 +- - glance/tests/unit/v1/test_api.py | 57 +++++++++++------------- - glance/tests/unit/v2/test_image_data_resource.py | 24 +++++----- - 15 files changed, 98 insertions(+), 80 deletions(-) - -diff --git a/glance/api/authorization.py b/glance/api/authorization.py -index 149ff55..77f7ed3 100644 ---- a/glance/api/authorization.py -+++ b/glance/api/authorization.py -@@ -158,10 +158,10 @@ class ImageMemberRepoProxy(glance.domain.proxy.Repo): - raise exception.Forbidden(message - % self.image.image_id) - -- def save(self, image_member): -+ def save(self, image_member, from_state=None): - if (self.context.is_admin or - self.context.owner == image_member.member_id): -- self.member_repo.save(image_member) -+ self.member_repo.save(image_member, from_state=from_state) - else: - message = _("You cannot update image member %s") - raise exception.Forbidden(message % image_member.member_id) -diff --git a/glance/api/policy.py b/glance/api/policy.py -index 0bc8d56..e395876 100644 ---- a/glance/api/policy.py -+++ b/glance/api/policy.py -@@ -182,9 +182,9 @@ class ImageRepoProxy(glance.domain.proxy.Repo): - self.policy.enforce(self.context, 'get_images', {}) - return super(ImageRepoProxy, self).list(*args, **kwargs) - -- def save(self, image): -+ def save(self, image, from_state=None): - self.policy.enforce(self.context, 'modify_image', {}) -- return super(ImageRepoProxy, self).save(image) -+ return super(ImageRepoProxy, self).save(image, from_state=from_state) - - def add(self, image): - self.policy.enforce(self.context, 'add_image', {}) -@@ -285,9 +285,9 @@ class ImageMemberRepoProxy(glance.domain.proxy.Repo): - self.policy.enforce(self.context, 'get_member', {}) - return self.member_repo.get(member_id) - -- def save(self, member): -+ def save(self, member, from_state=None): - self.policy.enforce(self.context, 'modify_member', {}) -- self.member_repo.save(member) -+ self.member_repo.save(member, from_state=from_state) - - def list(self, *args, **kwargs): - self.policy.enforce(self.context, 'get_members', {}) -diff --git a/glance/api/v1/upload_utils.py b/glance/api/v1/upload_utils.py -index 8a190fc..60c3d3d 100644 ---- a/glance/api/v1/upload_utils.py -+++ b/glance/api/v1/upload_utils.py -@@ -153,12 +153,19 @@ def upload_data_to_store(req, image_meta, image_data, store, notifier): - update_data = {'checksum': checksum, - 'size': size} - try: -- image_meta = registry.update_image_metadata(req.context, -- image_id, -- update_data, -- from_state='saving') -- -- except exception.NotFound as e: -+ try: -+ state = 'saving' -+ image_meta = registry.update_image_metadata(req.context, -+ image_id, -+ update_data, -+ from_state=state) -+ except exception.Duplicate: -+ image = registry.get_image_metadata(req.context, image_id) -+ if image['status'] == 'deleted': -+ raise exception.NotFound() -+ else: -+ raise -+ except exception.NotFound: - msg = _LI("Image %s could not be found after upload. The image may" - " have been deleted during the upload.") % image_id - LOG.info(msg) -diff --git a/glance/api/v2/image_data.py b/glance/api/v2/image_data.py -index 430ffc5..cdfa34b 100644 ---- a/glance/api/v2/image_data.py -+++ b/glance/api/v2/image_data.py -@@ -73,8 +73,8 @@ class ImageDataController(object): - try: - image_repo.save(image) - image.set_data(data, size) -- image_repo.save(image) -- except exception.NotFound as e: -+ image_repo.save(image, from_state='saving') -+ except (exception.NotFound, exception.Conflict) as e: - msg = (_("Image %(id)s could not be found after upload." - "The image may have been deleted during the upload: " - "%(error)s Cleaning up the chunks uploaded") % -@@ -152,6 +152,10 @@ class ImageDataController(object): - raise webob.exc.HTTPServiceUnavailable(explanation=msg, - request=req) - -+ except webob.exc.HTTPGone as e: -+ with excutils.save_and_reraise_exception(): -+ LOG.error(_LE("Failed to upload image data due to HTTP error")) -+ - except webob.exc.HTTPError as e: - with excutils.save_and_reraise_exception(): - LOG.error(_LE("Failed to upload image data due to HTTP error")) -diff --git a/glance/db/__init__.py b/glance/db/__init__.py -index 05db7f8..483ba21 100644 ---- a/glance/db/__init__.py -+++ b/glance/db/__init__.py -@@ -164,7 +164,7 @@ class ImageRepo(object): - image.created_at = new_values['created_at'] - image.updated_at = new_values['updated_at'] - -- def save(self, image): -+ def save(self, image, from_state=None): - image_values = self._format_image_to_db(image) - if image_values['size'] > CONF.image_size_cap: - raise exception.ImageSizeLimitExceeded -@@ -172,7 +172,8 @@ class ImageRepo(object): - new_values = self.db_api.image_update(self.context, - image.image_id, - image_values, -- purge_props=True) -+ purge_props=True, -+ from_state=from_state) - except (exception.NotFound, exception.Forbidden): - msg = _("No image found with ID %s") % image.image_id - raise exception.NotFound(msg) -@@ -265,7 +266,7 @@ class ImageMemberRepo(object): - msg = _("The specified member %s could not be found") - raise exception.NotFound(msg % image_member.id) - -- def save(self, image_member): -+ def save(self, image_member, from_state=None): - image_member_values = self._format_image_member_to_db(image_member) - try: - new_values = self.db_api.image_member_update(self.context, -diff --git a/glance/domain/proxy.py b/glance/domain/proxy.py -index 5a91d34..09c0fb2 100644 ---- a/glance/domain/proxy.py -+++ b/glance/domain/proxy.py -@@ -94,9 +94,9 @@ class Repo(object): - result = self.base.add(base_item) - return self.helper.proxy(result) - -- def save(self, item): -+ def save(self, item, from_state=None): - base_item = self.helper.unproxy(item) -- result = self.base.save(base_item) -+ result = self.base.save(base_item, from_state=from_state) - return self.helper.proxy(result) - - def remove(self, item): -diff --git a/glance/location.py b/glance/location.py -index f83fa7a..b49546d 100644 ---- a/glance/location.py -+++ b/glance/location.py -@@ -60,8 +60,8 @@ class ImageRepoProxy(glance.domain.proxy.Repo): - self._set_acls(image) - return result - -- def save(self, image): -- result = super(ImageRepoProxy, self).save(image) -+ def save(self, image, from_state=None): -+ result = super(ImageRepoProxy, self).save(image, from_state=from_state) - self._set_acls(image) - return result - -diff --git a/glance/notifier.py b/glance/notifier.py -index 5ec0854..21223da 100644 ---- a/glance/notifier.py -+++ b/glance/notifier.py -@@ -122,8 +122,8 @@ class ImageRepoProxy(glance.domain.proxy.Repo): - item_proxy_class=ImageProxy, - item_proxy_kwargs=proxy_kwargs) - -- def save(self, image): -- super(ImageRepoProxy, self).save(image) -+ def save(self, image, from_state=None): -+ super(ImageRepoProxy, self).save(image, from_state=from_state) - self.notifier.info('image.update', - format_image_notification(image)) - -diff --git a/glance/quota/__init__.py b/glance/quota/__init__.py -index 4051992..d628a8c 100644 ---- a/glance/quota/__init__.py -+++ b/glance/quota/__init__.py -@@ -104,10 +104,10 @@ class ImageRepoProxy(glance.domain.proxy.Repo): - LOG.debug(six.text_type(exc)) - raise exc - -- def save(self, image): -+ def save(self, image, from_state=None): - if image.added_new_properties(): - self._enforce_image_property_quota(len(image.extra_properties)) -- return super(ImageRepoProxy, self).save(image) -+ return super(ImageRepoProxy, self).save(image, from_state=from_state) - - def add(self, image): - self._enforce_image_property_quota(len(image.extra_properties)) -diff --git a/glance/tests/unit/test_domain_proxy.py b/glance/tests/unit/test_domain_proxy.py -index 1bb6863..2b8f792 100644 ---- a/glance/tests/unit/test_domain_proxy.py -+++ b/glance/tests/unit/test_domain_proxy.py -@@ -74,7 +74,7 @@ class TestProxyRepoPlain(test_utils.BaseTestCase): - self._test_method('add', 'snuff', 'enough') - - def test_save(self): -- self._test_method('save', 'snuff', 'enough') -+ self._test_method('save', 'snuff', 'enough', from_state=None) - - def test_remove(self): - self._test_method('add', None, 'flying') -@@ -121,14 +121,14 @@ class TestProxyRepoWrapping(test_utils.BaseTestCase): - self.assertEqual(results[i].args, tuple()) - self.assertEqual(results[i].kwargs, {'a': 1}) - -- def _test_method_with_proxied_argument(self, name, result): -+ def _test_method_with_proxied_argument(self, name, result, **kwargs): - self.fake_repo.result = result - item = FakeProxy('snoop') - method = getattr(self.proxy_repo, name) - proxy_result = method(item) - -- self.assertEqual(self.fake_repo.args, ('snoop',)) -- self.assertEqual(self.fake_repo.kwargs, {}) -+ self.assertEqual(('snoop',), self.fake_repo.args) -+ self.assertEqual(kwargs, self.fake_repo.kwargs) - - if result is None: - self.assertIsNone(proxy_result) -@@ -145,10 +145,12 @@ class TestProxyRepoWrapping(test_utils.BaseTestCase): - self._test_method_with_proxied_argument('add', None) - - def test_save(self): -- self._test_method_with_proxied_argument('save', 'dog') -+ self._test_method_with_proxied_argument('save', 'dog', -+ from_state=None) - - def test_save_with_no_result(self): -- self._test_method_with_proxied_argument('save', None) -+ self._test_method_with_proxied_argument('save', None, -+ from_state=None) - - def test_remove(self): - self._test_method_with_proxied_argument('remove', 'dog') -diff --git a/glance/tests/unit/test_policy.py b/glance/tests/unit/test_policy.py -index 5b5e870..44546a0 100644 ---- a/glance/tests/unit/test_policy.py -+++ b/glance/tests/unit/test_policy.py -@@ -78,7 +78,7 @@ class MemberRepoStub(object): - def get(self, *args, **kwargs): - return 'member_repo_get' - -- def save(self, image_member): -+ def save(self, image_member, from_state=None): - image_member.output = 'member_repo_save' - - def list(self, *args, **kwargs): -diff --git a/glance/tests/unit/test_quota.py b/glance/tests/unit/test_quota.py -index c12eda2..1c40fb4 100644 ---- a/glance/tests/unit/test_quota.py -+++ b/glance/tests/unit/test_quota.py -@@ -367,7 +367,8 @@ class TestImagePropertyQuotas(test_utils.BaseTestCase): - self.image.extra_properties = {'foo': 'bar'} - self.image_repo_proxy.save(self.image) - -- self.image_repo_mock.save.assert_called_once_with(self.base_image) -+ self.image_repo_mock.save.assert_called_once_with(self.base_image, -+ from_state=None) - - def test_save_image_too_many_image_properties(self): - self.config(image_property_quota=1) -@@ -383,7 +384,8 @@ class TestImagePropertyQuotas(test_utils.BaseTestCase): - self.image.extra_properties = {'foo': 'bar'} - self.image_repo_proxy.save(self.image) - -- self.image_repo_mock.save.assert_called_once_with(self.base_image) -+ self.image_repo_mock.save.assert_called_once_with(self.base_image, -+ from_state=None) - - def test_add_image_with_image_property(self): - self.config(image_property_quota=1) -@@ -422,7 +424,8 @@ class TestImagePropertyQuotas(test_utils.BaseTestCase): - self.config(image_property_quota=1) - self.image.extra_properties = {'foo': 'frob', 'spam': 'eggs'} - self.image_repo_proxy.save(self.image) -- self.image_repo_mock.save.assert_called_once_with(self.base_image) -+ self.image_repo_mock.save.assert_called_once_with(self.base_image, -+ from_state=None) - self.assertEqual('frob', self.base_image.extra_properties['foo']) - self.assertEqual('eggs', self.base_image.extra_properties['spam']) - -@@ -431,7 +434,8 @@ class TestImagePropertyQuotas(test_utils.BaseTestCase): - self.config(image_property_quota=1) - del self.image.extra_properties['foo'] - self.image_repo_proxy.save(self.image) -- self.image_repo_mock.save.assert_called_once_with(self.base_image) -+ self.image_repo_mock.save.assert_called_once_with(self.base_image, -+ from_state=None) - self.assertNotIn('foo', self.base_image.extra_properties) - self.assertEqual('ham', self.base_image.extra_properties['spam']) - -@@ -447,7 +451,7 @@ class TestImagePropertyQuotas(test_utils.BaseTestCase): - del self.image.extra_properties['frob'] - del self.image.extra_properties['lorem'] - self.image_repo_proxy.save(self.image) -- call_args = mock.call(self.base_image) -+ call_args = mock.call(self.base_image, from_state=None) - self.assertEqual(call_args, self.image_repo_mock.save.call_args) - self.assertEqual('bar', self.base_image.extra_properties['foo']) - self.assertEqual('ham', self.base_image.extra_properties['spam']) -@@ -466,7 +470,8 @@ class TestImagePropertyQuotas(test_utils.BaseTestCase): - self.config(image_property_quota=1) - del self.image.extra_properties['foo'] - self.image_repo_proxy.save(self.image) -- self.image_repo_mock.save.assert_called_once_with(self.base_image) -+ self.image_repo_mock.save.assert_called_once_with(self.base_image, -+ from_state=None) - self.assertNotIn('foo', self.base_image.extra_properties) - self.assertEqual('ham', self.base_image.extra_properties['spam']) - self.assertEqual('baz', self.base_image.extra_properties['frob']) -diff --git a/glance/tests/unit/test_store_image.py b/glance/tests/unit/test_store_image.py -index 8b334ab..b656454 100644 ---- a/glance/tests/unit/test_store_image.py -+++ b/glance/tests/unit/test_store_image.py -@@ -36,7 +36,7 @@ class ImageRepoStub(object): - def add(self, image): - return image - -- def save(self, image): -+ def save(self, image, from_state=None): - return image - - -diff --git a/glance/tests/unit/v1/test_api.py b/glance/tests/unit/v1/test_api.py -index 39e9a44..7dc0737 100644 ---- a/glance/tests/unit/v1/test_api.py -+++ b/glance/tests/unit/v1/test_api.py -@@ -39,7 +39,6 @@ from glance.db.sqlalchemy import api as db_api - from glance.db.sqlalchemy import models as db_models - from glance.openstack.common import jsonutils - from glance.openstack.common import timeutils -- - import glance.registry.client.v1.api as registry - from glance.tests.unit import base - import glance.tests.unit.utils as unit_test_utils -@@ -1735,8 +1734,7 @@ class TestGlanceAPI(base.IsolatedUnitTest): - - self.assertEqual(1, mock_store_add_to_backend.call_count) - -- def test_delete_during_image_upload(self): -- req = unit_test_utils.get_fake_request() -+ def _check_delete_during_image_upload(self, is_admin=False): - - fixture_headers = {'x-image-meta-store': 'file', - 'x-image-meta-disk-format': 'vhd', -@@ -1744,8 +1742,8 @@ class TestGlanceAPI(base.IsolatedUnitTest): - 'x-image-meta-name': 'fake image #3', - 'x-image-meta-property-key1': 'value1'} - -- req = webob.Request.blank("/images") -- req.method = 'POST' -+ req = unit_test_utils.get_fake_request(path="/images", -+ is_admin=is_admin) - for k, v in six.iteritems(fixture_headers): - req.headers[k] = v - -@@ -1770,31 +1768,18 @@ class TestGlanceAPI(base.IsolatedUnitTest): - mock_initiate_deletion) - - orig_update_image_metadata = registry.update_image_metadata -- ctlr = glance.api.v1.controller.BaseController -- orig_get_image_meta_or_404 = ctlr.get_image_meta_or_404 -- -- def mock_update_image_metadata(*args, **kwargs): - -- if args[2].get('status', None) == 'deleted': -+ data = "somedata" - -- # One shot. -- def mock_get_image_meta_or_404(*args, **kwargs): -- ret = orig_get_image_meta_or_404(*args, **kwargs) -- ret['status'] = 'queued' -- self.stubs.Set(ctlr, 'get_image_meta_or_404', -- orig_get_image_meta_or_404) -- return ret -- -- self.stubs.Set(ctlr, 'get_image_meta_or_404', -- mock_get_image_meta_or_404) -+ def mock_update_image_metadata(*args, **kwargs): - -- req = webob.Request.blank("/images/%s" % image_id) -- req.method = 'PUT' -- req.headers['Content-Type'] = 'application/octet-stream' -- req.body = "somedata" -+ if args[2].get('size', None) == len(data): -+ path = "/images/%s" % image_id -+ req = unit_test_utils.get_fake_request(path=path, -+ method='DELETE', -+ is_admin=is_admin) - res = req.get_response(self.api) -- self.assertEqual(res.status_int, 200) -- self.assertFalse(res.location) -+ self.assertEqual(200, res.status_int) - - self.stubs.Set(registry, 'update_image_metadata', - orig_update_image_metadata) -@@ -1804,20 +1789,30 @@ class TestGlanceAPI(base.IsolatedUnitTest): - self.stubs.Set(registry, 'update_image_metadata', - mock_update_image_metadata) - -- req = webob.Request.blank("/images/%s" % image_id) -- req.method = 'DELETE' -+ req = unit_test_utils.get_fake_request(path="/images/%s" % image_id, -+ method='PUT') -+ req.headers['Content-Type'] = 'application/octet-stream' -+ req.body = data - res = req.get_response(self.api) -- self.assertEqual(res.status_int, 200) -+ self.assertEqual(412, res.status_int) -+ self.assertFalse(res.location) - - self.assertTrue(called['initiate_deletion']) - -- req = webob.Request.blank("/images/%s" % image_id) -- req.method = 'HEAD' -+ req = unit_test_utils.get_fake_request(path="/images/%s" % image_id, -+ method='HEAD', -+ is_admin=True) - res = req.get_response(self.api) - self.assertEqual(res.status_int, 200) - self.assertEqual(res.headers['x-image-meta-deleted'], 'True') - self.assertEqual(res.headers['x-image-meta-status'], 'deleted') - -+ def test_delete_during_image_upload_by_normal_user(self): -+ self._check_delete_during_image_upload(is_admin=False) -+ -+ def test_delete_during_image_upload_by_admin(self): -+ self._check_delete_during_image_upload(is_admin=True) -+ - def test_disable_purge_props(self): - """ - Test the special x-glance-registry-purge-props header controls -diff --git a/glance/tests/unit/v2/test_image_data_resource.py b/glance/tests/unit/v2/test_image_data_resource.py -index cc8148a..a121e82 100644 ---- a/glance/tests/unit/v2/test_image_data_resource.py -+++ b/glance/tests/unit/v2/test_image_data_resource.py -@@ -81,7 +81,7 @@ class FakeImageRepo(object): - else: - return self.result - -- def save(self, image): -+ def save(self, image, from_state=None): - self.saved_image = image - - -@@ -184,17 +184,21 @@ class TestImagesController(base.StoreClearingUnitTest): - request, unit_test_utils.UUID1, 'YYYY', 4) - - def test_upload_non_existent_image_during_save_initiates_deletion(self): -- def fake_save(self): -+ def fake_save_not_found(self): - raise exception.NotFound() - -- request = unit_test_utils.get_fake_request() -- image = FakeImage('abcd', locations=['http://example.com/image']) -- self.image_repo.result = image -- self.image_repo.save = fake_save -- image.delete = mock.Mock() -- self.assertRaises(webob.exc.HTTPGone, self.controller.upload, -- request, str(uuid.uuid4()), 'ABC', 3) -- self.assertTrue(image.delete.called) -+ def fake_save_conflict(self): -+ raise exception.Conflict() -+ -+ for fun in [fake_save_not_found, fake_save_conflict]: -+ request = unit_test_utils.get_fake_request() -+ image = FakeImage('abcd', locations=['http://example.com/image']) -+ self.image_repo.result = image -+ self.image_repo.save = fun -+ image.delete = mock.Mock() -+ self.assertRaises(webob.exc.HTTPGone, self.controller.upload, -+ request, str(uuid.uuid4()), 'ABC', 3) -+ self.assertTrue(image.delete.called) - - def test_upload_non_existent_image_raises_not_found_exception(self): - def fake_save(self): --- -2.0.5 - diff --git a/app-admin/glance/glance-2014.2.2.ebuild b/app-admin/glance/glance-2014.2.2.ebuild new file mode 100644 index 000000000000..28140ce6e116 --- /dev/null +++ b/app-admin/glance/glance-2014.2.2.ebuild @@ -0,0 +1,162 @@ +# Copyright 1999-2015 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Header: /var/cvsroot/gentoo-x86/app-admin/glance/glance-2014.2.2.ebuild,v 1.1 2015/02/08 01:51:56 prometheanfire Exp $ + +EAPI=5 +PYTHON_COMPAT=( python2_7 ) + +inherit distutils-r1 user + +DESCRIPTION="Provides services for discovering, registering, and retrieving +virtual machine images with Openstack" +HOMEPAGE="https://launchpad.net/glance" +SRC_URI="http://launchpad.net/${PN}/juno/${PV}/+download/${P}.tar.gz" + +LICENSE="Apache-2.0" +SLOT="0" +KEYWORDS="~amd64 ~x86" +IUSE="doc mysql postgres +sqlite +swift test" +REQUIRED_USE="|| ( mysql postgres sqlite )" + +DEPEND="dev-python/setuptools[${PYTHON_USEDEP}] + >=dev-python/pbr-0.8.0[${PYTHON_USEDEP}] + <dev-python/pbr-1.0[${PYTHON_USEDEP}] + test? ( + ${RDEPEND} + >=dev-python/hacking-0.8.0[${PYTHON_USEDEP}] + <dev-python/hacking-0.9[${PYTHON_USEDEP}] + >=dev-python/Babel-1.3[${PYTHON_USEDEP}] + >=dev-python/coverage-3.6[${PYTHON_USEDEP}] + >=dev-python/fixtures-0.3.14[${PYTHON_USEDEP}] + >=dev-python/mock-1.0[${PYTHON_USEDEP}] + >=dev-python/mox-0.5.3[${PYTHON_USEDEP}] + >=dev-python/sphinx-1.1.2[${PYTHON_USEDEP}] + !~dev-python/sphinx-1.2.0[${PYTHON_USEDEP}] + <dev-python/sphinx-1.3[${PYTHON_USEDEP}] + >=dev-python/requests-1.2.1[${PYTHON_USEDEP}] + !~dev-python/requests-2.4.0[${PYTHON_USEDEP}] + >=dev-python/testrepository-0.0.18[${PYTHON_USEDEP}] + >=dev-python/testtools-0.9.34[${PYTHON_USEDEP}] + >=dev-python/psutil-1.1.1[${PYTHON_USEDEP}] + <dev-python/psutil-2.0.0[${PYTHON_USEDEP}] + dev-python/mysql-python[${PYTHON_USEDEP}] + dev-python/psycopg[${PYTHON_USEDEP}] + ~dev-python/pysendfile-2.0.0[${PYTHON_USEDEP}] + dev-python/qpid-python[${PYTHON_USEDEP}] + >=dev-python/pyxattr-0.5.0[${PYTHON_USEDEP}] + >=dev-python/oslo-sphinx-2.2.0[${PYTHON_USEDEP}] + )" + +#note to self, wsgiref is a python builtin, no need to package it +#>=dev-python/wsgiref-0.1.2[${PYTHON_USEDEP}] + +RDEPEND=" + >=dev-python/greenlet-0.3.2[${PYTHON_USEDEP}] + sqlite? ( + >=dev-python/sqlalchemy-0.9.7[sqlite,${PYTHON_USEDEP}] + <=dev-python/sqlalchemy-0.9.99[sqlite,${PYTHON_USEDEP}] + ) + mysql? ( + dev-python/mysql-python + >=dev-python/sqlalchemy-0.9.7[${PYTHON_USEDEP}] + <=dev-python/sqlalchemy-0.9.99[${PYTHON_USEDEP}] + ) + postgres? ( + dev-python/psycopg:2 + >=dev-python/sqlalchemy-0.9.7[${PYTHON_USEDEP}] + <=dev-python/sqlalchemy-0.9.99[${PYTHON_USEDEP}] + ) + >=dev-python/anyjson-0.3.3[${PYTHON_USEDEP}] + >=dev-python/eventlet-0.15.1[${PYTHON_USEDEP}] + <dev-python/eventlet-0.16.0[${PYTHON_USEDEP}] + >=dev-python/pastedeploy-1.5.0[${PYTHON_USEDEP}] + >=dev-python/routes-1.12.3[${PYTHON_USEDEP}] + !~dev-python/routes-2.0[${PYTHON_USEDEP}] + >=dev-python/webob-1.2.3[${PYTHON_USEDEP}] + >=dev-python/boto-2.32.1[${PYTHON_USEDEP}] + >=dev-python/boto-2.35.0[${PYTHON_USEDEP}] + ~dev-python/sqlalchemy-migrate-0.9.1[${PYTHON_USEDEP}] + >=dev-python/httplib2-0.7.5[${PYTHON_USEDEP}] + >=dev-python/kombu-2.5.0[${PYTHON_USEDEP}] + >=dev-python/pycrypto-2.6[${PYTHON_USEDEP}] + >=dev-python/iso8601-0.1.9[${PYTHON_USEDEP}] + dev-python/ordereddict[${PYTHON_USEDEP}] + >=dev-python/oslo-config-1.4.0[${PYTHON_USEDEP}] + >=dev-python/stevedore-1.0.0[${PYTHON_USEDEP}] + >=dev-python/netaddr-0.7.12[${PYTHON_USEDEP}] + >=dev-python/keystonemiddleware-1.0.0[${PYTHON_USEDEP}] + >=dev-python/WSME-0.6[${PYTHON_USEDEP}] + dev-python/posix_ipc[${PYTHON_USEDEP}] + swift? ( + >=dev-python/python-swiftclient-2.2.0[${PYTHON_USEDEP}] + ) + >=dev-python/oslo-vmware-0.6.0[${PYTHON_USEDEP}] + <dev-python/oslo-vmware-0.9.0[${PYTHON_USEDEP}] + dev-python/paste[${PYTHON_USEDEP}] + >=dev-python/jsonschema-2.0.0[${PYTHON_USEDEP}] + <dev-python/jsonschema-3.0.0[${PYTHON_USEDEP}] + >=dev-python/python-cinderclient-1.1.0[${PYTHON_USEDEP}] + >=dev-python/python-keystoneclient-0.10.0[${PYTHON_USEDEP}] + >=dev-python/pyopenssl-0.11[${PYTHON_USEDEP}] + >=dev-python/six-1.7.0[${PYTHON_USEDEP}] + >=dev-python/oslo-db-1.0.0[${PYTHON_USEDEP}] + <dev-python/oslo-db-1.1.0[${PYTHON_USEDEP}] + >=dev-python/oslo-i18n-1.0.0[${PYTHON_USEDEP}] + >=dev-python/oslo-messaging-1.4.0[${PYTHON_USEDEP}] + !~dev-python/oslo-messaging-1.5.0[${PYTHON_USEDEP}] + <dev-python/oslo-messaging-1.6.0[${PYTHON_USEDEP}] + >=dev-python/retrying-1.2.2[${PYTHON_USEDEP}] + !~dev-python/retrying-1.3.0[${PYTHON_USEDEP}] + >=dev-python/osprofiler-0.3.0[${PYTHON_USEDEP}] + >=dev-python/glance_store-0.1.1[${PYTHON_USEDEP}]" + +PATCHES=( + "${FILESDIR}/${PN}-2013.2-sphinx_mapping.patch" +) + +pkg_setup() { + enewgroup glance + enewuser glance -1 -1 /var/lib/glance glance +} + +python_compile_all() { + use doc && "${PYTHON}" setup.py build_sphinx +} + +python_test() { + # https://bugs.launchpad.net/glance/+bug/1251105 + # https://bugs.launchpad.net/glance/+bug/1242501 + nosetests glance/ || die "tests failed under python2.7" +} + +python_install() { + distutils-r1_python_install + + for svc in api registry scrubber; do + newinitd "${FILESDIR}/glance.initd" glance-${svc} + done + + diropts -m 0750 -o glance -g glance + dodir /var/log/glance /var/lib/glance/images /var/lib/glance/scrubber + keepdir /etc/glance + keepdir /var/log/glance + keepdir /var/lib/glance/images + keepdir /var/lib/glance/scrubber + + insinto /etc/glance + insopts -m 0640 -o glance -g glance + doins "etc/glance-api-paste.ini" + doins "etc/glance-api.conf" + doins "etc/glance-cache.conf" + doins "etc/glance-registry-paste.ini" + doins "etc/glance-registry.conf" + doins "etc/glance-scrubber.conf" + doins "etc/logging.cnf.sample" + doins "etc/policy.json" + doins "etc/schema-image.json" +} + +python_install_all() { + use doc && local HTML_DOCS=( doc/build/html/. ) + distutils-r1_python_install_all +} diff --git a/app-admin/glance/glance-2014.2.9999.ebuild b/app-admin/glance/glance-2014.2.9999.ebuild index b25c6fbbec11..7ba4ef5cab3b 100644 --- a/app-admin/glance/glance-2014.2.9999.ebuild +++ b/app-admin/glance/glance-2014.2.9999.ebuild @@ -1,6 +1,6 @@ -# Copyright 1999-2014 Gentoo Foundation +# Copyright 1999-2015 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/app-admin/glance/glance-2014.2.9999.ebuild,v 1.5 2014/12/09 01:20:13 prometheanfire Exp $ +# $Header: /var/cvsroot/gentoo-x86/app-admin/glance/glance-2014.2.9999.ebuild,v 1.6 2015/02/08 01:51:56 prometheanfire Exp $ EAPI=5 PYTHON_COMPAT=( python2_7 ) @@ -22,28 +22,31 @@ REQUIRED_USE="|| ( mysql postgres sqlite )" DEPEND="dev-python/setuptools[${PYTHON_USEDEP}] >=dev-python/pbr-0.8.0[${PYTHON_USEDEP}] <dev-python/pbr-1.0[${PYTHON_USEDEP}] - test? ( >=dev-python/hacking-0.8.0[${PYTHON_USEDEP}] - <dev-python/hacking-0.9[${PYTHON_USEDEP}] - >=dev-python/Babel-1.3[${PYTHON_USEDEP}] - >=dev-python/coverage-3.6[${PYTHON_USEDEP}] - >=dev-python/fixtures-0.3.14[${PYTHON_USEDEP}] - >=dev-python/mock-1.0[${PYTHON_USEDEP}] - >=dev-python/mox-0.5.3[${PYTHON_USEDEP}] - >=dev-python/sphinx-1.1.2[${PYTHON_USEDEP}] - !~dev-python/sphinx-1.2.0[${PYTHON_USEDEP}] - <dev-python/sphinx-1.3[${PYTHON_USEDEP}] - >=dev-python/requests-1.2.1[${PYTHON_USEDEP}] - !~dev-python/requests-2.4.0[${PYTHON_USEDEP}] - >=dev-python/testrepository-0.0.18[${PYTHON_USEDEP}] - >=dev-python/testtools-0.9.34[${PYTHON_USEDEP}] - >=dev-python/psutil-1.1.1[${PYTHON_USEDEP}] - <dev-python/psutil-2.0.0[${PYTHON_USEDEP}] - dev-python/mysql-python[${PYTHON_USEDEP}] - dev-python/psycopg[${PYTHON_USEDEP}] - ~dev-python/pysendfile-2.0.0[${PYTHON_USEDEP}] - dev-python/qpid-python[${PYTHON_USEDEP}] - >=dev-python/pyxattr-0.5.0[${PYTHON_USEDEP}] - >=dev-python/oslo-sphinx-2.2.0[${PYTHON_USEDEP}] )" + test? ( + ${RDEPEND} + >=dev-python/hacking-0.8.0[${PYTHON_USEDEP}] + <dev-python/hacking-0.9[${PYTHON_USEDEP}] + >=dev-python/Babel-1.3[${PYTHON_USEDEP}] + >=dev-python/coverage-3.6[${PYTHON_USEDEP}] + >=dev-python/fixtures-0.3.14[${PYTHON_USEDEP}] + >=dev-python/mock-1.0[${PYTHON_USEDEP}] + >=dev-python/mox-0.5.3[${PYTHON_USEDEP}] + >=dev-python/sphinx-1.1.2[${PYTHON_USEDEP}] + !~dev-python/sphinx-1.2.0[${PYTHON_USEDEP}] + <dev-python/sphinx-1.3[${PYTHON_USEDEP}] + >=dev-python/requests-1.2.1[${PYTHON_USEDEP}] + !~dev-python/requests-2.4.0[${PYTHON_USEDEP}] + >=dev-python/testrepository-0.0.18[${PYTHON_USEDEP}] + >=dev-python/testtools-0.9.34[${PYTHON_USEDEP}] + >=dev-python/psutil-1.1.1[${PYTHON_USEDEP}] + <dev-python/psutil-2.0.0[${PYTHON_USEDEP}] + dev-python/mysql-python[${PYTHON_USEDEP}] + dev-python/psycopg[${PYTHON_USEDEP}] + ~dev-python/pysendfile-2.0.0[${PYTHON_USEDEP}] + dev-python/qpid-python[${PYTHON_USEDEP}] + >=dev-python/pyxattr-0.5.0[${PYTHON_USEDEP}] + >=dev-python/oslo-sphinx-2.2.0[${PYTHON_USEDEP}] + )" #note to self, wsgiref is a python builtin, no need to package it #>=dev-python/wsgiref-0.1.2[${PYTHON_USEDEP}] @@ -51,52 +54,29 @@ DEPEND="dev-python/setuptools[${PYTHON_USEDEP}] RDEPEND=" >=dev-python/greenlet-0.3.2[${PYTHON_USEDEP}] sqlite? ( - || ( - ( - >=dev-python/sqlalchemy-0.8.4[sqlite,${PYTHON_USEDEP}] - <=dev-python/sqlalchemy-0.8.99[sqlite,${PYTHON_USEDEP}] - ) - ( - >=dev-python/sqlalchemy-0.9.7[sqlite,${PYTHON_USEDEP}] - <=dev-python/sqlalchemy-0.9.99[sqlite,${PYTHON_USEDEP}] - ) - ) + >=dev-python/sqlalchemy-0.9.7[sqlite,${PYTHON_USEDEP}] + <=dev-python/sqlalchemy-0.9.99[sqlite,${PYTHON_USEDEP}] ) mysql? ( dev-python/mysql-python - || ( - ( - >=dev-python/sqlalchemy-0.8.4[${PYTHON_USEDEP}] - <=dev-python/sqlalchemy-0.8.99[${PYTHON_USEDEP}] - ) - ( - >=dev-python/sqlalchemy-0.9.7[${PYTHON_USEDEP}] - <=dev-python/sqlalchemy-0.9.99[${PYTHON_USEDEP}] - ) - ) + >=dev-python/sqlalchemy-0.9.7[${PYTHON_USEDEP}] + <=dev-python/sqlalchemy-0.9.99[${PYTHON_USEDEP}] ) postgres? ( dev-python/psycopg:2 - || ( - ( - >=dev-python/sqlalchemy-0.8.4[${PYTHON_USEDEP}] - <=dev-python/sqlalchemy-0.8.99[${PYTHON_USEDEP}] - ) - ( - >=dev-python/sqlalchemy-0.9.7[${PYTHON_USEDEP}] - <=dev-python/sqlalchemy-0.9.99[${PYTHON_USEDEP}] - ) - ) + >=dev-python/sqlalchemy-0.9.7[${PYTHON_USEDEP}] + <=dev-python/sqlalchemy-0.9.99[${PYTHON_USEDEP}] ) >=dev-python/anyjson-0.3.3[${PYTHON_USEDEP}] >=dev-python/eventlet-0.15.1[${PYTHON_USEDEP}] + <dev-python/eventlet-0.16.0[${PYTHON_USEDEP}] >=dev-python/pastedeploy-1.5.0[${PYTHON_USEDEP}] >=dev-python/routes-1.12.3[${PYTHON_USEDEP}] !~dev-python/routes-2.0[${PYTHON_USEDEP}] >=dev-python/webob-1.2.3[${PYTHON_USEDEP}] >=dev-python/boto-2.32.1[${PYTHON_USEDEP}] - >=dev-python/sqlalchemy-migrate-0.9.1[${PYTHON_USEDEP}] - !~dev-python/sqlalchemy-migrate-0.9.2[${PYTHON_USEDEP}] + >=dev-python/boto-2.35.0[${PYTHON_USEDEP}] + ~dev-python/sqlalchemy-migrate-0.9.1[${PYTHON_USEDEP}] >=dev-python/httplib2-0.7.5[${PYTHON_USEDEP}] >=dev-python/kombu-2.5.0[${PYTHON_USEDEP}] >=dev-python/pycrypto-2.6[${PYTHON_USEDEP}] @@ -112,6 +92,7 @@ RDEPEND=" >=dev-python/python-swiftclient-2.2.0[${PYTHON_USEDEP}] ) >=dev-python/oslo-vmware-0.6.0[${PYTHON_USEDEP}] + <dev-python/oslo-vmware-0.9.0[${PYTHON_USEDEP}] dev-python/paste[${PYTHON_USEDEP}] >=dev-python/jsonschema-2.0.0[${PYTHON_USEDEP}] <dev-python/jsonschema-3.0.0[${PYTHON_USEDEP}] @@ -120,15 +101,19 @@ RDEPEND=" >=dev-python/pyopenssl-0.11[${PYTHON_USEDEP}] >=dev-python/six-1.7.0[${PYTHON_USEDEP}] >=dev-python/oslo-db-1.0.0[${PYTHON_USEDEP}] + <dev-python/oslo-db-1.1.0[${PYTHON_USEDEP}] >=dev-python/oslo-i18n-1.0.0[${PYTHON_USEDEP}] >=dev-python/oslo-messaging-1.4.0[${PYTHON_USEDEP}] !~dev-python/oslo-messaging-1.5.0[${PYTHON_USEDEP}] + <dev-python/oslo-messaging-1.6.0[${PYTHON_USEDEP}] >=dev-python/retrying-1.2.2[${PYTHON_USEDEP}] !~dev-python/retrying-1.3.0[${PYTHON_USEDEP}] >=dev-python/osprofiler-0.3.0[${PYTHON_USEDEP}] >=dev-python/glance_store-0.1.1[${PYTHON_USEDEP}]" -PATCHES=( "${FILESDIR}/${PN}-2013.2-sphinx_mapping.patch" ) +PATCHES=( + "${FILESDIR}/${PN}-2013.2-sphinx_mapping.patch" +) pkg_setup() { enewgroup glance diff --git a/app-admin/glance/glance-9999.ebuild b/app-admin/glance/glance-9999.ebuild deleted file mode 100644 index cdbd8821afe8..000000000000 --- a/app-admin/glance/glance-9999.ebuild +++ /dev/null @@ -1,139 +0,0 @@ -# Copyright 1999-2014 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 -# $Header: /var/cvsroot/gentoo-x86/app-admin/glance/glance-9999.ebuild,v 1.12 2014/08/01 05:12:09 prometheanfire Exp $ - -EAPI=5 -PYTHON_COMPAT=( python2_7 ) - -inherit git-2 distutils-r1 user - -DESCRIPTION="Provides services for discovering, registering, and retrieving -virtual machine images with Openstack" -HOMEPAGE="https://launchpad.net/glance" -EGIT_REPO_URI="https://github.com/openstack/glance.git" - -LICENSE="Apache-2.0" -SLOT="0" -KEYWORDS="" -IUSE="doc mysql postgres +sqlite +swift test" -REQUIRED_USE="|| ( mysql postgres sqlite )" - -DEPEND="dev-python/setuptools[${PYTHON_USEDEP}] - >=dev-python/pbr-0.6.0[${PYTHON_USEDEP}] - <dev-python/pbr-1.0[${PYTHON_USEDEP}] - test? ( >=dev-python/hacking-0.8.0[${PYTHON_USEDEP}] - <dev-python/hacking-0.9[${PYTHON_USEDEP}] - >=dev-python/Babel-1.3[${PYTHON_USEDEP}] - >=dev-python/coverage-3.6[${PYTHON_USEDEP}] - >=dev-python/fixtures-0.3.14[${PYTHON_USEDEP}] - >=dev-python/mock-1.0[${PYTHON_USEDEP}] - >=dev-python/mox-0.5.3[${PYTHON_USEDEP}] - >=dev-python/sphinx-1.1.2[${PYTHON_USEDEP}] - <dev-python/sphinx-1.2[${PYTHON_USEDEP}] - >=dev-python/requests-1.1[${PYTHON_USEDEP}] - >=dev-python/testrepository-0.0.18[${PYTHON_USEDEP}] - >=dev-python/testtools-0.9.34[${PYTHON_USEDEP}] - >=dev-python/psutil-1.1.1[${PYTHON_USEDEP}] - dev-python/mysql-python[${PYTHON_USEDEP}] - dev-python/psycopg[${PYTHON_USEDEP}] - ~dev-python/pysendfile-2.0.0[${PYTHON_USEDEP}] - dev-python/qpid-python[${PYTHON_USEDEP}] - >=dev-python/pyxattr-0.5.0[${PYTHON_USEDEP}] - dev-python/oslo-sphinx[${PYTHON_USEDEP}] )" - -#note to self, wsgiref is a python builtin, no need to package it -#>=dev-python/wsgiref-0.1.2[${PYTHON_USEDEP}] - -RDEPEND=">=dev-python/greenlet-0.3.2[${PYTHON_USEDEP}] - sqlite? ( - >=dev-python/sqlalchemy-0.8.0[sqlite,${PYTHON_USEDEP}] - !~dev-python/sqlalchemy-0.9.5[sqlite,${PYTHON_USEDEP}] - <=dev-python/sqlalchemy-0.9.99[sqlite,${PYTHON_USEDEP}] - ) - mysql? ( - dev-python/mysql-python - >=dev-python/sqlalchemy-0.8.0[${PYTHON_USEDEP}] - !~dev-python/sqlalchemy-0.9.5[${PYTHON_USEDEP}] - <=dev-python/sqlalchemy-0.9.99[${PYTHON_USEDEP}] - ) - postgres? ( - dev-python/psycopg:2 - >=dev-python/sqlalchemy-0.8.0[${PYTHON_USEDEP}] - !~dev-python/sqlalchemy-0.9.5[${PYTHON_USEDEP}] - <=dev-python/sqlalchemy-0.9.99[${PYTHON_USEDEP}] - ) - >=dev-python/anyjson-0.3.3[${PYTHON_USEDEP}] - >=dev-python/eventlet-0.13.0[${PYTHON_USEDEP}] - >=dev-python/pastedeploy-1.5.0[${PYTHON_USEDEP}] - >=dev-python/routes-1.12.3[${PYTHON_USEDEP}] - >=dev-python/webob-1.2.3[${PYTHON_USEDEP}] - >=dev-python/boto-2.12.0[${PYTHON_USEDEP}] - !~dev-python/boto-2.13.0[${PYTHON_USEDEP}] - >=dev-python/sqlalchemy-migrate-0.9[${PYTHON_USEDEP}] - >=dev-python/httplib2-0.7.5[${PYTHON_USEDEP}] - >=dev-python/kombu-2.4.8[${PYTHON_USEDEP}] - >=dev-python/pycrypto-2.6[${PYTHON_USEDEP}] - >=dev-python/iso8601-0.1.9[${PYTHON_USEDEP}] - >=dev-python/oslo-config-1.2.1[${PYTHON_USEDEP}] - >=dev-python/stevedore-0.14[${PYTHON_USEDEP}] - swift? ( - >=dev-python/python-swiftclient-1.6[${PYTHON_USEDEP}] - ) - dev-python/paste[${PYTHON_USEDEP}] - >=dev-python/jsonschema-2.0.0[${PYTHON_USEDEP}] - <dev-python/jsonschema-3.0.0[${PYTHON_USEDEP}] - >=dev-python/python-cinderclient-1.0.6[${PYTHON_USEDEP}] - >=dev-python/python-keystoneclient-0.7.0[${PYTHON_USEDEP}] - >=dev-python/pyopenssl-0.11[${PYTHON_USEDEP}] - >=dev-python/six-1.6.0[${PYTHON_USEDEP}] - >=dev-python/oslo-messaging-1.3.0[${PYTHON_USEDEP}] - >=dev-python/oslo-vmware-0.2[${PYTHON_USEDEP}]" - -PATCHES=( "${FILESDIR}"/${PN}-2013.2-sphinx_mapping.patch ) - -pkg_setup() { - enewgroup glance - enewuser glance -1 -1 /var/lib/glance glance -} - -python_compile_all() { - use doc && "${PYTHON}" setup.py build_sphinx -} - -python_test() { - # https://bugs.launchpad.net/glance/+bug/1251105 - # https://bugs.launchpad.net/glance/+bug/1242501 - nosetests glance/ || die "tests failed under python2.7" -} - -python_install() { - distutils-r1_python_install - - for svc in api registry scrubber; do - newinitd "${FILESDIR}/glance.initd" glance-${svc} - done - - diropts -m 0750 -o glance -g glance - dodir /var/log/glance /var/lib/glance/images /var/lib/glance/scrubber - keepdir /etc/glance - keepdir /var/log/glance - keepdir /var/lib/glance/images - keepdir /var/lib/glance/scrubber - - insinto /etc/glance - insopts -m 0640 -o glance -g glance - doins "etc/glance-api-paste.ini" - doins "etc/glance-api.conf" - doins "etc/glance-cache.conf" - doins "etc/glance-registry-paste.ini" - doins "etc/glance-registry.conf" - doins "etc/glance-scrubber.conf" - doins "etc/logging.cnf.sample" - doins "etc/policy.json" - doins "etc/schema-image.json" -} - -python_install_all() { - use doc && local HTML_DOCS=( doc/build/html/. ) - distutils-r1_python_install_all -} |