Merge "cephfs_native: enhance update_access()"
This commit is contained in:
commit
faef310caa
manila
releasenotes/notes
@ -231,7 +231,8 @@ class CephFSNativeDriver(driver.ShareDriver,):
|
||||
else:
|
||||
readonly = access['access_level'] == constants.ACCESS_LEVEL_RO
|
||||
auth_result = self.volume_client.authorize(
|
||||
self._share_path(share), ceph_auth_id, readonly=readonly)
|
||||
self._share_path(share), ceph_auth_id, readonly=readonly,
|
||||
tenant_id=share['project_id'])
|
||||
|
||||
return auth_result['auth_key']
|
||||
|
||||
@ -250,25 +251,45 @@ class CephFSNativeDriver(driver.ShareDriver,):
|
||||
|
||||
def update_access(self, context, share, access_rules, add_rules,
|
||||
delete_rules, share_server=None):
|
||||
# The interface to Ceph just provides add/remove methods, since it
|
||||
# was created at start of mitaka cycle when there was no requirement
|
||||
# to be able to list access rules or set them en masse. Therefore
|
||||
# we implement update_access as best we can. In future ceph's
|
||||
# interface should be extended to enable a full implementation
|
||||
# of update_access.
|
||||
access_keys = {}
|
||||
|
||||
if not (add_rules or delete_rules): # recovery/maintenance mode
|
||||
add_rules = access_rules
|
||||
|
||||
existing_auths = None
|
||||
|
||||
# The unversioned volume client cannot fetch from the Ceph backend,
|
||||
# the list of auth IDs that have share access.
|
||||
if getattr(self.volume_client, 'version', None):
|
||||
existing_auths = self.volume_client.get_authorized_ids(
|
||||
self._share_path(share))
|
||||
|
||||
if existing_auths:
|
||||
existing_auth_ids = set(
|
||||
[auth[0] for auth in existing_auths])
|
||||
want_auth_ids = set(
|
||||
[rule['access_to'] for rule in add_rules])
|
||||
delete_auth_ids = existing_auth_ids.difference(
|
||||
want_auth_ids)
|
||||
for delete_auth_id in delete_auth_ids:
|
||||
delete_rules.append(
|
||||
{
|
||||
'access_to': delete_auth_id,
|
||||
'access_type': CEPHX_ACCESS_TYPE,
|
||||
})
|
||||
|
||||
# During recovery mode, re-authorize share access for auth IDs that
|
||||
# were already granted access by the backend. Do this to fetch their
|
||||
# access keys and ensure that after recovery, manila and the Ceph
|
||||
# backend are in sync.
|
||||
for rule in add_rules:
|
||||
self._allow_access(context, share, rule)
|
||||
access_key = self._allow_access(context, share, rule)
|
||||
access_keys.update({rule['id']: access_key})
|
||||
|
||||
for rule in delete_rules:
|
||||
self._deny_access(context, share, rule)
|
||||
|
||||
# This is where we would list all permitted clients and remove
|
||||
# those that are not in `access_rules` if the ceph interface
|
||||
# enabled it.
|
||||
if not (add_rules or delete_rules):
|
||||
for rule in access_rules:
|
||||
self._allow_access(context, share, rule)
|
||||
return access_keys
|
||||
|
||||
def delete_share(self, context, share, share_server=None):
|
||||
extra_specs = share_types.get_extra_specs_from_share(share)
|
||||
|
@ -58,12 +58,14 @@ class MockVolumeClientModule(object):
|
||||
"delete_volume", "purge_volume",
|
||||
"deauthorize", "evict", "set_max_bytes",
|
||||
"destroy_snapshot_group", "create_snapshot_group",
|
||||
"disconnect"
|
||||
"get_authorized_ids"
|
||||
])
|
||||
self.create_volume = mock.Mock(return_value={
|
||||
"mount_path": "/foo/bar"
|
||||
})
|
||||
self.get_mon_addrs = mock.Mock(return_value=["1.2.3.4", "5.6.7.8"])
|
||||
self.get_authorized_ids = mock.Mock(
|
||||
return_value=[('eve', 'rw')])
|
||||
self.authorize = mock.Mock(return_value={"auth_key": "abc123"})
|
||||
self.get_used_bytes = mock.Mock(return_value=self.mock_used_bytes)
|
||||
self.rados = mock.Mock()
|
||||
@ -176,6 +178,7 @@ class CephFSNativeDriverTestCase(test.TestCase):
|
||||
self._context, self._share, rule)
|
||||
|
||||
self.assertEqual("abc123", auth_key)
|
||||
|
||||
if not volume_client_version:
|
||||
self._driver._volume_client.authorize.assert_called_once_with(
|
||||
self._driver._share_path(self._share),
|
||||
@ -184,7 +187,8 @@ class CephFSNativeDriverTestCase(test.TestCase):
|
||||
self._driver._volume_client.authorize.assert_called_once_with(
|
||||
self._driver._share_path(self._share),
|
||||
"alice",
|
||||
readonly=False)
|
||||
readonly=False,
|
||||
tenant_id=self._share['project_id'])
|
||||
|
||||
@ddt.data(None, 1)
|
||||
def test_allow_access_ro(self, volume_client_version):
|
||||
@ -207,7 +211,9 @@ class CephFSNativeDriverTestCase(test.TestCase):
|
||||
self._driver._volume_client.authorize.assert_called_once_with(
|
||||
self._driver._share_path(self._share),
|
||||
"alice",
|
||||
readonly=True)
|
||||
readonly=True,
|
||||
tenant_id=self._share['project_id'],
|
||||
)
|
||||
|
||||
def test_allow_access_wrong_type(self):
|
||||
self.assertRaises(exception.InvalidShareAccess,
|
||||
@ -243,43 +249,69 @@ class CephFSNativeDriverTestCase(test.TestCase):
|
||||
|
||||
def test_update_access_add_rm(self):
|
||||
alice = {
|
||||
'id': 'accessid1',
|
||||
'access_level': 'rw',
|
||||
'access_type': 'cephx',
|
||||
'access_to': 'alice'
|
||||
}
|
||||
bob = {
|
||||
'id': 'accessid2',
|
||||
'access_level': 'rw',
|
||||
'access_type': 'cephx',
|
||||
'access_to': 'bob'
|
||||
}
|
||||
self._driver.update_access(self._context, self._share,
|
||||
access_rules=[alice],
|
||||
add_rules=[alice],
|
||||
delete_rules=[bob])
|
||||
|
||||
access_keys = self._driver.update_access(self._context, self._share,
|
||||
access_rules=[alice],
|
||||
add_rules=[alice],
|
||||
delete_rules=[bob])
|
||||
|
||||
self.assertEqual({'accessid1': 'abc123'}, access_keys)
|
||||
self._driver._volume_client.authorize.assert_called_once_with(
|
||||
self._driver._share_path(self._share),
|
||||
"alice",
|
||||
readonly=False)
|
||||
readonly=False,
|
||||
tenant_id=self._share['project_id'])
|
||||
self._driver._volume_client.deauthorize.assert_called_once_with(
|
||||
self._driver._share_path(self._share),
|
||||
"bob")
|
||||
|
||||
def test_update_access_all(self):
|
||||
@ddt.data(None, 1)
|
||||
def test_update_access_all(self, volume_client_version):
|
||||
alice = {
|
||||
'id': 'accessid1',
|
||||
'access_level': 'rw',
|
||||
'access_type': 'cephx',
|
||||
'access_to': 'alice'
|
||||
}
|
||||
self._driver.volume_client.version = volume_client_version
|
||||
|
||||
self._driver.update_access(self._context, self._share,
|
||||
access_rules=[alice], add_rules=[],
|
||||
delete_rules=[])
|
||||
access_keys = self._driver.update_access(self._context, self._share,
|
||||
access_rules=[alice],
|
||||
add_rules=[],
|
||||
delete_rules=[])
|
||||
|
||||
self._driver._volume_client.authorize.assert_called_once_with(
|
||||
self._driver._share_path(self._share),
|
||||
"alice",
|
||||
readonly=False)
|
||||
self.assertEqual({'accessid1': 'abc123'}, access_keys)
|
||||
if volume_client_version:
|
||||
(self._driver._volume_client.get_authorized_ids.
|
||||
assert_called_once_with(self._driver._share_path(self._share)))
|
||||
self._driver._volume_client.authorize.assert_called_once_with(
|
||||
self._driver._share_path(self._share),
|
||||
"alice",
|
||||
readonly=False,
|
||||
tenant_id=self._share['project_id']
|
||||
)
|
||||
self._driver._volume_client.deauthorize.assert_called_once_with(
|
||||
self._driver._share_path(self._share),
|
||||
"eve",
|
||||
)
|
||||
else:
|
||||
self.assertFalse(
|
||||
self._driver._volume_client.get_authorized_ids.called)
|
||||
self._driver._volume_client.authorize.assert_called_once_with(
|
||||
self._driver._share_path(self._share),
|
||||
"alice",
|
||||
)
|
||||
|
||||
def test_extend_share(self):
|
||||
new_size_gb = self._share['size'] * 2
|
||||
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Enhanced ``cephfs_native`` driver's update_access() to,
|
||||
|
||||
- remove undesired rules existing in the backend during recovery mode.
|
||||
- return ``access_keys`` of ceph auth IDs that are allowed access.
|
Loading…
x
Reference in New Issue
Block a user