Fixes lp653358
Using swift.common.client rather than python-cloudfiles for Teller's Swift backend.
This commit is contained in:
commit
543911e581
@ -30,36 +30,48 @@ class SwiftBackend(Backend):
|
|||||||
Takes a parsed_uri in the format of:
|
Takes a parsed_uri in the format of:
|
||||||
swift://user:password@auth_url/container/file.gz.0, connects to the
|
swift://user:password@auth_url/container/file.gz.0, connects to the
|
||||||
swift instance at auth_url and downloads the file. Returns the generator
|
swift instance at auth_url and downloads the file. Returns the generator
|
||||||
provided by stream() on the swift object representing the file.
|
resp_body provided by get_object.
|
||||||
"""
|
"""
|
||||||
(user, api_key, authurl, container, file) = \
|
|
||||||
cls.parse_swift_tokens(parsed_uri)
|
|
||||||
|
|
||||||
if conn_class:
|
if conn_class:
|
||||||
pass # Use the provided conn_class
|
pass # Use the provided conn_class
|
||||||
else:
|
else:
|
||||||
|
# NOTE(sirp): A standard import statement won't work here because
|
||||||
|
# this file ('swift.py') is shadowing the swift module, and since
|
||||||
|
# the import statement searches locally before globally, we'd end
|
||||||
|
# up importing ourselves.
|
||||||
|
#
|
||||||
|
# see http://docs.python.org/library/functions.html#__import__
|
||||||
|
PERFORM_ABSOLUTE_IMPORTS = 0
|
||||||
|
swift = __import__('swift.common.client', globals(), locals(), [],
|
||||||
|
PERFORM_ABSOLUTE_IMPORTS)
|
||||||
|
|
||||||
# Import cloudfiles here because stubout will replace this call
|
# Import cloudfiles here because stubout will replace this call
|
||||||
# with a faked swift client in the unittests, avoiding import
|
# with a faked swift client in the unittests, avoiding import
|
||||||
# errors if the test system does not have cloudfiles installed
|
# errors if the test system does not have cloudfiles installed
|
||||||
import cloudfiles
|
conn_class = swift.common.client.Connection
|
||||||
conn_class = cloudfiles
|
|
||||||
|
|
||||||
swift_conn = conn_class.get_connection(username=user, api_key=api_key,
|
(user, key, authurl, container, obj) = \
|
||||||
authurl=authurl)
|
cls._parse_swift_tokens(parsed_uri)
|
||||||
|
|
||||||
|
# TODO(sirp): snet=False for now, however, if the instance of
|
||||||
|
# swift we're talking to is within our same region, we should set
|
||||||
|
# snet=True
|
||||||
|
swift_conn = conn_class(
|
||||||
|
authurl=authurl, user=user, key=key, snet=False)
|
||||||
|
|
||||||
container = swift_conn.get_container(container)
|
(resp_headers, resp_body) = swift_conn.get_object(
|
||||||
|
container=container, obj=obj, resp_chunk_size=cls.CHUNKSIZE)
|
||||||
obj = container.get_object(file)
|
|
||||||
|
|
||||||
if obj.size != expected_size:
|
|
||||||
raise BackendException("Expected %s size file, Swift has %s"
|
|
||||||
% (expected_size, obj.size))
|
|
||||||
|
|
||||||
# Return the generator provided from obj.stream()
|
|
||||||
return obj.stream(chunksize=cls.CHUNKSIZE)
|
|
||||||
|
|
||||||
|
obj_size = int(resp_headers['content-length'])
|
||||||
|
if obj_size != expected_size:
|
||||||
|
raise BackendException("Expected %s byte file, Swift has %s bytes"
|
||||||
|
% (expected_size, obj_size))
|
||||||
|
|
||||||
|
return resp_body
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_swift_tokens(cls, parsed_uri):
|
def _parse_swift_tokens(cls, parsed_uri):
|
||||||
"""
|
"""
|
||||||
Parsing the swift uri is three phases:
|
Parsing the swift uri is three phases:
|
||||||
1) urlparse to split the tokens
|
1) urlparse to split the tokens
|
||||||
@ -77,9 +89,9 @@ class SwiftBackend(Backend):
|
|||||||
# see lp659445 and Python issue7904
|
# see lp659445 and Python issue7904
|
||||||
creds, path = path.split('@')
|
creds, path = path.split('@')
|
||||||
|
|
||||||
user, api_key = creds.split(':')
|
user, key = creds.split(':')
|
||||||
path_parts = path.split('/')
|
path_parts = path.split('/')
|
||||||
file = path_parts.pop()
|
obj = path_parts.pop()
|
||||||
container = path_parts.pop()
|
container = path_parts.pop()
|
||||||
except (ValueError, IndexError):
|
except (ValueError, IndexError):
|
||||||
raise BackendException(
|
raise BackendException(
|
||||||
@ -89,4 +101,4 @@ class SwiftBackend(Backend):
|
|||||||
|
|
||||||
authurl = "https://%s" % '/'.join(path_parts)
|
authurl = "https://%s" % '/'.join(path_parts)
|
||||||
|
|
||||||
return user, api_key, authurl, container, file
|
return user, key, authurl, container, obj
|
||||||
|
@ -108,8 +108,8 @@ def stub_out_swift_backend(stubs):
|
|||||||
SwiftBackend = glance.teller.backends.swift.SwiftBackend
|
SwiftBackend = glance.teller.backends.swift.SwiftBackend
|
||||||
|
|
||||||
# raise BackendException if URI is bad.
|
# raise BackendException if URI is bad.
|
||||||
(user, api_key, authurl, container, file) = \
|
(user, key, authurl, container, obj) = \
|
||||||
SwiftBackend.parse_swift_tokens(parsed_uri)
|
SwiftBackend._parse_swift_tokens(parsed_uri)
|
||||||
|
|
||||||
def chunk_it():
|
def chunk_it():
|
||||||
for i in xrange(0, len(cls.DATA), cls.CHUNK_SIZE):
|
for i in xrange(0, len(cls.DATA), cls.CHUNK_SIZE):
|
||||||
|
@ -31,7 +31,7 @@ def make_real_image():
|
|||||||
dict(name="testsnap",
|
dict(name="testsnap",
|
||||||
state="available",
|
state="available",
|
||||||
public=True,
|
public=True,
|
||||||
image_type="tarball"))
|
image_type="raw"))
|
||||||
|
|
||||||
location = (
|
location = (
|
||||||
"swift://%s:%s@"
|
"swift://%s:%s@"
|
||||||
@ -52,7 +52,7 @@ def make_fake_image():
|
|||||||
dict(name="Test Image",
|
dict(name="Test Image",
|
||||||
state="available",
|
state="available",
|
||||||
public=True,
|
public=True,
|
||||||
image_type="tarball"))
|
image_type="raw"))
|
||||||
|
|
||||||
db.image_file_create(
|
db.image_file_create(
|
||||||
None,
|
None,
|
||||||
|
@ -18,10 +18,10 @@
|
|||||||
"""Common utilities used in testing"""
|
"""Common utilities used in testing"""
|
||||||
|
|
||||||
|
|
||||||
def is_cloudfiles_available():
|
def is_swift_available():
|
||||||
"""Returns True if Swift/Cloudfiles is importable"""
|
"""Returns True if Swift/Cloudfiles is importable"""
|
||||||
try:
|
try:
|
||||||
import cloudfiles
|
import swift
|
||||||
return True
|
return True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
return False
|
return False
|
||||||
|
Loading…
x
Reference in New Issue
Block a user