Merge "Update oslo policy and its dependencies"

This commit is contained in:
Jenkins 2014-09-01 19:49:46 +00:00 committed by Gerrit Code Review
commit 6b62908dfd
14 changed files with 1067 additions and 722 deletions

View File

@ -24,7 +24,7 @@ import traceback
import six
from cinder.openstack.common.gettextutils import _
from cinder.openstack.common.gettextutils import _LE
class save_and_reraise_exception(object):
@ -49,9 +49,22 @@ class save_and_reraise_exception(object):
decide_if_need_reraise()
if not should_be_reraised:
ctxt.reraise = False
If another exception occurs and reraise flag is False,
the saved exception will not be logged.
If the caller wants to raise new exception during exception handling
he/she sets reraise to False initially with an ability to set it back to
True if needed::
except Exception:
with save_and_reraise_exception(reraise=False) as ctxt:
[if statements to determine whether to raise a new exception]
# Not raising a new exception, so reraise
ctxt.reraise = True
"""
def __init__(self):
self.reraise = True
def __init__(self, reraise=True):
self.reraise = reraise
def __enter__(self):
self.type_, self.value, self.tb, = sys.exc_info()
@ -59,10 +72,11 @@ class save_and_reraise_exception(object):
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is not None:
logging.error(_('Original exception being dropped: %s'),
traceback.format_exception(self.type_,
self.value,
self.tb))
if self.reraise:
logging.error(_LE('Original exception being dropped: %s'),
traceback.format_exception(self.type_,
self.value,
self.tb))
return False
if self.reraise:
six.reraise(self.type_, self.value, self.tb)
@ -88,8 +102,8 @@ def forever_retry_uncaught_exceptions(infunc):
if (cur_time - last_log_time > 60 or
this_exc_message != last_exc_message):
logging.exception(
_('Unexpected exception occurred %d time(s)... '
'retrying.') % exc_count)
_LE('Unexpected exception occurred %d time(s)... '
'retrying.') % exc_count)
last_log_time = cur_time
last_exc_message = this_exc_message
exc_count = 0

View File

@ -1,5 +1,3 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2011 OpenStack Foundation.
# All Rights Reserved.
#
@ -15,13 +13,12 @@
# License for the specific language governing permissions and limitations
# under the License.
import contextlib
import errno
import os
import tempfile
from cinder.openstack.common import excutils
from cinder.openstack.common.gettextutils import _
from cinder.openstack.common import log as logging
LOG = logging.getLogger(__name__)
@ -53,15 +50,15 @@ def read_cached_file(filename, force_reload=False):
"""
global _FILE_CACHE
if force_reload and filename in _FILE_CACHE:
del _FILE_CACHE[filename]
if force_reload:
delete_cached_file(filename)
reloaded = False
mtime = os.path.getmtime(filename)
cache_info = _FILE_CACHE.setdefault(filename, {})
if not cache_info or mtime > cache_info.get('mtime', 0):
LOG.debug(_("Reloading cached file %s") % filename)
LOG.debug("Reloading cached file %s" % filename)
with open(filename) as fap:
cache_info['data'] = fap.read()
cache_info['mtime'] = mtime
@ -69,42 +66,81 @@ def read_cached_file(filename, force_reload=False):
return (reloaded, cache_info['data'])
def delete_if_exists(path):
def delete_cached_file(filename):
"""Delete cached file if present.
:param filename: filename to delete
"""
global _FILE_CACHE
if filename in _FILE_CACHE:
del _FILE_CACHE[filename]
def delete_if_exists(path, remove=os.unlink):
"""Delete a file, but ignore file not found error.
:param path: File to delete
:param remove: Optional function to remove passed path
"""
try:
os.unlink(path)
remove(path)
except OSError as e:
if e.errno == errno.ENOENT:
return
else:
if e.errno != errno.ENOENT:
raise
@contextlib.contextmanager
def remove_path_on_error(path):
def remove_path_on_error(path, remove=delete_if_exists):
"""Protect code that wants to operate on PATH atomically.
Any exception will cause PATH to be removed.
:param path: File to work with
:param remove: Optional function to remove passed path
"""
try:
yield
except Exception:
with excutils.save_and_reraise_exception():
delete_if_exists(path)
remove(path)
def file_open(*args, **kwargs):
"""Open file
see built-in file() documentation for more details
see built-in open() documentation for more details
Note: The reason this is kept in a separate module is to easily
be able to provide a stub module that doesn't alter system
state at all (for unit tests)
"""
return file(*args, **kwargs)
return open(*args, **kwargs)
def write_to_tempfile(content, path=None, suffix='', prefix='tmp'):
"""Create temporary file or use existing file.
This util is needed for creating temporary file with
specified content, suffix and prefix. If path is not None,
it will be used for writing content. If the path doesn't
exist it'll be created.
:param content: content for temporary file.
:param path: same as parameter 'dir' for mkstemp
:param suffix: same as parameter 'suffix' for mkstemp
:param prefix: same as parameter 'prefix' for mkstemp
For example: it can be used in database tests for creating
configuration files.
"""
if path:
ensure_tree(path)
(fd, path) = tempfile.mkstemp(suffix=suffix, dir=path, prefix=prefix)
try:
os.write(fd, content)
finally:
os.close(fd)
return path

