Merge "udevadm settle before processing osd-devices"
This commit is contained in:
commit
4a3a981e9d
|
@ -521,6 +521,7 @@ def prepare_disks_and_activate():
|
||||||
log('ceph bootstrapped, rescanning disks')
|
log('ceph bootstrapped, rescanning disks')
|
||||||
emit_cephconf()
|
emit_cephconf()
|
||||||
bluestore = use_bluestore()
|
bluestore = use_bluestore()
|
||||||
|
ceph.udevadm_settle()
|
||||||
for dev in get_devices():
|
for dev in get_devices():
|
||||||
ceph.osdize(dev, config('osd-format'),
|
ceph.osdize(dev, config('osd-format'),
|
||||||
osd_journal,
|
osd_journal,
|
||||||
|
|
|
@ -85,6 +85,7 @@ POOL_KEYS = {
|
||||||
"compression_mode": [str, ["none", "passive", "aggressive", "force"]],
|
"compression_mode": [str, ["none", "passive", "aggressive", "force"]],
|
||||||
"compression_algorithm": [str, ["lz4", "snappy", "zlib", "zstd"]],
|
"compression_algorithm": [str, ["lz4", "snappy", "zlib", "zstd"]],
|
||||||
"compression_required_ratio": [float, [0.0, 1.0]],
|
"compression_required_ratio": [float, [0.0, 1.0]],
|
||||||
|
"crush_rule": [str],
|
||||||
}
|
}
|
||||||
|
|
||||||
CEPH_BUCKET_TYPES = [
|
CEPH_BUCKET_TYPES = [
|
||||||
|
@ -368,7 +369,8 @@ def handle_erasure_pool(request, service):
|
||||||
"""
|
"""
|
||||||
pool_name = request.get('name')
|
pool_name = request.get('name')
|
||||||
erasure_profile = request.get('erasure-profile')
|
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')
|
weight = request.get('weight')
|
||||||
group_name = request.get('group')
|
group_name = request.get('group')
|
||||||
|
|
||||||
|
@ -408,8 +410,9 @@ def handle_erasure_pool(request, service):
|
||||||
pool.create()
|
pool.create()
|
||||||
|
|
||||||
# Set a quota if requested
|
# Set a quota if requested
|
||||||
if quota is not None:
|
if max_bytes or max_objects:
|
||||||
set_pool_quota(service=service, pool_name=pool_name, max_bytes=quota)
|
set_pool_quota(service=service, pool_name=pool_name,
|
||||||
|
max_bytes=max_bytes, max_objects=max_objects)
|
||||||
|
|
||||||
|
|
||||||
def handle_replicated_pool(request, service):
|
def handle_replicated_pool(request, service):
|
||||||
|
@ -421,7 +424,8 @@ def handle_replicated_pool(request, service):
|
||||||
"""
|
"""
|
||||||
pool_name = request.get('name')
|
pool_name = request.get('name')
|
||||||
replicas = request.get('replicas')
|
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')
|
weight = request.get('weight')
|
||||||
group_name = request.get('group')
|
group_name = request.get('group')
|
||||||
|
|
||||||
|
@ -468,8 +472,9 @@ def handle_replicated_pool(request, service):
|
||||||
level=DEBUG)
|
level=DEBUG)
|
||||||
|
|
||||||
# Set a quota if requested
|
# Set a quota if requested
|
||||||
if quota is not None:
|
if max_bytes or max_objects:
|
||||||
set_pool_quota(service=service, pool_name=pool_name, max_bytes=quota)
|
set_pool_quota(service=service, pool_name=pool_name,
|
||||||
|
max_bytes=max_bytes, max_objects=max_objects)
|
||||||
|
|
||||||
|
|
||||||
def handle_create_cache_tier(request, service):
|
def handle_create_cache_tier(request, service):
|
||||||
|
|
|
@ -935,6 +935,11 @@ def start_osds(devices):
|
||||||
subprocess.check_call(['ceph-disk', 'activate', dev_or_path])
|
subprocess.check_call(['ceph-disk', 'activate', dev_or_path])
|
||||||
|
|
||||||
|
|
||||||
|
def udevadm_settle():
|
||||||
|
cmd = ['udevadm', 'settle']
|
||||||
|
subprocess.call(cmd)
|
||||||
|
|
||||||
|
|
||||||
def rescan_osd_devices():
|
def rescan_osd_devices():
|
||||||
cmd = [
|
cmd = [
|
||||||
'udevadm', 'trigger',
|
'udevadm', 'trigger',
|
||||||
|
@ -943,8 +948,7 @@ def rescan_osd_devices():
|
||||||
|
|
||||||
subprocess.call(cmd)
|
subprocess.call(cmd)
|
||||||
|
|
||||||
cmd = ['udevadm', 'settle']
|
udevadm_settle()
|
||||||
subprocess.call(cmd)
|
|
||||||
|
|
||||||
|
|
||||||
_bootstrap_keyring = "/var/lib/ceph/bootstrap-osd/ceph.keyring"
|
_bootstrap_keyring = "/var/lib/ceph/bootstrap-osd/ceph.keyring"
|
||||||
|
@ -1072,8 +1076,8 @@ _upgrade_caps = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_radosgw_key(pool_list=None):
|
def get_radosgw_key(pool_list=None, name=None):
|
||||||
return get_named_key(name='radosgw.gateway',
|
return get_named_key(name=name or 'radosgw.gateway',
|
||||||
caps=_radosgw_caps,
|
caps=_radosgw_caps,
|
||||||
pool_list=pool_list)
|
pool_list=pool_list)
|
||||||
|
|
||||||
|
@ -1128,6 +1132,15 @@ osd_upgrade_caps = collections.OrderedDict([
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
|
||||||
|
rbd_mirror_caps = collections.OrderedDict([
|
||||||
|
('mon', ['profile rbd']),
|
||||||
|
('osd', ['profile rbd']),
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
def get_rbd_mirror_key(name):
|
||||||
|
return get_named_key(name=name, caps=rbd_mirror_caps)
|
||||||
|
|
||||||
|
|
||||||
def create_named_keyring(entity, name, caps=None):
|
def create_named_keyring(entity, name, caps=None):
|
||||||
caps = caps or _default_caps
|
caps = caps or _default_caps
|
||||||
|
@ -1819,6 +1832,13 @@ def _initialize_disk(dev, dev_uuid, encrypt=False,
|
||||||
'--uuid', dev_uuid,
|
'--uuid', dev_uuid,
|
||||||
dev,
|
dev,
|
||||||
])
|
])
|
||||||
|
subprocess.check_call([
|
||||||
|
'dd',
|
||||||
|
'if=/dev/zero',
|
||||||
|
'of={}'.format(dm_crypt),
|
||||||
|
'bs=512',
|
||||||
|
'count=1',
|
||||||
|
])
|
||||||
|
|
||||||
if use_vaultlocker:
|
if use_vaultlocker:
|
||||||
return dm_crypt
|
return dm_crypt
|
||||||
|
@ -1899,6 +1919,7 @@ def osdize_dir(path, encrypt=False, bluestore=False):
|
||||||
return
|
return
|
||||||
|
|
||||||
mkdir(path, owner=ceph_user(), group=ceph_user(), perms=0o755)
|
mkdir(path, owner=ceph_user(), group=ceph_user(), perms=0o755)
|
||||||
|
chownr('/var/lib/ceph', ceph_user(), ceph_user())
|
||||||
cmd = [
|
cmd = [
|
||||||
'sudo', '-u', ceph_user(),
|
'sudo', '-u', ceph_user(),
|
||||||
'ceph-disk',
|
'ceph-disk',
|
||||||
|
@ -2499,18 +2520,21 @@ def update_owner(path, recurse_dirs=True):
|
||||||
secs=elapsed_time.total_seconds(), path=path), DEBUG)
|
secs=elapsed_time.total_seconds(), path=path), DEBUG)
|
||||||
|
|
||||||
|
|
||||||
def list_pools(service):
|
def list_pools(client='admin'):
|
||||||
"""This will list the current pools that Ceph has
|
"""This will list the current pools that Ceph has
|
||||||
|
|
||||||
:param service: String service id to run under
|
:param client: (Optional) client id for ceph key to use
|
||||||
:returns: list. Returns a list of the ceph pools.
|
Defaults to ``admin``
|
||||||
:raises: CalledProcessError if the subprocess fails to run.
|
:type cilent: str
|
||||||
|
:returns: Returns a list of available pools.
|
||||||
|
:rtype: list
|
||||||
|
:raises: subprocess.CalledProcessError if the subprocess fails to run.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
pool_list = []
|
pool_list = []
|
||||||
pools = str(subprocess
|
pools = subprocess.check_output(['rados', '--id', client, 'lspools'],
|
||||||
.check_output(['rados', '--id', service, 'lspools'])
|
universal_newlines=True,
|
||||||
.decode('UTF-8'))
|
stderr=subprocess.STDOUT)
|
||||||
for pool in pools.splitlines():
|
for pool in pools.splitlines():
|
||||||
pool_list.append(pool)
|
pool_list.append(pool)
|
||||||
return pool_list
|
return pool_list
|
||||||
|
@ -2519,6 +2543,140 @@ def list_pools(service):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def get_pool_param(pool, param, client='admin'):
|
||||||
|
"""Get parameter from pool.
|
||||||
|
|
||||||
|
:param pool: Name of pool to get variable from
|
||||||
|
:type pool: str
|
||||||
|
:param param: Name of variable to get
|
||||||
|
:type param: str
|
||||||
|
:param client: (Optional) client id for ceph key to use
|
||||||
|
Defaults to ``admin``
|
||||||
|
:type cilent: str
|
||||||
|
:returns: Value of variable on pool or None
|
||||||
|
:rtype: str or None
|
||||||
|
:raises: subprocess.CalledProcessError
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
output = subprocess.check_output(
|
||||||
|
['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
|
||||||
|
raise
|
||||||
|
if ':' in output:
|
||||||
|
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.
|
||||||
|
|
||||||
|
: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: Dictionary with quota variables
|
||||||
|
:rtype: dict
|
||||||
|
:raises: subprocess.CalledProcessError
|
||||||
|
"""
|
||||||
|
output = subprocess.check_output(
|
||||||
|
['ceph', '--id', client, 'osd', 'pool', 'get-quota', pool],
|
||||||
|
universal_newlines=True, stderr=subprocess.STDOUT)
|
||||||
|
rc = re.compile(r'\s+max\s+(\S+)\s*:\s+(\d+)')
|
||||||
|
result = {}
|
||||||
|
for line in output.splitlines():
|
||||||
|
m = rc.match(line)
|
||||||
|
if m:
|
||||||
|
result.update({'max_{}'.format(m.group(1)): m.group(2)})
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def get_pool_applications(pool='', client='admin'):
|
||||||
|
"""Get pool applications.
|
||||||
|
|
||||||
|
:param pool: (Optional) Name of pool to get applications for
|
||||||
|
Defaults to get for all pools
|
||||||
|
:type pool: str
|
||||||
|
:param client: (Optional) client id for ceph key to use
|
||||||
|
Defaults to ``admin``
|
||||||
|
:type cilent: str
|
||||||
|
:returns: Dictionary with pool name as key
|
||||||
|
:rtype: dict
|
||||||
|
:raises: subprocess.CalledProcessError
|
||||||
|
"""
|
||||||
|
|
||||||
|
cmd = ['ceph', '--id', client, 'osd', 'pool', 'application', 'get']
|
||||||
|
if pool:
|
||||||
|
cmd.append(pool)
|
||||||
|
try:
|
||||||
|
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 {}
|
||||||
|
raise
|
||||||
|
return json.loads(output)
|
||||||
|
|
||||||
|
|
||||||
|
def list_pools_detail():
|
||||||
|
"""Get detailed information about pools.
|
||||||
|
|
||||||
|
Structure:
|
||||||
|
{'pool_name_1': {'applications': {'application': {}},
|
||||||
|
'parameters': {'pg_num': '42', 'size': '42'},
|
||||||
|
'quota': {'max_bytes': '1000',
|
||||||
|
'max_objects': '10'},
|
||||||
|
},
|
||||||
|
'pool_name_2': ...
|
||||||
|
}
|
||||||
|
|
||||||
|
:returns: Dictionary with detailed pool information.
|
||||||
|
:rtype: dict
|
||||||
|
:raises: subproces.CalledProcessError
|
||||||
|
"""
|
||||||
|
get_params = ['pg_num', 'size']
|
||||||
|
result = {}
|
||||||
|
applications = get_pool_applications()
|
||||||
|
for pool in list_pools():
|
||||||
|
result[pool] = {
|
||||||
|
'applications': applications.get(pool, {}),
|
||||||
|
'parameters': {},
|
||||||
|
'quota': get_pool_quota(pool),
|
||||||
|
}
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
def dirs_need_ownership_update(service):
|
def dirs_need_ownership_update(service):
|
||||||
"""Determines if directories still need change of ownership.
|
"""Determines if directories still need change of ownership.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue