summaryrefslogtreecommitdiff
path: root/tests/unit/test_swift_store.py
diff options
context:
space:
mode:
authorFlavio Percoco <flaper87@gmail.com>2014-07-17 09:48:37 +0200
committerFlavio Percoco <flaper87@gmail.com>2014-07-17 11:53:18 +0200
commit2450528776035950898607dc0436da0515934244 (patch)
tree63dbe54fc4d638ddac09ce2be9fa78c2e4634bab /tests/unit/test_swift_store.py
parent80af4f414ab236daf7aa04519233c71cad7cf623 (diff)
downloadglance_store-2450528776035950898607dc0436da0515934244.tar.gz
Add .gitreview to the repo
This patch also removes `swift` related code until we port it. Change-Id: I5c78af7334cb39e6d32afe7ca342f91c5521d30b
Diffstat (limited to 'tests/unit/test_swift_store.py')
-rw-r--r--tests/unit/test_swift_store.py965
1 files changed, 0 insertions, 965 deletions
diff --git a/tests/unit/test_swift_store.py b/tests/unit/test_swift_store.py
deleted file mode 100644
index eaa2a14..0000000
--- a/tests/unit/test_swift_store.py
+++ /dev/null
@@ -1,965 +0,0 @@
-# Copyright 2011 OpenStack Foundation
-# 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.
-
-"""Tests the Swift backend store"""
-
-import hashlib
-import httplib
-import mock
-import StringIO
-import tempfile
-import urllib
-import uuid
-
-from oslo.config import cfg
-import swiftclient
-
-from glance.store import exceptions
-from glance.store.location import get_location_from_uri
-from glance.store._drivers import swift
-from glance.tests.unit import base
-
-CONF = cfg.CONF
-
-FAKE_UUID = lambda: str(uuid.uuid4())
-
-Store = glance.store.swift.Store
-FIVE_KB = 5 * 1024
-FIVE_GB = 5 * 1024 * 3
-MAX_SWIFT_OBJECT_SIZE = FIVE_GB
-SWIFT_PUT_OBJECT_CALLS = 0
-SWIFT_CONF = {'verbose': True,
- 'debug': True,
- 'known_stores': ['glance.store.swift.Store'],
- 'default_store': 'swift',
- 'swift_store_user': 'user',
- 'swift_store_key': 'key',
- 'swift_store_auth_address': 'localhost:8080',
- 'swift_store_container': 'glance'}
-
-
-# We stub out as little as possible to ensure that the code paths
-# between glance.store.swift and swiftclient are tested
-# thoroughly
-def stub_out_swiftclient(test, swift_store_auth_version):
- fixture_containers = ['glance']
- fixture_container_headers = {}
- fixture_headers = {
- 'glance/%s' % FAKE_UUID: {
- 'content-length': FIVE_KB,
- 'etag': 'c2e5db72bd7fd153f53ede5da5a06de3'
- }
- }
- fixture_objects = {'glance/%s' % FAKE_UUID:
- StringIO.StringIO("*" * FIVE_KB)}
-
- def fake_head_container(url, token, container, **kwargs):
- if container not in fixture_containers:
- msg = "No container %s found" % container
- raise swiftclient.ClientException(msg,
- http_status=httplib.NOT_FOUND)
- return fixture_container_headers
-
- def fake_put_container(url, token, container, **kwargs):
- fixture_containers.append(container)
-
- def fake_post_container(url, token, container, headers, http_conn=None):
- for key, value in headers.iteritems():
- fixture_container_headers[key] = value
-
- def fake_put_object(url, token, container, name, contents, **kwargs):
- # PUT returns the ETag header for the newly-added object
- # Large object manifest...
- global SWIFT_PUT_OBJECT_CALLS
- SWIFT_PUT_OBJECT_CALLS += 1
- CHUNKSIZE = 64 * units.Ki
- fixture_key = "%s/%s" % (container, name)
- if fixture_key not in fixture_headers:
- if kwargs.get('headers'):
- etag = kwargs['headers']['ETag']
- fixture_headers[fixture_key] = {'manifest': True,
- 'etag': etag}
- return etag
- if hasattr(contents, 'read'):
- fixture_object = StringIO.StringIO()
- chunk = contents.read(CHUNKSIZE)
- checksum = hashlib.md5()
- while chunk:
- fixture_object.write(chunk)
- checksum.update(chunk)
- chunk = contents.read(CHUNKSIZE)
- etag = checksum.hexdigest()
- else:
- fixture_object = StringIO.StringIO(contents)
- etag = hashlib.md5(fixture_object.getvalue()).hexdigest()
- read_len = fixture_object.len
- if read_len > MAX_SWIFT_OBJECT_SIZE:
- msg = ('Image size:%d exceeds Swift max:%d' %
- (read_len, MAX_SWIFT_OBJECT_SIZE))
- raise swiftclient.ClientException(
- msg, http_status=httplib.REQUEST_ENTITY_TOO_LARGE)
- fixture_objects[fixture_key] = fixture_object
- fixture_headers[fixture_key] = {
- 'content-length': read_len,
- 'etag': etag}
- return etag
- else:
- msg = ("Object PUT failed - Object with key %s already exists"
- % fixture_key)
- raise swiftclient.ClientException(msg,
- http_status=httplib.CONFLICT)
-
- def fake_get_object(url, token, container, name, **kwargs):
- # GET returns the tuple (list of headers, file object)
- fixture_key = "%s/%s" % (container, name)
- if fixture_key not in fixture_headers:
- msg = "Object GET failed"
- raise swiftclient.ClientException(msg,
- http_status=httplib.NOT_FOUND)
-
- fixture = fixture_headers[fixture_key]
- if 'manifest' in fixture:
- # Large object manifest... we return a file containing
- # all objects with prefix of this fixture key
- chunk_keys = sorted([k for k in fixture_headers.keys()
- if k.startswith(fixture_key) and
- k != fixture_key])
- result = StringIO.StringIO()
- for key in chunk_keys:
- result.write(fixture_objects[key].getvalue())
- return fixture_headers[fixture_key], result
-
- else:
- return fixture_headers[fixture_key], fixture_objects[fixture_key]
-
- def fake_head_object(url, token, container, name, **kwargs):
- # HEAD returns the list of headers for an object
- try:
- fixture_key = "%s/%s" % (container, name)
- return fixture_headers[fixture_key]
- except KeyError:
- msg = "Object HEAD failed - Object does not exist"
- raise swiftclient.ClientException(msg,
- http_status=httplib.NOT_FOUND)
-
- def fake_delete_object(url, token, container, name, **kwargs):
- # DELETE returns nothing
- fixture_key = "%s/%s" % (container, name)
- if fixture_key not in fixture_headers:
- msg = "Object DELETE failed - Object does not exist"
- raise swiftclient.ClientException(msg,
- http_status=httplib.NOT_FOUND)
- else:
- del fixture_headers[fixture_key]
- del fixture_objects[fixture_key]
-
- def fake_http_connection(*args, **kwargs):
- return None
-
- def fake_get_auth(url, user, key, snet, auth_version, **kwargs):
- if url is None:
- return None, None
- if 'http' in url and '://' not in url:
- raise ValueError('Invalid url %s' % url)
- # Check the auth version against the configured value
- if swift_store_auth_version != auth_version:
- msg = 'AUTHENTICATION failed (version mismatch)'
- raise swiftclient.ClientException(msg)
- return None, None
-
- to_mock = [('head_container', fake_head_container),
- ('put_container', fake_put_container),
- ('post_container', fake_post_container),
- ('put_object', fake_put_object),
- ('delete_object', fake_delete_object),
- ('head_object', fake_head_object),
- ('get_object', fake_get_object),
- ('get_auth', fake_get_auth),
- ('http_connection', fake_http_connection)]
-
- for (meth, fake_meth) in to_mock:
- mocked = mock.patch.object(swiftclient.client, meth).start()
- mocked.side_effect = fake_meth
- test.add_cleanUp(mocked.stop)
-
-
-class SwiftTests(object):
-
- @property
- def swift_store_user(self):
- return urllib.quote(CONF.swift_store_user)
-
- def test_get_size(self):
- """
- Test that we can get the size of an object in the swift store
- """
- uri = "swift://%s:key@auth_address/glance/%s" % (
- self.swift_store_user, FAKE_UUID)
- loc = get_location_from_uri(uri)
- image_size = self.store.get_size(loc)
- self.assertEqual(image_size, 5120)
-
- def test_get_size_with_multi_tenant_on(self):
- """Test that single tenant uris work with multi tenant on."""
- uri = ("swift://%s:key@auth_address/glance/%s" %
- (self.swift_store_user, FAKE_UUID))
- self.config(swift_store_multi_tenant=True)
- #NOTE(markwash): ensure the image is found
- context = glance.context.RequestContext()
- size = glance.store.get_size_from_backend(context, uri)
- self.assertEqual(size, 5120)
-
- def test_get(self):
- """Test a "normal" retrieval of an image in chunks"""
- uri = "swift://%s:key@auth_address/glance/%s" % (
- self.swift_store_user, FAKE_UUID)
- loc = get_location_from_uri(uri)
- (image_swift, image_size) = self.store.get(loc)
- self.assertEqual(image_size, 5120)
-
- expected_data = "*" * FIVE_KB
- data = ""
-
- for chunk in image_swift:
- data += chunk
- self.assertEqual(expected_data, data)
-
- def test_get_with_http_auth(self):
- """
- Test a retrieval from Swift with an HTTP authurl. This is
- specified either via a Location header with swift+http:// or using
- http:// in the swift_store_auth_address config value
- """
- loc = get_location_from_uri("swift+http://%s:key@auth_address/"
- "glance/%s" %
- (self.swift_store_user, FAKE_UUID))
- (image_swift, image_size) = self.store.get(loc)
- self.assertEqual(image_size, 5120)
-
- expected_data = "*" * FIVE_KB
- data = ""
-
- for chunk in image_swift:
- data += chunk
- self.assertEqual(expected_data, data)
-
- def test_get_non_existing(self):
- """
- Test that trying to retrieve a swift that doesn't exist
- raises an error
- """
- loc = get_location_from_uri("swift://%s:key@authurl/glance/noexist" % (
- self.swift_store_user))
- self.assertRaises(exceptions.NotFound,
- self.store.get,
- loc)
-
- def test_add(self):
- """Test that we can add an image via the swift backend"""
- expected_swift_size = FIVE_KB
- expected_swift_contents = "*" * expected_swift_size
- expected_checksum = hashlib.md5(expected_swift_contents).hexdigest()
- expected_image_id = str(uuid.uuid4())
- loc = 'swift+https://%s:key@localhost:8080/glance/%s'
- expected_location = loc % (self.swift_store_user,
- expected_image_id)
- image_swift = StringIO.StringIO(expected_swift_contents)
-
- global SWIFT_PUT_OBJECT_CALLS
- SWIFT_PUT_OBJECT_CALLS = 0
-
- location, size, checksum, _ = self.store.add(expected_image_id,
- image_swift,
- expected_swift_size)
-
- self.assertEqual(expected_location, location)
- self.assertEqual(expected_swift_size, size)
- self.assertEqual(expected_checksum, checksum)
- # Expecting a single object to be created on Swift i.e. no chunking.
- self.assertEqual(SWIFT_PUT_OBJECT_CALLS, 1)
-
- loc = get_location_from_uri(expected_location)
- (new_image_swift, new_image_size) = self.store.get(loc)
- new_image_contents = new_image_swift.getvalue()
- new_image_swift_size = len(new_image_swift)
-
- self.assertEqual(expected_swift_contents, new_image_contents)
- self.assertEqual(expected_swift_size, new_image_swift_size)
-
- def test_add_auth_url_variations(self):
- """
- Test that we can add an image via the swift backend with
- a variety of different auth_address values
- """
- variations = {
- 'http://localhost:80': 'swift+http://%s:key@localhost:80'
- '/glance/%s',
- 'http://localhost': 'swift+http://%s:key@localhost/glance/%s',
- 'http://localhost/v1': 'swift+http://%s:key@localhost'
- '/v1/glance/%s',
- 'http://localhost/v1/': 'swift+http://%s:key@localhost'
- '/v1/glance/%s',
- 'https://localhost': 'swift+https://%s:key@localhost/glance/%s',
- 'https://localhost:8080': 'swift+https://%s:key@localhost:8080'
- '/glance/%s',
- 'https://localhost/v1': 'swift+https://%s:key@localhost'
- '/v1/glance/%s',
- 'https://localhost/v1/': 'swift+https://%s:key@localhost'
- '/v1/glance/%s',
- 'localhost': 'swift+https://%s:key@localhost/glance/%s',
- 'localhost:8080/v1': 'swift+https://%s:key@localhost:8080'
- '/v1/glance/%s',
- }
-
- for variation, expected_location in variations.items():
- image_id = str(uuid.uuid4())
- expected_location = expected_location % (
- self.swift_store_user, image_id)
- expected_swift_size = FIVE_KB
- expected_swift_contents = "*" * expected_swift_size
- expected_checksum = \
- hashlib.md5(expected_swift_contents).hexdigest()
-
- image_swift = StringIO.StringIO(expected_swift_contents)
-
- global SWIFT_PUT_OBJECT_CALLS
- SWIFT_PUT_OBJECT_CALLS = 0
-
- self.config(swift_store_auth_address=variation)
- self.store = Store()
- location, size, checksum, _ = self.store.add(image_id, image_swift,
- expected_swift_size)
-
- self.assertEqual(expected_location, location)
- self.assertEqual(expected_swift_size, size)
- self.assertEqual(expected_checksum, checksum)
- self.assertEqual(SWIFT_PUT_OBJECT_CALLS, 1)
-
- loc = get_location_from_uri(expected_location)
- (new_image_swift, new_image_size) = self.store.get(loc)
- new_image_contents = new_image_swift.getvalue()
- new_image_swift_size = len(new_image_swift)
-
- self.assertEqual(expected_swift_contents, new_image_contents)
- self.assertEqual(expected_swift_size, new_image_swift_size)
-
- def test_add_no_container_no_create(self):
- """
- Tests that adding an image with a non-existing container
- raises an appropriate exception
- """
- self.config(swift_store_create_container_on_put=False,
- swift_store_container='noexist')
- self.store = Store()
-
- image_swift = StringIO.StringIO("nevergonnamakeit")
-
- global SWIFT_PUT_OBJECT_CALLS
- SWIFT_PUT_OBJECT_CALLS = 0
-
- # We check the exception text to ensure the container
- # missing text is found in it, otherwise, we would have
- # simply used self.assertRaises here
- exception_caught = False
- try:
- self.store.add(str(uuid.uuid4()), image_swift, 0)
- except backend.BackendException as e:
- exception_caught = True
- self.assertTrue("container noexist does not exist "
- "in Swift" in str(e))
- self.assertTrue(exception_caught)
- self.assertEqual(SWIFT_PUT_OBJECT_CALLS, 0)
-
- def test_add_no_container_and_create(self):
- """
- Tests that adding an image with a non-existing container
- creates the container automatically if flag is set
- """
- expected_swift_size = FIVE_KB
- expected_swift_contents = "*" * expected_swift_size
- expected_checksum = hashlib.md5(expected_swift_contents).hexdigest()
- expected_image_id = str(uuid.uuid4())
- loc = 'swift+https://%s:key@localhost:8080/noexist/%s'
- expected_location = loc % (self.swift_store_user,
- expected_image_id)
- image_swift = StringIO.StringIO(expected_swift_contents)
-
- global SWIFT_PUT_OBJECT_CALLS
- SWIFT_PUT_OBJECT_CALLS = 0
-
- self.config(swift_store_create_container_on_put=True,
- swift_store_container='noexist')
- self.store = Store()
- location, size, checksum, _ = self.store.add(expected_image_id,
- image_swift,
- expected_swift_size)
-
- self.assertEqual(expected_location, location)
- self.assertEqual(expected_swift_size, size)
- self.assertEqual(expected_checksum, checksum)
- self.assertEqual(SWIFT_PUT_OBJECT_CALLS, 1)
-
- loc = get_location_from_uri(expected_location)
- (new_image_swift, new_image_size) = self.store.get(loc)
- new_image_contents = new_image_swift.getvalue()
- new_image_swift_size = len(new_image_swift)
-
- self.assertEqual(expected_swift_contents, new_image_contents)
- self.assertEqual(expected_swift_size, new_image_swift_size)
-
- def test_add_large_object(self):
- """
- Tests that adding a very large image. We simulate the large
- object by setting store.large_object_size to a small number
- and then verify that there have been a number of calls to
- put_object()...
- """
- expected_swift_size = FIVE_KB
- expected_swift_contents = "*" * expected_swift_size
- expected_checksum = hashlib.md5(expected_swift_contents).hexdigest()
- expected_image_id = str(uuid.uuid4())
- loc = 'swift+https://%s:key@localhost:8080/glance/%s'
- expected_location = loc % (self.swift_store_user,
- expected_image_id)
- image_swift = StringIO.StringIO(expected_swift_contents)
-
- global SWIFT_PUT_OBJECT_CALLS
- SWIFT_PUT_OBJECT_CALLS = 0
-
- self.config(swift_store_container='glance')
- self.store = Store()
- orig_max_size = self.store.large_object_size
- orig_temp_size = self.store.large_object_chunk_size
- try:
- self.store.large_object_size = 1024
- self.store.large_object_chunk_size = 1024
- location, size, checksum, _ = self.store.add(expected_image_id,
- image_swift,
- expected_swift_size)
- finally:
- self.store.large_object_chunk_size = orig_temp_size
- self.store.large_object_size = orig_max_size
-
- self.assertEqual(expected_location, location)
- self.assertEqual(expected_swift_size, size)
- self.assertEqual(expected_checksum, checksum)
- # Expecting 6 objects to be created on Swift -- 5 chunks and 1
- # manifest.
- self.assertEqual(SWIFT_PUT_OBJECT_CALLS, 6)
-
- loc = get_location_from_uri(expected_location)
- (new_image_swift, new_image_size) = self.store.get(loc)
- new_image_contents = new_image_swift.getvalue()
- new_image_swift_size = len(new_image_swift)
-
- self.assertEqual(expected_swift_contents, new_image_contents)
- self.assertEqual(expected_swift_size, new_image_swift_size)
-
- def test_add_large_object_zero_size(self):
- """
- Tests that adding an image to Swift which has both an unknown size and
- exceeds Swift's maximum limit of 5GB is correctly uploaded.
-
- We avoid the overhead of creating a 5GB object for this test by
- temporarily setting MAX_SWIFT_OBJECT_SIZE to 1KB, and then adding
- an object of 5KB.
-
- Bug lp:891738
- """
- # Set up a 'large' image of 5KB
- expected_swift_size = FIVE_KB
- expected_swift_contents = "*" * expected_swift_size
- expected_checksum = hashlib.md5(expected_swift_contents).hexdigest()
- expected_image_id = str(uuid.uuid4())
- loc = 'swift+https://%s:key@localhost:8080/glance/%s'
- expected_location = loc % (self.swift_store_user,
- expected_image_id)
- image_swift = StringIO.StringIO(expected_swift_contents)
-
- global SWIFT_PUT_OBJECT_CALLS
- SWIFT_PUT_OBJECT_CALLS = 0
-
- # Temporarily set Swift MAX_SWIFT_OBJECT_SIZE to 1KB and add our image,
- # explicitly setting the image_length to 0
- self.config(swift_store_container='glance')
- self.store = Store()
- orig_max_size = self.store.large_object_size
- orig_temp_size = self.store.large_object_chunk_size
- global MAX_SWIFT_OBJECT_SIZE
- orig_max_swift_object_size = MAX_SWIFT_OBJECT_SIZE
- try:
- MAX_SWIFT_OBJECT_SIZE = 1024
- self.store.large_object_size = 1024
- self.store.large_object_chunk_size = 1024
- location, size, checksum, _ = self.store.add(expected_image_id,
- image_swift, 0)
- finally:
- self.store.large_object_chunk_size = orig_temp_size
- self.store.large_object_size = orig_max_size
- MAX_SWIFT_OBJECT_SIZE = orig_max_swift_object_size
-
- self.assertEqual(expected_location, location)
- self.assertEqual(expected_swift_size, size)
- self.assertEqual(expected_checksum, checksum)
- # Expecting 7 calls to put_object -- 5 chunks, a zero chunk which is
- # then deleted, and the manifest. Note the difference with above
- # where the image_size is specified in advance (there's no zero chunk
- # in that case).
- self.assertEqual(SWIFT_PUT_OBJECT_CALLS, 7)
-
- loc = get_location_from_uri(expected_location)
- (new_image_swift, new_image_size) = self.store.get(loc)
- new_image_contents = new_image_swift.getvalue()
- new_image_swift_size = len(new_image_swift)
-
- self.assertEqual(expected_swift_contents, new_image_contents)
- self.assertEqual(expected_swift_size, new_image_swift_size)
-
- def test_add_already_existing(self):
- """
- Tests that adding an image with an existing identifier
- raises an appropriate exception
- """
- image_swift = StringIO.StringIO("nevergonnamakeit")
- self.assertRaises(exceptions.Duplicate,
- self.store.add,
- FAKE_UUID, image_swift, 0)
-
- def test_add_saves_and_reraises_and_not_uses_wildcard_raise(self):
- image_id = str(uuid.uuid4())
- swift_size = self.store.large_object_size = 1024
- loc = 'swift+https://%s:key@localhost:8080/glance/%s'
- swift_contents = "*" * swift_size
- connection = mock.Mock()
-
- def fake_delete_chunk(connection,
- container,
- chunks):
- try:
- raise Exception()
- except Exception:
- pass
-
- image_swift = StringIO.StringIO(swift_contents)
- connection.put_object.side_effect = exceptions.ClientConnectionError
- self.store._delete_stale_chunks = fake_delete_chunk
-
- self.assertRaises(exceptions.ClientConnectionError,
- self.store.add,
- image_id,
- image_swift,
- swift_size,
- connection)
-
- def _option_required(self, key):
- conf = self.getConfig()
- conf[key] = None
-
- try:
- self.config(**conf)
- self.store = Store()
- return self.store.add == self.store.add_disabled
- except Exception:
- return False
- return False
-
- def test_no_user(self):
- """
- Tests that options without user disables the add method
- """
- self.assertTrue(self._option_required('swift_store_user'))
-
- def test_no_key(self):
- """
- Tests that options without key disables the add method
- """
- self.assertTrue(self._option_required('swift_store_key'))
-
- def test_no_auth_address(self):
- """
- Tests that options without auth address disables the add method
- """
- self.assertTrue(self._option_required('swift_store_auth_address'))
-
- def test_delete(self):
- """
- Test we can delete an existing image in the swift store
- """
- uri = "swift://%s:key@authurl/glance/%s" % (
- self.swift_store_user, FAKE_UUID)
- loc = get_location_from_uri(uri)
- self.store.delete(loc)
-
- self.assertRaises(exceptions.NotFound, self.store.get, loc)
-
- def test_delete_non_existing(self):
- """
- Test that trying to delete a swift that doesn't exist
- raises an error
- """
- loc = get_location_from_uri("swift://%s:key@authurl/glance/noexist" % (
- self.swift_store_user))
- self.assertRaises(exceptions.NotFound, self.store.delete, loc)
-
- def test_read_acl_public(self):
- """
- Test that we can set a public read acl.
- """
- self.config(swift_store_multi_tenant=True)
- context = glance.context.RequestContext()
- store = Store(context)
- uri = "swift+http://storeurl/glance/%s" % FAKE_UUID
- loc = get_location_from_uri(uri)
- store.set_acls(loc, public=True)
- container_headers = swiftclient.client.head_container('x', 'y',
- 'glance')
- self.assertEqual(container_headers['X-Container-Read'],
- ".r:*,.rlistings")
-
- def test_read_acl_tenants(self):
- """
- Test that we can set read acl for tenants.
- """
- self.config(swift_store_multi_tenant=True)
- context = glance.context.RequestContext()
- store = Store(context)
- uri = "swift+http://storeurl/glance/%s" % FAKE_UUID
- loc = get_location_from_uri(uri)
- read_tenants = ['matt', 'mark']
- store.set_acls(loc, read_tenants=read_tenants)
- container_headers = swiftclient.client.head_container('x', 'y',
- 'glance')
- self.assertEqual(container_headers['X-Container-Read'],
- 'matt:*,mark:*')
-
- def test_write_acls(self):
- """
- Test that we can set write acl for tenants.
- """
- self.config(swift_store_multi_tenant=True)
- context = glance.context.RequestContext()
- store = Store(context)
- uri = "swift+http://storeurl/glance/%s" % FAKE_UUID
- loc = get_location_from_uri(uri)
- read_tenants = ['frank', 'jim']
- store.set_acls(loc, write_tenants=read_tenants)
- container_headers = swiftclient.client.head_container('x', 'y',
- 'glance')
- self.assertEqual(container_headers['X-Container-Write'],
- 'frank:*,jim:*')
-
-
-class TestStoreAuthV1(base.StoreClearingUnitTest, SwiftTests):
-
- def getConfig(self):
- conf = SWIFT_CONF.copy()
- conf['swift_store_auth_version'] = '1'
- conf['swift_store_user'] = 'user'
- return conf
-
- def setUp(self):
- """Establish a clean test environment"""
- conf = self.getConfig()
- self.config(**conf)
- super(TestStoreAuthV1, self).setUp()
- stub_out_swiftclient(self, conf['swift_store_auth_version'])
- self.store = Store()
-
-class TestStoreAuthV2(TestStoreAuthV1):
-
- def getConfig(self):
- conf = super(TestStoreAuthV2, self).getConfig()
- conf['swift_store_user'] = 'tenant:user'
- conf['swift_store_auth_version'] = '2'
- return conf
-
- def test_v2_with_no_tenant(self):
- conf = self.getConfig()
- conf['swift_store_user'] = 'failme'
- uri = "swift://%s:key@auth_address/glance/%s" % (
- conf['swift_store_user'], FAKE_UUID)
- loc = get_location_from_uri(uri)
- self.assertRaises(exceptions.BadStoreUri,
- self.store.get,
- loc)
-
- def test_v2_multi_tenant_location(self):
- conf = self.getConfig()
- conf['swift_store_multi_tenant'] = True
- uri = "swift://auth_address/glance/%s" % (FAKE_UUID)
- loc = get_location_from_uri(uri)
- self.assertEqual('swift', loc.store_name)
-
-
-class FakeConnection(object):
- def __init__(self, authurl, user, key, retries=5, preauthurl=None,
- preauthtoken=None, snet=False, starting_backoff=1,
- tenant_name=None, os_options={}, auth_version="1",
- insecure=False, ssl_compression=True):
- self.authurl = authurl
- self.user = user
- self.key = key
- self.preauthurl = preauthurl
- self.preauthtoken = preauthtoken
- self.snet = snet
- self.tenant_name = tenant_name
- self.os_options = os_options
- self.auth_version = auth_version
- self.insecure = insecure
-
-
-class TestSingleTenantStoreConnections(base.IsolatedUnitTest):
- def setUp(self):
- super(TestSingleTenantStoreConnections, self).setUp()
- self.stubs.Set(swiftclient, 'Connection', FakeConnection)
- self.store = glance.store.swift.SingleTenantStore()
- specs = {'scheme': 'swift',
- 'auth_or_store_url': 'example.com/v2/',
- 'user': 'tenant:user',
- 'key': 'abcdefg',
- 'container': 'cont',
- 'obj': 'object'}
- self.location = glance.store.swift.StoreLocation(specs)
-
- def test_basic_connection(self):
- connection = self.store.get_connection(self.location)
- self.assertEqual(connection.authurl, 'https://example.com/v2/')
- self.assertEqual(connection.auth_version, '2')
- self.assertEqual(connection.user, 'user')
- self.assertEqual(connection.tenant_name, 'tenant')
- self.assertEqual(connection.key, 'abcdefg')
- self.assertFalse(connection.snet)
- self.assertEqual(connection.preauthurl, None)
- self.assertEqual(connection.preauthtoken, None)
- self.assertFalse(connection.insecure)
- self.assertEqual(connection.os_options,
- {'service_type': 'object-store',
- 'endpoint_type': 'publicURL'})
-
- def test_connection_with_no_trailing_slash(self):
- self.location.auth_or_store_url = 'example.com/v2'
- connection = self.store.get_connection(self.location)
- self.assertEqual(connection.authurl, 'https://example.com/v2/')
-
- def test_connection_insecure(self):
- self.config(swift_store_auth_insecure=True)
- self.store.configure()
- connection = self.store.get_connection(self.location)
- self.assertTrue(connection.insecure)
-
- def test_connection_with_auth_v1(self):
- self.config(swift_store_auth_version='1')
- self.store.configure()
- self.location.user = 'auth_v1_user'
- connection = self.store.get_connection(self.location)
- self.assertEqual(connection.auth_version, '1')
- self.assertEqual(connection.user, 'auth_v1_user')
- self.assertEqual(connection.tenant_name, None)
-
- def test_connection_invalid_user(self):
- self.store.configure()
- self.location.user = 'invalid:format:user'
- self.assertRaises(exceptions.BadStoreUri,
- self.store.get_connection, self.location)
-
- def test_connection_missing_user(self):
- self.store.configure()
- self.location.user = None
- self.assertRaises(exceptions.BadStoreUri,
- self.store.get_connection, self.location)
-
- def test_connection_with_region(self):
- self.config(swift_store_region='Sahara')
- self.store.configure()
- connection = self.store.get_connection(self.location)
- self.assertEqual(connection.os_options,
- {'region_name': 'Sahara',
- 'service_type': 'object-store',
- 'endpoint_type': 'publicURL'})
-
- def test_connection_with_service_type(self):
- self.config(swift_store_service_type='shoe-store')
- self.store.configure()
- connection = self.store.get_connection(self.location)
- self.assertEqual(connection.os_options,
- {'service_type': 'shoe-store',
- 'endpoint_type': 'publicURL'})
-
- def test_connection_with_endpoint_type(self):
- self.config(swift_store_endpoint_type='internalURL')
- self.store.configure()
- connection = self.store.get_connection(self.location)
- self.assertEqual(connection.os_options,
- {'service_type': 'object-store',
- 'endpoint_type': 'internalURL'})
-
- def test_connection_with_snet(self):
- self.config(swift_enable_snet=True)
- self.store.configure()
- connection = self.store.get_connection(self.location)
- self.assertTrue(connection.snet)
-
-
-class TestMultiTenantStoreConnections(base.IsolatedUnitTest):
- def setUp(self):
- super(TestMultiTenantStoreConnections, self).setUp()
- self.stubs.Set(swiftclient, 'Connection', FakeConnection)
- self.context = glance.context.RequestContext(
- user='user', tenant='tenant', auth_tok='0123')
- self.store = glance.store.swift.MultiTenantStore(self.context)
- specs = {'scheme': 'swift',
- 'auth_or_store_url': 'example.com',
- 'container': 'cont',
- 'obj': 'object'}
- self.location = glance.store.swift.StoreLocation(specs)
-
- def test_basic_connection(self):
- self.store.configure()
- connection = self.store.get_connection(self.location)
- self.assertEqual(connection.authurl, None)
- self.assertEqual(connection.auth_version, '2')
- self.assertEqual(connection.user, 'user')
- self.assertEqual(connection.tenant_name, 'tenant')
- self.assertEqual(connection.key, None)
- self.assertFalse(connection.snet)
- self.assertEqual(connection.preauthurl, 'https://example.com')
- self.assertEqual(connection.preauthtoken, '0123')
- self.assertEqual(connection.os_options, {})
-
- def test_connection_with_snet(self):
- self.config(swift_enable_snet=True)
- self.store.configure()
- connection = self.store.get_connection(self.location)
- self.assertTrue(connection.snet)
-
-
-class FakeGetEndpoint(object):
- def __init__(self, response):
- self.response = response
-
- def __call__(self, service_catalog, service_type=None,
- endpoint_region=None, endpoint_type=None):
- self.service_type = service_type
- self.endpoint_region = endpoint_region
- self.endpoint_type = endpoint_type
- return self.response
-
-
-class TestCreatingLocations(base.IsolatedUnitTest):
- def test_single_tenant_location(self):
- self.config(swift_store_auth_address='example.com/v2',
- swift_store_container='container',
- swift_store_user='tenant:user',
- swift_store_key='auth_key')
- store = glance.store.swift.SingleTenantStore()
- location = store.create_location('image-id')
- self.assertEqual(location.scheme, 'swift+https')
- self.assertEqual(location.swift_url, 'https://example.com/v2')
- self.assertEqual(location.container, 'container')
- self.assertEqual(location.obj, 'image-id')
- self.assertEqual(location.user, 'tenant:user')
- self.assertEqual(location.key, 'auth_key')
-
- def test_single_tenant_location_http(self):
- self.config(swift_store_auth_address='http://example.com/v2',
- swift_store_container='container',
- swift_store_user='tenant:user',
- swift_store_key='auth_key')
- store = glance.store.swift.SingleTenantStore()
- location = store.create_location('image-id')
- self.assertEqual(location.scheme, 'swift+http')
- self.assertEqual(location.swift_url, 'http://example.com/v2')
-
- def test_multi_tenant_location(self):
- self.config(swift_store_container='container')
- fake_get_endpoint = FakeGetEndpoint('https://some_endpoint')
- self.stubs.Set(glance.store.common.auth, 'get_endpoint', fake_get_endpoint)
- context = glance.context.RequestContext(
- user='user', tenant='tenant', auth_tok='123',
- service_catalog={})
- store = glance.store.swift.MultiTenantStore(context)
- location = store.create_location('image-id')
- self.assertEqual(location.scheme, 'swift+https')
- self.assertEqual(location.swift_url, 'https://some_endpoint')
- self.assertEqual(location.container, 'container_image-id')
- self.assertEqual(location.obj, 'image-id')
- self.assertEqual(location.user, None)
- self.assertEqual(location.key, None)
- self.assertEqual(fake_get_endpoint.service_type, 'object-store')
-
- def test_multi_tenant_location_http(self):
- fake_get_endpoint = FakeGetEndpoint('http://some_endpoint')
- self.stubs.Set(glance.store.common.auth, 'get_endpoint', fake_get_endpoint)
- context = glance.context.RequestContext(
- user='user', tenant='tenant', auth_tok='123',
- service_catalog={})
- store = glance.store.swift.MultiTenantStore(context)
- location = store.create_location('image-id')
- self.assertEqual(location.scheme, 'swift+http')
- self.assertEqual(location.swift_url, 'http://some_endpoint')
-
- def test_multi_tenant_location_with_region(self):
- self.config(swift_store_region='WestCarolina')
- fake_get_endpoint = FakeGetEndpoint('https://some_endpoint')
- self.stubs.Set(glance.store.common.auth, 'get_endpoint', fake_get_endpoint)
- context = glance.context.RequestContext(
- user='user', tenant='tenant', auth_tok='123',
- service_catalog={})
- store = glance.store.swift.MultiTenantStore(context)
- self.assertEqual(fake_get_endpoint.endpoint_region, 'WestCarolina')
-
- def test_multi_tenant_location_custom_service_type(self):
- self.config(swift_store_service_type='toy-store')
- fake_get_endpoint = FakeGetEndpoint('https://some_endpoint')
- self.stubs.Set(glance.store.common.auth, 'get_endpoint', fake_get_endpoint)
- context = glance.context.RequestContext(
- user='user', tenant='tenant', auth_tok='123',
- service_catalog={})
- store = glance.store.swift.MultiTenantStore(context)
- self.assertEqual(fake_get_endpoint.service_type, 'toy-store')
-
- def test_multi_tenant_location_custom_endpoint_type(self):
- self.config(swift_store_endpoint_type='InternalURL')
- fake_get_endpoint = FakeGetEndpoint('https://some_endpoint')
- self.stubs.Set(glance.store.common.auth, 'get_endpoint', fake_get_endpoint)
- context = glance.context.RequestContext(
- user='user', tenant='tenant', auth_tok='123',
- service_catalog={})
- store = glance.store.swift.MultiTenantStore(context)
- self.assertEqual(fake_get_endpoint.endpoint_type, 'InternalURL')
-
-
-class TestChunkReader(base.StoreClearingUnitTest):
-
- def test_read_all_data(self):
- """
- Replicate what goes on in the Swift driver with the
- repeated creation of the ChunkReader object
- """
- CHUNKSIZE = 100
- checksum = hashlib.md5()
- data_file = tempfile.NamedTemporaryFile()
- data_file.write('*' * units.Ki)
- data_file.flush()
- infile = open(data_file.name, 'rb')
- bytes_read = 0
- while True:
- cr = glance.store.swift.ChunkReader(infile, checksum, CHUNKSIZE)
- chunk = cr.read(CHUNKSIZE)
- bytes_read += len(chunk)
- if not chunk:
- break
- self.assertEqual(1024, bytes_read)
- data_file.close()