File diff suppressed because it is too large Load Diff

View File

@ -19,46 +19,17 @@
from oslo.config import cfg
from cinder import exception
from cinder.i18n import _
from cinder.openstack.common import policy
from cinder import utils
policy_opts = [
cfg.StrOpt('policy_file',
default='policy.json',
help=_('JSON file representing policy')),
cfg.StrOpt('policy_default_rule',
default='default',
help=_('Rule checked when requested rule is not found')), ]
CONF = cfg.CONF
CONF.register_opts(policy_opts)
_POLICY_PATH = None
_POLICY_CACHE = {}
def reset():
global _POLICY_PATH
global _POLICY_CACHE
_POLICY_PATH = None
_POLICY_CACHE = {}
policy.reset()
_ENFORCER = None
def init():
global _POLICY_PATH
global _POLICY_CACHE
if not _POLICY_PATH:
_POLICY_PATH = utils.find_config(CONF.policy_file)
utils.read_cached_file(_POLICY_PATH, _POLICY_CACHE,
reload_func=_set_brain)
def _set_brain(data):
default_rule = CONF.policy_default_rule
policy.set_brain(policy.Brain.load_json(data, default_rule))
global _ENFORCER
if not _ENFORCER:
_ENFORCER = policy.Enforcer()
def enforce_action(context, action):
@ -68,11 +39,8 @@ def enforce_action(context, action):
applied to the given action using the policy enforcement api.
"""
target = {
'project_id': context.project_id,
'user_id': context.user_id,
}
enforce(context, action, target)
return enforce(context, action, {'project_id': context.project_id,
'user_id': context.user_id})
def enforce(context, action, target):
@ -89,16 +57,15 @@ def enforce(context, action, target):
for object creation this should be a dictionary representing the
location of the object e.g. ``{'project_id': context.project_id}``
:raises cinder.exception.PolicyNotAuthorized: if verification fails.
:raises PolicyNotAuthorized: if verification fails.
"""
init()
match_list = ('rule:%s' % action,)
credentials = context.to_dict()
policy.enforce(match_list, target, credentials,
exception.PolicyNotAuthorized, action=action)
return _ENFORCER.enforce(action, target, context.to_dict(),
do_raise=True,
exc=exception.PolicyNotAuthorized,
action=action)
def check_is_admin(roles):
@ -107,8 +74,6 @@ def check_is_admin(roles):
"""
init()
action = 'context_is_admin'
match_list = ('rule:%s' % action,)
# include project_id on target to avoid KeyError if context_is_admin
# policy definition is missing, and default admin_or_owner rule
# attempts to apply. Since our credentials dict does not include a
@ -116,4 +81,4 @@ def check_is_admin(roles):
target = {'project_id': ''}
credentials = {'roles': roles}
return policy.enforce(match_list, target, credentials)
return _ENFORCER.enforce('context_is_admin', target, credentials)

View File

@ -187,6 +187,15 @@ class TestCase(testtools.TestCase):
CONF.set_override('fatal_exception_format_errors', True)
# This will be cleaned up by the NestedTempfile fixture
CONF.set_override('lock_path', tempfile.mkdtemp())
CONF.set_override('policy_file',
os.path.join(
os.path.abspath(
os.path.join(
os.path.dirname(__file__),
'..',
)
),
'cinder/tests/policy.json'))
def _common_cleanup(self):
"""Runs after each test method to tear down test environment."""

View File

@ -1,92 +1,92 @@
{
"context_is_admin": [["role:admin"]],
"admin_api": [["is_admin:True"]],
"admin_or_owner": [["is_admin:True"], ["project_id:%(project_id)s"]],
"context_is_admin": "role:admin",
"admin_api": "is_admin:True",
"admin_or_owner": "is_admin:True or project_id:%(project_id)s",
"volume:create": [],
"volume:get": [["rule:admin_or_owner"]],
"volume:get_all": [],
"volume:get_volume_metadata": [],
"volume:delete_volume_metadata": [],
"volume:update_volume_metadata": [],
"volume:get_volume_admin_metadata": [["rule:admin_api"]],
"volume:delete_volume_admin_metadata": [["rule:admin_api"]],
"volume:update_volume_admin_metadata": [["rule:admin_api"]],
"volume:delete": [],
"volume:update": [],
"volume:attach": [],
"volume:detach": [],
"volume:reserve_volume": [],
"volume:unreserve_volume": [],
"volume:begin_detaching": [],
"volume:roll_detaching": [],
"volume:initialize_connection": [],
"volume:terminate_connection": [],
"volume:create_snapshot": [],
"volume:delete_snapshot": [],
"volume:get_snapshot": [],
"volume:get_all_snapshots": [],
"volume:update_snapshot": [],
"volume:extend": [],
"volume:migrate_volume": [["rule:admin_api"]],
"volume:migrate_volume_completion": [["rule:admin_api"]],
"volume:update_readonly_flag": [],
"volume:retype": [],
"volume:copy_volume_to_image": [],
"volume:create": "",
"volume:get": "rule:admin_or_owner",
"volume:get_all": "",
"volume:get_volume_metadata": "",
"volume:delete_volume_metadata": "",
"volume:update_volume_metadata": "",
"volume:get_volume_admin_metadata": "rule:admin_api",
"volume:delete_volume_admin_metadata": "rule:admin_api",
"volume:update_volume_admin_metadata": "rule:admin_api",
"volume:delete": "",
"volume:update": "",
"volume:attach": "",
"volume:detach": "",
"volume:reserve_volume": "",
"volume:unreserve_volume": "",
"volume:begin_detaching": "",
"volume:roll_detaching": "",
"volume:initialize_connection": "",
"volume:terminate_connection": "",
"volume:create_snapshot": "",
"volume:delete_snapshot": "",
"volume:get_snapshot": "",
"volume:get_all_snapshots": "",
"volume:update_snapshot": "",
"volume:extend": "",
"volume:migrate_volume": "rule:admin_api",
"volume:migrate_volume_completion": "rule:admin_api",
"volume:update_readonly_flag": "",
"volume:retype": "",
"volume:copy_volume_to_image": "",
"volume_extension:volume_admin_actions:reset_status": [["rule:admin_api"]],
"volume_extension:snapshot_admin_actions:reset_status": [["rule:admin_api"]],
"volume_extension:volume_admin_actions:force_delete": [["rule:admin_api"]],
"volume_extension:snapshot_admin_actions:force_delete": [["rule:admin_api"]],
"volume_extension:volume_admin_actions:force_detach": [["rule:admin_api"]],
"volume_extension:volume_admin_actions:migrate_volume": [["rule:admin_api"]],
"volume_extension:volume_admin_actions:migrate_volume_completion": [["rule:admin_api"]],
"volume_extension:volume_actions:upload_image": [],
"volume_extension:types_manage": [],
"volume_extension:types_extra_specs": [],
"volume_extension:volume_type_encryption": [["rule:admin_api"]],
"volume_extension:volume_encryption_metadata": [["rule:admin_or_owner"]],
"volume_extension:qos_specs_manage": [],
"volume_extension:extended_snapshot_attributes": [],
"volume_extension:volume_image_metadata": [],
"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:quotas:show": [],
"volume_extension:quotas:update": [],
"volume_extension:quotas:delete": [],
"volume_extension:quota_classes": [],
"volume_extension:volume_manage": [["rule:admin_api"]],
"volume_extension:volume_unmanage": [["rule:admin_api"]],
"volume_extension:volume_admin_actions:reset_status": "rule:admin_api",
"volume_extension:snapshot_admin_actions:reset_status": "rule:admin_api",
"volume_extension:volume_admin_actions:force_delete": "rule:admin_api",
"volume_extension:snapshot_admin_actions:force_delete": "rule:admin_api",
"volume_extension:volume_admin_actions:force_detach": "rule:admin_api",
"volume_extension:volume_admin_actions:migrate_volume": "rule:admin_api",
"volume_extension:volume_admin_actions:migrate_volume_completion": "rule:admin_api",
"volume_extension:volume_actions:upload_image": "",
"volume_extension:types_manage": "",
"volume_extension:types_extra_specs": "",
"volume_extension:volume_type_encryption": "rule:admin_api",
"volume_extension:volume_encryption_metadata": "rule:admin_or_owner",
"volume_extension:qos_specs_manage": "",
"volume_extension:extended_snapshot_attributes": "",
"volume_extension:volume_image_metadata": "",
"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:quotas:show": "",
"volume_extension:quotas:update": "",
"volume_extension:quotas:delete": "",
"volume_extension:quota_classes": "",
"volume_extension:volume_manage": "rule:admin_api",
"volume_extension:volume_unmanage": "rule:admin_api",
"limits_extension:used_limits": [],
"limits_extension:used_limits": "",
"snapshot_extension:snapshot_actions:update_snapshot_status": [],
"snapshot_extension:snapshot_actions:update_snapshot_status": "",
"volume:create_transfer": [],
"volume:accept_transfer": [],
"volume:delete_transfer": [],
"volume:get_all_transfers": [],
"volume:create_transfer": "",
"volume:accept_transfer": "",
"volume:delete_transfer": "",
"volume:get_all_transfers": "",
"backup:create" : [],
"backup:delete": [],
"backup:get": [],
"backup:get_all": [],
"backup:restore": [],
"backup:backup-import": [["rule:admin_api"]],
"backup:backup-export": [["rule:admin_api"]],
"backup:create" : "",
"backup:delete": "",
"backup:get": "",
"backup:get_all": "",
"backup:restore": "",
"backup:backup-import": "rule:admin_api",
"backup:backup-export": "rule:admin_api",
"volume_extension:replication:promote": [["rule:admin_api"]],
"volume_extension:replication:reenable": [["rule:admin_api"]],
"volume_extension:replication:promote": "rule:admin_api",
"volume_extension:replication:reenable": "rule:admin_api",
"consistencygroup:create" : [],
"consistencygroup:delete": [],
"consistencygroup:get": [],
"consistencygroup:get_all": [],
"consistencygroup:create" : "",
"consistencygroup:delete": "",
"consistencygroup:get": "",
"consistencygroup:get_all": "",
"consistencygroup:create_cgsnapshot" : [],
"consistencygroup:delete_cgsnapshot": [],
"consistencygroup:get_cgsnapshot": [],
"consistencygroup:get_all_cgsnapshots": []
"consistencygroup:create_cgsnapshot" : "",
"consistencygroup:delete_cgsnapshot": "",
"consistencygroup:get_cgsnapshot": "",
"consistencygroup:get_all_cgsnapshots": ""
}

View File

@ -25,6 +25,7 @@ from oslo.config import cfg
from cinder import context
from cinder import exception
from cinder.image import image_utils
from cinder.openstack.common import fileutils
from cinder.openstack.common import processutils
from cinder.openstack.common import units
from cinder import test
@ -621,10 +622,10 @@ class TestTemporaryFile(test.TestCase):
def test_file_unlinked(self):
mox = self.mox
mox.StubOutWithMock(image_utils, 'create_temporary_file')
mox.StubOutWithMock(image_utils.os, 'unlink')
mox.StubOutWithMock(fileutils, 'delete_if_exists')
image_utils.create_temporary_file().AndReturn('somefile')
image_utils.os.unlink('somefile')
fileutils.delete_if_exists('somefile')
mox.ReplayAll()
@ -634,10 +635,10 @@ class TestTemporaryFile(test.TestCase):
def test_file_unlinked_on_error(self):
mox = self.mox
mox.StubOutWithMock(image_utils, 'create_temporary_file')
mox.StubOutWithMock(image_utils.os, 'unlink')
mox.StubOutWithMock(fileutils, 'delete_if_exists')
image_utils.create_temporary_file().AndReturn('somefile')
image_utils.os.unlink('somefile')
fileutils.delete_if_exists('somefile')
mox.ReplayAll()
@ -706,6 +707,7 @@ class TestXenServerImageToCoalescedVhd(test.TestCase):
mox.StubOutWithMock(image_utils, 'fix_vhd_chain')
mox.StubOutWithMock(image_utils, 'coalesce_chain')
mox.StubOutWithMock(image_utils.os, 'unlink')
mox.StubOutWithMock(fileutils, 'delete_if_exists')
mox.StubOutWithMock(image_utils, 'rename_file')
image_utils.temporary_dir().AndReturn(fake_context('somedir'))
@ -715,7 +717,7 @@ class TestXenServerImageToCoalescedVhd(test.TestCase):
image_utils.fix_vhd_chain(['somedir/0.vhd', 'somedir/1.vhd'])
image_utils.coalesce_chain(
['somedir/0.vhd', 'somedir/1.vhd']).AndReturn('somedir/1.vhd')
image_utils.os.unlink('image')
fileutils.delete_if_exists('image')
image_utils.rename_file('somedir/1.vhd', 'image')
mox.ReplayAll()

View File

@ -1,225 +0,0 @@
# Copyright 2011 Piston Cloud Computing, Inc.
# All Rights Reserved.
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Test of Policy Engine For Cinder."""
import os.path
import urllib2
from oslo.config import cfg
import six
from cinder import context
from cinder import exception
import cinder.openstack.common.policy
from cinder.openstack.common import policy as common_policy
from cinder import policy
from cinder import test
from cinder import utils
CONF = cfg.CONF
class PolicyFileTestCase(test.TestCase):
def setUp(self):
super(PolicyFileTestCase, self).setUp()
# since is_admin is defined by policy, create context before reset
self.context = context.RequestContext('fake', 'fake')
policy.reset()
self.target = {}
self.addCleanup(policy.reset)
def test_modified_policy_reloads(self):
with utils.tempdir() as tmpdir:
tmpfilename = os.path.join(tmpdir, 'policy')
self.flags(policy_file=tmpfilename)
action = "example:test"
with open(tmpfilename, "w") as policyfile:
policyfile.write("""{"example:test": []}""")
policy.enforce(self.context, action, self.target)
with open(tmpfilename, "w") as policyfile:
policyfile.write("""{"example:test": ["false:false"]}""")
# NOTE(vish): reset stored policy cache so we don't have to
# sleep(1)
policy._POLICY_CACHE = {}
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
self.context, action, self.target)
class PolicyTestCase(test.TestCase):
def setUp(self):
super(PolicyTestCase, self).setUp()
policy.reset()
# NOTE(vish): preload rules to circumvent reloading from file
policy.init()
rules = {
"true": [],
"example:allowed": [],
"example:denied": [["false:false"]],
"example:get_http": [["http:http://www.example.com"]],
"example:my_file": [["role:compute_admin"],
["project_id:%(project_id)s"]],
"example:early_and_fail": [["false:false", "rule:true"]],
"example:early_or_success": [["rule:true"], ["false:false"]],
"example:lowercase_admin": [["role:admin"], ["role:sysadmin"]],
"example:uppercase_admin": [["role:ADMIN"], ["role:sysadmin"]],
}
# NOTE(vish): then overload underlying brain
common_policy.set_brain(common_policy.Brain(rules))
self.context = context.RequestContext('fake', 'fake', roles=['member'])
self.target = {}
self.addCleanup(policy.reset)
def test_enforce_nonexistent_action_throws(self):
action = "example:noexist"
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
self.context, action, self.target)
def test_enforce_bad_action_throws(self):
action = "example:denied"
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
self.context, action, self.target)
def test_enforce_good_action(self):
action = "example:allowed"
policy.enforce(self.context, action, self.target)
def test_enforce_http_true(self):
def fakeurlopen(url, post_data):
return six.StringIO("True")
self.stubs.Set(urllib2, 'urlopen', fakeurlopen)
action = "example:get_http"
target = {}
result = policy.enforce(self.context, action, target)
self.assertIsNone(result)
def test_enforce_http_false(self):
def fakeurlopen(url, post_data):
return six.StringIO("False")
self.stubs.Set(urllib2, 'urlopen', fakeurlopen)
action = "example:get_http"
target = {}
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
self.context, action, target)
def test_templatized_enforcement(self):
target_mine = {'project_id': 'fake'}
target_not_mine = {'project_id': 'another'}
action = "example:my_file"
policy.enforce(self.context, action, target_mine)
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
self.context, action, target_not_mine)
def test_early_AND_enforcement(self):
action = "example:early_and_fail"
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
self.context, action, self.target)
def test_early_OR_enforcement(self):
action = "example:early_or_success"
policy.enforce(self.context, action, self.target)
def test_ignore_case_role_check(self):
lowercase_action = "example:lowercase_admin"
uppercase_action = "example:uppercase_admin"
# NOTE(dprince) we mix case in the Admin role here to ensure
# case is ignored
admin_context = context.RequestContext('admin',
'fake',
roles=['AdMiN'])
policy.enforce(admin_context, lowercase_action, self.target)
policy.enforce(admin_context, uppercase_action, self.target)
class DefaultPolicyTestCase(test.TestCase):
def setUp(self):
super(DefaultPolicyTestCase, self).setUp()
policy.reset()
policy.init()
self.rules = {
"default": [],
"example:exist": [["false:false"]]
}
self._set_brain('default')
self.context = context.RequestContext('fake', 'fake')
self.addCleanup(policy.reset)
def _set_brain(self, default_rule):
brain = cinder.openstack.common.policy.Brain(self.rules,
default_rule)
cinder.openstack.common.policy.set_brain(brain)
def test_policy_called(self):
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
self.context, "example:exist", {})
def test_not_found_policy_calls_default(self):
policy.enforce(self.context, "example:noexist", {})
def test_default_not_found(self):
self._set_brain("default_noexist")
self.assertRaises(exception.PolicyNotAuthorized, policy.enforce,
self.context, "example:noexist", {})
class ContextIsAdminPolicyTestCase(test.TestCase):
def setUp(self):
super(ContextIsAdminPolicyTestCase, self).setUp()
policy.reset()
policy.init()
def test_default_admin_role_is_admin(self):
ctx = context.RequestContext('fake', 'fake', roles=['johnny-admin'])
self.assertFalse(ctx.is_admin)
ctx = context.RequestContext('fake', 'fake', roles=['admin'])
self.assertTrue(ctx.is_admin)
def test_custom_admin_role_is_admin(self):
# define explicit rules for context_is_admin
rules = {
'context_is_admin': [["role:administrator"], ["role:johnny-admin"]]
}
brain = common_policy.Brain(rules, CONF.policy_default_rule)
common_policy.set_brain(brain)
ctx = context.RequestContext('fake', 'fake', roles=['johnny-admin'])
self.assertTrue(ctx.is_admin)
ctx = context.RequestContext('fake', 'fake', roles=['administrator'])
self.assertTrue(ctx.is_admin)
# default rule no longer applies
ctx = context.RequestContext('fake', 'fake', roles=['admin'])
self.assertFalse(ctx.is_admin)
def test_context_is_admin_undefined(self):
rules = {
"admin_or_owner": [["role:admin"], ["project_id:%(project_id)s"]],
"default": [["rule:admin_or_owner"]],
}
brain = common_policy.Brain(rules, CONF.policy_default_rule)
common_policy.set_brain(brain)
ctx = context.RequestContext('fake', 'fake')
self.assertFalse(ctx.is_admin)
ctx = context.RequestContext('fake', 'fake', roles=['admin'])
self.assertTrue(ctx.is_admin)

