[policy in code] Add support for service, limits
This patch adds policy in code support for capabilities, hosts, services, limits and depends on the quota patch [1]. [1]: https://review.openstack.org/#/c/508091/ Change-Id: Ib2bac2d28d950c0d8b734a54e300dd4185d98ca9 Partial-Implements: blueprint policy-in-code
This commit is contained in:
parent
5a099de01a
commit
5b5715e2ad
@ -21,13 +21,10 @@ from cinder.api.views import capabilities as capabilities_view
|
|||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
from cinder import objects
|
from cinder import objects
|
||||||
|
from cinder.policies import capabilities as policy
|
||||||
from cinder.volume import rpcapi
|
from cinder.volume import rpcapi
|
||||||
|
|
||||||
|
|
||||||
def authorize(context, action_name):
|
|
||||||
extensions.extension_authorizer('volume', action_name)(context)
|
|
||||||
|
|
||||||
|
|
||||||
class CapabilitiesController(wsgi.Controller):
|
class CapabilitiesController(wsgi.Controller):
|
||||||
"""The Capabilities controller for the OpenStack API."""
|
"""The Capabilities controller for the OpenStack API."""
|
||||||
|
|
||||||
@ -43,7 +40,7 @@ class CapabilitiesController(wsgi.Controller):
|
|||||||
def show(self, req, id):
|
def show(self, req, id):
|
||||||
"""Return capabilities list of given backend."""
|
"""Return capabilities list of given backend."""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
authorize(context, 'capabilities')
|
context.authorize(policy.CAPABILITIES_POLICY)
|
||||||
filters = {'host_or_cluster': id, 'binary': 'cinder-volume'}
|
filters = {'host_or_cluster': id, 'binary': 'cinder-volume'}
|
||||||
services = objects.ServiceList.get_all(context, filters)
|
services = objects.ServiceList.get_all(context, filters)
|
||||||
if not services:
|
if not services:
|
||||||
|
@ -27,13 +27,13 @@ from cinder import db
|
|||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
from cinder import objects
|
from cinder import objects
|
||||||
|
from cinder.policies import hosts as policy
|
||||||
from cinder.volume import api as volume_api
|
from cinder.volume import api as volume_api
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
authorize = extensions.extension_authorizer('volume', 'hosts')
|
|
||||||
|
|
||||||
|
|
||||||
def _list_hosts(req, service=None):
|
def _list_hosts(req, service=None):
|
||||||
@ -91,12 +91,14 @@ class HostController(wsgi.Controller):
|
|||||||
super(HostController, self).__init__()
|
super(HostController, self).__init__()
|
||||||
|
|
||||||
def index(self, req):
|
def index(self, req):
|
||||||
authorize(req.environ['cinder.context'])
|
context = req.environ['cinder.context']
|
||||||
|
context.authorize(policy.MANAGE_POLICY)
|
||||||
return {'hosts': _list_hosts(req)}
|
return {'hosts': _list_hosts(req)}
|
||||||
|
|
||||||
@check_host
|
@check_host
|
||||||
def update(self, req, id, body):
|
def update(self, req, id, body):
|
||||||
authorize(req.environ['cinder.context'])
|
context = req.environ['cinder.context']
|
||||||
|
context.authorize(policy.MANAGE_POLICY)
|
||||||
update_values = {}
|
update_values = {}
|
||||||
for raw_key, raw_val in body.items():
|
for raw_key, raw_val in body.items():
|
||||||
key = raw_key.lower().strip()
|
key = raw_key.lower().strip()
|
||||||
|
@ -19,15 +19,11 @@ from cinder.api import extensions
|
|||||||
from cinder.api import microversions as mv
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
from cinder.api.views import scheduler_stats as scheduler_stats_view
|
from cinder.api.views import scheduler_stats as scheduler_stats_view
|
||||||
|
from cinder.policies import scheduler_stats as policy
|
||||||
from cinder.scheduler import rpcapi
|
from cinder.scheduler import rpcapi
|
||||||
from cinder import utils
|
from cinder import utils
|
||||||
|
|
||||||
|
|
||||||
def authorize(context, action_name):
|
|
||||||
action = 'scheduler_stats:%s' % action_name
|
|
||||||
extensions.extension_authorizer('scheduler', action)(context)
|
|
||||||
|
|
||||||
|
|
||||||
class SchedulerStatsController(wsgi.Controller):
|
class SchedulerStatsController(wsgi.Controller):
|
||||||
"""The Scheduler Stats controller for the OpenStack API."""
|
"""The Scheduler Stats controller for the OpenStack API."""
|
||||||
|
|
||||||
@ -46,7 +42,7 @@ class SchedulerStatsController(wsgi.Controller):
|
|||||||
def get_pools(self, req):
|
def get_pools(self, req):
|
||||||
"""List all active pools in scheduler."""
|
"""List all active pools in scheduler."""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
authorize(context, 'get_pools')
|
context.authorize(policy.GET_POOL_POLICY)
|
||||||
|
|
||||||
detail = utils.get_bool_param('detail', req.params)
|
detail = utils.get_bool_param('detail', req.params)
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ from cinder.common import constants
|
|||||||
from cinder import exception
|
from cinder import exception
|
||||||
from cinder.i18n import _
|
from cinder.i18n import _
|
||||||
from cinder import objects
|
from cinder import objects
|
||||||
|
from cinder.policies import services as policy
|
||||||
from cinder.scheduler import rpcapi as scheduler_rpcapi
|
from cinder.scheduler import rpcapi as scheduler_rpcapi
|
||||||
from cinder import utils
|
from cinder import utils
|
||||||
from cinder import volume
|
from cinder import volume
|
||||||
@ -38,7 +39,6 @@ from cinder.volume import rpcapi as volume_rpcapi
|
|||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
authorize = extensions.extension_authorizer('volume', 'services')
|
|
||||||
|
|
||||||
|
|
||||||
class ServiceController(wsgi.Controller):
|
class ServiceController(wsgi.Controller):
|
||||||
@ -61,7 +61,7 @@ class ServiceController(wsgi.Controller):
|
|||||||
Filter by host & service name.
|
Filter by host & service name.
|
||||||
"""
|
"""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
authorize(context, action='index')
|
context.authorize(policy.GET_ALL_POLICY)
|
||||||
detailed = self.ext_mgr.is_loaded('os-extended-services')
|
detailed = self.ext_mgr.is_loaded('os-extended-services')
|
||||||
now = timeutils.utcnow(with_timezone=True)
|
now = timeutils.utcnow(with_timezone=True)
|
||||||
|
|
||||||
@ -223,7 +223,7 @@ class ServiceController(wsgi.Controller):
|
|||||||
directly in this API layer.
|
directly in this API layer.
|
||||||
"""
|
"""
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
authorize(context, action='update')
|
context.authorize(policy.UPDATE_POLICY)
|
||||||
|
|
||||||
support_dynamic_log = req.api_version_request.matches(mv.LOG_LEVEL)
|
support_dynamic_log = req.api_version_request.matches(mv.LOG_LEVEL)
|
||||||
|
|
||||||
|
@ -15,19 +15,19 @@
|
|||||||
from cinder.api import extensions
|
from cinder.api import extensions
|
||||||
from cinder.api import microversions as mv
|
from cinder.api import microversions as mv
|
||||||
from cinder.api.openstack import wsgi
|
from cinder.api.openstack import wsgi
|
||||||
|
from cinder.policies import limits as policy
|
||||||
from cinder import quota
|
from cinder import quota
|
||||||
|
|
||||||
QUOTAS = quota.QUOTAS
|
QUOTAS = quota.QUOTAS
|
||||||
|
|
||||||
authorize = extensions.soft_extension_authorizer('limits', 'used_limits')
|
|
||||||
|
|
||||||
|
|
||||||
class UsedLimitsController(wsgi.Controller):
|
class UsedLimitsController(wsgi.Controller):
|
||||||
|
|
||||||
@wsgi.extends
|
@wsgi.extends
|
||||||
def index(self, req, resp_obj):
|
def index(self, req, resp_obj):
|
||||||
context = req.environ['cinder.context']
|
context = req.environ['cinder.context']
|
||||||
if authorize(context):
|
if context.authorize(
|
||||||
|
policy.EXTEND_LIMIT_ATTRIBUTE_POLICY, fatal=False):
|
||||||
params = req.params.copy()
|
params = req.params.copy()
|
||||||
req_version = req.api_version_request
|
req_version = req.api_version_request
|
||||||
|
|
||||||
|
@ -19,17 +19,22 @@ from cinder.policies import attachments
|
|||||||
from cinder.policies import backup_actions
|
from cinder.policies import backup_actions
|
||||||
from cinder.policies import backups
|
from cinder.policies import backups
|
||||||
from cinder.policies import base
|
from cinder.policies import base
|
||||||
|
from cinder.policies import capabilities
|
||||||
from cinder.policies import clusters
|
from cinder.policies import clusters
|
||||||
from cinder.policies import group_actions
|
from cinder.policies import group_actions
|
||||||
from cinder.policies import group_snapshot_actions
|
from cinder.policies import group_snapshot_actions
|
||||||
from cinder.policies import group_snapshots
|
from cinder.policies import group_snapshots
|
||||||
from cinder.policies import group_types
|
from cinder.policies import group_types
|
||||||
from cinder.policies import groups
|
from cinder.policies import groups
|
||||||
|
from cinder.policies import hosts
|
||||||
|
from cinder.policies import limits
|
||||||
from cinder.policies import manageable_snapshots
|
from cinder.policies import manageable_snapshots
|
||||||
from cinder.policies import messages
|
from cinder.policies import messages
|
||||||
from cinder.policies import qos_specs
|
from cinder.policies import qos_specs
|
||||||
from cinder.policies import quota_class
|
from cinder.policies import quota_class
|
||||||
from cinder.policies import quotas
|
from cinder.policies import quotas
|
||||||
|
from cinder.policies import scheduler_stats
|
||||||
|
from cinder.policies import services
|
||||||
from cinder.policies import snapshot_actions
|
from cinder.policies import snapshot_actions
|
||||||
from cinder.policies import snapshot_metadata
|
from cinder.policies import snapshot_metadata
|
||||||
from cinder.policies import snapshots
|
from cinder.policies import snapshots
|
||||||
@ -57,4 +62,9 @@ def list_rules():
|
|||||||
qos_specs.list_rules(),
|
qos_specs.list_rules(),
|
||||||
quota_class.list_rules(),
|
quota_class.list_rules(),
|
||||||
quotas.list_rules(),
|
quotas.list_rules(),
|
||||||
|
capabilities.list_rules(),
|
||||||
|
services.list_rules(),
|
||||||
|
scheduler_stats.list_rules(),
|
||||||
|
hosts.list_rules(),
|
||||||
|
limits.list_rules(),
|
||||||
)
|
)
|
||||||
|
39
cinder/policies/capabilities.py
Normal file
39
cinder/policies/capabilities.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# Copyright (c) 2017 Huawei Technologies Co., Ltd.
|
||||||
|
# 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 oslo_policy import policy
|
||||||
|
|
||||||
|
from cinder.policies import base
|
||||||
|
|
||||||
|
|
||||||
|
CAPABILITIES_POLICY = "volume_extension:capabilities",
|
||||||
|
|
||||||
|
|
||||||
|
capabilities_policies = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=CAPABILITIES_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_API,
|
||||||
|
description="Show backend capabilities.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/capabilities/{host_name}'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return capabilities_policies
|
42
cinder/policies/hosts.py
Normal file
42
cinder/policies/hosts.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Copyright (c) 2017 Huawei Technologies Co., Ltd.
|
||||||
|
# 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 oslo_policy import policy
|
||||||
|
|
||||||
|
from cinder.policies import base
|
||||||
|
|
||||||
|
|
||||||
|
MANAGE_POLICY = "volume_extension:hosts"
|
||||||
|
|
||||||
|
hosts_policies = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=MANAGE_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_API,
|
||||||
|
description="List or update hosts for a project.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/os-hosts'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'method': 'PUT',
|
||||||
|
'path': '/os-hosts/{host_name}'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return hosts_policies
|
38
cinder/policies/limits.py
Normal file
38
cinder/policies/limits.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Copyright (c) 2017 Huawei Technologies Co., Ltd.
|
||||||
|
# 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 oslo_policy import policy
|
||||||
|
|
||||||
|
from cinder.policies import base
|
||||||
|
|
||||||
|
EXTEND_LIMIT_ATTRIBUTE_POLICY = "limits_extension:used_limits"
|
||||||
|
|
||||||
|
|
||||||
|
limits_policies = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=EXTEND_LIMIT_ATTRIBUTE_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||||
|
description="Show limits with used limit attributes.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/limits'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return limits_policies
|
38
cinder/policies/scheduler_stats.py
Normal file
38
cinder/policies/scheduler_stats.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Copyright (c) 2017 Huawei Technologies Co., Ltd.
|
||||||
|
# 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 oslo_policy import policy
|
||||||
|
|
||||||
|
from cinder.policies import base
|
||||||
|
|
||||||
|
|
||||||
|
GET_POOL_POLICY = "scheduler_extension:scheduler_stats:get_pools"
|
||||||
|
|
||||||
|
pools_policies = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=GET_POOL_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_API,
|
||||||
|
description="List all backend pools.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/scheduler-stats/get_pools'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return pools_policies
|
83
cinder/policies/services.py
Normal file
83
cinder/policies/services.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
# Copyright (c) 2017 Huawei Technologies Co., Ltd.
|
||||||
|
# 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 oslo_policy import policy
|
||||||
|
|
||||||
|
from cinder.policies import base
|
||||||
|
|
||||||
|
|
||||||
|
GET_ALL_POLICY = "volume_extension:services:index"
|
||||||
|
UPDATE_POLICY = "volume_extension:services:update"
|
||||||
|
FAILOVER_POLICY = "volume:failover_host"
|
||||||
|
FREEZE_POLICY = "volume:freeze_host"
|
||||||
|
THAW_POLICY = "volume:thaw_host"
|
||||||
|
|
||||||
|
services_policies = [
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=GET_ALL_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_API,
|
||||||
|
description="List all services.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'GET',
|
||||||
|
'path': '/os-services'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=UPDATE_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_API,
|
||||||
|
description="Update service, including failover_host, thaw, freeze, "
|
||||||
|
"disable, enable, set-log and get-log actions.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'PUT',
|
||||||
|
'path': '/os-services/{action}'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=FREEZE_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_API,
|
||||||
|
description="Freeze a backend host.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'PUT',
|
||||||
|
'path': '/os-services/freeze'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=THAW_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_API,
|
||||||
|
description="Thaw a backend host.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'PUT',
|
||||||
|
'path': '/os-services/thaw'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
policy.DocumentedRuleDefault(
|
||||||
|
name=FAILOVER_POLICY,
|
||||||
|
check_str=base.RULE_ADMIN_API,
|
||||||
|
description="Failover a backend host.",
|
||||||
|
operations=[
|
||||||
|
{
|
||||||
|
'method': 'PUT',
|
||||||
|
'path': '/os-services/failover_host'
|
||||||
|
}
|
||||||
|
]),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def list_rules():
|
||||||
|
return services_policies
|
@ -174,7 +174,7 @@ def fake_service_update(context, service_id, values):
|
|||||||
'disabled': values['disabled']}
|
'disabled': values['disabled']}
|
||||||
|
|
||||||
|
|
||||||
def fake_policy_enforce(context, action, target):
|
def fake_policy_authorize(context, action, target):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ def fake_utcnow(with_timezone=False):
|
|||||||
@mock.patch('cinder.db.service_get', fake_service_get)
|
@mock.patch('cinder.db.service_get', fake_service_get)
|
||||||
@mock.patch('oslo_utils.timeutils.utcnow', fake_utcnow)
|
@mock.patch('oslo_utils.timeutils.utcnow', fake_utcnow)
|
||||||
@mock.patch('cinder.db.sqlalchemy.api.service_update', fake_service_update)
|
@mock.patch('cinder.db.sqlalchemy.api.service_update', fake_service_update)
|
||||||
@mock.patch('cinder.policy.enforce', fake_policy_enforce)
|
@mock.patch('cinder.policy.authorize', fake_policy_authorize)
|
||||||
class ServicesTest(test.TestCase):
|
class ServicesTest(test.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -47,8 +47,8 @@ class UsedLimitsTestCase(test.TestCase):
|
|||||||
(mv.LIMITS_ADMIN_FILTER, True),
|
(mv.LIMITS_ADMIN_FILTER, True),
|
||||||
(mv.LIMITS_ADMIN_FILTER, False))
|
(mv.LIMITS_ADMIN_FILTER, False))
|
||||||
@mock.patch('cinder.quota.QUOTAS.get_project_quotas')
|
@mock.patch('cinder.quota.QUOTAS.get_project_quotas')
|
||||||
@mock.patch('cinder.policy.enforce')
|
@mock.patch('cinder.policy.authorize')
|
||||||
def test_used_limits(self, ver_project, _mock_policy_enforce,
|
def test_used_limits(self, ver_project, _mock_policy_authorize,
|
||||||
_mock_get_project_quotas):
|
_mock_get_project_quotas):
|
||||||
version, has_project = ver_project
|
version, has_project = ver_project
|
||||||
fake_req = FakeRequest(fakes.FakeRequestContext(fake.USER_ID,
|
fake_req = FakeRequest(fakes.FakeRequestContext(fake.USER_ID,
|
||||||
@ -77,7 +77,7 @@ class UsedLimitsTestCase(test.TestCase):
|
|||||||
|
|
||||||
_mock_get_project_quotas.side_effect = get_project_quotas
|
_mock_get_project_quotas.side_effect = get_project_quotas
|
||||||
# allow user to access used limits
|
# allow user to access used limits
|
||||||
_mock_policy_enforce.return_value = None
|
_mock_policy_authorize.return_value = True
|
||||||
|
|
||||||
self.controller.index(fake_req, res)
|
self.controller.index(fake_req, res)
|
||||||
abs_limits = res.obj['limits']['absolute']
|
abs_limits = res.obj['limits']['absolute']
|
||||||
@ -111,7 +111,7 @@ class UsedLimitsTestCase(test.TestCase):
|
|||||||
res = wsgi.ResponseObject(obj)
|
res = wsgi.ResponseObject(obj)
|
||||||
|
|
||||||
# unallow user to access used limits
|
# unallow user to access used limits
|
||||||
_mock_policy_enforce.side_effect = exception.NotAuthorized
|
_mock_policy_authorize.side_effect = exception.NotAuthorized
|
||||||
|
|
||||||
self.controller.index(fake_req, res)
|
self.controller.index(fake_req, res)
|
||||||
abs_limits = res.obj['limits']['absolute']
|
abs_limits = res.obj['limits']['absolute']
|
||||||
|
@ -39,9 +39,6 @@
|
|||||||
"volume:update_readonly_flag": "",
|
"volume:update_readonly_flag": "",
|
||||||
"volume:retype": "",
|
"volume:retype": "",
|
||||||
"volume:copy_volume_to_image": "",
|
"volume:copy_volume_to_image": "",
|
||||||
"volume:failover_host": "rule:admin_api",
|
|
||||||
"volume:freeze_host": "rule:admin_api",
|
|
||||||
"volume:thaw_host": "rule:admin_api",
|
|
||||||
"volume:revert_to_snapshot": "",
|
"volume:revert_to_snapshot": "",
|
||||||
"volume_extension:volume_admin_actions:reset_status": "rule:admin_api",
|
"volume_extension:volume_admin_actions:reset_status": "rule:admin_api",
|
||||||
"volume_extension:volume_admin_actions:force_delete": "rule:admin_api",
|
"volume_extension:volume_admin_actions:force_delete": "rule:admin_api",
|
||||||
@ -68,13 +65,11 @@
|
|||||||
"volume_extension:volume_host_attribute": "rule:admin_api",
|
"volume_extension:volume_host_attribute": "rule:admin_api",
|
||||||
"volume_extension:volume_tenant_attribute": "rule:admin_api",
|
"volume_extension:volume_tenant_attribute": "rule:admin_api",
|
||||||
"volume_extension:volume_mig_status_attribute": "rule:admin_api",
|
"volume_extension:volume_mig_status_attribute": "rule:admin_api",
|
||||||
"volume_extension:hosts": "rule:admin_api",
|
|
||||||
"volume_extension:services:index": "",
|
"volume_extension:services:index": "",
|
||||||
"volume_extension:services:update" : "rule:admin_api",
|
"volume_extension:services:update" : "rule:admin_api",
|
||||||
"volume_extension:volume_manage": "rule:admin_api",
|
"volume_extension:volume_manage": "rule:admin_api",
|
||||||
"volume_extension:volume_unmanage": "rule:admin_api",
|
"volume_extension:volume_unmanage": "rule:admin_api",
|
||||||
"volume_extension:list_manageable": "rule:admin_api",
|
"volume_extension:list_manageable": "rule:admin_api",
|
||||||
"volume_extension:capabilities": "rule:admin_api",
|
|
||||||
|
|
||||||
"limits_extension:used_limits": "",
|
"limits_extension:used_limits": "",
|
||||||
|
|
||||||
@ -115,8 +110,6 @@
|
|||||||
"group:enable_replication": "",
|
"group:enable_replication": "",
|
||||||
"group:disable_replication": "",
|
"group:disable_replication": "",
|
||||||
"group:failover_replication": "",
|
"group:failover_replication": "",
|
||||||
"group:list_replication_targets": "",
|
"group:list_replication_targets": ""
|
||||||
|
|
||||||
"scheduler_extension:scheduler_stats:get_pools" : "rule:admin_api",
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ from cinder import objects
|
|||||||
from cinder.objects import base as objects_base
|
from cinder.objects import base as objects_base
|
||||||
from cinder.objects import fields
|
from cinder.objects import fields
|
||||||
from cinder.policies import attachments as attachment_policy
|
from cinder.policies import attachments as attachment_policy
|
||||||
|
from cinder.policies import services as svr_policy
|
||||||
from cinder.policies import snapshot_metadata as s_meta_policy
|
from cinder.policies import snapshot_metadata as s_meta_policy
|
||||||
from cinder.policies import snapshots as snapshot_policy
|
from cinder.policies import snapshots as snapshot_policy
|
||||||
import cinder.policy
|
import cinder.policy
|
||||||
@ -1843,7 +1844,7 @@ class API(base.Base):
|
|||||||
return cluster, services
|
return cluster, services
|
||||||
|
|
||||||
def failover(self, ctxt, host, cluster_name, secondary_id=None):
|
def failover(self, ctxt, host, cluster_name, secondary_id=None):
|
||||||
check_policy(ctxt, 'failover_host')
|
ctxt.authorize(svr_policy.FAILOVER_POLICY)
|
||||||
ctxt = ctxt if ctxt.is_admin else ctxt.elevated()
|
ctxt = ctxt if ctxt.is_admin else ctxt.elevated()
|
||||||
|
|
||||||
# TODO(geguileo): In P - Remove this version check
|
# TODO(geguileo): In P - Remove this version check
|
||||||
@ -1864,7 +1865,7 @@ class API(base.Base):
|
|||||||
self.volume_rpcapi.failover(ctxt, services[0], secondary_id)
|
self.volume_rpcapi.failover(ctxt, services[0], secondary_id)
|
||||||
|
|
||||||
def freeze_host(self, ctxt, host, cluster_name):
|
def freeze_host(self, ctxt, host, cluster_name):
|
||||||
check_policy(ctxt, 'freeze_host')
|
ctxt.authorize(svr_policy.FREEZE_POLICY)
|
||||||
ctxt = ctxt if ctxt.is_admin else ctxt.elevated()
|
ctxt = ctxt if ctxt.is_admin else ctxt.elevated()
|
||||||
|
|
||||||
expected = False
|
expected = False
|
||||||
@ -1879,7 +1880,7 @@ class API(base.Base):
|
|||||||
self.volume_rpcapi.freeze_host(ctxt, services[0])
|
self.volume_rpcapi.freeze_host(ctxt, services[0])
|
||||||
|
|
||||||
def thaw_host(self, ctxt, host, cluster_name):
|
def thaw_host(self, ctxt, host, cluster_name):
|
||||||
check_policy(ctxt, 'thaw_host')
|
ctxt.authorize(svr_policy.THAW_POLICY)
|
||||||
ctxt = ctxt if ctxt.is_admin else ctxt.elevated()
|
ctxt = ctxt if ctxt.is_admin else ctxt.elevated()
|
||||||
|
|
||||||
expected = True
|
expected = True
|
||||||
|
@ -46,26 +46,17 @@
|
|||||||
"volume_extension:volume_host_attribute": "rule:admin_api",
|
"volume_extension:volume_host_attribute": "rule:admin_api",
|
||||||
"volume_extension:volume_tenant_attribute": "rule:admin_or_owner",
|
"volume_extension:volume_tenant_attribute": "rule:admin_or_owner",
|
||||||
"volume_extension:volume_mig_status_attribute": "rule:admin_api",
|
"volume_extension:volume_mig_status_attribute": "rule:admin_api",
|
||||||
"volume_extension:hosts": "rule:admin_api",
|
|
||||||
"volume_extension:services:index": "rule:admin_api",
|
|
||||||
"volume_extension:services:update" : "rule:admin_api",
|
|
||||||
|
|
||||||
"volume_extension:volume_manage": "rule:admin_api",
|
"volume_extension:volume_manage": "rule:admin_api",
|
||||||
"volume_extension:volume_unmanage": "rule:admin_api",
|
"volume_extension:volume_unmanage": "rule:admin_api",
|
||||||
"volume_extension:list_manageable": "rule:admin_api",
|
"volume_extension:list_manageable": "rule:admin_api",
|
||||||
|
|
||||||
"volume_extension:capabilities": "rule:admin_api",
|
|
||||||
|
|
||||||
"volume:create_transfer": "rule:admin_or_owner",
|
"volume:create_transfer": "rule:admin_or_owner",
|
||||||
"volume:accept_transfer": "",
|
"volume:accept_transfer": "",
|
||||||
"volume:delete_transfer": "rule:admin_or_owner",
|
"volume:delete_transfer": "rule:admin_or_owner",
|
||||||
"volume:get_transfer": "rule:admin_or_owner",
|
"volume:get_transfer": "rule:admin_or_owner",
|
||||||
"volume:get_all_transfers": "rule:admin_or_owner",
|
"volume:get_all_transfers": "rule:admin_or_owner",
|
||||||
|
|
||||||
"volume:failover_host": "rule:admin_api",
|
|
||||||
"volume:freeze_host": "rule:admin_api",
|
|
||||||
"volume:thaw_host": "rule:admin_api",
|
|
||||||
|
|
||||||
"consistencygroup:create" : "group:nobody",
|
"consistencygroup:create" : "group:nobody",
|
||||||
"consistencygroup:delete": "group:nobody",
|
"consistencygroup:delete": "group:nobody",
|
||||||
"consistencygroup:update": "group:nobody",
|
"consistencygroup:update": "group:nobody",
|
||||||
@ -77,6 +68,4 @@
|
|||||||
"consistencygroup:get_cgsnapshot": "group:nobody",
|
"consistencygroup:get_cgsnapshot": "group:nobody",
|
||||||
"consistencygroup:get_all_cgsnapshots": "group:nobody",
|
"consistencygroup:get_all_cgsnapshots": "group:nobody",
|
||||||
|
|
||||||
"scheduler_extension:scheduler_stats:get_pools" : "rule:admin_api",
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user