[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.i18n import _
|
||||
from cinder import objects
|
||||
from cinder.policies import capabilities as policy
|
||||
from cinder.volume import rpcapi
|
||||
|
||||
|
||||
def authorize(context, action_name):
|
||||
extensions.extension_authorizer('volume', action_name)(context)
|
||||
|
||||
|
||||
class CapabilitiesController(wsgi.Controller):
|
||||
"""The Capabilities controller for the OpenStack API."""
|
||||
|
||||
@ -43,7 +40,7 @@ class CapabilitiesController(wsgi.Controller):
|
||||
def show(self, req, id):
|
||||
"""Return capabilities list of given backend."""
|
||||
context = req.environ['cinder.context']
|
||||
authorize(context, 'capabilities')
|
||||
context.authorize(policy.CAPABILITIES_POLICY)
|
||||
filters = {'host_or_cluster': id, 'binary': 'cinder-volume'}
|
||||
services = objects.ServiceList.get_all(context, filters)
|
||||
if not services:
|
||||
|
@ -27,13 +27,13 @@ from cinder import db
|
||||
from cinder import exception
|
||||
from cinder.i18n import _
|
||||
from cinder import objects
|
||||
from cinder.policies import hosts as policy
|
||||
from cinder.volume import api as volume_api
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
authorize = extensions.extension_authorizer('volume', 'hosts')
|
||||
|
||||
|
||||
def _list_hosts(req, service=None):
|
||||
@ -91,12 +91,14 @@ class HostController(wsgi.Controller):
|
||||
super(HostController, self).__init__()
|
||||
|
||||
def index(self, req):
|
||||
authorize(req.environ['cinder.context'])
|
||||
context = req.environ['cinder.context']
|
||||
context.authorize(policy.MANAGE_POLICY)
|
||||
return {'hosts': _list_hosts(req)}
|
||||
|
||||
@check_host
|
||||
def update(self, req, id, body):
|
||||
authorize(req.environ['cinder.context'])
|
||||
context = req.environ['cinder.context']
|
||||
context.authorize(policy.MANAGE_POLICY)
|
||||
update_values = {}
|
||||
for raw_key, raw_val in body.items():
|
||||
key = raw_key.lower().strip()
|
||||
|
@ -19,15 +19,11 @@ from cinder.api import extensions
|
||||
from cinder.api import microversions as mv
|
||||
from cinder.api.openstack import wsgi
|
||||
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 import utils
|
||||
|
||||
|
||||
def authorize(context, action_name):
|
||||
action = 'scheduler_stats:%s' % action_name
|
||||
extensions.extension_authorizer('scheduler', action)(context)
|
||||
|
||||
|
||||
class SchedulerStatsController(wsgi.Controller):
|
||||
"""The Scheduler Stats controller for the OpenStack API."""
|
||||
|
||||
@ -46,7 +42,7 @@ class SchedulerStatsController(wsgi.Controller):
|
||||
def get_pools(self, req):
|
||||
"""List all active pools in scheduler."""
|
||||
context = req.environ['cinder.context']
|
||||
authorize(context, 'get_pools')
|
||||
context.authorize(policy.GET_POOL_POLICY)
|
||||
|
||||
detail = utils.get_bool_param('detail', req.params)
|
||||
|
||||
|
@ -29,6 +29,7 @@ from cinder.common import constants
|
||||
from cinder import exception
|
||||
from cinder.i18n import _
|
||||
from cinder import objects
|
||||
from cinder.policies import services as policy
|
||||
from cinder.scheduler import rpcapi as scheduler_rpcapi
|
||||
from cinder import utils
|
||||
from cinder import volume
|
||||
@ -38,7 +39,6 @@ from cinder.volume import rpcapi as volume_rpcapi
|
||||
CONF = cfg.CONF
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
authorize = extensions.extension_authorizer('volume', 'services')
|
||||
|
||||
|
||||
class ServiceController(wsgi.Controller):
|
||||
@ -61,7 +61,7 @@ class ServiceController(wsgi.Controller):
|
||||
Filter by host & service name.
|
||||
"""
|
||||
context = req.environ['cinder.context']
|
||||
authorize(context, action='index')
|
||||
context.authorize(policy.GET_ALL_POLICY)
|
||||
detailed = self.ext_mgr.is_loaded('os-extended-services')
|
||||
now = timeutils.utcnow(with_timezone=True)
|
||||
|
||||
@ -223,7 +223,7 @@ class ServiceController(wsgi.Controller):
|
||||
directly in this API layer.
|
||||
"""
|
||||
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)
|
||||
|
||||
|
@ -15,19 +15,19 @@
|
||||
from cinder.api import extensions
|
||||
from cinder.api import microversions as mv
|
||||
from cinder.api.openstack import wsgi
|
||||
from cinder.policies import limits as policy
|
||||
from cinder import quota
|
||||
|
||||
QUOTAS = quota.QUOTAS
|
||||
|
||||
authorize = extensions.soft_extension_authorizer('limits', 'used_limits')
|
||||
|
||||
|
||||
class UsedLimitsController(wsgi.Controller):
|
||||
|
||||
@wsgi.extends
|
||||
def index(self, req, resp_obj):
|
||||
context = req.environ['cinder.context']
|
||||
if authorize(context):
|
||||
if context.authorize(
|
||||
policy.EXTEND_LIMIT_ATTRIBUTE_POLICY, fatal=False):
|
||||
params = req.params.copy()
|
||||
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 backups
|
||||
from cinder.policies import base
|
||||
from cinder.policies import capabilities
|
||||
from cinder.policies import clusters
|
||||
from cinder.policies import group_actions
|
||||
from cinder.policies import group_snapshot_actions
|
||||
from cinder.policies import group_snapshots
|
||||
from cinder.policies import group_types
|
||||
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 messages
|
||||
from cinder.policies import qos_specs
|
||||
from cinder.policies import quota_class
|
||||
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_metadata
|
||||
from cinder.policies import snapshots
|
||||
@ -57,4 +62,9 @@ def list_rules():
|
||||
qos_specs.list_rules(),
|
||||
quota_class.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']}
|
||||
|
||||
|
||||
def fake_policy_enforce(context, action, target):
|
||||
def fake_policy_authorize(context, action, target):
|
||||
pass
|
||||
|
||||
|
||||
@ -188,7 +188,7 @@ def fake_utcnow(with_timezone=False):
|
||||
@mock.patch('cinder.db.service_get', fake_service_get)
|
||||
@mock.patch('oslo_utils.timeutils.utcnow', fake_utcnow)
|
||||
@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):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -47,8 +47,8 @@ class UsedLimitsTestCase(test.TestCase):
|
||||
(mv.LIMITS_ADMIN_FILTER, True),
|
||||
(mv.LIMITS_ADMIN_FILTER, False))
|
||||
@mock.patch('cinder.quota.QUOTAS.get_project_quotas')
|
||||
@mock.patch('cinder.policy.enforce')
|
||||
def test_used_limits(self, ver_project, _mock_policy_enforce,
|
||||
@mock.patch('cinder.policy.authorize')
|
||||
def test_used_limits(self, ver_project, _mock_policy_authorize,
|
||||
_mock_get_project_quotas):
|
||||
version, has_project = ver_project
|
||||
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
|
||||
# allow user to access used limits
|
||||
_mock_policy_enforce.return_value = None
|
||||
_mock_policy_authorize.return_value = True
|
||||
|
||||
self.controller.index(fake_req, res)
|
||||
abs_limits = res.obj['limits']['absolute']
|
||||
@ -111,7 +111,7 @@ class UsedLimitsTestCase(test.TestCase):
|
||||
res = wsgi.ResponseObject(obj)
|
||||
|
||||
# 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)
|
||||
abs_limits = res.obj['limits']['absolute']
|
||||
|
@ -39,9 +39,6 @@
|
||||
"volume:update_readonly_flag": "",
|
||||
"volume:retype": "",
|
||||
"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_extension:volume_admin_actions:reset_status": "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_tenant_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:update" : "rule:admin_api",
|
||||
"volume_extension:volume_manage": "rule:admin_api",
|
||||
"volume_extension:volume_unmanage": "rule:admin_api",
|
||||
"volume_extension:list_manageable": "rule:admin_api",
|
||||
"volume_extension:capabilities": "rule:admin_api",
|
||||
|
||||
"limits_extension:used_limits": "",
|
||||
|
||||
@ -115,8 +110,6 @@
|
||||
"group:enable_replication": "",
|
||||
"group:disable_replication": "",
|
||||
"group:failover_replication": "",
|
||||
"group:list_replication_targets": "",
|
||||
|
||||
"scheduler_extension:scheduler_stats:get_pools" : "rule:admin_api",
|
||||
"group:list_replication_targets": ""
|
||||
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ from cinder import objects
|
||||
from cinder.objects import base as objects_base
|
||||
from cinder.objects import fields
|
||||
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 snapshots as snapshot_policy
|
||||
import cinder.policy
|
||||
@ -1843,7 +1844,7 @@ class API(base.Base):
|
||||
return cluster, services
|
||||
|
||||
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()
|
||||
|
||||
# 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)
|
||||
|
||||
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()
|
||||
|
||||
expected = False
|
||||
@ -1879,7 +1880,7 @@ class API(base.Base):
|
||||
self.volume_rpcapi.freeze_host(ctxt, services[0])
|
||||
|
||||
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()
|
||||
|
||||
expected = True
|
||||
|
@ -46,26 +46,17 @@
|
||||
"volume_extension:volume_host_attribute": "rule:admin_api",
|
||||
"volume_extension:volume_tenant_attribute": "rule:admin_or_owner",
|
||||
"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_unmanage": "rule:admin_api",
|
||||
"volume_extension:list_manageable": "rule:admin_api",
|
||||
|
||||
"volume_extension:capabilities": "rule:admin_api",
|
||||
|
||||
"volume:create_transfer": "rule:admin_or_owner",
|
||||
"volume:accept_transfer": "",
|
||||
"volume:delete_transfer": "rule:admin_or_owner",
|
||||
"volume:get_transfer": "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:delete": "group:nobody",
|
||||
"consistencygroup:update": "group:nobody",
|
||||
@ -77,6 +68,4 @@
|
||||
"consistencygroup:get_cgsnapshot": "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