View File

@ -367,31 +367,6 @@ class GenericUtilsTestCase(test.TestCase):
CONF.glance_port)
self.assertEqual(generated_url, actual_url)
@mock.patch('__builtin__.open')
@mock.patch('os.path.getmtime', return_value=1)
def test_read_cached_file(self, mock_mtime, mock_open):
fake_file = "/this/is/a/fake"
cache_data = {"data": 1123, "mtime": 2}
mock_open.return_value = _get_local_mock_open()
data = utils.read_cached_file(fake_file, cache_data)
self.assertEqual(cache_data["data"], data)
mock_open.assert_called_once_with(fake_file)
@mock.patch('__builtin__.open')
@mock.patch('os.path.getmtime', return_value=1)
def test_read_modified_cached_file(self, mock_mtime, mock_open):
fake_data = 'lorem ipsum'
fake_file = "/this/is/a/fake"
mock_open.return_value = _get_local_mock_open(fake_data)
cache_data = {"data": 'original data', "mtime": 2}
mock_reload = mock.Mock()
data = utils.read_cached_file(fake_file,
cache_data,
reload_func=mock_reload)
self.assertEqual(data, fake_data)
mock_reload.assert_called_once_with(fake_data)
mock_open.assert_called_once_with(fake_file)
def test_read_file_as_root(self):
def fake_execute(*args, **kwargs):
if args[1] == 'bad':

