def _upload(self, req, image_meta): """ Uploads the payload of the request to a backend store in Glance. If the `x-image-meta-store` header is set, Glance will attempt to use that scheme; if not, Glance will use the scheme set by the flag `default_store` to find the backing store. :param req: The WSGI/Webob Request object :param image_meta: Mapping of metadata about image :raises HTTPConflict if image already exists :retval The location where the image was stored """ copy_from = self._copy_from(req) if copy_from: try: image_data, image_size = self._get_from_store( req.context, copy_from) except Exception as e: upload_utils.safe_kill(req, image_meta['id'], 'queued') msg = _("Copy from external source failed: %s") % e LOG.debug(msg) return image_meta['size'] = image_size or image_meta['size'] else: try: req.get_content_type(('application/octet-stream', )) except exception.InvalidContentType: upload_utils.safe_kill(req, image_meta['id'], 'queued') msg = _("Content-Type must be application/octet-stream") LOG.debug(msg) raise HTTPBadRequest(explanation=msg) image_data = req.body_file scheme = req.headers.get('x-image-meta-store', CONF.default_store) store = self.get_store_or_400(req, scheme) image_id = image_meta['id'] LOG.debug(_("Setting image %s to status 'saving'"), image_id) registry.update_image_metadata(req.context, image_id, {'status': 'saving'}) LOG.debug( _("Uploading image data for image %(image_id)s " "to %(scheme)s store"), { 'image_id': image_id, 'scheme': scheme }) self.notifier.info("image.prepare", redact_loc(image_meta)) image_meta, location, loc_meta = upload_utils.upload_data_to_store( req, image_meta, image_data, store, self.notifier) self.notifier.info('image.upload', redact_loc(image_meta)) return location, loc_meta
def test_upload_data_to_store(self): # 'user_storage_quota' is not set def store_add(image_id, data, size, **kwargs): # Check if 'data' is instance of 'CooperativeReader' when # 'user_storage_quota' is disabled. self.assertIsInstance(data, utils.CooperativeReader) return location, 10, "checksum", {} req = unit_test_utils.get_fake_request() with self._get_store_and_notifier( ext_update_data={'size': 10}, exc_class=store_add) as (location, checksum, image_meta, image_data, store, notifier, update_data): ret = image_meta.update(update_data) with patch.object(registry, 'update_image_metadata', return_value=ret) as mock_update_image_metadata: actual_meta, location_data = upload_utils.upload_data_to_store( req, image_meta, image_data, store, notifier) self.assertEqual(location, location_data['url']) self.assertEqual(image_meta.update(update_data), actual_meta) mock_update_image_metadata.assert_called_once_with( req.context, image_meta['id'], update_data, from_state='saving')
def test_upload_data_to_store(self): req = unit_test_utils.get_fake_request() location = "file://foo/bar" size = 10 checksum = "checksum" image_meta = {'id': unit_test_utils.UUID1, 'size': size} image_data = "blah" notifier = self.mox.CreateMockAnything() store = self.mox.CreateMockAnything() store.add( image_meta['id'], mox.IgnoreArg(), image_meta['size']).AndReturn((location, size, checksum, {})) self.mox.StubOutWithMock(registry, "update_image_metadata") update_data = {'checksum': checksum, 'size': size} registry.update_image_metadata( req.context, image_meta['id'], update_data).AndReturn(image_meta.update(update_data)) self.mox.ReplayAll() actual_meta, location_data = upload_utils.upload_data_to_store( req, image_meta, image_data, store, notifier) self.mox.VerifyAll() self.assertEqual(location_data['url'], location) self.assertEqual(actual_meta, image_meta.update(update_data))
def test_upload_data_to_store(self): req = unit_test_utils.get_fake_request() location = "file://foo/bar" size = 10 checksum = "checksum" image_meta = {'id': unit_test_utils.UUID1, 'size': size} image_data = "blah" notifier = self.mox.CreateMockAnything() store = self.mox.CreateMockAnything() store.add( image_meta['id'], mox.IgnoreArg(), image_meta['size']).AndReturn((location, size, checksum, {})) self.mox.StubOutWithMock(registry, "update_image_metadata") update_data = {'checksum': checksum, 'size': size} registry.update_image_metadata(req.context, image_meta['id'], update_data ).AndReturn( image_meta.update(update_data)) self.mox.ReplayAll() actual_meta, actual_loc, loc_meta = upload_utils.upload_data_to_store( req, image_meta, image_data, store, notifier) self.mox.VerifyAll() self.assertEqual(actual_loc, location) self.assertEqual(actual_meta, image_meta.update(update_data))
def _upload(self, req, image_meta): """ Uploads the payload of the request to a backend store in Glance. If the `x-image-meta-store` header is set, Glance will attempt to use that scheme; if not, Glance will use the scheme set by the flag `default_store` to find the backing store. :param req: The WSGI/Webob Request object :param image_meta: Mapping of metadata about image :raises HTTPConflict if image already exists :retval The location where the image was stored """ copy_from = self._copy_from(req) if copy_from: try: image_data, image_size = self._get_from_store(req.context, copy_from) except Exception as e: upload_utils.safe_kill(req, image_meta['id']) msg = _("Copy from external source failed: %s") % e LOG.debug(msg) return image_meta['size'] = image_size or image_meta['size'] else: try: req.get_content_type('application/octet-stream') except exception.InvalidContentType: upload_utils.safe_kill(req, image_meta['id']) msg = _("Content-Type must be application/octet-stream") LOG.debug(msg) raise HTTPBadRequest(explanation=msg) image_data = req.body_file scheme = req.headers.get('x-image-meta-store', CONF.default_store) store = self.get_store_or_400(req, scheme) image_id = image_meta['id'] LOG.debug(_("Setting image %s to status 'saving'"), image_id) registry.update_image_metadata(req.context, image_id, {'status': 'saving'}) LOG.debug(_("Uploading image data for image %(image_id)s " "to %(scheme)s store"), locals()) self.notifier.info("image.prepare", redact_loc(image_meta)) image_meta, location = upload_utils.upload_data_to_store(req, image_meta, image_data, store, self.notifier) self.notifier.info('image.upload', redact_loc(image_meta)) return location
def _upload(self, req, image_meta): """ Uploads the payload of the request to a backend store in Glance. If the `x-image-meta-store` header is set, Glance will attempt to use that scheme; if not, Glance will use the scheme set by the flag `default_store` to find the backing store. :param req: The WSGI/Webob Request object :param image_meta: Mapping of metadata about image :raises HTTPConflict if image already exists :retval The location where the image was stored """ scheme = req.headers.get("x-image-meta-store", CONF.glance_store.default_store) store = self.get_store_or_400(req, scheme) copy_from = self._copy_from(req) if copy_from: try: image_data, image_size = self._get_from_store(req.context, copy_from, dest=store) except Exception: upload_utils.safe_kill(req, image_meta["id"], "queued") msg = _LE("Copy from external source '%(scheme)s' failed for " "image: %(image)s") % { "scheme": scheme, "image": image_meta["id"], } LOG.exception(msg) return image_meta["size"] = image_size or image_meta["size"] else: try: req.get_content_type(("application/octet-stream",)) except exception.InvalidContentType: upload_utils.safe_kill(req, image_meta["id"], "queued") msg = "Content-Type must be application/octet-stream" LOG.debug(msg) raise HTTPBadRequest(explanation=msg) image_data = req.body_file image_id = image_meta["id"] LOG.debug("Setting image %s to status 'saving'", image_id) registry.update_image_metadata(req.context, image_id, {"status": "saving"}) LOG.debug( "Uploading image data for image %(image_id)s " "to %(scheme)s store", {"image_id": image_id, "scheme": scheme}, ) self.notifier.info("image.prepare", redact_loc(image_meta)) image_meta, location_data = upload_utils.upload_data_to_store(req, image_meta, image_data, store, self.notifier) self.notifier.info("image.upload", redact_loc(image_meta)) return location_data
def test_upload_data_to_store(self): req = unit_test_utils.get_fake_request() with self._get_store_and_notifier( ext_update_data={'size': 10}) as (location, checksum, image_meta, image_data, store, notifier, update_data): ret = image_meta.update(update_data) with patch.object(registry, 'update_image_metadata', return_value=ret) as mock_update_image_metadata: actual_meta, location_data = upload_utils.upload_data_to_store( req, image_meta, image_data, store, notifier) self.assertEqual(location, location_data['url']) self.assertEqual(image_meta.update(update_data), actual_meta) mock_update_image_metadata.assert_called_once_with( req.context, image_meta['id'], update_data, from_state='saving')
def test_upload_data_to_store(self): req = unit_test_utils.get_fake_request() with self._get_store_and_notifier( ext_update_data={'size': 10}) as (location, checksum, image_meta, image_data, store, notifier, update_data): ret = image_meta.update(update_data) with patch.object(registry, 'update_image_metadata', return_value=ret) as mock_update_image_metadata: actual_meta, location_data = upload_utils.upload_data_to_store( req, image_meta, image_data, store, notifier) self.assertEqual(location_data['url'], location) self.assertEqual(actual_meta, image_meta.update(update_data)) mock_update_image_metadata.assert_called_once_with( req.context, image_meta['id'], update_data, from_state='saving')
def test_upload_data_to_store_user_storage_quota_enabled(self): # Enable user_storage_quota self.config(user_storage_quota='100B') def store_add(image_id, data, size, **kwargs): # Check if 'data' is instance of 'LimitingReader' when # 'user_storage_quota' is enabled. self.assertIsInstance(data, utils.LimitingReader) return location, 10, "checksum", {} req = unit_test_utils.get_fake_request() with self._get_store_and_notifier( ext_update_data={'size': 10}, exc_class=store_add) as (location, checksum, image_meta, image_data, store, notifier, update_data): ret = image_meta.update(update_data) # mock 'check_quota' mock_check_quota = patch('glance.api.common.check_quota', return_value=100) mock_check_quota.start() self.addCleanup(mock_check_quota.stop) with patch.object(registry, 'update_image_metadata', return_value=ret) as mock_update_image_metadata: actual_meta, location_data = upload_utils.upload_data_to_store( req, image_meta, image_data, store, notifier) self.assertEqual(location, location_data['url']) self.assertEqual(image_meta.update(update_data), actual_meta) mock_update_image_metadata.assert_called_once_with( req.context, image_meta['id'], update_data, from_state='saving') # 'check_quota' is called two times check_quota_call_count = ( mock_check_quota.target.check_quota.call_count) self.assertEqual(2, check_quota_call_count)
def test_upload_data_to_store_user_storage_quota_enabled(self): # Enable user_storage_quota self.config(user_storage_quota='100B') def store_add(image_id, data, size, **kwargs): # Check if 'data' is instance of 'LimitingReader' when # 'user_storage_quota' is enabled. self.assertIsInstance(data, utils.LimitingReader) return location, 10, "checksum", {} req = unit_test_utils.get_fake_request() with self._get_store_and_notifier( ext_update_data={'size': 10}, exc_class=store_add) as (location, checksum, image_meta, image_data, store, notifier, update_data): ret = image_meta.update(update_data) # mock 'check_quota' mock_check_quota = patch('glance.api.common.check_quota', return_value=100) mock_check_quota.start() self.addCleanup(mock_check_quota.stop) with patch.object(registry, 'update_image_metadata', return_value=ret) as mock_update_image_metadata: actual_meta, location_data = upload_utils.upload_data_to_store( req, image_meta, image_data, store, notifier) self.assertEqual(location, location_data['url']) self.assertEqual(image_meta.update(update_data), actual_meta) mock_update_image_metadata.assert_called_once_with( req.context, image_meta['id'], update_data, from_state='saving') # 'check_quota' is called two times check_quota_call_count =\ mock_check_quota.target.check_quota.call_count self.assertEqual(2, check_quota_call_count)