Add profile-name parameter in create-pool action

This change adds a profile name parameter in the create-pool action that
allows a replicated pool to be created with a CRUSH profile other than
the default replicated_rule.

Closes-Bug: #1905573

Change-Id: Ib21ded8f4a977b4a2d57c6b6b4bb82721b12c4ea
This commit is contained in:
Aqsa Malik 2022-02-04 13:06:53 +01:00
parent 05a03bd10d
commit da798bdd95
3 changed files with 45 additions and 5 deletions

View File

@ -30,10 +30,12 @@ def create_pool():
try:
if pool_type == "replicated":
replicas = action_get("replicas")
crush_profile_name = action_get("profile-name")
replicated_pool = ReplicatedPool(name=pool_name,
service='admin',
replicas=replicas,
app_name=app_name,
profile_name=crush_profile_name,
percent_data=float(percent_data),
)
replicated_pool.create()

View File

@ -615,7 +615,8 @@ class Pool(BasePool):
class ReplicatedPool(BasePool):
def __init__(self, service, name=None, pg_num=None, replicas=None,
percent_data=None, app_name=None, op=None):
percent_data=None, app_name=None, op=None,
profile_name='replicated_rule'):
"""Initialize ReplicatedPool object.
Pool information is either initialized from individual keyword
@ -632,6 +633,8 @@ class ReplicatedPool(BasePool):
to this replicated pool.
:type replicas: int
:raises: KeyError
:param profile_name: Crush Profile to use
:type profile_name: Optional[str]
"""
# NOTE: Do not perform initialization steps that require live data from
# a running cluster here. The *Pool classes may be used for validation.
@ -646,11 +649,20 @@ class ReplicatedPool(BasePool):
# we will fail with KeyError if it is not provided.
self.replicas = op['replicas']
self.pg_num = op.get('pg_num')
self.profile_name = op.get('crush-profile', profile_name)
else:
self.replicas = replicas or 2
self.pg_num = pg_num
self.profile_name = profile_name or 'replicated_rule'
def _create(self):
# Validate if crush profile exists
if self.profile_name is None:
msg = ("Failed to discover crush profile named "
"{}".format(self.profile_name))
log(msg, level=ERROR)
raise PoolCreationError(msg)
# Do extra validation on pg_num with data from live cluster
if self.pg_num:
# Since the number of placement groups were specified, ensure
@ -668,12 +680,12 @@ class ReplicatedPool(BasePool):
'--pg-num-min={}'.format(
min(AUTOSCALER_DEFAULT_PGS, self.pg_num)
),
self.name, str(self.pg_num)
self.name, str(self.pg_num), self.profile_name
]
else:
cmd = [
'ceph', '--id', self.service, 'osd', 'pool', 'create',
self.name, str(self.pg_num)
self.name, str(self.pg_num), self.profile_name
]
check_call(cmd)
@ -692,7 +704,7 @@ class ErasurePool(BasePool):
def __init__(self, service, name=None, erasure_code_profile=None,
percent_data=None, app_name=None, op=None,
allow_ec_overwrites=False):
"""Initialize ReplicatedPool object.
"""Initialize ErasurePool object.
Pool information is either initialized from individual keyword
arguments or from a individual CephBrokerRq operation Dict.
@ -1859,7 +1871,7 @@ class CephBrokerRq(object):
}
def add_op_create_replicated_pool(self, name, replica_count=3, pg_num=None,
**kwargs):
crush_profile=None, **kwargs):
"""Adds an operation to create a replicated pool.
Refer to docstring for ``_partial_build_common_op_create`` for
@ -1873,6 +1885,10 @@ class CephBrokerRq(object):
for pool.
:type pg_num: int
:raises: AssertionError if provided data is of invalid type/range
:param crush_profile: Name of crush profile to use. If not set the
ceph-mon unit handling the broker request will
set its default value.
:type crush_profile: Optional[str]
"""
if pg_num and kwargs.get('weight'):
raise ValueError('pg_num and weight are mutually exclusive')
@ -1882,6 +1898,7 @@ class CephBrokerRq(object):
'name': name,
'replicas': replica_count,
'pg_num': pg_num,
'crush-profile': crush_profile
}
op.update(self._partial_build_common_op_create(**kwargs))

View File

@ -66,6 +66,27 @@ class TestCephOps(unittest.TestCase):
mock_delete_pool.assert_called_with(service='admin', name='foo')
self.assertEqual(json.loads(rc), {'exit-code': 0})
@patch('charmhelpers.contrib.storage.linux.ceph.cmp_pkgrevno')
@patch.object(broker, 'pool_exists')
@patch.object(broker.ReplicatedPool, 'create')
@patch.object(broker, 'log', lambda *args, **kwargs: None)
def test_process_requests_create_replicated_pool(self,
mock_replicated_pool,
mock_pool_exists,
mock_cmp_pkgrevno):
mock_pool_exists.return_value = False
mock_cmp_pkgrevno.return_value = 1
reqs = json.dumps({'api-version': 1,
'ops': [{
'op': 'create-pool',
'name': 'foo',
'replicas': 3
}]})
rc = broker.process_requests(reqs)
mock_pool_exists.assert_called_with(service='admin', name='foo')
mock_replicated_pool.assert_called_with()
self.assertEqual(json.loads(rc), {'exit-code': 0})
@patch('charmhelpers.contrib.storage.linux.ceph.cmp_pkgrevno')
@patch.object(broker, 'pool_exists')
@patch.object(broker.ErasurePool, 'create')