View File

@ -3965,15 +3965,10 @@ class VolumePolicyTestCase(test.TestCase):
def setUp(self):
super(VolumePolicyTestCase, self).setUp()
cinder.policy.reset()
cinder.policy.init()
self.context = context.get_admin_context()
self.stubs.Set(brick_lvm.LVM, '_vg_exists', lambda x: True)
self.addCleanup(cinder.policy.reset)
def _set_rules(self, rules):
cinder.common.policy.set_brain(cinder.common.policy.Brain(rules))
def test_check_policy(self):
self.mox.StubOutWithMock(cinder.policy, 'enforce')

View File

@ -284,7 +284,6 @@ class TestWindowsDriver(test.TestCase):
mox.IgnoreArg())
windows_utils.WindowsUtils.change_disk_status(volume['name'],
mox.IsA(bool))
os.unlink(mox.IsA(str))
vhdutils.VHDUtils.convert_vhd(fake_temp_path,
fake_volume_path,
constants.VHD_TYPE_FIXED)

View File

@ -493,26 +493,6 @@ def sanitize_hostname(hostname):
return hostname
def read_cached_file(filename, cache_info, reload_func=None):
"""Read from a file if it has been modified.
:param cache_info: dictionary to hold opaque cache.
:param reload_func: optional function to be called with data when
file is reloaded due to a modification.
:returns: data from file
"""
mtime = os.path.getmtime(filename)
if not cache_info or mtime != cache_info.get('mtime'):
with open(filename) as fap:
cache_info['data'] = fap.read()
cache_info['mtime'] = mtime
if reload_func:
reload_func(cache_info['data'])
return cache_info['data']
def hash_file(file_like_object):
"""Generate a hash for the contents of a file."""
checksum = hashlib.sha1()

