]> xenbits.xensource.com Git - osstest/openstack-nova.git/commitdiff
[proxy-api] microversion 2.39 deprecates image-metadata proxy API
authorPavel Kholkin <pkholkin@mirantis.com>
Thu, 1 Dec 2016 15:37:28 +0000 (18:37 +0300)
committerPavel Kholkin <pkholkin@mirantis.com>
Wed, 7 Dec 2016 16:22:43 +0000 (19:22 +0300)
Almost all proxy APIs were deprecated in microversion 2.36.
But the sub-resource image-metadata of image was forgotten to deprecate.
This patch deprecates the image-metdata API from 2.39.

Implements blueprint deprecate-image-meta-proxy-api
Closes-bug: #1614578

Change-Id: I5507337ab6fe4a377f66dec3fe275d75618cd7b4

21 files changed:
api-ref/source/limits.inc
api-ref/source/parameters.yaml
api-ref/source/servers-actions.inc
api-ref/source/servers-admin-action.inc
doc/api_samples/limits/v2.39/limit-get-resp.json [new file with mode: 0644]
doc/api_samples/versions/v21-version-get-resp.json
doc/api_samples/versions/versions-get-resp.json
nova/api/openstack/api_version_request.py
nova/api/openstack/compute/create_backup.py
nova/api/openstack/compute/image_metadata.py
nova/api/openstack/compute/limits.py
nova/api/openstack/compute/servers.py
nova/api/openstack/compute/views/limits.py
nova/api/openstack/rest_api_version_history.rst
nova/tests/functional/api_sample_tests/api_samples/limits/v2.39/limit-get-resp.json.tpl [new file with mode: 0644]
nova/tests/functional/api_sample_tests/test_limits.py
nova/tests/unit/api/openstack/compute/test_create_backup.py
nova/tests/unit/api/openstack/compute/test_image_metadata.py
nova/tests/unit/api/openstack/compute/test_limits.py
nova/tests/unit/api/openstack/compute/test_serversV21.py
releasenotes/notes/bp-deprecate-image-meta-proxy-api-7f21e1e6a94944ee.yaml [new file with mode: 0644]

index 71b47b39025d7ccd52b620ef8e2cf421cb957ab8..fcf5e6ada0dc4795a03f7e15680ea56bc3898488 100644 (file)
@@ -24,7 +24,7 @@ Response
 
   - limits: limits
   - absolute: limits_absolutes
-  - maxImageMeta: metadata_items
+  - maxImageMeta: image_metadata_items
   - maxPersonality: injected_files
   - maxPersonalitySize: injected_file_content_bytes
   - maxSecurityGroupRules: security_group_rules
index 7813770a19e151f60aef4477017de4c261ff9601..917254980a0272fbe0f28aa3753be8b68e98e7cf 100644 (file)
@@ -2361,6 +2361,15 @@ image_id_body:
   in: body
   required: true
   type: string
+image_metadata_items:
+  description: |
+    The number of allowed metadata items for each image. Starting from
+    version 2.39 this field is dropped from 'os-limits' response, because
+    'image-metadata' proxy API was deprecated.
+  in: body
+  required: true
+  type: integer
+  max_version: 2.38
 image_name:
   description: |
     The display name of an Image.
index 18f1d48b55dabdd3d0d8ce6cf4a399db4c53fc31..ce22f10eefd3f699710b60671c8c823c1ebaa423 100644 (file)
@@ -219,6 +219,10 @@ If the operation succeeds, the created image has a status of ``active`` and
 the server status returns to the original status. You can also see the new
 image in the image back end that OpenStack Image service manages.
 
+.. note::
+    Starting from version 2.39 the image quota enforcement with Nova `metadata`
+    is removed and quota checks should be performed using Glance API directly.
+
 **Preconditions**
 
 The server must exist.
index 5a8550d88fdf48be640b1f3a3be01e9f724a85a9..f3508fee7330bf566a8fb722e41a3440e3376772 100644 (file)
@@ -26,6 +26,10 @@ Policy defaults enable only users with the administrative role or the
 owner of the server to perform this operation. Cloud providers can
 change these permissions through the ``policy.json`` file.
 
+.. note::
+    Starting from version 2.39 the image quota enforcement with Nova `metadata`
+    is removed and quota checks should be performed using Glance API directly.
+
 Normal response codes: 202
 
 Error response codes: badRequest(400), unauthorized(401), forbidden(403),
