Add ability to upload duplicate images

In the basic case, avoiding re-uploading images is nice because
uploading images is a costly operation. However, there are also usecases
for uploading new images with the same name as an operator which are
quite valid. Support these by allowing for a flag that overrides the
duplicate checking logic.

Change-Id: I6a00753654d500d68750e46c5ec2423a36903552
This commit is contained in:
Monty Taylor 2016-08-01 16:19:33 -05:00
parent 1a1107ad73
commit 3ef3864785
No known key found for this signature in database
GPG Key ID: 7BAE94BC7141A594
2 changed files with 70 additions and 7 deletions

View File

@ -2546,7 +2546,8 @@ class OpenStackCloud(object):
md5=None, sha256=None, md5=None, sha256=None,
disk_format=None, container_format=None, disk_format=None, container_format=None,
disable_vendor_agent=True, disable_vendor_agent=True,
wait=False, timeout=3600, **kwargs): wait=False, timeout=3600,
allow_duplicates=False, **kwargs):
"""Upload an image to Glance. """Upload an image to Glance.
:param str name: Name of the image to create. If it is a pathname :param str name: Name of the image to create. If it is a pathname
@ -2578,6 +2579,8 @@ class OpenStackCloud(object):
true - however, be aware that one of the upload true - however, be aware that one of the upload
methods is always synchronous. methods is always synchronous.
:param timeout: Seconds to wait for image creation. None is forever. :param timeout: Seconds to wait for image creation. None is forever.
:param allow_duplicates: If true, skips checks that enforce unique
image name. (optional, defaults to False)
Additional kwargs will be passed to the image creation as additional Additional kwargs will be passed to the image creation as additional
metadata for the image. metadata for the image.
@ -2603,12 +2606,15 @@ class OpenStackCloud(object):
container_format = 'bare' container_format = 'bare'
if not md5 or not sha256: if not md5 or not sha256:
(md5, sha256) = self._get_file_hashes(filename) (md5, sha256) = self._get_file_hashes(filename)
current_image = self.get_image(name) if allow_duplicates:
if (current_image and current_image.get(IMAGE_MD5_KEY, '') == md5 current_image = None
and current_image.get(IMAGE_SHA256_KEY, '') == sha256): else:
self.log.debug( current_image = self.get_image(name)
"image {name} exists and is up to date".format(name=name)) if (current_image and current_image.get(IMAGE_MD5_KEY, '') == md5
return current_image and current_image.get(IMAGE_SHA256_KEY, '') == sha256):
self.log.debug(
"image {name} exists and is up to date".format(name=name))
return current_image
kwargs[IMAGE_MD5_KEY] = md5 kwargs[IMAGE_MD5_KEY] = md5
kwargs[IMAGE_SHA256_KEY] = sha256 kwargs[IMAGE_SHA256_KEY] = sha256
kwargs[IMAGE_OBJECT_KEY] = '/'.join([container, name]) kwargs[IMAGE_OBJECT_KEY] = '/'.join([container, name])

View File

@ -69,3 +69,60 @@ class TestImage(base.BaseFunctionalTestCase):
self.addCleanup(os.remove, output) self.addCleanup(os.remove, output)
self.assertTrue(filecmp.cmp(test_image.name, output), self.assertTrue(filecmp.cmp(test_image.name, output),
"Downloaded contents don't match created image") "Downloaded contents don't match created image")
def test_create_image_skip_duplicate(self):
test_image = tempfile.NamedTemporaryFile(delete=False)
test_image.write('\0' * 1024 * 1024)
test_image.close()
image_name = self.getUniqueString('image')
try:
first_image = self.demo_cloud.create_image(
name=image_name,
filename=test_image.name,
disk_format='raw',
container_format='bare',
min_disk=10,
min_ram=1024,
wait=True)
second_image = self.demo_cloud.create_image(
name=image_name,
filename=test_image.name,
disk_format='raw',
container_format='bare',
min_disk=10,
min_ram=1024,
wait=True)
self.assertEqual(first_image.id, second_image.id)
finally:
self.demo_cloud.delete_image(image_name, wait=True)
def test_create_image_force_duplicate(self):
test_image = tempfile.NamedTemporaryFile(delete=False)
test_image.write('\0' * 1024 * 1024)
test_image.close()
image_name = self.getUniqueString('image')
second_image = None
try:
first_image = self.demo_cloud.create_image(
name=image_name,
filename=test_image.name,
disk_format='raw',
container_format='bare',
min_disk=10,
min_ram=1024,
wait=True)
second_image = self.demo_cloud.create_image(
name=image_name,
filename=test_image.name,
disk_format='raw',
container_format='bare',
min_disk=10,
min_ram=1024,
allow_duplicates=True,
wait=True)
self.assertNotEqual(first_image.id, second_image.id)
finally:
if first_image:
self.demo_cloud.delete_image(first_image.id, wait=True)
if second_image:
self.demo_cloud.delete_image(second_image.id, wait=True)