View File

@ -202,17 +202,6 @@
#fatal_exception_format_errors=false
#
# Options defined in cinder.policy
#
# JSON file representing policy (string value)
#policy_file=policy.json
# Rule checked when requested rule is not found (string value)
#policy_default_rule=default
#
# Options defined in cinder.quota
#
@ -855,6 +844,18 @@
#run_external_periodic_tasks=true
#
# Options defined in cinder.openstack.common.policy
#
# The JSON file that defines policies. (string value)
#policy_file=policy.json
# Default rule. Enforced when a requested rule is not found.
# (string value)
#policy_default_rule=default
#
# Options defined in cinder.scheduler.driver
#

View File

@ -1,77 +1,77 @@
{
"context_is_admin": [["role:admin"]],
"admin_or_owner": [["is_admin:True"], ["project_id:%(project_id)s"]],
"default": [["rule:admin_or_owner"]],
"context_is_admin": "role:admin",
"admin_or_owner": "is_admin:True or project_id:%(project_id)s",
"default": "rule:admin_or_owner",
"admin_api": [["is_admin:True"]],
"admin_api": "is_admin:True",
"volume:create": [],
"volume:get_all": [],
"volume:get_volume_metadata": [],
"volume:get_volume_admin_metadata": [["rule:admin_api"]],
"volume:delete_volume_admin_metadata": [["rule:admin_api"]],
"volume:update_volume_admin_metadata": [["rule:admin_api"]],
"volume:get_snapshot": [],
"volume:get_all_snapshots": [],
"volume:extend": [],
"volume:update_readonly_flag": [],
"volume:retype": [],
"volume:create": "",
"volume:get_all": "",
"volume:get_volume_metadata": "",
"volume:get_volume_admin_metadata": "rule:admin_api",
"volume:delete_volume_admin_metadata": "rule:admin_api",
"volume:update_volume_admin_metadata": "rule:admin_api",
"volume:get_snapshot": "",
"volume:get_all_snapshots": "",
"volume:extend": "",
"volume:update_readonly_flag": "",
"volume:retype": "",
"volume_extension:types_manage": [["rule:admin_api"]],
"volume_extension:types_extra_specs": [["rule:admin_api"]],
"volume_extension:volume_type_encryption": [["rule:admin_api"]],
"volume_extension:volume_encryption_metadata": [["rule:admin_or_owner"]],
"volume_extension:extended_snapshot_attributes": [],
"volume_extension:volume_image_metadata": [],
"volume_extension:types_manage": "rule:admin_api",
"volume_extension:types_extra_specs": "rule:admin_api",
"volume_extension:volume_type_encryption": "rule:admin_api",
"volume_extension:volume_encryption_metadata": "rule:admin_or_owner",
"volume_extension:extended_snapshot_attributes": "",
"volume_extension:volume_image_metadata": "",
"volume_extension:quotas:show": [],
"volume_extension:quotas:update": [["rule:admin_api"]],
"volume_extension:quota_classes": [],
"volume_extension:quotas:show": "",
"volume_extension:quotas:update": "rule:admin_api",
"volume_extension:quota_classes": "",
"volume_extension:volume_admin_actions:reset_status": [["rule:admin_api"]],
"volume_extension:snapshot_admin_actions:reset_status": [["rule:admin_api"]],
"volume_extension:volume_admin_actions:force_delete": [["rule:admin_api"]],
"volume_extension:volume_admin_actions:force_detach": [["rule:admin_api"]],
"volume_extension:snapshot_admin_actions:force_delete": [["rule:admin_api"]],
"volume_extension:volume_admin_actions:migrate_volume": [["rule:admin_api"]],
"volume_extension:volume_admin_actions:migrate_volume_completion": [["rule:admin_api"]],
"volume_extension:volume_admin_actions:reset_status": "rule:admin_api",
"volume_extension:snapshot_admin_actions:reset_status": "rule:admin_api",
"volume_extension:volume_admin_actions:force_delete": "rule:admin_api",
"volume_extension:volume_admin_actions:force_detach": "rule:admin_api",
"volume_extension:snapshot_admin_actions:force_delete": "rule:admin_api",
"volume_extension:volume_admin_actions:migrate_volume": "rule:admin_api",
"volume_extension:volume_admin_actions:migrate_volume_completion": "rule:admin_api",
"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": [["rule:admin_api"]],
"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": "rule:admin_api",
"volume_extension:volume_manage": [["rule:admin_api"]],
"volume_extension:volume_unmanage": [["rule:admin_api"]],
"volume_extension:volume_manage": "rule:admin_api",
"volume_extension:volume_unmanage": "rule:admin_api",
"volume:services": [["rule:admin_api"]],
"volume:services": "rule:admin_api",
"volume:create_transfer": [],
"volume:accept_transfer": [],
"volume:delete_transfer": [],
"volume:get_all_transfers": [],
"volume:create_transfer": "",
"volume:accept_transfer": "",
"volume:delete_transfer": "",
"volume:get_all_transfers": "",
"volume_extension:replication:promote": ["rule:admin_api"],
"volume_extension:replication:reenable": ["rule:admin_api"],
"volume_extension:replication:promote": "rule:admin_api",
"volume_extension:replication:reenable": "rule:admin_api",
"backup:create" : [],
"backup:delete": [],
"backup:get": [],
"backup:get_all": [],
"backup:restore": [],
"backup:backup-import": [["rule:admin_api"]],
"backup:backup-export": [["rule:admin_api"]],
"backup:create" : "",
"backup:delete": "",
"backup:get": "",
"backup:get_all": "",
"backup:restore": "",
"backup:backup-import": "rule:admin_api",
"backup:backup-export": "rule:admin_api",
"snapshot_extension:snapshot_actions:update_snapshot_status": [],
"snapshot_extension:snapshot_actions:update_snapshot_status": "",
"consistencygroup:create" : [["group:nobody"]],
"consistencygroup:delete": [["group:nobody"]],
"consistencygroup:get": [["group:nobody"]],
"consistencygroup:get_all": [["group:nobody"]],
"consistencygroup:create" : "group:nobody",
"consistencygroup:delete": "group:nobody",
"consistencygroup:get": "group:nobody",
"consistencygroup:get_all": "group:nobody",
"consistencygroup:create_cgsnapshot" : [],
"consistencygroup:delete_cgsnapshot": [],
"consistencygroup:get_cgsnapshot": [],
"consistencygroup:get_all_cgsnapshots": []
"consistencygroup:create_cgsnapshot" : "",
"consistencygroup:delete_cgsnapshot": "",
"consistencygroup:get_cgsnapshot": "",
"consistencygroup:get_all_cgsnapshots": ""
}