diff --git a/doc/api_samples/limits/v2.39/limit-get-resp.json b/doc/api_samples/limits/v2.39/limit-get-resp.json
new file mode 100644 (file)
index 0000000..68b29ea
--- /dev/null
@@ -0,0 +1,20 @@
+{
+    "limits": {
+        "absolute": {
+            "maxPersonality": 5,
+            "maxPersonalitySize": 10240,
+            "maxServerMeta": 128,
+            "maxTotalCores": 20,
+            "maxTotalInstances": 10,
+            "maxTotalKeypairs": 100,
+            "maxTotalRAMSize": 51200,
+            "maxServerGroups": 10,
+            "maxServerGroupMembers": 10,
+            "totalCoresUsed": 0,
+            "totalInstancesUsed": 0,
+            "totalRAMUsed": 0,
+            "totalServerGroupsUsed": 0
+        },
+        "rate": []
+    }
+}
index 79a37afb0ca40d54bd4b5f8a8320bcea1d3a8098..e46112e48d5f3046a0ee8c27393fd0582ff13b47 100644 (file)
@@ -19,7 +19,7 @@
             }
         ],
         "status": "CURRENT",
-        "version": "2.38",
+        "version": "2.39",
         "min_version": "2.1",
         "updated": "2013-07-23T11:33:21Z"
     }
index c672f1e6e82516b2f7b608d95974aabbbd62c052..6922ff85e7878d8f5a4e92f5f7b053b24ed275c1 100644 (file)
@@ -22,7 +22,7 @@
                 }
             ],
             "status": "CURRENT",
-            "version": "2.38",
+            "version": "2.39",
             "min_version": "2.1",
             "updated": "2013-07-23T11:33:21Z"
         }
index 6a3865f96796fa137d06698bd7f83485e83082f3..d80f710b4154decc8fdfb098bec986ebf9a5153b 100644 (file)
@@ -95,6 +95,7 @@ REST_API_VERSION_HISTORY = """REST API Version History:
              UUID format.
     * 2.38 - Add a condition to return HTTPBadRequest if invalid status is
              provided for listing servers.
+    * 2.39 - Deprecates image-metadata proxy API
 """
 
 # The minimum and maximum versions of the API supported
