Add setting ``max_objects`` quota and retrieving erasure code profile

Also fix a few missing redirects of STDERR

Change-Id: I243328af5db202f092c53b4d48e0d293378d2ca0
This commit is contained in:
Frode Nordahl 2019-02-26 16:09:15 +01:00
parent 03685ca4a6
commit 203840bd69
No known key found for this signature in database
GPG Key ID: 6A5D59A3BA48373F
3 changed files with 93 additions and 33 deletions

View File

@ -369,7 +369,8 @@ def handle_erasure_pool(request, service):
"""
pool_name = request.get('name')
erasure_profile = request.get('erasure-profile')
quota = request.get('max-bytes')
max_bytes = request.get('max-bytes')
max_objects = request.get('max-objects')
weight = request.get('weight')
group_name = request.get('group')
@ -409,8 +410,9 @@ def handle_erasure_pool(request, service):
pool.create()
# Set a quota if requested
if quota is not None:
set_pool_quota(service=service, pool_name=pool_name, max_bytes=quota)
if max_bytes or max_objects:
set_pool_quota(service=service, pool_name=pool_name,
max_bytes=max_bytes, max_objects=max_objects)
def handle_replicated_pool(request, service):
@ -422,7 +424,8 @@ def handle_replicated_pool(request, service):
"""
pool_name = request.get('name')
replicas = request.get('replicas')
quota = request.get('max-bytes')
max_bytes = request.get('max-bytes')
max_objects = request.get('max-objects')
weight = request.get('weight')
group_name = request.get('group')
@ -469,8 +472,9 @@ def handle_replicated_pool(request, service):
level=DEBUG)
# Set a quota if requested
if quota is not None:
set_pool_quota(service=service, pool_name=pool_name, max_bytes=quota)
if max_bytes or max_objects:
set_pool_quota(service=service, pool_name=pool_name,
max_bytes=max_bytes, max_objects=max_objects)
def handle_create_cache_tier(request, service):

View File

