diff options
-rw-r--r-- | app-admin/glance/Manifest | 7 | ||||
-rw-r--r-- | app-admin/glance/files/glance-swift-authv2.patch | 914 | ||||
-rw-r--r-- | app-admin/glance/glance-2012.2.1.ebuild (renamed from app-admin/glance/glance-2012.2.ebuild) | 49 | ||||
-rw-r--r-- | app-admin/glance/glance-9999.ebuild | 58 |
4 files changed, 64 insertions, 964 deletions
diff --git a/app-admin/glance/Manifest b/app-admin/glance/Manifest index bf48017..47be57e 100644 --- a/app-admin/glance/Manifest +++ b/app-admin/glance/Manifest @@ -1,7 +1,6 @@ -AUX glance-swift-authv2.patch 38569 SHA256 651afe783f515121d28cbbb94c7d14de5a5c3f7616edba8bf83e941c2c0eb4b4 SHA512 5038c473052b316a524f60f5be6fbf90bec565f74f8f8f44e1c55d5b8e079d68057551998470ee5b8f2da13a865d308dd52504128129f91ec141c846b590b4c3 WHIRLPOOL b077b62101be3b674256ffbd96064441b79c2fefb003011a5f8343e228b133982ecedbf750617e886f5291ca8727df361ce74b7809f8ba6feb156acff541f190 AUX glance.confd 25 SHA256 5a53dcf1eece81a06a2dd0856b15f8abe20eb1072361b110f752e396e86a7843 SHA512 13e671d4544e58d7397c1a87eb1048ed4bb9561587fcd63783e377b2d25e810222ca3944e0c8cf13c524e64f94c435b456a0d6f7cacfb148e275377699a11ca9 WHIRLPOOL 862a310fbdd7b68f132c45797210011b607d9b5c8937d60c9f5933a4d625bc985ad0277fea26804681b7e0a674dc9da15fbef40502c4052d6742ef0a94e88f3d AUX glance.initd 1101 SHA256 6fe85f10513646263755a2b2e232385dfc8dccb1be4f24b5c7e4f8879fb4f288 SHA512 674c68f13566ebd3443af9d6756f4cf4ebf6a17037a03ea93cb89d39f4f5a0141e572576890e481723b82e857040bfe075238d8c919e7a5fb33e1086e2a1e93a WHIRLPOOL 404e53d29f2f01218e445ce6dcdcdf6620ed6a9f245f2dc9020bd059ca461e1b72a692e7cd9c488daaaacb246160a8ca3a07e9481e536386891c07f3ee79b774 -DIST glance-2012.2.tar.gz 632955 SHA256 10f7ffaa1465a747a1f935bef7941334f47b62c8ede99d49fd002c8b4fed2cfc SHA512 60b298bc57523d6e7984e1c7aee8fb7bbef5815dcc20a273516d838e3d37aa9d62075ba036d2d711bf16ce537597cfe97dca04d0cff0cd720b8f540d51b0c561 WHIRLPOOL 8e40b6449a2c1a19937f3f4cbfc0a13e4d48c95ec33c1630b6ccfa623d3c035340177ec79a52e628312f00708111256812431ff1c92628e02d7ae5251d98403b -EBUILD glance-2012.2.ebuild 1624 SHA256 d6fdc6dabde6107ac23b9dc59dc0549513ec8d9516d75f91cb7ce8246e5675d0 SHA512 78ff601ff74cd34018690fe99f6111563361a4a863709a0c603af37edb083b3b2ac694e99343bc52ed537b8ec991e64bd51ab1d9b76c0461c2343254b6185c8f WHIRLPOOL 58ebdb82bf50a6a8f28f355fcc4db92d9b81dbe311165b5dac2ea62420984a97c9654bba3994d209c80cc0b0bb018f42a0bbc5a006391515dc060491971bbe02 -EBUILD glance-9999.ebuild 1004 SHA256 00343d1772aaa3a87462d711ea6369a3231bc5021e27d37d10fc91afd99bf19b SHA512 38a1d196880481470b51b5a3498373d6e0bda196f4955016990220d21e556ec9ffc5d23ccc5e0faf75d46c2291406d6e997ed49b683c826ef45414d44740b201 WHIRLPOOL 21c6f5e0591f1a5817a0729406a3fe4b6a080f6cee203b6c9358d070cf67893513f633c1f3bbe02745baf8adac93f2ddf297df31f23e69275e9959b345d30e34 +DIST glance-2012.2.1.tar.gz 636828 SHA256 1c806f434e4f69bb7c5e30bbabb77df39849baffa310d03e7fd995ece681a2fc SHA512 d88b8108506dc71adc1acc614e036694768fc5564e756cfda8eff05b08e647b061d9b97d78a5561fad88f233fd35549a7728125df9132178b36698f37ebfc3fb WHIRLPOOL 0fb585b43360e875c32841e26711d1c336f7c2b0aee105152798fa0ff99b9066124bf145b3e1dea758ceab74bac0b9d83c2ebaf222960d13e13dabb11c99cdce +EBUILD glance-2012.2.1.ebuild 1881 SHA256 73527ab252605354d2e4afd8cd63db4e45f6a57c195cbf78e66b4559a6bed775 SHA512 73651dd3d43a84d961410fd6714e62094488aea098845faa18248118a1ca825cdea67ed1f98e899744712005e68d0a7f45ecade87651f7d2c7f0368a66920539 WHIRLPOOL dbcfd155aac653d7be3e3b1caf322a45eda2ea0b91cf13b12d3f4030dd3c8c28e7bf7cb9f5696b570c702a5c2a05e67c22ad188a708b64f6cf9e4e751eea262a +EBUILD glance-9999.ebuild 1871 SHA256 3e49e7ba7b2684f22fa7d4e119041f527933648956bcb829428a1bfa94f934bc SHA512 3a8aae684362248b03140fd0acdee43b1ed84d345772ded0d94aab727a11704aa54b4d2696b6708d0dadc3ba4e937a493188ebd823bfbca86e15fe4ce8a51a77 WHIRLPOOL 3096577d7b538950b1236fa5a6db979ee5a3b9d1b2f5c37c0a81b4c56de89f4c14b29fa5bf51ba878cc61994e7513bd01551ae087ecb279f0e498ece3f55c157 MISC metadata.xml 551 SHA256 de9d9d349c334c740b04384a4f1288e7f2f8491751c38b5846fa5fdc801dd3c0 SHA512 0141af1612f84846713c8ffe8d0c4e653a77772d4e050deb5b9a47882aed9f803c7a0ebe7709f64279b04a19658f10da4aef962a70ecc7aebc2e7dce2ede4c68 WHIRLPOOL 4858e7841f26f04b1e35838cfb475cf34506fdb26e1a03f75c219d599dddac73fbc3429c80b5ac7c752fe2782445e2d492f58fc0b87da44ddc6d03b4710c8f13 diff --git a/app-admin/glance/files/glance-swift-authv2.patch b/app-admin/glance/files/glance-swift-authv2.patch deleted file mode 100644 index 7c8f507..0000000 --- a/app-admin/glance/files/glance-swift-authv2.patch +++ /dev/null @@ -1,914 +0,0 @@ -diff -urN glance-2012.1.orig/Authors glance-2012.1/Authors ---- glance-2012.1.orig/Authors 2012-03-21 10:51:12.000000000 +0100 -+++ glance-2012.1/Authors 2012-03-28 17:48:31.000000000 +0200 -@@ -27,6 +27,7 @@ - Johannes Erdfelt <johannes.erdfelt@rackspace.com> - Josh Durgin <josh.durgin@dreamhost.com> - Josh Kearney <josh@jk0.org> -+Juerg Haefliger <juerg.haefliger@hp.com> - Justin Santa Barbara <justin@fathomdb.com> - Justin Shepherd <jshepher@rackspace.com> - Ken Pepple <ken.pepple@gmail.com> -diff -urN glance-2012.1.orig/Authors.orig glance-2012.1/Authors.orig ---- glance-2012.1.orig/Authors.orig 1970-01-01 01:00:00.000000000 +0100 -+++ glance-2012.1/Authors.orig 2012-03-21 10:51:12.000000000 +0100 -@@ -0,0 +1,62 @@ -+Adam Gandelman <adam.gandelman@canonical.com> -+Alex Meade <alex.meade@rackspace.com> -+Andrew Hutchings <andrew@linuxjedi.co.uk> -+Andrey Brindeyev <abrindeyev@griddynamics.com> -+Brian Lamar <brian.lamar@rackspace.com> -+Brian Waldon <brian.waldon@rackspace.com> -+Chris Behrens <cbehrens@codestud.com> -+Christopher MacGown <chris@pistoncloud.com> -+Chuck Short <chuck.short@canonical.com> -+Cory Wright <corywright@gmail.com> -+Dan Prince <dprince@redhat.com> -+Dean Troyer <dtroyer@gmail.com> -+Derek Higgins <derekh@redhat.com> -+Donal Lafferty <donal.lafferty@citrix.com> -+Eldar Nugaev <enugaev@griddynamics.com> -+Eoghan Glynn <eglynn@redhat.com> -+Ewan Mellor <ewan.mellor@citrix.com> -+Gabriel Hurley <gabriel@strikeawe.com> -+Hengqing Hu <hudayou@hotmail.com> -+Isaku Yamahata <yamahata@valinux.co.jp> -+Jason Koelker <jason@koelker.net> -+Jay Pipes <jaypipes@gmail.com> -+James E. Blair <jeblair@hp.com> -+Jesse Andrews <anotherjesse@gmail.com> -+Jinwoo 'Joseph' Suh <jsuh@isi.edu> -+Joe Gordon <jogo@cloudscaling.com> -+Johannes Erdfelt <johannes.erdfelt@rackspace.com> -+Josh Durgin <josh.durgin@dreamhost.com> -+Josh Kearney <josh@jk0.org> -+Justin Santa Barbara <justin@fathomdb.com> -+Justin Shepherd <jshepher@rackspace.com> -+Ken Pepple <ken.pepple@gmail.com> -+Ken Thomas <krt@yahoo-inc.com> -+Kevin L. Mitchell <kevin.mitchell@rackspace.com> -+Lorin Hochstein <lorin@isi.edu> -+Major Hayden <major@mhtx.net> -+Mark McLoughlin <markmc@redhat.com> -+Mark Washenberger <mark.washenberger@rackspace.com> -+Maru Newby <mnewby@internap.com> -+Matt Dietz <matt.dietz@rackspace.com> -+Mike Lundy <mike@pistoncloud.com> -+Monty Taylor <mordred@inaugust.com> -+Pádraig Brady <P@draigBrady.com> -+Paul Bourke <paul-david.bourke@hp.com> -+Pavan Kumar Sunkara <pavan.sss1991@gmail.com> -+Peng Yong <ppyy@pubyun.com> -+Pete Zaitcev <zaitcev@kotori.zaitcev.us> -+Rick Clark <rick@openstack.org> -+Rick Harris <rconradharris@gmail.com> -+Reynolds Chin <benzwt@gmail.com> -+Russell Bryant <rbryant@redhat.com> -+Soren Hansen <soren.hansen@rackspace.com> -+Stuart McLaren <stuart.mclaren@hp.com> -+Taku Fukushima <tfukushima@dcl.info.waseda.ac.jp> -+Thierry Carrez <thierry@openstack.org> -+Tom Hancock <tom.hancock@hp.com> -+Wayne A. Walls <wayne.walls@rackspace.com> -+William Wolf <throughnothing@gmail.com> -+Vishvananda Ishaya <vishvananda@gmail.com> -+Yaguang Tang <heut2008@gmail.com> -+Yuriy Taraday <yorik.sar@gmail.com> -+Zhongyue Luo <lzyeval@gmail.com> -diff -urN glance-2012.1.orig/etc/glance-api.conf glance-2012.1/etc/glance-api.conf ---- glance-2012.1.orig/etc/glance-api.conf 2012-03-21 10:51:12.000000000 +0100 -+++ glance-2012.1/etc/glance-api.conf 2012-03-28 17:48:31.000000000 +0200 -@@ -130,10 +130,15 @@ - - # ============ Swift Store Options ============================= - -+# Version of the authentication service to use -+# Valid versions are '2' for keystone and '1' for swauth and rackspace -+swift_store_auth_version = 2 -+ - # Address where the Swift authentication service lives - # Valid schemes are 'http://' and 'https://' - # If no scheme specified, default to 'https://' --swift_store_auth_address = 127.0.0.1:8080/v1.0/ -+# For swauth, use something like '127.0.0.1:8080/v1.0/' -+swift_store_auth_address = 127.0.0.1:35357/v2.0/ - - # User to authenticate against the Swift authentication service - # If you use Swift authentication service, set it to 'account':'user' -diff -urN glance-2012.1.orig/glance/store/swift.py glance-2012.1/glance/store/swift.py ---- glance-2012.1.orig/glance/store/swift.py 2012-03-21 10:51:12.000000000 +0100 -+++ glance-2012.1/glance/store/swift.py 2012-03-28 17:50:34.000000000 +0200 -@@ -192,9 +192,10 @@ - cfg.StrOpt('swift_store_auth_address'), - cfg.StrOpt('swift_store_user'), - cfg.StrOpt('swift_store_key'), -+ cfg.StrOpt('swift_store_auth_version', default='2'), - cfg.StrOpt('swift_store_container', - default=DEFAULT_CONTAINER), -- cfg.IntOpt('swift_store_large_object_size', -+ cfg.IntOpt('swift_store_large_object_size', - default=DEFAULT_LARGE_OBJECT_SIZE), - cfg.IntOpt('swift_store_large_object_chunk_size', - default=DEFAULT_LARGE_OBJECT_CHUNK_SIZE), -@@ -204,6 +205,7 @@ - def configure(self): - self.conf.register_opts(self.opts) - self.snet = self.conf.swift_enable_snet -+ self.auth_version = self._option_get('swift_store_auth_version') - - def configure_add(self): - """ -@@ -300,11 +302,14 @@ - Creates a connection using the Swift client library. - """ - snet = self.snet -+ auth_version = self.auth_version - logger.debug(_("Creating Swift connection with " - "(auth_address=%(auth_url)s, user=%(user)s, " -- "snet=%(snet)s)") % locals()) -+ "snet=%(snet)s, auth_version=%(auth_version)s)") % -+ locals()) - return swift_client.Connection( -- authurl=auth_url, user=user, key=key, snet=snet) -+ authurl=auth_url, user=user, key=key, snet=snet, -+ auth_version=auth_version) - - def _option_get(self, param): - result = getattr(self.conf, param) -diff -urN glance-2012.1.orig/glance/store/swift.py.orig glance-2012.1/glance/store/swift.py.orig ---- glance-2012.1.orig/glance/store/swift.py.orig 1970-01-01 01:00:00.000000000 +0100 -+++ glance-2012.1/glance/store/swift.py.orig 2012-03-21 10:51:12.000000000 +0100 -@@ -0,0 +1,560 @@ -+# vim: tabstop=4 shiftwidth=4 softtabstop=4 -+ -+# Copyright 2010-2011 OpenStack, LLC -+# All Rights Reserved. -+# -+# Licensed under the Apache License, Version 2.0 (the "License"); you may -+# not use this file except in compliance with the License. You may obtain -+# a copy of the License at -+# -+# http://www.apache.org/licenses/LICENSE-2.0 -+# -+# Unless required by applicable law or agreed to in writing, software -+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -+# License for the specific language governing permissions and limitations -+# under the License. -+ -+"""Storage backend for SWIFT""" -+ -+from __future__ import absolute_import -+ -+import hashlib -+import httplib -+import logging -+import math -+import urlparse -+ -+from glance.common import cfg -+from glance.common import exception -+import glance.store -+import glance.store.base -+import glance.store.location -+ -+try: -+ from swift.common import client as swift_client -+except ImportError: -+ pass -+ -+DEFAULT_CONTAINER = 'glance' -+DEFAULT_LARGE_OBJECT_SIZE = 5 * 1024 # 5GB -+DEFAULT_LARGE_OBJECT_CHUNK_SIZE = 200 # 200M -+ONE_MB = 1000 * 1024 -+ -+logger = logging.getLogger('glance.store.swift') -+ -+ -+class StoreLocation(glance.store.location.StoreLocation): -+ -+ """ -+ Class describing a Swift URI. A Swift URI can look like any of -+ the following: -+ -+ swift://user:pass@authurl.com/container/obj-id -+ swift://account:user:pass@authurl.com/container/obj-id -+ swift+http://user:pass@authurl.com/container/obj-id -+ swift+https://user:pass@authurl.com/container/obj-id -+ -+ The swift+http:// URIs indicate there is an HTTP authentication URL. -+ The default for Swift is an HTTPS authentication URL, so swift:// and -+ swift+https:// are the same... -+ """ -+ -+ def process_specs(self): -+ self.scheme = self.specs.get('scheme', 'swift+https') -+ self.user = self.specs.get('user') -+ self.key = self.specs.get('key') -+ self.authurl = self.specs.get('authurl') -+ self.container = self.specs.get('container') -+ self.obj = self.specs.get('obj') -+ -+ def _get_credstring(self): -+ if self.user: -+ return '%s:%s@' % (self.user, self.key) -+ return '' -+ -+ def get_uri(self): -+ authurl = self.authurl -+ if authurl.startswith('http://'): -+ authurl = authurl[7:] -+ elif authurl.startswith('https://'): -+ authurl = authurl[8:] -+ -+ credstring = self._get_credstring() -+ authurl = authurl.strip('/') -+ container = self.container.strip('/') -+ obj = self.obj.strip('/') -+ -+ return '%s://%s%s/%s/%s' % (self.scheme, credstring, authurl, -+ container, obj) -+ -+ def parse_uri(self, uri): -+ """ -+ Parse URLs. This method fixes an issue where credentials specified -+ in the URL are interpreted differently in Python 2.6.1+ than prior -+ versions of Python. It also deals with the peculiarity that new-style -+ Swift URIs have where a username can contain a ':', like so: -+ -+ swift://account:user:pass@authurl.com/container/obj -+ """ -+ # Make sure that URIs that contain multiple schemes, such as: -+ # swift://user:pass@http://authurl.com/v1/container/obj -+ # are immediately rejected. -+ if uri.count('://') != 1: -+ reason = _( -+ "URI cannot contain more than one occurrence of a scheme." -+ "If you have specified a URI like " -+ "swift://user:pass@http://authurl.com/v1/container/obj" -+ ", you need to change it to use the swift+http:// scheme, " -+ "like so: " -+ "swift+http://user:pass@authurl.com/v1/container/obj" -+ ) -+ raise exception.BadStoreUri(uri, reason) -+ -+ pieces = urlparse.urlparse(uri) -+ assert pieces.scheme in ('swift', 'swift+http', 'swift+https') -+ self.scheme = pieces.scheme -+ netloc = pieces.netloc -+ path = pieces.path.lstrip('/') -+ if netloc != '': -+ # > Python 2.6.1 -+ if '@' in netloc: -+ creds, netloc = netloc.split('@') -+ else: -+ creds = None -+ else: -+ # Python 2.6.1 compat -+ # see lp659445 and Python issue7904 -+ if '@' in path: -+ creds, path = path.split('@') -+ else: -+ creds = None -+ netloc = path[0:path.find('/')].strip('/') -+ path = path[path.find('/'):].strip('/') -+ if creds: -+ cred_parts = creds.split(':') -+ -+ # User can be account:user, in which case cred_parts[0:2] will be -+ # the account and user. Combine them into a single username of -+ # account:user -+ if len(cred_parts) == 1: -+ reason = (_("Badly formed credentials '%(creds)s' in Swift " -+ "URI") % locals()) -+ raise exception.BadStoreUri(uri, reason) -+ elif len(cred_parts) == 3: -+ user = ':'.join(cred_parts[0:2]) -+ else: -+ user = cred_parts[0] -+ key = cred_parts[-1] -+ self.user = user -+ self.key = key -+ else: -+ self.user = None -+ path_parts = path.split('/') -+ try: -+ self.obj = path_parts.pop() -+ self.container = path_parts.pop() -+ if not netloc.startswith('http'): -+ # push hostname back into the remaining to build full authurl -+ path_parts.insert(0, netloc) -+ self.authurl = '/'.join(path_parts) -+ except IndexError: -+ reason = _("Badly formed Swift URI") -+ raise exception.BadStoreUri(uri, reason) -+ -+ @property -+ def swift_auth_url(self): -+ """ -+ Creates a fully-qualified auth url that the Swift client library can -+ use. The scheme for the auth_url is determined using the scheme -+ included in the `location` field. -+ -+ HTTPS is assumed, unless 'swift+http' is specified. -+ """ -+ if self.scheme in ('swift+https', 'swift'): -+ auth_scheme = 'https://' -+ else: -+ auth_scheme = 'http://' -+ -+ full_url = ''.join([auth_scheme, self.authurl]) -+ return full_url -+ -+ -+class Store(glance.store.base.Store): -+ """An implementation of the swift backend adapter.""" -+ -+ EXAMPLE_URL = "swift://<USER>:<KEY>@<AUTH_ADDRESS>/<CONTAINER>/<FILE>" -+ -+ CHUNKSIZE = 65536 -+ -+ opts = [ -+ cfg.BoolOpt('swift_enable_snet', default=False), -+ cfg.StrOpt('swift_store_auth_address'), -+ cfg.StrOpt('swift_store_user'), -+ cfg.StrOpt('swift_store_key'), -+ cfg.StrOpt('swift_store_container', -+ default=DEFAULT_CONTAINER), -+ cfg.IntOpt('swift_store_large_object_size', -+ default=DEFAULT_LARGE_OBJECT_SIZE), -+ cfg.IntOpt('swift_store_large_object_chunk_size', -+ default=DEFAULT_LARGE_OBJECT_CHUNK_SIZE), -+ cfg.BoolOpt('swift_store_create_container_on_put', default=False), -+ ] -+ -+ def configure(self): -+ self.conf.register_opts(self.opts) -+ self.snet = self.conf.swift_enable_snet -+ -+ def configure_add(self): -+ """ -+ Configure the Store to use the stored configuration options -+ Any store that needs special configuration should implement -+ this method. If the store was not able to successfully configure -+ itself, it should raise `exception.BadStoreConfiguration` -+ """ -+ self.auth_address = self._option_get('swift_store_auth_address') -+ self.user = self._option_get('swift_store_user') -+ self.key = self._option_get('swift_store_key') -+ self.container = self.conf.swift_store_container -+ try: -+ # The config file has swift_store_large_object_*size in MB, but -+ # internally we store it in bytes, since the image_size parameter -+ # passed to add() is also in bytes. -+ self.large_object_size = \ -+ self.conf.swift_store_large_object_size * ONE_MB -+ self.large_object_chunk_size = \ -+ self.conf.swift_store_large_object_chunk_size * ONE_MB -+ except cfg.ConfigFileValueError, e: -+ reason = _("Error in configuration conf: %s") % e -+ logger.error(reason) -+ raise exception.BadStoreConfiguration(store_name="swift", -+ reason=reason) -+ -+ self.scheme = 'swift+https' -+ if self.auth_address.startswith('http://'): -+ self.scheme = 'swift+http' -+ self.full_auth_address = self.auth_address -+ elif self.auth_address.startswith('https://'): -+ self.full_auth_address = self.auth_address -+ else: # Defaults https -+ self.full_auth_address = 'https://' + self.auth_address -+ -+ def get(self, location): -+ """ -+ Takes a `glance.store.location.Location` object that indicates -+ where to find the image file, and returns a tuple of generator -+ (for reading the image file) and image_size -+ -+ :param location `glance.store.location.Location` object, supplied -+ from glance.store.location.get_location_from_uri() -+ :raises `glance.exception.NotFound` if image does not exist -+ """ -+ loc = location.store_location -+ swift_conn = self._make_swift_connection( -+ auth_url=loc.swift_auth_url, user=loc.user, key=loc.key) -+ -+ try: -+ (resp_headers, resp_body) = swift_conn.get_object( -+ container=loc.container, obj=loc.obj, -+ resp_chunk_size=self.CHUNKSIZE) -+ except swift_client.ClientException, e: -+ if e.http_status == httplib.NOT_FOUND: -+ uri = location.get_store_uri() -+ raise exception.NotFound(_("Swift could not find image at " -+ "uri %(uri)s") % locals()) -+ else: -+ raise -+ -+ class ResponseIndexable(glance.store.Indexable): -+ def another(self): -+ try: -+ return self.wrapped.next() -+ except StopIteration: -+ return '' -+ -+ length = resp_headers.get('content-length') -+ return (ResponseIndexable(resp_body, length), length) -+ -+ def get_size(self, location): -+ """ -+ Takes a `glance.store.location.Location` object that indicates -+ where to find the image file, and returns the image_size (or 0 -+ if unavailable) -+ -+ :param location `glance.store.location.Location` object, supplied -+ from glance.store.location.get_location_from_uri() -+ """ -+ loc = location.store_location -+ swift_conn = self._make_swift_connection( -+ auth_url=loc.swift_auth_url, user=loc.user, key=loc.key) -+ -+ try: -+ resp_headers = swift_conn.head_object(container=loc.container, -+ obj=loc.obj) -+ return resp_headers.get('content-length', 0) -+ except Exception: -+ return 0 -+ -+ def _make_swift_connection(self, auth_url, user, key): -+ """ -+ Creates a connection using the Swift client library. -+ """ -+ snet = self.snet -+ logger.debug(_("Creating Swift connection with " -+ "(auth_address=%(auth_url)s, user=%(user)s, " -+ "snet=%(snet)s)") % locals()) -+ return swift_client.Connection( -+ authurl=auth_url, user=user, key=key, snet=snet) -+ -+ def _option_get(self, param): -+ result = getattr(self.conf, param) -+ if not result: -+ reason = (_("Could not find %(param)s in configuration " -+ "options.") % locals()) -+ logger.error(reason) -+ raise exception.BadStoreConfiguration(store_name="swift", -+ reason=reason) -+ return result -+ -+ def add(self, image_id, image_file, image_size): -+ """ -+ Stores an image file with supplied identifier to the backend -+ storage system and returns an `glance.store.ImageAddResult` object -+ containing information about the stored image. -+ -+ :param image_id: The opaque image identifier -+ :param image_file: The image data to write, as a file-like object -+ :param image_size: The size of the image data to write, in bytes -+ -+ :retval `glance.store.ImageAddResult` object -+ :raises `glance.common.exception.Duplicate` if the image already -+ existed -+ -+ Swift writes the image data using the scheme: -+ ``swift://<USER>:<KEY>@<AUTH_ADDRESS>/<CONTAINER>/<ID>` -+ where: -+ <USER> = ``swift_store_user`` -+ <KEY> = ``swift_store_key`` -+ <AUTH_ADDRESS> = ``swift_store_auth_address`` -+ <CONTAINER> = ``swift_store_container`` -+ <ID> = The id of the image being added -+ -+ :note Swift auth URLs by default use HTTPS. To specify an HTTP -+ auth URL, you can specify http://someurl.com for the -+ swift_store_auth_address config option -+ -+ :note Swift cannot natively/transparently handle objects >5GB -+ in size. So, if the image is greater than 5GB, we write -+ chunks of image data to Swift and then write an manifest -+ to Swift that contains information about the chunks. -+ This same chunking process is used by default for images -+ of an unknown size, as pushing them directly to swift would -+ fail if the image turns out to be greater than 5GB. -+ """ -+ swift_conn = self._make_swift_connection( -+ auth_url=self.full_auth_address, user=self.user, key=self.key) -+ -+ create_container_if_missing(self.container, swift_conn, self.conf) -+ -+ obj_name = str(image_id) -+ location = StoreLocation({'scheme': self.scheme, -+ 'container': self.container, -+ 'obj': obj_name, -+ 'authurl': self.auth_address, -+ 'user': self.user, -+ 'key': self.key}) -+ -+ logger.debug(_("Adding image object '%(obj_name)s' " -+ "to Swift") % locals()) -+ try: -+ if image_size > 0 and image_size < self.large_object_size: -+ # Image size is known, and is less than large_object_size. -+ # Send to Swift with regular PUT. -+ obj_etag = swift_conn.put_object(self.container, obj_name, -+ image_file, -+ content_length=image_size) -+ else: -+ # Write the image into Swift in chunks. -+ chunk_id = 1 -+ if image_size > 0: -+ total_chunks = str(int( -+ math.ceil(float(image_size) / -+ float(self.large_object_chunk_size)))) -+ else: -+ # image_size == 0 is when we don't know the size -+ # of the image. This can occur with older clients -+ # that don't inspect the payload size. -+ logger.debug(_("Cannot determine image size. Adding as a " -+ "segmented object to Swift.")) -+ total_chunks = '?' -+ -+ checksum = hashlib.md5() -+ combined_chunks_size = 0 -+ while True: -+ chunk_size = self.large_object_chunk_size -+ if image_size == 0: -+ content_length = None -+ else: -+ left = image_size - combined_chunks_size -+ if left == 0: -+ break -+ if chunk_size > left: -+ chunk_size = left -+ content_length = chunk_size -+ -+ chunk_name = "%s-%05d" % (obj_name, chunk_id) -+ reader = ChunkReader(image_file, checksum, chunk_size) -+ chunk_etag = swift_conn.put_object( -+ self.container, chunk_name, reader, -+ content_length=content_length) -+ bytes_read = reader.bytes_read -+ logger.debug(_("Wrote chunk %(chunk_id)d/" -+ "%(total_chunks)s of length %(bytes_read)d " -+ "to Swift returning MD5 of content: " -+ "%(chunk_etag)s") -+ % locals()) -+ -+ if bytes_read == 0: -+ # Delete the last chunk, because it's of zero size. -+ # This will happen if image_size == 0. -+ logger.debug(_("Deleting final zero-length chunk")) -+ swift_conn.delete_object(self.container, chunk_name) -+ break -+ -+ chunk_id += 1 -+ combined_chunks_size += bytes_read -+ -+ # In the case we have been given an unknown image size, -+ # set the image_size to the total size of the combined chunks. -+ if image_size == 0: -+ image_size = combined_chunks_size -+ -+ # Now we write the object manifest and return the -+ # manifest's etag... -+ manifest = "%s/%s" % (self.container, obj_name) -+ headers = {'ETag': hashlib.md5("").hexdigest(), -+ 'X-Object-Manifest': manifest} -+ -+ # The ETag returned for the manifest is actually the -+ # MD5 hash of the concatenated checksums of the strings -+ # of each chunk...so we ignore this result in favour of -+ # the MD5 of the entire image file contents, so that -+ # users can verify the image file contents accordingly -+ swift_conn.put_object(self.container, obj_name, -+ None, headers=headers) -+ obj_etag = checksum.hexdigest() -+ -+ # NOTE: We return the user and key here! Have to because -+ # location is used by the API server to return the actual -+ # image data. We *really* should consider NOT returning -+ # the location attribute from GET /images/<ID> and -+ # GET /images/details -+ -+ return (location.get_uri(), image_size, obj_etag) -+ except swift_client.ClientException, e: -+ if e.http_status == httplib.CONFLICT: -+ raise exception.Duplicate(_("Swift already has an image at " -+ "location %s") % location.get_uri()) -+ msg = (_("Failed to add object to Swift.\n" -+ "Got error from Swift: %(e)s") % locals()) -+ logger.error(msg) -+ raise glance.store.BackendException(msg) -+ -+ def delete(self, location): -+ """ -+ Takes a `glance.store.location.Location` object that indicates -+ where to find the image file to delete -+ -+ :location `glance.store.location.Location` object, supplied -+ from glance.store.location.get_location_from_uri() -+ -+ :raises NotFound if image does not exist -+ """ -+ loc = location.store_location -+ swift_conn = self._make_swift_connection( -+ auth_url=loc.swift_auth_url, user=loc.user, key=loc.key) -+ -+ try: -+ # We request the manifest for the object. If one exists, -+ # that means the object was uploaded in chunks/segments, -+ # and we need to delete all the chunks as well as the -+ # manifest. -+ manifest = None -+ try: -+ headers = swift_conn.head_object(loc.container, loc.obj) -+ manifest = headers.get('x-object-manifest') -+ except swift_client.ClientException, e: -+ if e.http_status != httplib.NOT_FOUND: -+ raise -+ if manifest: -+ # Delete all the chunks before the object manifest itself -+ obj_container, obj_prefix = manifest.split('/', 1) -+ for segment in swift_conn.get_container(obj_container, -+ prefix=obj_prefix)[1]: -+ # TODO(jaypipes): This would be an easy area to parallelize -+ # since we're simply sending off parallelizable requests -+ # to Swift to delete stuff. It's not like we're going to -+ # be hogging up network or file I/O here... -+ swift_conn.delete_object(obj_container, segment['name']) -+ -+ else: -+ swift_conn.delete_object(loc.container, loc.obj) -+ -+ except swift_client.ClientException, e: -+ if e.http_status == httplib.NOT_FOUND: -+ uri = location.get_store_uri() -+ raise exception.NotFound(_("Swift could not find image at " -+ "uri %(uri)s") % locals()) -+ else: -+ raise -+ -+ -+class ChunkReader(object): -+ def __init__(self, fd, checksum, total): -+ self.fd = fd -+ self.checksum = checksum -+ self.total = total -+ self.bytes_read = 0 -+ -+ def read(self, i): -+ left = self.total - self.bytes_read -+ if i > left: -+ i = left -+ result = self.fd.read(i) -+ self.bytes_read += len(result) -+ self.checksum.update(result) -+ return result -+ -+ -+def create_container_if_missing(container, swift_conn, conf): -+ """ -+ Creates a missing container in Swift if the -+ ``swift_store_create_container_on_put`` option is set. -+ -+ :param container: Name of container to create -+ :param swift_conn: Connection to Swift -+ :param conf: Option mapping -+ """ -+ try: -+ swift_conn.head_container(container) -+ except swift_client.ClientException, e: -+ if e.http_status == httplib.NOT_FOUND: -+ if conf.swift_store_create_container_on_put: -+ try: -+ swift_conn.put_container(container) -+ except swift_client.ClientException, e: -+ msg = _("Failed to add container to Swift.\n" -+ "Got error from Swift: %(e)s") % locals() -+ raise glance.store.BackendException(msg) -+ else: -+ msg = (_("The container %(container)s does not exist in " -+ "Swift. Please set the " -+ "swift_store_create_container_on_put option" -+ "to add container to Swift automatically.") -+ % locals()) -+ raise glance.store.BackendException(msg) -+ else: -+ raise -+ -+ -+glance.store.register_store(__name__, ['swift', 'swift+http', 'swift+https']) -diff -urN glance-2012.1.orig/glance/store/swift.py.rej glance-2012.1/glance/store/swift.py.rej ---- glance-2012.1.orig/glance/store/swift.py.rej 1970-01-01 01:00:00.000000000 +0100 -+++ glance-2012.1/glance/store/swift.py.rej 2012-03-28 17:48:31.000000000 +0200 -@@ -0,0 +1,16 @@ -+*************** -+*** 192,197 **** -+ cfg.StrOpt('swift_store_auth_address'), -+ cfg.StrOpt('swift_store_user', secret=True), -+ cfg.StrOpt('swift_store_key', secret=True), -+ cfg.StrOpt('swift_store_container', -+ default=DEFAULT_CONTAINER), -+ cfg.IntOpt('swift_store_large_object_size', -+--- 192,198 ---- -+ cfg.StrOpt('swift_store_auth_address'), -+ cfg.StrOpt('swift_store_user', secret=True), -+ cfg.StrOpt('swift_store_key', secret=True), -++ cfg.StrOpt('swift_store_auth_version', default='2'), -+ cfg.StrOpt('swift_store_container', -+ default=DEFAULT_CONTAINER), -+ cfg.IntOpt('swift_store_large_object_size', -diff -urN glance-2012.1.orig/glance/tests/unit/test_swift_store.py glance-2012.1/glance/tests/unit/test_swift_store.py ---- glance-2012.1.orig/glance/tests/unit/test_swift_store.py 2012-03-21 10:51:12.000000000 +0100 -+++ glance-2012.1/glance/tests/unit/test_swift_store.py 2012-03-28 17:48:31.000000000 +0200 -@@ -52,7 +52,7 @@ - # We stub out as little as possible to ensure that the code paths - # between glance.store.swift and swift.common.client are tested - # thoroughly --def stub_out_swift_common_client(stubs): -+def stub_out_swift_common_client(stubs, conf): - - fixture_containers = ['glance'] - fixture_headers = {'glance/%s' % FAKE_UUID: -@@ -158,9 +158,13 @@ - def fake_http_connection(*args, **kwargs): - return None - -- def fake_get_auth(url, *args, **kwargs): -+ def fake_get_auth(url, user, key, snet, auth_version, **kwargs): - if 'http' in url and '://' not in url: - raise ValueError('Invalid url %s' % url) -+ # Check the auth version against the configured value -+ if conf['swift_store_auth_version'] != auth_version: -+ msg = 'AUTHENTICATION failed (version mismatch)' -+ raise swift.common.client.ClientException(msg) - return None, None - - stubs.Set(swift.common.client, -@@ -181,17 +185,16 @@ - 'http_connection', fake_http_connection) - - --class TestStore(unittest.TestCase): -+class SwiftTests(object): - -- def setUp(self): -- """Establish a clean test environment""" -- self.stubs = stubout.StubOutForTesting() -- stub_out_swift_common_client(self.stubs) -- self.store = Store(test_utils.TestConfigOpts(SWIFT_CONF)) -- -- def tearDown(self): -- """Clear the test environment""" -- self.stubs.UnsetAll() -+ def test_get_size(self): -+ """ -+ Test that we can get the size of an object in the swift store -+ """ -+ uri = "swift://user:key@auth_address/glance/%s" % FAKE_UUID -+ loc = get_location_from_uri(uri) -+ image_size = self.store.get_size(loc) -+ self.assertEqual(image_size, 5120) - - def test_get(self): - """Test a "normal" retrieval of an image in chunks""" -@@ -298,15 +301,14 @@ - expected_swift_contents = "*" * expected_swift_size - expected_checksum = \ - hashlib.md5(expected_swift_contents).hexdigest() -- new_conf = SWIFT_CONF.copy() -- new_conf['swift_store_auth_address'] = variation -+ self.conf['swift_store_auth_address'] = variation - - image_swift = StringIO.StringIO(expected_swift_contents) - - global SWIFT_PUT_OBJECT_CALLS - SWIFT_PUT_OBJECT_CALLS = 0 - -- self.store = Store(test_utils.TestConfigOpts(new_conf)) -+ self.store = Store(test_utils.TestConfigOpts(self.conf)) - location, size, checksum = self.store.add(image_id, image_swift, - expected_swift_size) - -@@ -328,11 +330,10 @@ - Tests that adding an image with a non-existing container - raises an appropriate exception - """ -- conf = SWIFT_CONF.copy() -- conf['swift_store_create_container_on_put'] = 'False' -- conf['swift_store_container'] = 'noexist' -+ self.conf['swift_store_create_container_on_put'] = 'False' -+ self.conf['swift_store_container'] = 'noexist' - image_swift = StringIO.StringIO("nevergonnamakeit") -- self.store = Store(test_utils.TestConfigOpts(conf)) -+ self.store = Store(test_utils.TestConfigOpts(self.conf)) - - global SWIFT_PUT_OBJECT_CALLS - SWIFT_PUT_OBJECT_CALLS = 0 -@@ -355,9 +356,8 @@ - Tests that adding an image with a non-existing container - creates the container automatically if flag is set - """ -- conf = SWIFT_CONF.copy() -- conf['swift_store_create_container_on_put'] = 'True' -- conf['swift_store_container'] = 'noexist' -+ self.conf['swift_store_create_container_on_put'] = 'True' -+ self.conf['swift_store_container'] = 'noexist' - expected_swift_size = FIVE_KB - expected_swift_contents = "*" * expected_swift_size - expected_checksum = hashlib.md5(expected_swift_contents).hexdigest() -@@ -369,7 +369,7 @@ - global SWIFT_PUT_OBJECT_CALLS - SWIFT_PUT_OBJECT_CALLS = 0 - -- self.store = Store(test_utils.TestConfigOpts(conf)) -+ self.store = Store(test_utils.TestConfigOpts(self.conf)) - location, size, checksum = self.store.add(expected_image_id, - image_swift, - expected_swift_size) -@@ -394,8 +394,7 @@ - and then verify that there have been a number of calls to - put_object()... - """ -- conf = SWIFT_CONF.copy() -- conf['swift_store_container'] = 'glance' -+ self.conf['swift_store_container'] = 'glance' - expected_swift_size = FIVE_KB - expected_swift_contents = "*" * expected_swift_size - expected_checksum = hashlib.md5(expected_swift_contents).hexdigest() -@@ -407,7 +406,7 @@ - global SWIFT_PUT_OBJECT_CALLS - SWIFT_PUT_OBJECT_CALLS = 0 - -- self.store = Store(test_utils.TestConfigOpts(conf)) -+ self.store = Store(test_utils.TestConfigOpts(self.conf)) - orig_max_size = self.store.large_object_size - orig_temp_size = self.store.large_object_chunk_size - try: -@@ -446,8 +445,7 @@ - - Bug lp:891738 - """ -- conf = SWIFT_CONF.copy() -- conf['swift_store_container'] = 'glance' -+ self.conf['swift_store_container'] = 'glance' - - # Set up a 'large' image of 5KB - expected_swift_size = FIVE_KB -@@ -463,7 +461,7 @@ - - # Temporarily set Swift MAX_SWIFT_OBJECT_SIZE to 1KB and add our image, - # explicitly setting the image_length to 0 -- self.store = Store(test_utils.TestConfigOpts(conf)) -+ self.store = Store(test_utils.TestConfigOpts(self.conf)) - orig_max_size = self.store.large_object_size - orig_temp_size = self.store.large_object_chunk_size - global MAX_SWIFT_OBJECT_SIZE -@@ -507,11 +505,10 @@ - FAKE_UUID, image_swift, 0) - - def _option_required(self, key): -- conf = SWIFT_CONF.copy() -- del conf[key] -+ del self.conf[key] - - try: -- self.store = Store(test_utils.TestConfigOpts(conf)) -+ self.store = Store(test_utils.TestConfigOpts(self.conf)) - return self.store.add == self.store.add_disabled - except: - return False -@@ -554,6 +551,32 @@ - self.assertRaises(exception.NotFound, self.store.delete, loc) - - -+class TestStoreAuthV1(unittest.TestCase, SwiftTests): -+ -+ def setUp(self): -+ """Establish a clean test environment""" -+ self.conf = SWIFT_CONF.copy() -+ self.conf['swift_store_auth_version'] = '1' -+ self.stubs = stubout.StubOutForTesting() -+ stub_out_swift_common_client(self.stubs, self.conf) -+ self.store = Store(test_utils.TestConfigOpts(self.conf)) -+ -+ def tearDown(self): -+ """Clear the test environment""" -+ self.stubs.UnsetAll() -+ -+ -+class TestStoreAuthV2(TestStoreAuthV1): -+ -+ def setUp(self): -+ """Establish a clean test environment""" -+ self.conf = SWIFT_CONF.copy() -+ self.conf['swift_store_auth_version'] = '2' -+ self.stubs = stubout.StubOutForTesting() -+ stub_out_swift_common_client(self.stubs, self.conf) -+ self.store = Store(test_utils.TestConfigOpts(self.conf)) -+ -+ - class TestChunkReader(unittest.TestCase): - - def test_read_all_data(self): diff --git a/app-admin/glance/glance-2012.2.ebuild b/app-admin/glance/glance-2012.2.1.ebuild index 6a83a04..22fd593 100644 --- a/app-admin/glance/glance-2012.2.ebuild +++ b/app-admin/glance/glance-2012.2.1.ebuild @@ -1,14 +1,11 @@ -# Copyright 1999-2012 Gentoo Foundation +# Copyright 1999-2013 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ -EAPI=4 +EAPI=5 +PYTHON_COMPAT=( python2_7 ) -PYTHON_DEPENDS="2" -SUPPORT_PYTHON_ABIS="1" -RESTRICT_PYTHON_ABIS="3.*" - -inherit distutils +inherit distutils-r1 DESCRIPTION="Provides services for discovering, registering, and retrieving virtual machine images with Openstack" @@ -17,45 +14,41 @@ SRC_URI="http://launchpad.net/${PN}/folsom/${PV}/+download/${P}.tar.gz" LICENSE="Apache-2.0" SLOT="0" -KEYWORDS="~amd64" +KEYWORDS="~amd64 ~x86" IUSE="ldap mysql postgres +sqlite +swift" +REQUIRED_USE="|| ( ldap mysql postgres sqlite )" -DEPEND="" +DEPEND="dev-python/setuptools[${PYTHON_USEDEP}]" RDEPEND="${DEPEND} >=dev-python/boto-2.1.1 - dev-python/anyjson + dev-python/anyjson[${PYTHON_USEDEP}] dev-python/eventlet dev-python/greenlet - dev-python/httplib2 - dev-python/iso8601 - dev-python/jsonschema + dev-python/httplib2[${PYTHON_USEDEP}] + dev-python/iso8601[${PYTHON_USEDEP}] + dev-python/jsonschema[${PYTHON_USEDEP}] dev-python/kombu - dev-python/lxml - dev-python/passlib + dev-python/lxml[${PYTHON_USEDEP}] + dev-python/passlib[${PYTHON_USEDEP}] dev-python/paste dev-python/pastedeploy dev-python/pycrypto + dev-python/python-glanceclient[${PYTHON_USEDEP}] dev-python/routes >=dev-python/sqlalchemy-migrate-0.7 >=dev-python/webob-1.0.8 - virtual/python-argparse + virtual/python-argparse[${PYTHON_USEDEP}] swift? ( - >=dev-python/python-swiftclient-1.2 - <dev-python/python-swiftclient-2 + >=dev-python/python-swiftclient-1.2[${PYTHON_USEDEP}] + <dev-python/python-swiftclient-2[${PYTHON_USEDEP}] ) sqlite? ( dev-python/sqlalchemy[sqlite] ) mysql? ( dev-python/sqlalchemy[mysql] ) postgres? ( dev-python/sqlalchemy[postgres] ) - ldap? ( dev-python/python-ldap ) - ( || ( - app-admin/glance[sqlite] - app-admin/glance[mysql] - app-admin/glance[postgres] - app-admin/glance[ldap] - ) )" + ldap? ( dev-python/python-ldap )" -src_install() { - distutils_src_install +python_install() { + distutils-r1_python_install newconfd "${FILESDIR}/glance.confd" glance newinitd "${FILESDIR}/glance.initd" glance @@ -65,4 +58,6 @@ src_install() { diropts -m 0750 dodir /var/run/glance /var/log/nova /var/lock/nova + #removed because it conflicts with glanceclient, which we install in rdepend + rm ${D}"/usr/bin/glance" } diff --git a/app-admin/glance/glance-9999.ebuild b/app-admin/glance/glance-9999.ebuild index e94264e..0120011 100644 --- a/app-admin/glance/glance-9999.ebuild +++ b/app-admin/glance/glance-9999.ebuild @@ -1,13 +1,11 @@ -# Copyright 1999-2012 Gentoo Foundation +# Copyright 1999-2013 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ -EAPI=3 -PYTHON_DEPENDS="2" -SUPPORT_PYTHON_ABIS="1" -RESTRICT_PYTHON_ABIS="3.*" +EAPI=5 +PYTHON_COMPAT=( python2_7 ) -inherit git-2 distutils +inherit git-2 distutils-r1 DESCRIPTION="Provides services for discovering, registering, and retrieving virtual machine images with Openstack" @@ -16,21 +14,41 @@ EGIT_REPO_URI="https://github.com/openstack/glance.git" LICENSE="Apache-2.0" SLOT="0" -KEYWORDS="~amd64" -IUSE="" +KEYWORDS="~amd64 ~x86" +IUSE="ldap mysql postgres +sqlite +swift" +REQUIRED_USE="|| ( ldap mysql postgres sqlite )" -DEPEND="dev-python/setuptools" +DEPEND="dev-python/setuptools[${PYTHON_USEDEP}]" RDEPEND="${DEPEND} - dev-python/webob - dev-python/httplib2 - dev-python/routes - dev-python/paste - dev-python/pastedeploy - dev-python/pyxattr - dev-python/kombu" - -src_install() { - distutils_src_install + >=dev-python/boto-2.1.1 + dev-python/anyjson[${PYTHON_USEDEP}] + dev-python/eventlet + dev-python/greenlet + dev-python/httplib2[${PYTHON_USEDEP}] + dev-python/iso8601[${PYTHON_USEDEP}] + dev-python/jsonschema[${PYTHON_USEDEP}] + dev-python/kombu + dev-python/lxml[${PYTHON_USEDEP}] + dev-python/passlib[${PYTHON_USEDEP}] + dev-python/paste + dev-python/pastedeploy + dev-python/pycrypto + dev-python/python-glanceclient[${PYTHON_USEDEP}] + dev-python/routes + >=dev-python/sqlalchemy-migrate-0.7 + >=dev-python/webob-1.0.8 + virtual/python-argparse[${PYTHON_USEDEP}] + swift? ( + >=dev-python/python-swiftclient-1.2[${PYTHON_USEDEP}] + <dev-python/python-swiftclient-2[${PYTHON_USEDEP}] + ) + sqlite? ( dev-python/sqlalchemy[sqlite] ) + mysql? ( dev-python/sqlalchemy[mysql] ) + postgres? ( dev-python/sqlalchemy[postgres] ) + ldap? ( dev-python/python-ldap )" + +python_install() { + distutils-r1_python_install newconfd "${FILESDIR}/glance.confd" glance newinitd "${FILESDIR}/glance.initd" glance @@ -40,4 +58,6 @@ src_install() { diropts -m 0750 dodir /var/run/glance /var/log/nova /var/lock/nova + #removed because it conflicts with glanceclient, which we install in rdepend + rm ${D}"/usr/bin/glance" } |