@@ -103,14 +104,18 @@ REST_API_VERSION_HISTORY = """REST API Version History:
 # Note(cyeoh): This only applies for the v2.1 API once microversions
 # support is fully merged. It does not affect the V2 API.
 _MIN_API_VERSION = "2.1"
-_MAX_API_VERSION = "2.38"
+_MAX_API_VERSION = "2.39"
 DEFAULT_API_VERSION = _MIN_API_VERSION
 
-# All the proxy APIs which related network, images and baremetal
+# Almost all proxy APIs which related to network, images and baremetal
 # were deprecated from 2.36.
 MAX_PROXY_API_SUPPORT_VERSION = '2.35'
 MIN_WITHOUT_PROXY_API_SUPPORT_VERSION = '2.36'
 
+# Starting from microversion 2.39 also image-metadata proxy API is deprecated.
+MAX_IMAGE_META_PROXY_API_VERSION = '2.38'
+MIN_WITHOUT_IMAGE_META_PROXY_API_VERSION = '2.39'
+
 
 # NOTE(cyeoh): min and max versions declared as functions so we can
 # mock them for unittests. Do not use the constants directly anywhere
index 38368e95bc023fc85db9782fbfe0841e9d863935..fbe950f7c38861ddde92a2d82281f6b091c84d42 100644 (file)
@@ -15,6 +15,7 @@
 
 import webob
 
+from nova.api.openstack import api_version_request
 from nova.api.openstack import common
 from nova.api.openstack.compute.schemas import create_backup
 from nova.api.openstack import extensions
@@ -57,7 +58,11 @@ class CreateBackupController(wsgi.Controller):
 
         props = {}
         metadata = entity.get('metadata', {})
-        common.check_img_metadata_properties_quota(context, metadata)
+        # Starting from microversion 2.39 we don't check quotas on createBackup
+        if api_version_request.is_supported(
+                req, max_version=
+                api_version_request.MAX_IMAGE_META_PROXY_API_VERSION):
+            common.check_img_metadata_properties_quota(context, metadata)
         props.update(metadata)
 
         instance = common.get_instance(self.compute_api, context, id)
index 8c50687894ac7801d0019dfac1193785b25c099c..ab28fe48f88a8cfd055c04daad9488ef75416ffc 100644 (file)
@@ -16,6 +16,8 @@
 import six
 from webob import exc
 
+from nova.api.openstack.api_version_request import \
+    MAX_IMAGE_META_PROXY_API_VERSION
 from nova.api.openstack import common
 from nova.api.openstack.compute.schemas import image_metadata
 from nova.api.openstack import extensions
@@ -43,6 +45,7 @@ class ImageMetadataController(wsgi.Controller):
             msg = _("Image not found.")
             raise exc.HTTPNotFound(explanation=msg)
 
+    @wsgi.Controller.api_version("2.1", MAX_IMAGE_META_PROXY_API_VERSION)
     @extensions.expected_errors((403, 404))
     def index(self, req, image_id):
         """Returns the list of metadata for a given instance."""
@@ -50,6 +53,7 @@ class ImageMetadataController(wsgi.Controller):
         metadata = self._get_image(context, image_id)['properties']
         return dict(metadata=metadata)
 
+    @wsgi.Controller.api_version("2.1", MAX_IMAGE_META_PROXY_API_VERSION)
     @extensions.expected_errors((403, 404))
     def show(self, req, image_id, id):
         context = req.environ['nova.context']
@@ -59,6 +63,7 @@ class ImageMetadataController(wsgi.Controller):
         else:
             raise exc.HTTPNotFound()
 
+    @wsgi.Controller.api_version("2.1", MAX_IMAGE_META_PROXY_API_VERSION)
     @extensions.expected_errors((400, 403, 404))
     @validation.schema(image_metadata.create)
     def create(self, req, image_id, body):
@@ -75,6 +80,7 @@ class ImageMetadataController(wsgi.Controller):
             raise exc.HTTPForbidden(explanation=e.format_message())
         return dict(metadata=image['properties'])
 
+    @wsgi.Controller.api_version("2.1", MAX_IMAGE_META_PROXY_API_VERSION)
     @extensions.expected_errors((400, 403, 404))
     @validation.schema(image_metadata.update)
     def update(self, req, image_id, id, body):
@@ -97,6 +103,7 @@ class ImageMetadataController(wsgi.Controller):
             raise exc.HTTPForbidden(explanation=e.format_message())
         return dict(meta=meta)
 
+    @wsgi.Controller.api_version("2.1", MAX_IMAGE_META_PROXY_API_VERSION)
     @extensions.expected_errors((400, 403, 404))
     @validation.schema(image_metadata.update_all)
     def update_all(self, req, image_id, body):
@@ -112,6 +119,7 @@ class ImageMetadataController(wsgi.Controller):
             raise exc.HTTPForbidden(explanation=e.format_message())
         return dict(metadata=metadata)
 
+    @wsgi.Controller.api_version("2.1", MAX_IMAGE_META_PROXY_API_VERSION)
     @extensions.expected_errors((403, 404))
     @wsgi.response(204)
     def delete(self, req, image_id, id):
index 6027d9ed74a874f50db9c7451c668108bcae0809..3d77ad75108285603facabedb9d8b4a90c776c06 100644 (file)
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from nova.api.openstack.api_version_request \
+    import MAX_IMAGE_META_PROXY_API_VERSION
 from nova.api.openstack.api_version_request \
     import MAX_PROXY_API_SUPPORT_VERSION
+from nova.api.openstack.api_version_request \
+    import MIN_WITHOUT_IMAGE_META_PROXY_API_VERSION
 from nova.api.openstack.api_version_request \
     import MIN_WITHOUT_PROXY_API_SUPPORT_VERSION
 from nova.api.openstack.compute.views import limits as limits_views
@@ -36,12 +40,19 @@ class LimitsController(wsgi.Controller):
     def index(self, req):
         return self._index(req)
 
-    @wsgi.Controller.api_version(MIN_WITHOUT_PROXY_API_SUPPORT_VERSION)  # noqa
+    @wsgi.Controller.api_version(MIN_WITHOUT_PROXY_API_SUPPORT_VERSION,  # noqa
+                                 MAX_IMAGE_META_PROXY_API_VERSION)  # noqa
     @extensions.expected_errors(())
     def index(self, req):
         return self._index(req, filter_result=True)
 
-    def _index(self, req, filter_result=False):
+    @wsgi.Controller.api_version(  # noqa
+        MIN_WITHOUT_IMAGE_META_PROXY_API_VERSION)  # noqa
+    @extensions.expected_errors(())
+    def index(self, req):
+        return self._index(req, filter_result=True, max_image_meta=False)
+
+    def _index(self, req, filter_result=False, max_image_meta=True):
         """Return all global limit information."""
         context = req.environ['nova.context']
         context.can(limits_policies.BASE_POLICY_NAME)
@@ -51,7 +62,8 @@ class LimitsController(wsgi.Controller):
         abs_limits = {k: v['limit'] for k, v in quotas.items()}
 
         builder = self._get_view_builder(req)
-        return builder.build(abs_limits, filter_result=filter_result)
+        return builder.build(abs_limits, filter_result=filter_result,
+                             max_image_meta=max_image_meta)
 
     def _get_view_builder(self, req):
         return limits_views.ViewBuilderV21()
index 314e40a8aa144b63bc8ecb64669bb4ef6d22ecec..eaf1e6d2697f3568e4cc066b7a97ee0a740487b9 100644 (file)
@@ -1053,7 +1053,11 @@ class ServersController(wsgi.Controller):
         image_name = common.normalize_name(entity["name"])
         metadata = entity.get('metadata', {})
 
-        common.check_img_metadata_properties_quota(context, metadata)
+        # Starting from microversion 2.39 we don't check quotas on createImage
+        if api_version_request.is_supported(
+                req, max_version=
+                api_version_request.MAX_IMAGE_META_PROXY_API_VERSION):
+            common.check_img_metadata_properties_quota(context, metadata)
 
         instance = self._get_server(context, req, id)
 
index 79610677f38e2caaeac8866f36013dea6fece5c8..3955032905a970af5c92d76dd0d49fa914bc907c 100644 (file)
@@ -41,9 +41,10 @@ class ViewBuilder(object):
             "security_group_rules": ["maxSecurityGroupRules"],
     }
 
-    def build(self, absolute_limits, filter_result=False):
+    def build(self, absolute_limits, filter_result=False, max_image_meta=True):
         absolute_limits = self._build_absolute_limits(
-            absolute_limits, filter_result=filter_result)
+            absolute_limits, filter_result=filter_result,
+            max_image_meta=max_image_meta)
 
         output = {
             "limits": {
@@ -54,7 +55,8 @@ class ViewBuilder(object):
 
         return output
 
-    def _build_absolute_limits(self, absolute_limits, filter_result=False):
+    def _build_absolute_limits(self, absolute_limits, filter_result=False,
+                               max_image_meta=True):
         """Builder for absolute limits
 
         absolute_limits should be given as a dict of limits.