@ -2533,7 +2533,8 @@ def list_pools(client='admin'):
try:
pool_list = []
pools = subprocess.check_output(['rados', '--id', client, 'lspools'],
universal_newlines=True)
universal_newlines=True,
stderr=subprocess.STDOUT)
for pool in pools.splitlines():
pool_list.append(pool)
return pool_list
@ -2558,8 +2559,8 @@ def get_pool_param(pool, param, client='admin'):
"""
try:
output = subprocess.check_output(
['ceph', '--id', client, 'osd', 'pool', 'get',
pool, param], universal_newlines=True)
['ceph', '--id', client, 'osd', 'pool', 'get', pool, param],
universal_newlines=True, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as cp:
if cp.returncode == 2 and 'ENOENT: option' in cp.output:
return None
@ -2568,6 +2569,27 @@ def get_pool_param(pool, param, client='admin'):
return output.split(':')[1].lstrip().rstrip()
def get_pool_erasure_profile(pool, client='admin'):
"""Get erasure code profile for pool.
:param pool: Name of pool to get variable from
:type pool: str
:param client: (Optional) client id for ceph key to use
Defaults to ``admin``
:type cilent: str
:returns: Erasure code profile of pool or None
:rtype: str or None
:raises: subprocess.CalledProcessError
"""
try:
return get_pool_param(pool, 'erasure_code_profile', client=client)
except subprocess.CalledProcessError as cp:
if cp.returncode == 13 and 'EACCES: pool' in cp.output:
# Not a Erasure coded pool
return None
raise
def get_pool_quota(pool, client='admin'):
"""Get pool quota.
@ -2582,7 +2604,7 @@ def get_pool_quota(pool, client='admin'):
"""
output = subprocess.check_output(
['ceph', '--id', client, 'osd', 'pool', 'get-quota', pool],
universal_newlines=True)
universal_newlines=True, stderr=subprocess.STDOUT)
rc = re.compile(r'\s+max\s+(\S+)\s*:\s+(\d+)')
result = {}
for line in output.splitlines():
@ -2610,7 +2632,9 @@ def get_pool_applications(pool='', client='admin'):
if pool:
cmd.append(pool)
try:
output = subprocess.check_output(cmd, universal_newlines=True)
output = subprocess.check_output(cmd,
universal_newlines=True,
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as cp:
if cp.returncode == 2 and 'ENOENT' in cp.output:
return {}
@ -2646,6 +2670,10 @@ def list_pools_detail():
for param in get_params:
result[pool]['parameters'].update({
param: get_pool_param(pool, param)})
erasure_profile = get_pool_erasure_profile(pool)
if erasure_profile:
result[pool]['parameters'].update({
'erasure_code_profile': erasure_profile})
return result

View File

@ -13,6 +13,7 @@
# limitations under the License.
import collections
import subprocess
import unittest
from mock import (
@ -821,15 +822,18 @@ class CephTestCase(unittest.TestCase):
_check_output.return_value = 'poola\npoolb\n'
self.assertEqual(utils.list_pools('someuser'), ['poola', 'poolb'])
_check_output.assert_called_with(['rados', '--id', 'someuser',
'lspools'], universal_newlines=True)
'lspools'], universal_newlines=True,
stderr=subprocess.STDOUT)
self.assertEqual(utils.list_pools(client='someotheruser'),
['poola', 'poolb'])
_check_output.assert_called_with(['rados', '--id', 'someotheruser',
'lspools'], universal_newlines=True)
'lspools'], universal_newlines=True,
stderr=subprocess.STDOUT)
self.assertEqual(utils.list_pools(),
['poola', 'poolb'])
_check_output.assert_called_with(['rados', '--id', 'admin',
'lspools'], universal_newlines=True)
'lspools'], universal_newlines=True,
stderr=subprocess.STDOUT)
@patch.object(utils.subprocess, 'check_output')
def test_get_pool_param(self, _check_output):
@ -837,7 +841,22 @@ class CephTestCase(unittest.TestCase):
self.assertEqual(utils.get_pool_param('rbd', 'size'), '3')
_check_output.assert_called_with(['ceph', '--id', 'admin', 'osd',
'pool', 'get', 'rbd', 'size'],
universal_newlines=True)
universal_newlines=True,
stderr=subprocess.STDOUT)
@patch.object(utils, 'get_pool_param')
def test_get_pool_erasure_profile(self, _get_pool_param):
_get_pool_param.side_effect = subprocess.CalledProcessError(
13, [], 'EACCES: pool')
self.assertEqual(utils.get_pool_erasure_profile('cinder-ceph'), None)
_get_pool_param.side_effect = subprocess.CalledProcessError(
22, [], 'EINVAL: invalid')
with self.assertRaises(subprocess.CalledProcessError):
utils.get_pool_erasure_profile('cinder-ceph')
_get_pool_param.side_effect = None
_get_pool_param.return_value = 'my-ec-profile'
self.assertEqual(utils.get_pool_erasure_profile('cinder-ceph'),
'my-ec-profile')
@patch.object(utils.subprocess, 'check_output')
def test_get_pool_quota(self, _check_output):
@ -849,7 +868,8 @@ class CephTestCase(unittest.TestCase):
{})
_check_output.assert_called_with(['ceph', '--id', 'admin', 'osd',
'pool', 'get-quota', 'rbd'],
universal_newlines=True)
universal_newlines=True,
stderr=subprocess.STDOUT)
_check_output.return_value = (
"quotas for pool 'rbd':\n"
" max objects: 10\n"
@ -879,38 +899,46 @@ class CephTestCase(unittest.TestCase):
{'pool': {'application': {}}})
_check_output.assert_called_with(['ceph', '--id', 'admin', 'osd',
'pool', 'application', 'get'],
universal_newlines=True)
universal_newlines=True,
stderr=subprocess.STDOUT)
utils.get_pool_applications('42')
_check_output.assert_called_with(['ceph', '--id', 'admin', 'osd',
'pool', 'application', 'get', '42'],
universal_newlines=True)
universal_newlines=True,
stderr=subprocess.STDOUT)
@patch.object(utils, 'get_pool_erasure_profile')
@patch.object(utils, 'get_pool_param')
@patch.object(utils, 'get_pool_quota')
@patch.object(utils, 'list_pools')
@patch.object(utils, 'get_pool_applications')
def test_list_pools_detail(self, _get_pool_applications, _list_pools,
_get_pool_quota, _get_pool_param):
_get_pool_quota, _get_pool_param,
_get_pool_erasure_profile):
self.assertEqual(utils.list_pools_detail(), {})
_get_pool_applications.return_value = {'pool': {'application': {}}}
_list_pools.return_value = ['pool', 'pool2']
_get_pool_quota.return_value = {'max_objects': '10',
'max_bytes': '1000'}
_get_pool_param.return_value = '42'
self.assertEqual(utils.list_pools_detail(),
{'pool': {'applications': {'application': {}},
'parameters': {'pg_num': '42',
'size': '42'},
'quota': {'max_bytes': '1000',
'max_objects': '10'},
},
'pool2': {'applications': {},
'parameters': {'pg_num': '42',
'size': '42'},
'quota': {'max_bytes': '1000',
'max_objects': '10'},
},
})
_get_pool_erasure_profile.return_value = 'my-ec-profile'
self.assertEqual(
utils.list_pools_detail(),
{'pool': {'applications': {'application': {}},
'parameters': {'pg_num': '42',
'size': '42',
'erasure_code_profile': 'my-ec-profile'},
'quota': {'max_bytes': '1000',
'max_objects': '10'},
},
'pool2': {'applications': {},
'parameters': {'pg_num': '42',
'size': '42',
'erasure_code_profile': 'my-ec-profile'},
'quota': {'max_bytes': '1000',
'max_objects': '10'},
},
})
class CephVolumeSizeCalculatorTestCase(unittest.TestCase):