Port availability zones to core API

Changes:
- Register availability zones API as core API using old link.
- Remove extension code for availability zones.
- Leave rename of API url for future update which will be done with
  bump of microversion after port of all extensions to core API.

Partially implements bp ext-to-core

Change-Id: Ifc75ef2d16121634ad12e5e12960c928e4d24b90
This commit is contained in:
Valeriy Ponomaryov 2015-10-16 12:48:47 +03:00
parent 099145a07b
commit e4428f5e6c
10 changed files with 144 additions and 69 deletions

View File

@ -5,6 +5,8 @@
"admin_api": "is_admin:True",
"availability_zone:index": "rule:default",
"share:create": "",
"share:delete": "rule:default",
"share:get": "rule:default",

View File

@ -31,6 +31,7 @@ from manila import exception
from manila.i18n import _
from manila.i18n import _LE
from manila.i18n import _LI
from manila import policy
from manila import wsgi
LOG = log.getLogger(__name__)
@ -1110,6 +1111,12 @@ class Controller(object):
return decorator
def authorize(self, context, action):
try:
policy.check_policy(context, self.resource_name, action)
except exception.PolicyNotAuthorized:
raise webob.exc.HTTPForbidden()
@staticmethod
def is_valid_body(body, entity_name):
if not (body and entity_name in body):

View File

@ -13,31 +13,26 @@
# License for the specific language governing permissions and limitations
# under the License.
from manila.api import extensions
from manila.api.openstack import wsgi
from manila.api.views import availability_zones as availability_zones_views
from manila import db
authorize = extensions.extension_authorizer('share', 'availability_zones')
class AvailabilityZoneController(wsgi.Controller):
"""The Availability Zone API controller for the OpenStack API."""
resource_name = "availability_zone"
_view_builder_class = availability_zones_views.ViewBuilder
class Controller(wsgi.Controller):
def index(self, req):
self.authorize(req.environ['manila.context'], 'index')
return self._index(req)
def _index(self, req):
"""Describe all known availability zones."""
context = req.environ['manila.context']
authorize(context)
azs = db.availability_zone_get_all(context)
return {'availability_zones': azs}
views = db.availability_zone_get_all(req.environ['manila.context'])
return self._view_builder.detail_list(views)
class Availability_zones(extensions.ExtensionDescriptor):
"""Describe Availability Zones."""
name = 'AvailabilityZones'
alias = 'os-availability-zone'
updated = '2015-07-28T00:00:00+00:00'
def get_resources(self):
controller = Controller()
res = extensions.ResourceExtension(Availability_zones.alias,
controller)
return [res]
def create_resource():
return wsgi.Resource(AvailabilityZoneController())

View File

