def test_image_glance_direct_import(self): """Test 'glance-direct' import functionalities Create image, stage image data, import image and verify that import succeeded. """ self._require_import_method('glance-direct') image_id = self._stage_and_check() # import image from staging to backend resp = self.client.image_import(image_id, method='glance-direct') waiters.wait_for_image_imported_to_stores(self.client, image_id) if not self.versions_client.has_version('2.12'): # API is not new enough to support image/tasks API LOG.info('Glance does not support v2.12, so I am unable to ' 'validate the image/tasks API.') return # Make sure we can access the task and that some of the key # fields look legit. tasks = self.client.show_image_tasks(image_id) self.assertEqual(1, len(tasks['tasks'])) task = tasks['tasks'][0] self.assertEqual('success', task['status']) self.assertEqual(resp.response['x-openstack-request-id'], task['request_id']) self.assertEqual('glance-direct', task['input']['import_req']['method']['name'])
def test_wait_for_image_imported_to_stores(self): self.client.show_image.return_value = ({'status': 'active', 'stores': 'fake_store'}) start_time = int(time.time()) waiters.wait_for_image_imported_to_stores( self.client, 'fake_image_id', 'fake_store') end_time = int(time.time()) # Ensure waiter returns before build_timeout self.assertLess((end_time - start_time), 10)
def test_glance_direct_import_image_to_specific_stores(self): """Test image is imported in all available stores Create image, import image to specified store(s) using glance-direct import method and verify that import succeeded. """ image, stores = self._create_and_stage_image() self.client.image_import(image['id'], method='glance-direct', stores=stores) waiters.wait_for_image_imported_to_stores(self.client, image['id'], (','.join(stores)))
def test_glance_direct_import_image_to_all_stores(self): """Test image is imported in all available stores Create image, import image to all available stores using glance-direct import method and verify that import succeeded. """ image, stores = self._create_and_stage_image(all_stores=True) self.client.image_import(image['id'], method='glance-direct', all_stores=True) waiters.wait_for_image_imported_to_stores(self.client, image['id'], stores)
def test_remote_import(self): """Test image import against a different worker than stage. This creates and stages an image against the primary API worker, but then calls import on a secondary worker (if available) to test that distributed image import works (i.e. proxies the import request to the proper worker). """ self._require_import_method('glance-direct') if not CONF.image.alternate_image_endpoint: raise self.skipException('No image_remote service to test ' 'against') image_id = self._stage_and_check() # import image from staging to backend, but on the alternate worker self.os_primary.image_client_remote.image_import( image_id, method='glance-direct') waiters.wait_for_image_imported_to_stores(self.client, image_id)
def test_image_web_download_import(self): """Test 'web-download' import functionalities Create image, import image and verify that import succeeded. """ self._require_import_method('web-download') image = self._create_image() # Now try to get image details body = self.client.show_image(image['id']) self.assertEqual(image['id'], body['id']) self.assertEqual('queued', body['status']) # import image from web to backend image_uri = CONF.image.http_image self.client.image_import(image['id'], method='web-download', image_uri=image_uri) waiters.wait_for_image_imported_to_stores(self.client, image['id'])
def test_image_web_download_import(self): """Test 'web-download' import functionalities Create image, import image and verify that import succeeded. """ if 'web-download' not in self.available_import_methods: raise self.skipException('Server does not support ' 'web-download import method') image = self._create_image() # Now try to get image details body = self.client.show_image(image['id']) self.assertEqual(image['id'], body['id']) self.assertEqual('queued', body['status']) # import image from web to backend image_uri = CONF.image.http_image self.client.image_import(image['id'], method='web-download', image_uri=image_uri) waiters.wait_for_image_imported_to_stores(self.client, image['id'])
def test_image_glance_direct_import(self): """Test 'glance-direct' import functionalities Create image, stage image data, import image and verify that import succeeded. """ if 'glance-direct' not in self.available_import_methods: raise self.skipException('Server does not support ' 'glance-direct import method') image = self._create_image() # Stage image data file_content = data_utils.random_bytes() image_file = io.BytesIO(file_content) self.client.stage_image_file(image['id'], image_file) # Check image status is 'uploading' body = self.client.show_image(image['id']) self.assertEqual(image['id'], body['id']) self.assertEqual('uploading', body['status']) # import image from staging to backend self.client.image_import(image['id'], method='glance-direct') waiters.wait_for_image_imported_to_stores(self.client, image['id'])
def test_image_stage_quota(self): if not CONF.image_feature_enabled.import_image: skip_msg = ("%s skipped as image import is not available" % __name__) raise self.skipException(skip_msg) self.check_quotas_enabled() # Create a staging quota of 1MiB, allow 10MiB of active # images, and a total of ten images. self._update_limit('image_stage_total', 1) self._update_limit('image_size_total', 10) self._update_limit('image_count_total', 10) self._update_limit('image_count_uploading', 10) file_content = data_utils.random_bytes(1 * units.Mi) # Create and stage a 1MiB image. image1 = self.create_image(name='first', container_format='bare', disk_format='raw', visibility='private') self.image_client.stage_image_file(image1['id'], io.BytesIO(file_content)) # Create and stage a second 1MiB image. This succeeds, but # after completion, we are over quota. image2 = self.create_image(name='second', container_format='bare', disk_format='raw', visibility='private') self.image_client.stage_image_file(image2['id'], io.BytesIO(file_content)) # Create and attempt to stage a third 1MiB image. This should fail to # stage (but not create) because we are over quota. image3 = self.create_image(name='third', container_format='bare', disk_format='raw', visibility='private') self.assertRaises(lib_exc.OverLimit, self.image_client.stage_image_file, image3['id'], io.BytesIO(file_content)) # Make sure that even though we are over our stage quota, we # can still create and upload an image the regular way. image_upload = self.create_image(name='uploaded', container_format='bare', disk_format='raw', visibility='private') self.image_client.store_image_file(image_upload['id'], io.BytesIO(file_content)) # Increase our stage quota to two MiB. self._update_limit('image_stage_total', 2) # Now the upload of the already-created image is allowed, but # after completion, we are over quota again. self.image_client.stage_image_file(image3['id'], io.BytesIO(file_content)) # Create and attempt to stage a fourth 1MiB image. This should # fail to stage (but not create) because we are over quota. image4 = self.create_image(name='fourth', container_format='bare', disk_format='raw', visibility='private') self.assertRaises(lib_exc.OverLimit, self.image_client.stage_image_file, image4['id'], io.BytesIO(file_content)) # Finish our import of image1 to make space in our stage quota. self.image_client.image_import(image1['id'], method='glance-direct') waiters.wait_for_image_imported_to_stores(self.image_client, image1['id']) # Now the upload of the already-created image is allowed. self.image_client.stage_image_file(image4['id'], io.BytesIO(file_content)) # Delete all the images we created before the next test runs, # so that it starts with full quota. self._cleanup_images()
def test_image_count_uploading_quota(self): if not CONF.image_feature_enabled.import_image: skip_msg = ("%s skipped as image import is not available" % __name__) raise self.skipException(skip_msg) self.check_quotas_enabled() # Set a quota on the number of images we can have in uploading state. self._update_limit('image_stage_total', 10) self._update_limit('image_size_total', 10) self._update_limit('image_count_total', 10) self._update_limit('image_count_uploading', 1) file_content = data_utils.random_bytes(1 * units.Mi) # Create and stage an image image1 = self.create_image(name='first', container_format='bare', disk_format='raw', visibility='private') self.image_client.stage_image_file(image1['id'], io.BytesIO(file_content)) # Check that we can not stage another image2 = self.create_image(name='second', container_format='bare', disk_format='raw', visibility='private') self.assertRaises(lib_exc.OverLimit, self.image_client.stage_image_file, image2['id'], io.BytesIO(file_content)) # ... nor upload directly image3 = self.create_image(name='third', container_format='bare', disk_format='raw', visibility='private') self.assertRaises(lib_exc.OverLimit, self.image_client.store_image_file, image3['id'], io.BytesIO(file_content)) # Update our quota to make room self._update_limit('image_count_uploading', 2) # Now our upload should work self.image_client.store_image_file(image3['id'], io.BytesIO(file_content)) # ...and because that is no longer in uploading state, we should be # able to stage our second image from above. self.image_client.stage_image_file(image2['id'], io.BytesIO(file_content)) # Finish our import of image2 self.image_client.image_import(image2['id'], method='glance-direct') waiters.wait_for_image_imported_to_stores(self.image_client, image2['id']) # Set our quota back to one self._update_limit('image_count_uploading', 1) # Since image1 is still staged, we should not be able to upload # an image. image4 = self.create_image(name='fourth', container_format='bare', disk_format='raw', visibility='private') self.assertRaises(lib_exc.OverLimit, self.image_client.store_image_file, image4['id'], io.BytesIO(file_content)) # Finish our import of image1 to make space in our uploading quota. self.image_client.image_import(image1['id'], method='glance-direct') waiters.wait_for_image_imported_to_stores(self.image_client, image1['id']) # Make sure that freed up the one upload quota to complete our upload self.image_client.store_image_file(image4['id'], io.BytesIO(file_content)) # Delete all the images we created before the next test runs, # so that it starts with full quota. self._cleanup_images()