Handle images which exist but can't be seen.

If the master and the slave glance have different permissions, you
can end up with a 409 exception at upload. For example:

 - the image is visible to the replication user on the master
 - the image is present on the slave, but not visible to the
   replication user

The replicator checks for the existance of the image by doing a HEAD
on http://server:port/v1/images/uuid and gets a 404 back. It therefore
decides the image doesn't exist and that it should be replicated. It
does a POST for that URL, and gets a 409 back saying that UUID is
already in use.

Resolves bug 1030396.

Change-Id: Id5fdb7977692593fd6c2e203f0440d4aa5339d92
This commit is contained in:
Michael Still 2012-07-29 10:05:45 +10:00
parent 4ac0f4f0a4
commit 7335088d89
1 changed files with 30 additions and 10 deletions

View File

@ -52,18 +52,28 @@ COMMANDS = """Commands:
"""
class UploadException(Exception):
pass
IMAGE_ALREADY_PRESENT_MESSAGE = _('The image %s is already present on '
'the slave, but our check for it did '
'not find it. This indicates that we '
'do not have permissions to see all '
'the images on the slave server.')
class AuthenticationException(Exception):
pass
class ImageAlreadyPresentException(Exception):
pass
class ServerErrorException(Exception):
pass
class UploadException(Exception):
pass
class ImageService(object):
def __init__(self, conn, auth_token):
""" Initialize the ImageService.
@ -111,7 +121,10 @@ class ImageService(object):
raise ServerErrorException(response.read())
if code in [401, 403]:
raise AuthenticationException()
raise AuthenticationException(response.read())
if code == 409:
raise ImageAlreadyPresentException(response.read())
if ignore_result_body:
# NOTE: because we are pipelining requests through a single HTTP
@ -364,7 +377,7 @@ def replication_load(options, args):
image_uuid = ent
logging.info(_('Considering: %s') % image_uuid)
meta_file_name = os.path.join(path, uuid)
meta_file_name = os.path.join(path, image_uuid)
with open(meta_file_name) as meta_file:
meta = json.loads(meta_file.read())
@ -397,10 +410,13 @@ def replication_load(options, args):
continue
# Upload the image itself
with open(os.path.join(path, uuid + '.img')) as img_file:
headers, body = client.add_image(meta, img_file)
_check_upload_response_headers(headers, body)
with open(os.path.join(path, image_uuid + '.img')) as img_file:
try:
headers, body = client.add_image(meta, img_file)
_check_upload_response_headers(headers, body)
except ImageAlreadyPresentException:
logging.error(IMAGE_ALREADY_PRESENT_MESSAGE
% image_uuid)
def replication_livecopy(options, args):
@ -455,8 +471,12 @@ def replication_livecopy(options, args):
logging.info(_('%s is being synced') % image['id'])
if not options.metaonly:
image_response = master_client.get_image(image['id'])
headers, body = slave_client.add_image(image, image_response)
_check_upload_response_headers(headers, body)
try:
headers, body = slave_client.add_image(image,
image_response)
_check_upload_response_headers(headers, body)
except ImageAlreadyPresentException:
logging.error(IMAGE_ALREADY_PRESENT_MESSAGE % image['id'])
def replication_compare(options, args):