Merge "[policy in code] Add support for group, g-snapshot resources"
This commit is contained in:
commit
a0d9face37
@ -23,7 +23,7 @@ from cinder.api.openstack import wsgi
|
||||
from cinder import db
|
||||
from cinder import exception
|
||||
from cinder.i18n import _
|
||||
from cinder import policy
|
||||
from cinder.policies import group_types as policy
|
||||
from cinder import rpc
|
||||
from cinder import utils
|
||||
from cinder.volume import group_types
|
||||
@ -32,13 +32,6 @@ from cinder.volume import group_types
|
||||
class GroupTypeSpecsController(wsgi.Controller):
|
||||
"""The group type specs API controller for the OpenStack API."""
|
||||
|
||||
def _check_policy(self, context):
|
||||
target = {
|
||||
'project_id': context.project_id,
|
||||
'user_id': context.user_id,
|
||||
}
|
||||
policy.enforce(context, 'group:group_types_specs', target)
|
||||
|
||||
def _get_group_specs(self, context, group_type_id):
|
||||
group_specs = db.group_type_specs_get(context, group_type_id)
|
||||
specs_dict = {}
|
||||
@ -56,7 +49,7 @@ class GroupTypeSpecsController(wsgi.Controller):
|
||||
def index(self, req, group_type_id):
|
||||
"""Returns the list of group specs for a given group type."""
|
||||
context = req.environ['cinder.context']
|
||||
self._check_policy(context)
|
||||
context.authorize(policy.SPEC_POLICY)
|
||||
self._check_type(context, group_type_id)
|
||||
return self._get_group_specs(context, group_type_id)
|
||||
|
||||
@ -64,7 +57,7 @@ class GroupTypeSpecsController(wsgi.Controller):
|
||||
@wsgi.response(http_client.ACCEPTED)
|
||||
def create(self, req, group_type_id, body=None):
|
||||
context = req.environ['cinder.context']
|
||||
self._check_policy(context)
|
||||
context.authorize(policy.SPEC_POLICY)
|
||||
self.assert_valid_body(body, 'group_specs')
|
||||
|
||||
self._check_type(context, group_type_id)
|
||||
@ -84,7 +77,7 @@ class GroupTypeSpecsController(wsgi.Controller):
|
||||
@wsgi.Controller.api_version(mv.GROUP_TYPE)
|
||||
def update(self, req, group_type_id, id, body=None):
|
||||
context = req.environ['cinder.context']
|
||||
self._check_policy(context)
|
||||
context.authorize(policy.SPEC_POLICY)
|
||||
|
||||
if not body:
|
||||
expl = _('Request body empty')
|
||||
@ -113,7 +106,7 @@ class GroupTypeSpecsController(wsgi.Controller):
|
||||
def show(self, req, group_type_id, id):
|
||||
"""Return a single extra spec item."""
|
||||
context = req.environ['cinder.context']
|
||||
self._check_policy(context)
|
||||
context.authorize(policy.SPEC_POLICY)
|
||||
|
||||
self._check_type(context, group_type_id)
|
||||
specs = self._get_group_specs(context, group_type_id)
|
||||
@ -128,7 +121,7 @@ class GroupTypeSpecsController(wsgi.Controller):
|
||||
def delete(self, req, group_type_id, id):
|
||||
"""Deletes an existing group spec."""
|
||||
context = req.environ['cinder.context']
|
||||
self._check_policy(context)
|
||||
context.authorize(policy.SPEC_POLICY)
|
||||
|
||||
self._check_type(context, group_type_id)
|
||||
|
||||
|
@ -26,7 +26,7 @@ from cinder.api.openstack import wsgi
|
||||
from cinder.api.v3.views import group_types as views_types
|
||||
from cinder import exception
|
||||
from cinder.i18n import _
|
||||
from cinder import policy
|
||||
from cinder.policies import group_types as policy
|
||||
from cinder import rpc
|
||||
from cinder import utils
|
||||
from cinder.volume import group_types
|
||||
@ -37,13 +37,6 @@ class GroupTypesController(wsgi.Controller):
|
||||
|
||||
_view_builder_class = views_types.ViewBuilder
|
||||
|
||||
def _check_policy(self, context):
|
||||
target = {
|
||||
'project_id': context.project_id,
|
||||
'user_id': context.user_id,
|
||||
}
|
||||
policy.enforce(context, 'group:group_types_manage', target)
|
||||
|
||||
@utils.if_notifications_enabled
|
||||
def _notify_group_type_error(self, context, method, err,
|
||||
group_type=None, id=None, name=None):
|
||||
@ -61,7 +54,7 @@ class GroupTypesController(wsgi.Controller):
|
||||
def create(self, req, body):
|
||||
"""Creates a new group type."""
|
||||
context = req.environ['cinder.context']
|
||||
self._check_policy(context)
|
||||
context.authorize(policy.MANAGE_POLICY)
|
||||
|
||||
self.assert_valid_body(body, 'group_type')
|
||||
|
||||
@ -108,7 +101,7 @@ class GroupTypesController(wsgi.Controller):
|
||||
def update(self, req, id, body):
|
||||
# Update description for a given group type.
|
||||
context = req.environ['cinder.context']
|
||||
self._check_policy(context)
|
||||
context.authorize(policy.MANAGE_POLICY)
|
||||
|
||||
self.assert_valid_body(body, 'group_type')
|
||||
|
||||
@ -168,7 +161,7 @@ class GroupTypesController(wsgi.Controller):
|
||||
def delete(self, req, id):
|
||||
"""Deletes an existing group type."""
|
||||
context = req.environ['cinder.context']
|
||||
self._check_policy(context)
|
||||
context.authorize(policy.MANAGE_POLICY)
|
||||
|
||||
try:
|
||||
grp_type = group_types.get_group_type(context, id)
|
||||
|
@ -14,6 +14,7 @@
|
||||
# under the License.
|
||||
|
||||
from cinder.api import common
|
||||
from cinder.policies import group_types as policy
|
||||
|
||||
|
||||
class ViewBuilder(common.ViewBuilder):
|
||||
@ -25,9 +26,7 @@ class ViewBuilder(common.ViewBuilder):
|
||||
name=group_type.get('name'),
|
||||
description=group_type.get('description'),
|
||||
is_public=group_type.get('is_public'))
|
||||
if common.validate_policy(
|
||||
context,
|
||||
'group:access_group_types_specs'):
|
||||
if context.authorize(policy.SHOW_ACCESS_POLICY, fatal=False):
|
||||
trimmed['group_specs'] = group_type.get('group_specs')
|
||||
return trimmed if brief else dict(group_type=trimmed)
|
||||
|
||||
|
@ -18,8 +18,6 @@ Handles all requests relating to groups.
|
||||
"""
|
||||
|
||||
|
||||
import functools
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
from oslo_utils import excutils
|
||||
@ -31,9 +29,11 @@ from cinder.db import base
|
||||
from cinder import exception
|
||||
from cinder.i18n import _
|
||||
from cinder import objects
|
||||
from cinder.objects import base as objects_base
|
||||
from cinder.objects import fields as c_fields
|
||||
import cinder.policy
|
||||
from cinder.policies import group_actions as gp_action_policy
|
||||
from cinder.policies import group_snapshot_actions as gsnap_action_policy
|
||||
from cinder.policies import group_snapshots as gsnap_policy
|
||||
from cinder.policies import groups as group_policy
|
||||
from cinder import quota
|
||||
from cinder import quota_utils
|
||||
from cinder.scheduler import rpcapi as scheduler_rpcapi
|
||||
@ -57,37 +57,6 @@ VALID_ADD_VOL_TO_GROUP_STATUS = (
|
||||
'in-use')
|
||||
|
||||
|
||||
def wrap_check_policy(func):
|
||||
"""Check policy corresponding to the wrapped methods prior to execution.
|
||||
|
||||
This decorator requires the first 3 args of the wrapped function
|
||||
to be (self, context, group)
|
||||
"""
|
||||
@functools.wraps(func)
|
||||
def wrapped(self, context, target_obj, *args, **kwargs):
|
||||
check_policy(context, func.__name__, target_obj)
|
||||
return func(self, context, target_obj, *args, **kwargs)
|
||||
|
||||
return wrapped
|
||||
|
||||
|
||||
def check_policy(context, action, target_obj=None):
|
||||
target = {
|
||||
'project_id': context.project_id,
|
||||
'user_id': context.user_id,
|
||||
}
|
||||
|
||||
if isinstance(target_obj, objects_base.CinderObject):
|
||||
# Turn object into dict so target.update can work
|
||||
target.update(
|
||||
target_obj.obj_to_primitive()['versioned_object.data'] or {})
|
||||
else:
|
||||
target.update(target_obj or {})
|
||||
|
||||
_action = 'group:%s' % action
|
||||
cinder.policy.enforce(context, _action, target)
|
||||
|
||||
|
||||
class API(base.Base):
|
||||
"""API for interacting with the volume manager for groups."""
|
||||
|
||||
@ -130,7 +99,7 @@ class API(base.Base):
|
||||
|
||||
def create(self, context, name, description, group_type,
|
||||
volume_types, availability_zone=None):
|
||||
check_policy(context, 'create')
|
||||
context.authorize(group_policy.CREATE_POLICY)
|
||||
|
||||
req_volume_types = []
|
||||
# NOTE: Admin context is required to get extra_specs of volume_types.
|
||||
@ -196,7 +165,7 @@ class API(base.Base):
|
||||
|
||||
def create_from_src(self, context, name, description=None,
|
||||
group_snapshot_id=None, source_group_id=None):
|
||||
check_policy(context, 'create')
|
||||
context.authorize(group_policy.CREATE_POLICY)
|
||||
|
||||
# Populate group_type_id and volume_type_ids
|
||||
group_type_id = None
|
||||
@ -514,9 +483,8 @@ class API(base.Base):
|
||||
finally:
|
||||
LOG.error("Failed to update quota for group %s.", group.id)
|
||||
|
||||
@wrap_check_policy
|
||||
def delete(self, context, group, delete_volumes=False):
|
||||
|
||||
context.authorize(gp_action_policy.DELETE_POLICY, target_obj=group)
|
||||
if not group.host:
|
||||
self.update_quota(context, group, -1, group.project_id)
|
||||
|
||||
@ -602,10 +570,10 @@ class API(base.Base):
|
||||
|
||||
self.volume_rpcapi.delete_group(context, group)
|
||||
|
||||
@wrap_check_policy
|
||||
def update(self, context, group, name, description,
|
||||
add_volumes, remove_volumes):
|
||||
"""Update group."""
|
||||
context.authorize(group_policy.UPDATE_POLICY, target_obj=group)
|
||||
# Validate name.
|
||||
if name == group.name:
|
||||
name = None
|
||||
@ -806,12 +774,12 @@ class API(base.Base):
|
||||
|
||||
def get(self, context, group_id):
|
||||
group = objects.Group.get_by_id(context, group_id)
|
||||
check_policy(context, 'get', group)
|
||||
context.authorize(group_policy.GET_POLICY, target_obj=group)
|
||||
return group
|
||||
|
||||
def get_all(self, context, filters=None, marker=None, limit=None,
|
||||
offset=None, sort_keys=None, sort_dirs=None):
|
||||
check_policy(context, 'get_all')
|
||||
context.authorize(group_policy.GET_ALL_POLICY)
|
||||
if filters is None:
|
||||
filters = {}
|
||||
|
||||
@ -830,10 +798,9 @@ class API(base.Base):
|
||||
sort_dirs=sort_dirs)
|
||||
return groups
|
||||
|
||||
@wrap_check_policy
|
||||
def reset_status(self, context, group, status):
|
||||
"""Reset status of generic group"""
|
||||
|
||||
context.authorize(gp_action_policy.RESET_STATUS, target_obj=group)
|
||||
if status not in c_fields.GroupStatus.ALL:
|
||||
msg = _("Group status: %(status)s is invalid, valid status "
|
||||
"are: %(valid)s.") % {'status': status,
|
||||
@ -844,8 +811,8 @@ class API(base.Base):
|
||||
group.update(field)
|
||||
group.save()
|
||||
|
||||
@wrap_check_policy
|
||||
def create_group_snapshot(self, context, group, name, description):
|
||||
context.authorize(gsnap_policy.CREATE_POLICY, target_obj=group)
|
||||
group.assert_not_frozen()
|
||||
options = {'group_id': group.id,
|
||||
'user_id': context.user_id,
|
||||
@ -884,7 +851,7 @@ class API(base.Base):
|
||||
return group_snapshot
|
||||
|
||||
def delete_group_snapshot(self, context, group_snapshot, force=False):
|
||||
check_policy(context, 'delete_group_snapshot')
|
||||
context.authorize(gsnap_policy.DELETE_POLICY)
|
||||
group_snapshot.assert_not_frozen()
|
||||
values = {'status': 'deleting'}
|
||||
expected = {'status': ('available', 'error')}
|
||||
@ -911,12 +878,12 @@ class API(base.Base):
|
||||
group_snapshot)
|
||||
|
||||
def update_group_snapshot(self, context, group_snapshot, fields):
|
||||
check_policy(context, 'update_group_snapshot')
|
||||
context.authorize(gsnap_policy.UPDATE_POLICY)
|
||||
group_snapshot.update(fields)
|
||||
group_snapshot.save()
|
||||
|
||||
def get_group_snapshot(self, context, group_snapshot_id):
|
||||
check_policy(context, 'get_group_snapshot')
|
||||
context.authorize(gsnap_policy.GET_POLICY)
|
||||
group_snapshots = objects.GroupSnapshot.get_by_id(context,
|
||||
group_snapshot_id)
|
||||
return group_snapshots
|
||||
@ -924,7 +891,7 @@ class API(base.Base):
|
||||
def get_all_group_snapshots(self, context, filters=None, marker=None,
|
||||
limit=None, offset=None, sort_keys=None,
|
||||
sort_dirs=None):
|
||||
check_policy(context, 'get_all_group_snapshots')
|
||||
context.authorize(gsnap_policy.GET_ALL_POLICY)
|
||||
filters = filters or {}
|
||||
|
||||
if context.is_admin and 'all_tenants' in filters:
|
||||
@ -943,7 +910,7 @@ class API(base.Base):
|
||||
def reset_group_snapshot_status(self, context, gsnapshot, status):
|
||||
"""Reset status of group snapshot"""
|
||||
|
||||
check_policy(context, 'reset_group_snapshot_status')
|
||||
context.authorize(gsnap_action_policy.RESET_STATUS)
|
||||
if status not in c_fields.GroupSnapshotStatus.ALL:
|
||||
msg = _("Group snapshot status: %(status)s is invalid, "
|
||||
"valid statuses are: "
|
||||
@ -969,8 +936,8 @@ class API(base.Base):
|
||||
raise exception.InvalidVolumeType(reason=msg)
|
||||
|
||||
# Replication group API (Tiramisu)
|
||||
@wrap_check_policy
|
||||
def enable_replication(self, context, group):
|
||||
context.authorize(gp_action_policy.ENABLE_REP, target_obj=group)
|
||||
self._check_type(group)
|
||||
|
||||
valid_status = [c_fields.GroupStatus.AVAILABLE]
|
||||
@ -1030,8 +997,8 @@ class API(base.Base):
|
||||
|
||||
self.volume_rpcapi.enable_replication(context, group)
|
||||
|
||||
@wrap_check_policy
|
||||
def disable_replication(self, context, group):
|
||||
context.authorize(gp_action_policy.DISABLE_REP, target_obj=group)
|
||||
self._check_type(group)
|
||||
|
||||
valid_status = [c_fields.GroupStatus.AVAILABLE,
|
||||
@ -1080,10 +1047,10 @@ class API(base.Base):
|
||||
|
||||
self.volume_rpcapi.disable_replication(context, group)
|
||||
|
||||
@wrap_check_policy
|
||||
def failover_replication(self, context, group,
|
||||
allow_attached_volume=False,
|
||||
secondary_backend_id=None):
|
||||
context.authorize(gp_action_policy.FAILOVER_REP, target_obj=group)
|
||||
self._check_type(group)
|
||||
|
||||
valid_status = [c_fields.GroupStatus.AVAILABLE]
|
||||
@ -1148,8 +1115,8 @@ class API(base.Base):
|
||||
allow_attached_volume,
|
||||
secondary_backend_id)
|
||||
|
||||
@wrap_check_policy
|
||||
def list_replication_targets(self, context, group):
|
||||
context.authorize(gp_action_policy.LIST_REP, target_obj=group)
|
||||
self._check_type(group)
|
||||
|
||||
return self.volume_rpcapi.list_replication_targets(context, group)
|
||||
|
@ -20,6 +20,11 @@ from cinder.policies import backup_actions
|
||||
from cinder.policies import backups
|
||||
from cinder.policies import base
|
||||
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 manageable_snapshots
|
||||
from cinder.policies import messages
|
||||
from cinder.policies import snapshot_actions
|
||||
@ -41,4 +46,9 @@ def list_rules():
|
||||
manageable_snapshots.list_rules(),
|
||||
backups.list_rules(),
|
||||
backup_actions.list_rules(),
|
||||
groups.list_rules(),
|
||||
group_types.list_rules(),
|
||||
group_snapshots.list_rules(),
|
||||
group_snapshot_actions.list_rules(),
|
||||
group_actions.list_rules(),
|
||||
)
|
||||
|
93
cinder/policies/group_actions.py
Normal file
93
cinder/policies/group_actions.py
Normal file
@ -0,0 +1,93 @@
|
||||
# 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
|
||||
|
||||
|
||||
RESET_STATUS = 'group:reset_status'
|
||||
ENABLE_REP = 'group:enable_replication'
|
||||
DISABLE_REP = 'group:disable_replication'
|
||||
FAILOVER_REP = 'group:failover_replication'
|
||||
LIST_REP = 'group:list_replication_targets'
|
||||
DELETE_POLICY = 'group:delete'
|
||||
|
||||
group_actions_policies = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=DELETE_POLICY,
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
description="Delete group.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/groups/{group_id}/action (delete)'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=RESET_STATUS,
|
||||
check_str=base.RULE_ADMIN_API,
|
||||
description="Reset status of group.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/groups/{group_id}/action (reset_status)'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=ENABLE_REP,
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
description="Enable replication.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/groups/{group_id}/action (enable_replication)'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=DISABLE_REP,
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
description="Disable replication.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/groups/{group_id}/action (disable_replication)'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=FAILOVER_REP,
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
description="Fail over replication.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/groups/{group_id}/action (failover_replication)'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=LIST_REP,
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
description="List failover replication.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/groups/{group_id}/action (list_replication_targets)'
|
||||
}
|
||||
]),
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return group_actions_policies
|
40
cinder/policies/group_snapshot_actions.py
Normal file
40
cinder/policies/group_snapshot_actions.py
Normal file
@ -0,0 +1,40 @@
|
||||
# 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
|
||||
|
||||
|
||||
RESET_STATUS = 'group:reset_group_snapshot_status'
|
||||
|
||||
|
||||
group_snapshot_actions_policies = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=RESET_STATUS,
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
description="Reset status of group snapshot.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path':
|
||||
'/group_snapshots/{g_snapshot_id}/action (reset_status)'
|
||||
}
|
||||
]),
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return group_snapshot_actions_policies
|
87
cinder/policies/group_snapshots.py
Normal file
87
cinder/policies/group_snapshots.py
Normal file
@ -0,0 +1,87 @@
|
||||
# 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
|
||||
|
||||
|
||||
CREATE_POLICY = 'group:create_group_snapshot'
|
||||
DELETE_POLICY = 'group:delete_group_snapshot'
|
||||
UPDATE_POLICY = 'group:update_group_snapshot'
|
||||
GET_POLICY = 'group:get_group_snapshot'
|
||||
GET_ALL_POLICY = 'group:get_all_group_snapshots'
|
||||
|
||||
|
||||
group_snapshots_policies = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=GET_ALL_POLICY,
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
description="List group snapshots.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/group_snapshots'
|
||||
},
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/group_snapshots/detail'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CREATE_POLICY,
|
||||
check_str="",
|
||||
description="Create group snapshot.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/group_snapshots'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=GET_POLICY,
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
description="Show group snapshot.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/group_snapshots/{group_snapshot_id}'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=DELETE_POLICY,
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
description="Delete group snapshot.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'DELETE',
|
||||
'path': '/group_snapshots/{group_snapshot_id}'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=UPDATE_POLICY,
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
description="Update group snapshot.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'PUT',
|
||||
'path': '/group_snapshots/{group_snapshot_id}'
|
||||
}
|
||||
]),
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return group_snapshots_policies
|
86
cinder/policies/group_types.py
Normal file
86
cinder/policies/group_types.py
Normal file
@ -0,0 +1,86 @@
|
||||
# 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 = 'group:group_types_manage'
|
||||
SHOW_ACCESS_POLICY = 'group:access_group_types_specs'
|
||||
SPEC_POLICY = 'group:group_types_specs'
|
||||
|
||||
|
||||
group_types_policies = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=MANAGE_POLICY,
|
||||
check_str=base.RULE_ADMIN_API,
|
||||
description="Create, update or delete a group type.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/group_types/'
|
||||
},
|
||||
{
|
||||
'method': 'PUT',
|
||||
'path': '/group_types/{group_type_id}'
|
||||
},
|
||||
{
|
||||
'method': 'DELETE',
|
||||
'path': '/group_types/{group_type_id}'
|
||||
}
|
||||
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=SHOW_ACCESS_POLICY,
|
||||
check_str=base.RULE_ADMIN_API,
|
||||
description="Show group type with type specs attributes.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/group_types/{group_type_id}'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=SPEC_POLICY,
|
||||
check_str=base.RULE_ADMIN_API,
|
||||
description="Create, show, update and delete group type spec.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/group_types/{group_type_id}/group_specs/{g_spec_id}'
|
||||
},
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/group_types/{group_type_id}/group_specs'
|
||||
},
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/group_types/{group_type_id}/group_specs'
|
||||
},
|
||||
{
|
||||
'method': 'PUT',
|
||||
'path': '/group_types/{group_type_id}/group_specs/{g_spec_id}'
|
||||
},
|
||||
{
|
||||
'method': 'DELETE',
|
||||
'path': '/group_types/{group_type_id}/group_specs/{g_spec_id}'
|
||||
}
|
||||
]),
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return group_types_policies
|
75
cinder/policies/groups.py
Normal file
75
cinder/policies/groups.py
Normal file
@ -0,0 +1,75 @@
|
||||
# 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
|
||||
|
||||
CREATE_POLICY = 'group:create'
|
||||
UPDATE_POLICY = 'group:update'
|
||||
GET_POLICY = 'group:get'
|
||||
GET_ALL_POLICY = 'group:get_all'
|
||||
|
||||
|
||||
groups_policies = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name=GET_ALL_POLICY,
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
description="List groups.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/groups'
|
||||
},
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/groups/detail'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=CREATE_POLICY,
|
||||
check_str="",
|
||||
description="Create group.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/groups'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=GET_POLICY,
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
description="Show group.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/groups/{group_id}'
|
||||
}
|
||||
]),
|
||||
policy.DocumentedRuleDefault(
|
||||
name=UPDATE_POLICY,
|
||||
check_str=base.RULE_ADMIN_OR_OWNER,
|
||||
description="Update group.",
|
||||
operations=[
|
||||
{
|
||||
'method': 'PUT',
|
||||
'path': '/groups/{group_id}'
|
||||
}
|
||||
]),
|
||||
]
|
||||
|
||||
|
||||
def list_rules():
|
||||
return groups_policies
|
@ -22,7 +22,6 @@ from oslo_utils import timeutils
|
||||
import six
|
||||
import webob
|
||||
|
||||
import cinder.api.common as common
|
||||
from cinder.api import microversions as mv
|
||||
from cinder.api.v3 import group_specs as v3_group_specs
|
||||
from cinder.api.v3 import group_types as v3_group_types
|
||||
@ -462,8 +461,8 @@ class GroupTypesApiTest(test.TestCase):
|
||||
self.assertDictEqual(expected_group_type, output['group_type'])
|
||||
|
||||
def __test_view_builder_show_qos_specs_id_policy(self):
|
||||
with mock.patch.object(common,
|
||||
'validate_policy',
|
||||
with mock.patch.object(context.RequestContext,
|
||||
'authorize',
|
||||
side_effect=[False, True]):
|
||||
view_builder = views_types.ViewBuilder()
|
||||
now = timeutils.utcnow().isoformat()
|
||||
@ -492,8 +491,8 @@ class GroupTypesApiTest(test.TestCase):
|
||||
self.assertDictEqual(expected_group_type, output['group_type'])
|
||||
|
||||
def test_view_builder_show_group_specs_policy(self):
|
||||
with mock.patch.object(common,
|
||||
'validate_policy',
|
||||
with mock.patch.object(context.RequestContext,
|
||||
'authorize',
|
||||
side_effect=[True, False]):
|
||||
view_builder = views_types.ViewBuilder()
|
||||
now = timeutils.utcnow().isoformat()
|
||||
@ -524,9 +523,9 @@ class GroupTypesApiTest(test.TestCase):
|
||||
self.assertDictEqual(expected_group_type, output['group_type'])
|
||||
|
||||
def test_view_builder_show_pass_all_policy(self):
|
||||
with mock.patch.object(common,
|
||||
'validate_policy',
|
||||
side_effect=[True, True]):
|
||||
with mock.patch.object(context.RequestContext,
|
||||
'authorize',
|
||||
side_effect=[True, False]):
|
||||
view_builder = views_types.ViewBuilder()
|
||||
now = timeutils.utcnow().isoformat()
|
||||
raw_group_type = dict(
|
||||
@ -625,16 +624,3 @@ class GroupTypesApiTest(test.TestCase):
|
||||
)
|
||||
self.assertDictEqual(expected_group_type,
|
||||
output['group_types'][i])
|
||||
|
||||
def test_check_policy(self):
|
||||
self.controller._check_policy(self.ctxt)
|
||||
|
||||
self.assertRaises(exception.PolicyNotAuthorized,
|
||||
self.controller._check_policy,
|
||||
self.user_ctxt)
|
||||
|
||||
self.specs_controller._check_policy(self.ctxt)
|
||||
|
||||
self.assertRaises(exception.PolicyNotAuthorized,
|
||||
self.specs_controller._check_policy,
|
||||
self.user_ctxt)
|
||||
|
@ -49,19 +49,16 @@ class GroupAPITestCase(test.TestCase):
|
||||
fake.USER_ID, fake.PROJECT_ID, auth_token=True)
|
||||
|
||||
@mock.patch('cinder.objects.Group.get_by_id')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_get(self, mock_policy, mock_group_get):
|
||||
fake_group = 'fake_group'
|
||||
def test_get(self, mock_group_get):
|
||||
fake_group = {'name': 'fake_group'}
|
||||
mock_group_get.return_value = fake_group
|
||||
grp = self.group_api.get(self.ctxt, fake.GROUP_ID)
|
||||
self.assertEqual(fake_group, grp)
|
||||
mock_policy.assert_called_once_with(self.ctxt, 'get', mock.ANY)
|
||||
|
||||
@ddt.data(True, False)
|
||||
@mock.patch('cinder.objects.GroupList.get_all')
|
||||
@mock.patch('cinder.objects.GroupList.get_all_by_project')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_get_all(self, is_admin, mock_policy, mock_get_all_by_project,
|
||||
def test_get_all(self, is_admin, mock_get_all_by_project,
|
||||
mock_get_all):
|
||||
self.group_api.LOG = mock.Mock()
|
||||
fake_groups = ['fake_group1', 'fake_group2']
|
||||
@ -73,11 +70,9 @@ class GroupAPITestCase(test.TestCase):
|
||||
grps = self.group_api.get_all(self.ctxt,
|
||||
filters={'all_tenants': True})
|
||||
self.assertEqual(fake_groups, grps)
|
||||
mock_policy.assert_called_once_with(self.ctxt, 'get_all')
|
||||
else:
|
||||
grps = self.group_api.get_all(self.user_ctxt)
|
||||
self.assertEqual(fake_groups_by_project, grps)
|
||||
mock_policy.assert_called_once_with(self.user_ctxt, 'get_all')
|
||||
|
||||
@mock.patch('cinder.volume.rpcapi.VolumeAPI.delete_group')
|
||||
@mock.patch('cinder.db.volume_get_all_by_generic_group')
|
||||
@ -87,8 +82,7 @@ class GroupAPITestCase(test.TestCase):
|
||||
@mock.patch('cinder.objects.Group')
|
||||
@mock.patch('cinder.db.group_type_get')
|
||||
@mock.patch('cinder.db.volume_types_get_by_name_or_id')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_create_delete(self, mock_policy, mock_volume_types_get,
|
||||
def test_create_delete(self, mock_volume_types_get,
|
||||
mock_group_type_get, mock_group,
|
||||
mock_update_quota, mock_cast_create_group,
|
||||
mock_volumes_update, mock_volume_get_all,
|
||||
@ -108,7 +102,6 @@ class GroupAPITestCase(test.TestCase):
|
||||
fake.GROUP_TYPE_ID,
|
||||
[fake.VOLUME_TYPE_ID],
|
||||
availability_zone='nova')
|
||||
mock_policy.assert_called_with(self.ctxt, 'create')
|
||||
self.assertEqual(grp.obj_to_primitive(), ret_group.obj_to_primitive())
|
||||
|
||||
ret_group.host = "test_host@fakedrv#fakepool"
|
||||
@ -119,15 +112,13 @@ class GroupAPITestCase(test.TestCase):
|
||||
mock_volume_get_all.assert_called_once_with(mock.ANY, ret_group.id)
|
||||
mock_volumes_update.assert_called_once_with(self.ctxt, [])
|
||||
mock_rpc_delete_group.assert_called_once_with(self.ctxt, ret_group)
|
||||
mock_policy.assert_called_with(self.ctxt, 'delete', mock.ANY)
|
||||
|
||||
@mock.patch('cinder.group.api.API._cast_create_group')
|
||||
@mock.patch('cinder.group.api.API.update_quota')
|
||||
@mock.patch('cinder.objects.Group')
|
||||
@mock.patch('cinder.db.group_type_get_by_name')
|
||||
@mock.patch('cinder.db.volume_types_get_by_name_or_id')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_create_with_group_name(self, mock_policy, mock_volume_types_get,
|
||||
def test_create_with_group_name(self, mock_volume_types_get,
|
||||
mock_group_type_get, mock_group,
|
||||
mock_update_quota, mock_cast_create_group):
|
||||
mock_volume_types_get.return_value = [{'id': fake.VOLUME_TYPE_ID}]
|
||||
@ -149,14 +140,12 @@ class GroupAPITestCase(test.TestCase):
|
||||
|
||||
mock_group_type_get.assert_called_once_with(self.ctxt,
|
||||
"fake-grouptype-name")
|
||||
mock_policy.assert_called_with(self.ctxt, 'create')
|
||||
|
||||
@mock.patch('cinder.group.api.API._cast_create_group')
|
||||
@mock.patch('cinder.group.api.API.update_quota')
|
||||
@mock.patch('cinder.db.group_type_get_by_name')
|
||||
@mock.patch('cinder.db.volume_types_get_by_name_or_id')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_create_with_multi_types(self, mock_policy, mock_volume_types_get,
|
||||
def test_create_with_multi_types(self, mock_volume_types_get,
|
||||
mock_group_type_get,
|
||||
mock_update_quota,
|
||||
mock_cast_create_group):
|
||||
@ -180,12 +169,10 @@ class GroupAPITestCase(test.TestCase):
|
||||
"fake-grouptype-name")
|
||||
mock_volume_types_get.assert_called_once_with(mock.ANY,
|
||||
volume_type_names)
|
||||
mock_policy.assert_called_with(self.ctxt, 'create')
|
||||
|
||||
@mock.patch('oslo_utils.timeutils.utcnow')
|
||||
@mock.patch('cinder.objects.Group')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_reset_status(self, mock_policy, mock_group, mock_time_util):
|
||||
def test_reset_status(self, mock_group, mock_time_util):
|
||||
mock_time_util.return_value = "time_now"
|
||||
self.group_api.reset_status(self.ctxt, mock_group,
|
||||
fields.GroupStatus.AVAILABLE)
|
||||
@ -194,15 +181,12 @@ class GroupAPITestCase(test.TestCase):
|
||||
'status': fields.GroupStatus.AVAILABLE}
|
||||
mock_group.update.assert_called_once_with(update_field)
|
||||
mock_group.save.assert_called_once_with()
|
||||
mock_policy.assert_called_once_with(self.ctxt,
|
||||
'reset_status', mock.ANY)
|
||||
|
||||
@mock.patch.object(GROUP_QUOTAS, "reserve")
|
||||
@mock.patch('cinder.objects.Group')
|
||||
@mock.patch('cinder.db.group_type_get_by_name')
|
||||
@mock.patch('cinder.db.volume_types_get_by_name_or_id')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_create_group_failed_update_quota(self, mock_policy,
|
||||
def test_create_group_failed_update_quota(self,
|
||||
mock_volume_types_get,
|
||||
mock_group_type_get, mock_group,
|
||||
mock_group_quota_reserve):
|
||||
@ -230,7 +214,6 @@ class GroupAPITestCase(test.TestCase):
|
||||
"fake-grouptype-name",
|
||||
[fake.VOLUME_TYPE_ID],
|
||||
availability_zone='nova')
|
||||
mock_policy.assert_called_with(self.ctxt, 'create')
|
||||
|
||||
@mock.patch('cinder.objects.Group')
|
||||
@mock.patch('cinder.db.volume_get')
|
||||
@ -254,8 +237,7 @@ class GroupAPITestCase(test.TestCase):
|
||||
@mock.patch('cinder.objects.Group')
|
||||
@mock.patch('cinder.db.group_type_get')
|
||||
@mock.patch('cinder.db.volume_types_get_by_name_or_id')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_update(self, mock_policy, mock_volume_types_get,
|
||||
def test_update(self, mock_volume_types_get,
|
||||
mock_group_type_get, mock_group,
|
||||
mock_update_quota, mock_cast_create_group,
|
||||
mock_volume_get_all, mock_rpc_update_group):
|
||||
@ -313,23 +295,19 @@ class GroupAPITestCase(test.TestCase):
|
||||
mock_rpc_update_group.assert_called_once_with(self.ctxt, ret_group,
|
||||
add_volumes=vol1.id,
|
||||
remove_volumes=vol2.id)
|
||||
mock_policy.assert_called_with(self.ctxt, 'update', mock.ANY)
|
||||
|
||||
@mock.patch('cinder.objects.GroupSnapshot.get_by_id')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_get_group_snapshot(self, mock_policy, mock_group_snap):
|
||||
def test_get_group_snapshot(self, mock_group_snap):
|
||||
fake_group_snap = 'fake_group_snap'
|
||||
mock_group_snap.return_value = fake_group_snap
|
||||
grp_snap = self.group_api.get_group_snapshot(
|
||||
self.ctxt, fake.GROUP_SNAPSHOT_ID)
|
||||
self.assertEqual(fake_group_snap, grp_snap)
|
||||
mock_policy.assert_called_with(self.ctxt, 'get_group_snapshot')
|
||||
|
||||
@ddt.data(True, False)
|
||||
@mock.patch('cinder.objects.GroupSnapshotList.get_all')
|
||||
@mock.patch('cinder.objects.GroupSnapshotList.get_all_by_project')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_get_all_group_snapshots(self, is_admin, mock_policy,
|
||||
def test_get_all_group_snapshots(self, is_admin,
|
||||
mock_get_all_by_project,
|
||||
mock_get_all):
|
||||
fake_group_snaps = ['fake_group_snap1', 'fake_group_snap2']
|
||||
@ -341,25 +319,19 @@ class GroupAPITestCase(test.TestCase):
|
||||
grp_snaps = self.group_api.get_all_group_snapshots(
|
||||
self.ctxt, filters={'all_tenants': True})
|
||||
self.assertEqual(fake_group_snaps, grp_snaps)
|
||||
mock_policy.assert_called_with(self.ctxt,
|
||||
'get_all_group_snapshots')
|
||||
else:
|
||||
grp_snaps = self.group_api.get_all_group_snapshots(
|
||||
self.user_ctxt)
|
||||
self.assertEqual(fake_group_snaps_by_project, grp_snaps)
|
||||
mock_policy.assert_called_with(self.user_ctxt,
|
||||
'get_all_group_snapshots')
|
||||
|
||||
@mock.patch('cinder.objects.GroupSnapshot')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_update_group_snapshot(self, mock_policy, mock_group_snap):
|
||||
def test_update_group_snapshot(self, mock_group_snap):
|
||||
grp_snap_update = {"name": "new_name",
|
||||
"description": "This is a new description"}
|
||||
self.group_api.update_group_snapshot(self.ctxt, mock_group_snap,
|
||||
grp_snap_update)
|
||||
mock_group_snap.update.assert_called_once_with(grp_snap_update)
|
||||
mock_group_snap.save.assert_called_once_with()
|
||||
mock_policy.assert_called_with(self.ctxt, 'update_group_snapshot')
|
||||
|
||||
@mock.patch('cinder.volume.rpcapi.VolumeAPI.delete_group_snapshot')
|
||||
@mock.patch('cinder.volume.rpcapi.VolumeAPI.create_group_snapshot')
|
||||
@ -367,8 +339,7 @@ class GroupAPITestCase(test.TestCase):
|
||||
@mock.patch('cinder.objects.Group')
|
||||
@mock.patch('cinder.objects.GroupSnapshot')
|
||||
@mock.patch('cinder.objects.SnapshotList.get_all_for_group_snapshot')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_create_delete_group_snapshot(self, mock_policy,
|
||||
def test_create_delete_group_snapshot(self,
|
||||
mock_snap_get_all,
|
||||
mock_group_snap, mock_group,
|
||||
mock_create_in_db,
|
||||
@ -399,12 +370,9 @@ class GroupAPITestCase(test.TestCase):
|
||||
ret_group_snap.id)
|
||||
mock_create_api.assert_called_once_with(self.ctxt, ret_group_snap)
|
||||
|
||||
mock_policy.assert_called_once_with(self.ctxt, 'create_group_snapshot',
|
||||
mock.ANY)
|
||||
ret_group_snap.assert_not_frozen = mock.Mock(return_value=True)
|
||||
self.group_api.delete_group_snapshot(self.ctxt, ret_group_snap)
|
||||
mock_delete_api.assert_called_once_with(mock.ANY, ret_group_snap)
|
||||
mock_policy.assert_called_with(self.ctxt, 'delete_group_snapshot')
|
||||
|
||||
@mock.patch('cinder.objects.VolumeType.get_by_name_or_id')
|
||||
@mock.patch('cinder.db.group_volume_type_mapping_create')
|
||||
@ -484,8 +452,7 @@ class GroupAPITestCase(test.TestCase):
|
||||
@mock.patch('cinder.objects.Group.get_by_id')
|
||||
@mock.patch('cinder.volume.rpcapi.VolumeAPI.create_group_from_src')
|
||||
@mock.patch('cinder.objects.VolumeList.get_all_by_generic_group')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_create_group_from_group(self, mock_policy, mock_volume_get_all,
|
||||
def test_create_group_from_group(self, mock_volume_get_all,
|
||||
mock_rpc_create_group_from_src,
|
||||
mock_group_get,
|
||||
mock_volume_api_create,
|
||||
@ -548,8 +515,7 @@ class GroupAPITestCase(test.TestCase):
|
||||
@mock.patch('cinder.group.api.API.update_quota')
|
||||
@mock.patch('cinder.objects.GroupSnapshot.get_by_id')
|
||||
@mock.patch('cinder.objects.SnapshotList.get_all_for_group_snapshot')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_create_from_src(self, mock_policy, mock_snap_get_all,
|
||||
def test_create_from_src(self, mock_snap_get_all,
|
||||
mock_group_snap_get, mock_update_quota,
|
||||
mock_create_from_group,
|
||||
mock_create_from_snap):
|
||||
@ -606,8 +572,7 @@ class GroupAPITestCase(test.TestCase):
|
||||
|
||||
@mock.patch('oslo_utils.timeutils.utcnow')
|
||||
@mock.patch('cinder.objects.GroupSnapshot')
|
||||
@mock.patch('cinder.group.api.check_policy')
|
||||
def test_reset_group_snapshot_status(self, mock_policy,
|
||||
def test_reset_group_snapshot_status(self,
|
||||
mock_group_snapshot,
|
||||
mock_time_util):
|
||||
mock_time_util.return_value = "time_now"
|
||||
@ -618,8 +583,6 @@ class GroupAPITestCase(test.TestCase):
|
||||
'status': fields.GroupSnapshotStatus.ERROR}
|
||||
mock_group_snapshot.update.assert_called_once_with(update_field)
|
||||
mock_group_snapshot.save.assert_called_once_with()
|
||||
mock_policy.assert_called_once_with(self.ctxt,
|
||||
'reset_group_snapshot_status')
|
||||
|
||||
def test_create_group_from_src_frozen(self):
|
||||
service = utils.create_service(self.ctxt, {'frozen': True})
|
||||
|
@ -109,18 +109,12 @@
|
||||
"consistencygroup:get_cgsnapshot": "",
|
||||
"consistencygroup:get_all_cgsnapshots": "",
|
||||
|
||||
"group:group_types_manage": "rule:admin_api",
|
||||
"group:group_types_specs": "rule:admin_api",
|
||||
"group:access_group_types_specs": "rule:admin_api",
|
||||
"group:group_type_access": "rule:admin_or_owner",
|
||||
|
||||
"group:create" : "",
|
||||
"group:delete": "",
|
||||
"group:update": "",
|
||||
"group:get": "",
|
||||
"group:get_all": "",
|
||||
|
||||
"group:create_group_snapshot": "",
|
||||
"group:delete_group_snapshot": "",
|
||||
"group:update_group_snapshot": "",
|
||||
"group:get_group_snapshot": "",
|
||||
|
@ -89,30 +89,6 @@
|
||||
"consistencygroup:get_cgsnapshot": "group:nobody",
|
||||
"consistencygroup:get_all_cgsnapshots": "group:nobody",
|
||||
|
||||
"group:group_types_manage": "rule:admin_api",
|
||||
"group:group_types_specs": "rule:admin_api",
|
||||
"group:access_group_types_specs": "rule:admin_api",
|
||||
"group:group_type_access": "rule:admin_or_owner",
|
||||
|
||||
"group:create" : "",
|
||||
"group:delete": "rule:admin_or_owner",
|
||||
"group:update": "rule:admin_or_owner",
|
||||
"group:get": "rule:admin_or_owner",
|
||||
"group:get_all": "rule:admin_or_owner",
|
||||
|
||||
"group:create_group_snapshot": "",
|
||||
"group:delete_group_snapshot": "rule:admin_or_owner",
|
||||
"group:update_group_snapshot": "rule:admin_or_owner",
|
||||
"group:get_group_snapshot": "rule:admin_or_owner",
|
||||
"group:get_all_group_snapshots": "rule:admin_or_owner",
|
||||
"group:reset_group_snapshot_status":"rule:admin_api",
|
||||
"group:reset_status":"rule:admin_api",
|
||||
|
||||
"group:enable_replication": "rule:admin_or_owner",
|
||||
"group:disable_replication": "rule:admin_or_owner",
|
||||
"group:failover_replication": "rule:admin_or_owner",
|
||||
"group:list_replication_targets": "rule:admin_or_owner",
|
||||
|
||||
"scheduler_extension:scheduler_stats:get_pools" : "rule:admin_api",
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user