erasure-code: add crush rule profile to suites

Adding new yaml entry to handle create of crush profile before
creating new pool, will be skipped if no crush profile name
was set.

Signed-off-by: Nitzan Mordechai <nmordech@redhat.com>
This commit is contained in:
Nitzan Mordechai 2023-08-08 07:44:34 +00:00 committed by nmordech@redhat.com
parent 0debdf60df
commit 0c0d90d3ff
3 changed files with 65 additions and 4 deletions

View File

@ -20,7 +20,7 @@ from io import BytesIO, StringIO
from subprocess import DEVNULL
from teuthology import misc as teuthology
from tasks.scrub import Scrubber
from tasks.util.rados import cmd_erasure_code_profile
from tasks.util.rados import cmd_erasure_code_profile, cmd_ec_crush_profile
from tasks.util import get_remote
from teuthology.contextutil import safe_while
@ -2114,8 +2114,18 @@ class CephManager:
args = cmd_erasure_code_profile(profile_name, profile)
self.raw_cluster_cmd(*args)
def create_erasure_code_crush_rule(self, rule_name, profile):
"""
Create an erasure code crush rule that can be used as a parameter
when creating an erasure coded pool.
"""
with self.lock:
args = cmd_ec_crush_profile(rule_name, profile)
self.raw_cluster_cmd(*args)
def create_pool_with_unique_name(self, pg_num=16,
erasure_code_profile_name=None,
erasure_code_crush_rule_name=None,
min_size=None,
erasure_code_use_overwrites=False):
"""
@ -2129,6 +2139,7 @@ class CephManager:
name,
pg_num,
erasure_code_profile_name=erasure_code_profile_name,
erasure_code_crush_rule_name=erasure_code_crush_rule_name,
min_size=min_size,
erasure_code_use_overwrites=erasure_code_use_overwrites)
return name
@ -2141,6 +2152,7 @@ class CephManager:
def create_pool(self, pool_name, pg_num=16,
erasure_code_profile_name=None,
erasure_code_crush_rule_name=None,
min_size=None,
erasure_code_use_overwrites=False):
"""
@ -2149,6 +2161,8 @@ class CephManager:
:param pg_num: initial number of pgs.
:param erasure_code_profile_name: if set and !None create an
erasure coded pool using the profile
:param erasure_code_crush_rule_name: if set and !None create an
erasure coded pool using the crush rule
:param erasure_code_use_overwrites: if true, allow overwrites
"""
with self.lock:
@ -2157,9 +2171,14 @@ class CephManager:
assert pool_name not in self.pools
self.log("creating pool_name %s" % (pool_name,))
if erasure_code_profile_name:
self.raw_cluster_cmd('osd', 'pool', 'create',
pool_name, str(pg_num), str(pg_num),
'erasure', erasure_code_profile_name)
cmd_args = ['osd', 'pool', 'create',
pool_name, str(pg_num),
str(pg_num), 'erasure',
erasure_code_profile_name]
if erasure_code_crush_rule_name:
cmd_args.extend([erasure_code_crush_rule_name])
self.raw_cluster_cmd(*cmd_args)
else:
self.raw_cluster_cmd('osd', 'pool', 'create',
pool_name, str(pg_num))

View File

@ -237,8 +237,16 @@ def task(ctx, config):
profile = config.get('erasure_code_profile', {})
profile_name = profile.get('name', 'teuthologyprofile')
manager.create_erasure_code_profile(profile_name, profile)
crush_prof = config.get('erasure_code_crush', {})
crush_name = None
if crush_prof:
crush_name = crush_prof.get('name', 'teuthologycrush')
manager.create_erasure_code_crush_rule(crush_name, crush_prof)
else:
profile_name = None
crush_name = None
for i in range(int(config.get('runs', '1'))):
log.info("starting run %s out of %s", str(i), config.get('runs', '1'))
tests = {}
@ -256,6 +264,7 @@ def task(ctx, config):
else:
pool = manager.create_pool_with_unique_name(
erasure_code_profile_name=profile_name,
erasure_code_crush_rule_name=crush_name,
erasure_code_use_overwrites=
config.get('erasure_code_use_overwrites', False)
)

View File

@ -1,6 +1,7 @@
import logging
from teuthology import misc as teuthology
from teuthology.orchestra.run import Raw
log = logging.getLogger(__name__)
@ -85,3 +86,35 @@ def cmd_erasure_code_profile(profile_name, profile):
'osd', 'erasure-code-profile', 'set',
profile_name
] + [ str(key) + '=' + str(value) for key, value in profile.items() ]
def cmd_ec_crush_profile(crush_name, profile):
"""
Return the shell command to run to create the erasure code crush rule
described by the profile parameter.
:param crush_name: a string matching [A-Za-z0-9-_.]+
:param profile: a map whose semantic depends on the crush rule syntax
:returns: a shell command as an array suitable for Remote.run
If profile is {}, return an empty list.
"""
if profile == {}:
return []
id_value = profile.get('id', 1)
ec_type = profile.get('type', 'erasure')
min_size = profile.get('min_size', 1)
max_size = profile.get('max_size', 10)
steps = profile.get('steps', [])
crush_content = f"rule {crush_name}-{id_value} {{"
crush_content += f" id {id_value}"
crush_content += f" type {ec_type}"
crush_content += f" min_size {min_size}"
crush_content += f" max_size {max_size}"
for step in steps:
crush_content += f" step {step}"
crush_content += "}"
return ['osd', 'crush', 'rule', 'create-erasure', crush_name, '-i', '-', Raw("<<<"), crush_content]