Add image upload support
There are at least 2 known mechanisms in the wild for uploading images to public glance endpoints that are completely different. Based on which version of the API we're running switch between them seamlessly. Note that the wait parameter isn't going to do anything for v1 because it's a sync call - maybe we should throw an error if someone tries to leave if set to false? Change-Id: Ifccf8aaa6cd7793a1b827914e7da4b2b82248544
This commit is contained in:
parent
9344803010
commit
fe14bc166e
@ -37,6 +37,7 @@ from troveclient import exceptions as trove_exceptions
|
||||
from shade import meta
|
||||
|
||||
__version__ = pbr.version.VersionInfo('shade').version_string()
|
||||
IMAGE_MD5_KEY = 'org.openstack.shade.md5'
|
||||
|
||||
|
||||
class OpenStackCloudException(Exception):
|
||||
@ -410,7 +411,7 @@ class OpenStackCloud(object):
|
||||
self._image_cache = self._get_images_from_cloud()
|
||||
return self._image_cache
|
||||
|
||||
def get_image_name(self, image_id, exclude):
|
||||
def get_image_name(self, image_id, exclude=None):
|
||||
image = self.get_image(image_id, exclude)
|
||||
if image:
|
||||
return image.id
|
||||
@ -433,6 +434,70 @@ class OpenStackCloud(object):
|
||||
raise OpenStackCloudException(
|
||||
"Error finding image from %s" % name_or_id)
|
||||
|
||||
def create_image(
|
||||
self, name, filename, container='images', md5=None
|
||||
disk_format=None, container_format=None,
|
||||
wait=False, timeout=3600, **kwargs):
|
||||
if not md5:
|
||||
md5 = self._get_file_md5(filename)
|
||||
current_image = self.get_image(name)
|
||||
if current_image.get(IMAGE_MD5_KEY, '') == md5:
|
||||
self.log.debug(
|
||||
"image {name} exists and is up to date".format(name=name))
|
||||
return
|
||||
kwargs[IMAGE_MD5_KEY] = md5
|
||||
# This makes me want to die inside
|
||||
if self._get_glance_api_version() == '2':
|
||||
self._upload_image_v2(
|
||||
name, filename, container,
|
||||
current_image=current_image,
|
||||
wait=wait, timeout=timeout, **kwargs)
|
||||
else:
|
||||
self._upload_image_v1(name, filename, md5=md5)
|
||||
|
||||
def _upload_image_v1(self, name, filename,
|
||||
disk_format=None, container_format=None, **image_properties):
|
||||
image = self.glance_client.images.create(
|
||||
name=name, is_public=False, disk_format=disk_format,
|
||||
container_format=container_format, **image_properties)
|
||||
image.update(data=open(filename, 'rb'))
|
||||
return image.id
|
||||
|
||||
def _upload_image_v2(
|
||||
self, name, filename, container, current_image=None,
|
||||
wait=False, timeout=3600, **image_properties):
|
||||
self.create_object(
|
||||
container, name, filename, md5=image_properties['md5'])
|
||||
if not current_image:
|
||||
current_image = self.get_image(name)
|
||||
# TODO(mordred): Can we do something similar to what nodepool does
|
||||
# using glance properties to not delete then upload but instead make a
|
||||
# new "good" image and then mark the old one as "bad"
|
||||
# self.glance_client.images.delete(current_image)
|
||||
image_properties['name'] = name
|
||||
task = self.glance_client.tasks.create(
|
||||
type='import', input=dict(
|
||||
import_from='{container}/{name}'.format(
|
||||
container=container, name=name),
|
||||
image_properties=image_properties))
|
||||
if wait:
|
||||
expire = time.time() + timeout
|
||||
while time.time() < expire:
|
||||
status = self.glance_client.tasks.get(task.id)
|
||||
|
||||
if status.status == 'success':
|
||||
return status.result['image_id']
|
||||
if status.status == 'failure':
|
||||
raise OpenStackCloudException(
|
||||
"Image creation failed: {message}".format(
|
||||
message=status.message))
|
||||
time.sleep(10)
|
||||
|
||||
raise OpenStackCloudException(
|
||||
"Timeout waiting for the image to import.")
|
||||
else:
|
||||
return task
|
||||
|
||||
def _get_volumes_from_cloud(self):
|
||||
try:
|
||||
return self.cinder_client.volumes.list()
|
||||
|
Loading…
Reference in New Issue
Block a user