Merge "[proxy-api] microversion 2.39 deprecates image-metadata proxy API"
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -2370,6 +2370,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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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),
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										20
									
								
								doc/api_samples/limits/v2.39/limit-get-resp.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								doc/api_samples/limits/v2.39/limit-get-resp.json
									
									
									
									
									
										Normal file
									
								
							@@ -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": []
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -19,7 +19,7 @@
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "status": "CURRENT",
 | 
			
		||||
        "version": "2.38",
 | 
			
		||||
        "version": "2.39",
 | 
			
		||||
        "min_version": "2.1",
 | 
			
		||||
        "updated": "2013-07-23T11:33:21Z"
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "status": "CURRENT",
 | 
			
		||||
            "version": "2.38",
 | 
			
		||||
            "version": "2.39",
 | 
			
		||||
            "min_version": "2.1",
 | 
			
		||||
            "updated": "2013-07-23T11:33:21Z"
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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,6 +58,10 @@ class CreateBackupController(wsgi.Controller):
 | 
			
		||||
 | 
			
		||||
        props = {}
 | 
			
		||||
        metadata = entity.get('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)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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):
 | 
			
		||||
 
 | 
			
		||||
@@ -13,8 +13,12 @@
 | 
			
		||||
#    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()
 | 
			
		||||
 
 | 
			
		||||
@@ -1053,6 +1053,10 @@ class ServersController(wsgi.Controller):
 | 
			
		||||
        image_name = common.normalize_name(entity["name"])
 | 
			
		||||
        metadata = entity.get('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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
 
 | 
			
		||||
@@ -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": []
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -4834,3 +4834,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()
 | 
			
		||||
 
 | 
			
		||||
@@ -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.
 | 
			
		||||
		Reference in New Issue
	
	Block a user