@@ -69,6 +71,8 @@ class ViewBuilder(object):
             if (name in self.limit_names and
                     value is not None and name not in filtered_limits):
                 for limit_name in self.limit_names[name]:
+                    if not max_image_meta and limit_name == "maxImageMeta":
+                        continue
                     limits[limit_name] = value
         return limits
 
index 3b42bce13e0fad5a26c18030883797909ad1c818..5cbafd1988dfbbf43976284761afbec43c518c53 100644 (file)
@@ -415,3 +415,14 @@ user documentation.
   should not be accepted. From this version of the API admin as well as non
   admin user will get 400 HTTPBadRequest if invalid status is passed to nova
   list command.
+
+2.39
+----
+
+  Deprecates image-metadata proxy API that is just a proxy for Glance API
+  to operate the image metadata. Also removes the extra quota enforcement with
+  Nova `metadata` quota (quota checks for 'createImage' and 'createBackup'
+  actions in Nova were removed). After this version Glance configuration
+  option `image_property_quota` should be used to control the quota of
+  image metadatas. Also, removes the `maxImageMeta` field from `os-limits`
+  API response.
diff --git a/nova/tests/functional/api_sample_tests/api_samples/limits/v2.39/limit-get-resp.json.tpl b/nova/tests/functional/api_sample_tests/api_samples/limits/v2.39/limit-get-resp.json.tpl
new file mode 100644 (file)
index 0000000..68b29ea
--- /dev/null
@@ -0,0 +1,20 @@
+{
+    "limits": {
+        "absolute": {
+            "maxPersonality": 5,
+            "maxPersonalitySize": 10240,
+            "maxServerMeta": 128,
+            "maxTotalCores": 20,
+            "maxTotalInstances": 10,
+            "maxTotalKeypairs": 100,
+            "maxTotalRAMSize": 51200,
+            "maxServerGroups": 10,
+            "maxServerGroupMembers": 10,
+            "totalCoresUsed": 0,
+            "totalInstancesUsed": 0,
+            "totalRAMUsed": 0,
+            "totalServerGroupsUsed": 0
+        },
+        "rate": []
+    }
+}
index ab20aa7bd892c671dc0287eb79ef249bd0283741..939b79603e1802049d81067314ca3efec172c7e2 100644 (file)
@@ -48,3 +48,20 @@ class LimitsV236Test(api_sample_base.ApiSampleTestBaseV21):
         self.api.microversion = self.microversion
         response = self._do_get('limits')
         self._verify_response('limit-get-resp', {}, response, 200)