@ -23,6 +23,7 @@ from oslo_log import log
from manila.api import extensions
import manila.api.openstack
from manila.api.v1 import availability_zones
from manila.api.v1 import cgsnapshots
from manila.api.v1 import consistency_groups
from manila.api.v1 import limits
@ -56,6 +57,14 @@ class APIRouter(manila.api.openstack.APIRouter):
mapper.redirect("", "/")
self.resources["availability_zones"] = (
availability_zones.create_resource())
mapper.resource("availability-zone",
# TODO(vponomaryov): rename 'os-availability-zone' to
# 'availability-zones' when API urls rename happens.
"os-availability-zone",
controller=self.resources["availability_zones"])
self.resources['shares'] = shares.create_resource()
mapper.resource("share", "shares",
controller=self.resources['shares'],

View File

@ -19,7 +19,6 @@ from manila.api.openstack import wsgi
from manila.api.views import share_instance as instance_view
from manila import db
from manila import exception
from manila import policy
from manila import share
@ -33,16 +32,10 @@ class ShareInstancesController(wsgi.Controller):
self.share_api = share.API()
super(ShareInstancesController, self).__init__()
def _authorize(self, context, action):
try:
policy.check_policy(context, self.resource_name, action)
except exception.PolicyNotAuthorized:
raise exc.HTTPForbidden()
@wsgi.Controller.api_version("2.3")
def index(self, req):
context = req.environ['manila.context']
self._authorize(context, 'index')
self.authorize(context, 'index')
instances = db.share_instances_get_all(context)
return self._view_builder.detail_list(req, instances)
@ -50,7 +43,7 @@ class ShareInstancesController(wsgi.Controller):
@wsgi.Controller.api_version("2.3")
def show(self, req, id):
context = req.environ['manila.context']
self._authorize(context, 'show')
self.authorize(context, 'show')
try:
instance = db.share_instance_get(context, id)
@ -62,7 +55,7 @@ class ShareInstancesController(wsgi.Controller):
@wsgi.Controller.api_version("2.3")
def get_share_instances(self, req, share_id):
context = req.environ['manila.context']
self._authorize(context, 'index')
self.authorize(context, 'index')
try:
share = self.share_api.get(context, share_id)
@ -74,4 +67,4 @@ class ShareInstancesController(wsgi.Controller):
def create_resource():
return wsgi.Resource(ShareInstancesController())
return wsgi.Resource(ShareInstancesController())

View File

@ -0,0 +1,31 @@
# Copyright (c) 2015 Mirantis 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.
from manila.api import common
class ViewBuilder(common.ViewBuilder):
_collection_name = "availability_zones"
def _detail(self, availability_zone):
"""Detailed view of an single availability zone."""
keys = ('id', 'name', 'created_at', 'updated_at')
return {key: availability_zone.get(key) for key in keys}
def detail_list(self, availability_zones):
"""Detailed view of a list of availability zones."""
azs = [self._detail(az) for az in availability_zones]
return {self._collection_name: azs}

View File

@ -1,38 +0,0 @@
# Copyright 2015 Mirantis 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 mock
from manila.api.contrib import availability_zones
from manila import db
from manila import test
from manila.tests.api import fakes
class AvailabilityZonesApiTest(test.TestCase):
def setUp(self):
super(AvailabilityZonesApiTest, self).setUp()
self.controller = availability_zones.Controller()
def test_index(self):
fake_az = [{'test': 'test'}]
self.mock_object(db, 'availability_zone_get_all',
mock.Mock(return_value=fake_az))
req = fakes.HTTPRequest.blank('/v2/fake/types/1')
actual_result = self.controller.index(req)
self.assertDictMatch({'availability_zones': fake_az}, actual_result)
db.availability_zone_get_all.assert_called_once_with(mock.ANY)

View File

@ -0,0 +1,71 @@
# Copyright (c) 2015 Mirantis inc.
#
# 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 ddt
import mock
from manila.api.v1 import availability_zones
from manila import context
from manila import test
from manila.tests.api import fakes
@ddt.ddt
class AvailabilityZonesAPITest(test.TestCase):
def test_instantiate_controller(self):
controller = availability_zones.AvailabilityZoneController()
self.assertTrue(hasattr(controller, "resource_name"))
self.assertEqual("availability_zone", controller.resource_name)
self.assertTrue(hasattr(controller, "_view_builder"))
self.assertTrue(hasattr(controller._view_builder, "detail_list"))
@ddt.data('1.0', '2.0', '2.6')
def test_index(self, version):
azs = [
{
"id": "fake_id1",
"name": "fake_name1",
"created_at": "fake_created_at",
"updated_at": "fake_updated_at",
},
{
"id": "fake_id2",
"name": "fake_name2",
"created_at": "fake_created_at",
"updated_at": "fake_updated_at",
"deleted": "False",
"redundant_key": "redundant_value",
},
]
self.mock_object(availability_zones.db, 'availability_zone_get_all',
mock.Mock(return_value=azs))
controller = availability_zones.AvailabilityZoneController()
ctxt = context.RequestContext("admin", "fake", True)
req = fakes.HTTPRequest.blank('/shares', version=version)
req.environ['manila.context'] = ctxt
result = controller.index(req)
availability_zones.db.availability_zone_get_all.\
assert_called_once_with(ctxt)
self.assertTrue(isinstance(result, dict))
self.assertEqual(["availability_zones"], list(result.keys()))
self.assertTrue(isinstance(result["availability_zones"], list))
self.assertEqual(2, len(result["availability_zones"]))
self.assertTrue(azs[0] in result["availability_zones"])
azs[1].pop("deleted")
azs[1].pop("redundant_key")
self.assertTrue(azs[1] in result["availability_zones"])

View File

@ -4,6 +4,8 @@
"admin_or_owner": "is_admin:True or project_id:%(project_id)s",
"default": "rule:admin_or_owner",
"availability_zone:index": "rule:default",
"share:create": "",
"share:list_by_share_server_id": "rule:admin_api",
"share:get": "",

View File

@ -24,10 +24,13 @@ class AvailabilityZonesTest(base.BaseSharesTest):
self.assertTrue(len(availability_zones) > 0)
keys = ("created_at", "updated_at", "name", "id")
for az in availability_zones:
self.assertEqual(len(keys), len(az))
for key in keys:
self.assertIn(key, az)
@test.attr(type=["smoke", "gate"])
def test_list_availability_zones_extension(self):
def test_list_availability_zones_extension_url(self):
# NOTE(vponomaryov): remove this test with removal of availability zone
# extension url support.
azs = self.shares_client.list_availability_zones()
self._list_availability_zones_assertions(azs)