zun/zun/image/glance/driver.py

159 lines
6.1 KiB
Python

# 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.
import hashlib
import os
import six
from oslo_log import log as logging
from oslo_utils import fileutils
from zun.common import exception
from zun.common.i18n import _
from zun.common import utils as common_utils
import zun.conf
from zun.image import driver
from zun.image.glance import utils
CONF = zun.conf.CONF
LOG = logging.getLogger(__name__)
class GlanceDriver(driver.ContainerImageDriver):
def __init__(self):
super(GlanceDriver, self).__init__()
def _search_image_on_host(self, context, repo):
LOG.debug('Searching for image %s locally', repo)
images_directory = CONF.glance.images_directory
try:
# TODO(mkrai): Change this to search image entry in zun db
# after the image endpoint is merged.
image_meta = utils.find_image(context, repo)
except exception.ImageNotFound:
return None
if image_meta:
out_path = os.path.join(images_directory,
image_meta.id + '.tar')
if os.path.isfile(out_path):
return {
'image': repo,
'path': out_path,
'checksum': image_meta.checksum}
else:
return None
def pull_image(self, context, repo, tag, image_pull_policy):
# TODO(shubhams): glance driver does not handle tags
# once metadata is stored in db then handle tags
image_loaded = False
image = self._search_image_on_host(context, repo)
if image:
image_path = image['path']
image_checksum = image['checksum']
md5sum = hashlib.md5()
with open(image_path, 'rb') as fd:
while True:
# read 10MB of data each time
data = fd.read(10 * 1024 * 1024)
if not data:
break
md5sum.update(data)
md5sum = md5sum.hexdigest()
if md5sum == image_checksum:
image_loaded = True
return image, image_loaded
if not common_utils.should_pull_image(image_pull_policy, bool(image)):
if image:
LOG.debug('Image %s present locally', repo)
image_loaded = True
return image, image_loaded
else:
message = _('Image %s not present with pull policy of Never'
) % repo
raise exception.ImageNotFound(message)
LOG.debug('Pulling image from glance %s', repo)
try:
glance = utils.create_glanceclient(context)
image_meta = utils.find_image(context, repo)
LOG.debug('Image %s was found in glance, downloading now...', repo)
image_chunks = glance.images.data(image_meta.id)
except exception.ImageNotFound:
LOG.error('Image %s was not found in glance', repo)
raise
except Exception as e:
msg = _('Cannot download image from glance: {0}')
raise exception.ZunException(msg.format(e))
try:
images_directory = CONF.glance.images_directory
fileutils.ensure_tree(images_directory)
out_path = os.path.join(images_directory, image_meta.id + '.tar')
with open(out_path, 'wb') as fd:
for chunk in image_chunks:
fd.write(chunk)
except Exception as e:
msg = _('Error occurred while writing image: {0}')
raise exception.ZunException(msg.format(e))
LOG.debug('Image %(repo)s was downloaded to path : %(path)s',
{'repo': repo, 'path': out_path})
return {'image': repo, 'path': out_path}, image_loaded
def search_image(self, context, repo, tag, exact_match):
# TODO(mkrai): glance driver does not handle tags
# once metadata is stored in db then handle tags
LOG.debug('Searching image in glance %s', repo)
try:
# TODO(hongbin): find image by both repo and tag
images = utils.find_images(context, repo, exact_match)
return images
except Exception as e:
raise exception.ZunException(six.text_type(e))
def create_image(self, context, image_name):
"""Create an image."""
LOG.debug('Creating a new image in glance %s', image_name)
try:
img = utils.create_image(context, image_name)
return img
except Exception as e:
raise exception.ZunException(six.text_type(e))
def update_image(self, context, img_id, disk_format='qcow2',
container_format='docker', tag=None):
"""Update an image."""
LOG.debug('Updating an image %s in glance', img_id)
try:
if tag is not None:
tags = []
tags.append(tag)
img = utils.update_image_tags(context, img_id,
tags)
img = utils.update_image_format(context, img_id, disk_format,
container_format)
return img
except Exception as e:
raise exception.ZunException(six.text_type(e))
def upload_image_data(self, context, img_id, data):
"""Update an image."""
LOG.debug('Uploading an image to glance %s', img_id)
try:
img = utils.upload_image_data(context, img_id, data)
return img
except Exception as e:
raise exception.ZunException(six.text_type(e))