+
+
+class LimitsV239Test(api_sample_base.ApiSampleTestBaseV21):
+    """Test limits don't return 'maxImageMeta' field after 2.39.
+
+    We dropped the image-metadata proxy API in 2.39, which also means that we
+    shouldn't be returning 'maxImageMeta' field in 'os-limits' response.
+
+    """
+    sample_dir = "limits"
+    microversion = '2.39'
+    scenarios = [('v2_39', {'api_major_version': 'v2.1'})]
+
+    def test_limits_get(self):
+        self.api.microversion = self.microversion
+        response = self._do_get('limits')
+        self._verify_response('limit-get-resp', {}, response, 200)
index d3fca0d285e99a9b5ad56b12528c502ef3dbff5d..fe5a3d57c0e35a0b0057839cda45e73ae6b97fdd 100644 (file)
@@ -13,6 +13,7 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import mock
 import webob
 
 from nova.api.openstack import common
@@ -352,3 +353,34 @@ class CreateBackupPolicyEnforcementv21(test.NoDBTestCase):
         self.assertEqual(
             "Policy doesn't allow %s to be performed." % rule_name,
             exc.format_message())
+
+
+class CreateBackupTestsV239(test.NoDBTestCase):
+
+    def setUp(self):
+        super(CreateBackupTestsV239, self).setUp()
+        self.controller = create_backup_v21.CreateBackupController()
+        self.req = fakes.HTTPRequest.blank('', version='2.39')
+
+    @mock.patch.object(common, 'check_img_metadata_properties_quota')
+    @mock.patch.object(common, 'get_instance')
+    def test_create_backup_no_quota_checks(self, mock_get_instance,
+                                                 mock_check_quotas):
+        # 'mock_get_instance' helps to skip the whole logic of the action,
+        # but to make the test
+        mock_get_instance.side_effect = webob.exc.HTTPNotFound
+        metadata = {'123': 'asdf'}
+        body = {
+            'createBackup': {
+                'name': 'Backup 1',
+                'backup_type': 'daily',
+                'rotation': 1,
+                'metadata': metadata,
+            },
+        }
+        self.assertRaises(webob.exc.HTTPNotFound,
+                          self.controller._create_backup, self.req,
+                          fakes.FAKE_UUID, body=body)
+        # starting from version 2.39 no quota checks on Nova side are performed
+        # for 'createBackup' action after removing 'image-metadata' proxy API
+        mock_check_quotas.assert_not_called()
index 4a482ef15c65cb3ac305c892e12c1ec74698e54a..fb2903a4e2e0618dd95a2a66effedd0e9b9a44a0 100644 (file)
@@ -348,3 +348,28 @@ class ImageMetaDataTestV21(test.NoDBTestCase):
         self.assertRaises(webob.exc.HTTPForbidden,
                           self.controller.create, req, image_id,
                           body=body)
+
+
+class ImageMetadataControllerV239(test.NoDBTestCase):
+
+    def setUp(self):
+        super(ImageMetadataControllerV239, self).setUp()
+        self.controller = image_metadata_v21.ImageMetadataController()
+        self.req = fakes.HTTPRequest.blank('', version='2.39')
+
+    def test_not_found_for_all_image_metadata_api(self):
+        self.assertRaises(exception.VersionNotFoundForAPIMethod,
+                          self.controller.index, self.req)
+        self.assertRaises(exception.VersionNotFoundForAPIMethod,
+                          self.controller.show, self.req, fakes.FAKE_UUID)
+        self.assertRaises(exception.VersionNotFoundForAPIMethod,
+                          self.controller.create, self.req,
+                          fakes.FAKE_UUID, {'metadata': {}})
+        self.assertRaises(exception.VersionNotFoundForAPIMethod,
+                          self.controller.update, self.req,
+                          fakes.FAKE_UUID, 'id', {'metadata': {}})
+        self.assertRaises(exception.VersionNotFoundForAPIMethod,
+                          self.controller.update_all, self.req,
+                          fakes.FAKE_UUID, {'metadata': {}})
+        self.assertRaises(exception.VersionNotFoundForAPIMethod,
+                          self.controller.delete, self.req, fakes.FAKE_UUID)
index e588060f60e1093b6f3f6950e8211fa07e197e0a..46190d95a1da4239e13a6dd73822710cbdedf60e 100644 (file)
@@ -275,3 +275,36 @@ class LimitsControllerTestV236(BaseLimitTestSuite):
                 },
             }
             self.assertEqual(expected_response, response)
+
+
+class LimitsControllerTestV239(BaseLimitTestSuite):
+
+    def setUp(self):
+        super(LimitsControllerTestV239, self).setUp()
+        self.controller = limits_v21.LimitsController()
+        self.req = fakes.HTTPRequest.blank("/?tenant_id=faketenant",
+                                           version='2.39')
+
+    def test_index_filtered_no_max_image_meta(self):
+        absolute_limits = {
+            "metadata_items": 1,
+        }
+
+        def _get_project_quotas(context, project_id, usages=True):
+            return {k: dict(limit=v) for k, v in absolute_limits.items()}
+
+        with mock.patch('nova.quota.QUOTAS.get_project_quotas') as \
+                get_project_quotas:
+            get_project_quotas.side_effect = _get_project_quotas
+            response = self.controller.index(self.req)
+            # staring from version 2.39 there is no 'maxImageMeta' field
+            # in response after removing 'image-metadata' proxy API
+            expected_response = {
+                "limits": {
+                    "rate": [],
+                    "absolute": {
+                        "maxServerMeta": 1,
+                    },
+                },
+            }
+            self.assertEqual(expected_response, response)
index aa96d4687ba67f6add4992986914c47ab45c681c..945120e0406565181f5cc119e06cf540bf9ebd33 100644 (file)
@@ -4832,3 +4832,31 @@ class ServersPolicyEnforcementV21(test.NoDBTestCase):
                  "os_compute_api:servers:create:attach_volume": "@",
                  rule_name: "project:non_fake"}
         self._create_policy_check(rules, rule_name)
+
+
+class ServersActionsJsonTestV239(test.NoDBTestCase):
+
+    def setUp(self):
+        super(ServersActionsJsonTestV239, self).setUp()
+        ext_info = extension_info.LoadedExtensionInfo()
+        self.controller = servers.ServersController(extension_info=ext_info)
+        self.req = fakes.HTTPRequest.blank('', version='2.39')
+
+    @mock.patch.object(common, 'check_img_metadata_properties_quota')
+    @mock.patch.object(common, 'get_instance')
+    def test_server_create_image_no_quota_checks(self, mock_get_instance,
+                                                 mock_check_quotas):
+        # 'mock_get_instance' helps to skip the whole logic of the action,
+        # but to make the test
+        mock_get_instance.side_effect = webob.exc.HTTPNotFound
+        body = {
+            'createImage': {
+                'name': 'Snapshot 1',
+            },
+        }
+        self.assertRaises(webob.exc.HTTPNotFound,
+                          self.controller._action_create_image, self.req,
+                          FAKE_UUID, body=body)
+        # starting from version 2.39 no quota checks on Nova side are performed
+        # for 'createImage' action after removing 'image-metadata' proxy API
+        mock_check_quotas.assert_not_called()
diff --git a/releasenotes/notes/bp-deprecate-image-meta-proxy-api-7f21e1e6a94944ee.yaml b/releasenotes/notes/bp-deprecate-image-meta-proxy-api-7f21e1e6a94944ee.yaml
new file mode 100644 (file)
index 0000000..1e357d1
--- /dev/null
@@ -0,0 +1,9 @@
+---
+deprecations:
+  - Implemented microversion v2.39 that deprecates `image-metadata` proxy API,
+    removes image metadata quota checks for 'createImage' and 'createBackup'
+    actions.
+
+    After this version Glance configuration option `image_property_quota`
+    should be used to control the quota of image metadatas. Also, removes the
+    `maxImageMeta` field from `os-limits` API response.