Source code for image.v2.admin.test_image_caching

# Copyright 2022 Red Hat, Inc.
# All Rights Reserved.
#
#    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 io

from oslo_log import log as logging
from tempest.api.image import base
from tempest.common import waiters
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc


CONF = config.CONF
LOG = logging.getLogger(__name__)


[docs] class ImageCachingTest(base.BaseV2ImageTest): """Here we test the caching operations for image""" credentials = ['primary', 'admin'] def setUp(self): super(ImageCachingTest, self).setUp() # NOTE(abhishekk): As caching is enabled instance boot or volume # boot or image download can also cache image, so we are going to # maintain our caching information to avoid disturbing other tests self.cached_info = [] self.cached_info_remote = [] def tearDown(self): # Delete all from cache/queue if we exit abruptly for image_id in self.cached_info: self.os_admin.image_cache_client.cache_delete(image_id) for image_id in self.cached_info_remote: self.os_admin.image_cache_client.cache_delete(image_id) super(ImageCachingTest, self).tearDown() @classmethod def skip_checks(cls): super(ImageCachingTest, cls).skip_checks() # Check to see if we should even be running these tests. if not CONF.image.image_caching_enabled: raise cls.skipException('Target system is not configured with ' 'glance caching') def image_create_and_upload(self, upload=True, **kwargs): """Wrapper that returns a test image.""" if 'name' not in kwargs: name = data_utils.rand_name( prefix=CONF.resource_name_prefix, name=self.__name__ + "-image") kwargs['name'] = name params = dict(kwargs) image = self.create_image(**params) self.assertEqual('queued', image['status']) if not upload: return image file_content = data_utils.random_bytes() image_file = io.BytesIO(file_content) self.client.store_image_file(image['id'], image_file) image = self.client.show_image(image['id']) return image def _assertCheckCache(self, cached_images, cached): cached_list = [] for image in cached_images: cached_list.append(image['image_id']) for image in cached: self.assertIn(image, cached_list)
[docs] @decorators.idempotent_id('4bf6adba-2f9f-47e9-a6d5-37f21ad4387c') def test_image_caching_cycle(self): """Test image cache APIs""" # Ensure that non-admin user is not allowed to perform caching # operations self.assertRaises(lib_exc.Forbidden, self.os_primary.image_cache_client.list_cache) # Check there is nothing cached by us output = self.os_admin.image_cache_client.list_cache() self._assertCheckCache(output['cached_images'], self.cached_info) # Non-existing image should raise NotFound exception self.assertRaises(lib_exc.NotFound, self.os_admin.image_cache_client.cache_queue, 'non-existing-image-id') # Verify that we can not use queued image for queueing image = self.image_create_and_upload(name='queued', upload=False) self.assertRaises(lib_exc.BadRequest, self.os_admin.image_cache_client.cache_queue, image['id']) # Create one image image = self.image_create_and_upload(name='first', container_format='bare', disk_format='raw', visibility='private') self.assertEqual('active', image['status']) # Queue image for caching self.os_admin.image_cache_client.cache_queue(image['id']) # Wait for image caching LOG.info("Waiting for image %s to get cached", image['id']) caching = waiters.wait_for_caching( self.client, self.os_admin.image_cache_client, image['id']) self.cached_info.append(image['id']) # verify that we have image cached self._assertCheckCache(caching['cached_images'], self.cached_info) # Verify that we can delete images from caching and queueing with # api call. self.os_admin.image_cache_client.cache_clear() output = self.os_admin.image_cache_client.list_cache() self.assertEqual(0, len(output['queued_images'])) self.assertEqual(0, len(output['cached_images'])) # Verify that invalid header value for target returns 400 response self.assertRaises(lib_exc.BadRequest, self.os_admin.image_cache_client.cache_clear, target="invalid") # Remove all data from local information self.cached_info = []
[docs] @decorators.idempotent_id('0a6b7e10-bc30-4a41-91ff-69fb4f5e65f2') def test_remote_and_self_cache(self): """Test image cache works with self and remote glance service""" if not CONF.image.alternate_image_endpoint: raise self.skipException('No image_remote service to test ' 'against') # Check there is nothing is cached by us on current and # remote node output = self.os_admin.image_cache_client.list_cache() self._assertCheckCache(output['cached_images'], self.cached_info) output = self.os_admin.cache_client_remote.list_cache() self._assertCheckCache(output['cached_images'], self.cached_info_remote) # Create one image image = self.image_create_and_upload(name='first', container_format='bare', disk_format='raw', visibility='private') self.assertEqual('active', image['status']) # Queue image for caching on local node self.os_admin.image_cache_client.cache_queue(image['id']) # Wait for image caching LOG.info("Waiting for image %s to get cached", image['id']) caching = waiters.wait_for_caching( self.client, self.os_admin.image_cache_client, image['id']) self.cached_info.append(image['id']) # verify that we have image in cache on local node self._assertCheckCache(caching['cached_images'], self.cached_info) # verify that we don't have anything cached on remote node output = self.os_admin.cache_client_remote.list_cache() self._assertCheckCache(output['cached_images'], self.cached_info_remote) # cache same image on remote node self.os_admin.cache_client_remote.cache_queue(image['id']) # Wait for image caching LOG.info("Waiting for image %s to get cached", image['id']) caching = waiters.wait_for_caching( self.client, self.os_admin.cache_client_remote, image['id']) self.cached_info_remote.append(image['id']) # verify that we have image cached on remote node output = self.os_admin.cache_client_remote.list_cache() self._assertCheckCache(output['cached_images'], self.cached_info_remote) # Verify that we can delete image from remote cache and it # still present in local cache self.os_admin.cache_client_remote.cache_clear() output = self.os_admin.cache_client_remote.list_cache() self.assertEqual(0, len(output['queued_images'])) self.assertEqual(0, len(output['cached_images'])) output = self.os_admin.image_cache_client.list_cache() self._assertCheckCache(output['cached_images'], self.cached_info) # Delete image from local cache as well self.os_admin.image_cache_client.cache_clear() output = self.os_admin.image_cache_client.list_cache() self.assertEqual(0, len(output['queued_images'])) self.assertEqual(0, len(output['cached_images'])) # Remove all data from local and remote information self.cached_info = [] self.cached_info_remote = []