Merge "ignore devices that have already been processed"
This commit is contained in:
commit
fc4a4604ba
|
@ -28,6 +28,7 @@ from charmhelpers.contrib.storage.linux.utils import (
|
||||||
)
|
)
|
||||||
from charmhelpers.core.unitdata import kv
|
from charmhelpers.core.unitdata import kv
|
||||||
from ceph.utils import is_active_bluestore_device
|
from ceph.utils import is_active_bluestore_device
|
||||||
|
from ceph.utils import is_mapped_luks_device
|
||||||
|
|
||||||
|
|
||||||
def get_devices():
|
def get_devices():
|
||||||
|
@ -53,7 +54,9 @@ def zap():
|
||||||
for device in devices:
|
for device in devices:
|
||||||
if not is_block_device(device):
|
if not is_block_device(device):
|
||||||
not_block_devices.append(device)
|
not_block_devices.append(device)
|
||||||
if is_device_mounted(device) or is_active_bluestore_device(device):
|
if (is_device_mounted(device) or
|
||||||
|
is_active_bluestore_device(device) or
|
||||||
|
is_mapped_luks_device(device)):
|
||||||
failed_devices.append(device)
|
failed_devices.append(device)
|
||||||
|
|
||||||
if failed_devices or not_block_devices:
|
if failed_devices or not_block_devices:
|
||||||
|
|
|
@ -93,6 +93,8 @@ from charmhelpers.contrib.storage.linux.utils import (
|
||||||
from charmhelpers.contrib.charmsupport import nrpe
|
from charmhelpers.contrib.charmsupport import nrpe
|
||||||
from charmhelpers.contrib.hardening.harden import harden
|
from charmhelpers.contrib.hardening.harden import harden
|
||||||
|
|
||||||
|
from charmhelpers.core.unitdata import kv
|
||||||
|
|
||||||
import charmhelpers.contrib.openstack.vaultlocker as vaultlocker
|
import charmhelpers.contrib.openstack.vaultlocker as vaultlocker
|
||||||
|
|
||||||
hooks = Hooks()
|
hooks = Hooks()
|
||||||
|
@ -426,6 +428,15 @@ def prepare_disks_and_activate():
|
||||||
|
|
||||||
# pre-flight check of eligible device pristinity
|
# pre-flight check of eligible device pristinity
|
||||||
devices = get_devices()
|
devices = get_devices()
|
||||||
|
|
||||||
|
# if a device has been previously touched we need to consider it as
|
||||||
|
# non-pristine. If it needs to be re-processed it has to be zapped
|
||||||
|
# via the respective action which also clears the unitdata entry.
|
||||||
|
db = kv()
|
||||||
|
touched_devices = db.get('osd-devices', [])
|
||||||
|
devices = [dev for dev in devices if dev not in touched_devices]
|
||||||
|
log('Skipping osd devices previously processed by this unit: {}'
|
||||||
|
.format(touched_devices))
|
||||||
# filter osd-devices that are file system paths
|
# filter osd-devices that are file system paths
|
||||||
devices = [dev for dev in devices if dev.startswith('/dev')]
|
devices = [dev for dev in devices if dev.startswith('/dev')]
|
||||||
# filter osd-devices that does not exist on this unit
|
# filter osd-devices that does not exist on this unit
|
||||||
|
@ -435,6 +446,7 @@ def prepare_disks_and_activate():
|
||||||
# filter osd-devices that are active bluestore devices
|
# filter osd-devices that are active bluestore devices
|
||||||
devices = [dev for dev in devices
|
devices = [dev for dev in devices
|
||||||
if not ceph.is_active_bluestore_device(dev)]
|
if not ceph.is_active_bluestore_device(dev)]
|
||||||
|
|
||||||
log('Checking for pristine devices: "{}"'.format(devices), level=DEBUG)
|
log('Checking for pristine devices: "{}"'.format(devices), level=DEBUG)
|
||||||
if not all(ceph.is_pristine_disk(dev) for dev in devices):
|
if not all(ceph.is_pristine_disk(dev) for dev in devices):
|
||||||
status_set('blocked',
|
status_set('blocked',
|
||||||
|
|
|
@ -81,6 +81,10 @@ POOL_KEYS = {
|
||||||
"cache_min_flush_age": [int],
|
"cache_min_flush_age": [int],
|
||||||
"cache_min_evict_age": [int],
|
"cache_min_evict_age": [int],
|
||||||
"fast_read": [bool],
|
"fast_read": [bool],
|
||||||
|
"allow_ec_overwrites": [bool],
|
||||||
|
"compression_mode": [str, ["none", "passive", "aggressive", "force"]],
|
||||||
|
"compression_algorithm": [str, ["lz4", "snappy", "zlib", "zstd"]],
|
||||||
|
"compression_required_ratio": [float, [0.0, 1.0]],
|
||||||
}
|
}
|
||||||
|
|
||||||
CEPH_BUCKET_TYPES = [
|
CEPH_BUCKET_TYPES = [
|
||||||
|
@ -251,7 +255,8 @@ def pool_permission_list_for_service(service):
|
||||||
for prefix in prefixes:
|
for prefix in prefixes:
|
||||||
permissions.append("allow {} object_prefix {}".format(permission,
|
permissions.append("allow {} object_prefix {}".format(permission,
|
||||||
prefix))
|
prefix))
|
||||||
return ["mon", "allow r", "osd", ', '.join(permissions)]
|
return ['mon', 'allow r, allow command "osd blacklist"',
|
||||||
|
'osd', ', '.join(permissions)]
|
||||||
|
|
||||||
|
|
||||||
def get_service_groups(service, namespace=None):
|
def get_service_groups(service, namespace=None):
|
||||||
|
|
|
@ -1096,7 +1096,8 @@ def get_mds_bootstrap_key():
|
||||||
|
|
||||||
|
|
||||||
_default_caps = collections.OrderedDict([
|
_default_caps = collections.OrderedDict([
|
||||||
('mon', ['allow r']),
|
('mon', ['allow r',
|
||||||
|
'allow command "osd blacklist"']),
|
||||||
('osd', ['allow rwx']),
|
('osd', ['allow rwx']),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -1163,6 +1164,7 @@ def get_named_key(name, caps=None, pool_list=None):
|
||||||
:param caps: dict of cephx capabilities
|
:param caps: dict of cephx capabilities
|
||||||
:returns: Returns a cephx key
|
:returns: Returns a cephx key
|
||||||
"""
|
"""
|
||||||
|
key_name = 'client.{}'.format(name)
|
||||||
try:
|
try:
|
||||||
# Does the key already exist?
|
# Does the key already exist?
|
||||||
output = str(subprocess.check_output(
|
output = str(subprocess.check_output(
|
||||||
|
@ -1177,8 +1179,14 @@ def get_named_key(name, caps=None, pool_list=None):
|
||||||
),
|
),
|
||||||
'auth',
|
'auth',
|
||||||
'get',
|
'get',
|
||||||
'client.{}'.format(name),
|
key_name,
|
||||||
]).decode('UTF-8')).strip()
|
]).decode('UTF-8')).strip()
|
||||||
|
# NOTE(jamespage);
|
||||||
|
# Apply any changes to key capabilities, dealing with
|
||||||
|
# upgrades which requires new caps for operation.
|
||||||
|
upgrade_key_caps(key_name,
|
||||||
|
caps or _default_caps,
|
||||||
|
pool_list)
|
||||||
return parse_key(output)
|
return parse_key(output)
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
# Couldn't get the key, time to create it!
|
# Couldn't get the key, time to create it!
|
||||||
|
@ -1194,7 +1202,7 @@ def get_named_key(name, caps=None, pool_list=None):
|
||||||
'/var/lib/ceph/mon/ceph-{}/keyring'.format(
|
'/var/lib/ceph/mon/ceph-{}/keyring'.format(
|
||||||
socket.gethostname()
|
socket.gethostname()
|
||||||
),
|
),
|
||||||
'auth', 'get-or-create', 'client.{}'.format(name),
|
'auth', 'get-or-create', key_name,
|
||||||
]
|
]
|
||||||
# Add capabilities
|
# Add capabilities
|
||||||
for subsystem, subcaps in caps.items():
|
for subsystem, subcaps in caps.items():
|
||||||
|
@ -1213,7 +1221,7 @@ def get_named_key(name, caps=None, pool_list=None):
|
||||||
.strip()) # IGNORE:E1103
|
.strip()) # IGNORE:E1103
|
||||||
|
|
||||||
|
|
||||||
def upgrade_key_caps(key, caps):
|
def upgrade_key_caps(key, caps, pool_list=None):
|
||||||
""" Upgrade key to have capabilities caps """
|
""" Upgrade key to have capabilities caps """
|
||||||
if not is_leader():
|
if not is_leader():
|
||||||
# Not the MON leader OR not clustered
|
# Not the MON leader OR not clustered
|
||||||
|
@ -1222,6 +1230,12 @@ def upgrade_key_caps(key, caps):
|
||||||
"sudo", "-u", ceph_user(), 'ceph', 'auth', 'caps', key
|
"sudo", "-u", ceph_user(), 'ceph', 'auth', 'caps', key
|
||||||
]
|
]
|
||||||
for subsystem, subcaps in caps.items():
|
for subsystem, subcaps in caps.items():
|
||||||
|
if subsystem == 'osd':
|
||||||
|
if pool_list:
|
||||||
|
# This will output a string similar to:
|
||||||
|
# "pool=rgw pool=rbd pool=something"
|
||||||
|
pools = " ".join(['pool={0}'.format(i) for i in pool_list])
|
||||||
|
subcaps[0] = subcaps[0] + " " + pools
|
||||||
cmd.extend([subsystem, '; '.join(subcaps)])
|
cmd.extend([subsystem, '; '.join(subcaps)])
|
||||||
subprocess.check_call(cmd)
|
subprocess.check_call(cmd)
|
||||||
|
|
||||||
|
@ -1453,6 +1467,11 @@ def osdize_dev(dev, osd_format, osd_journal, ignore_errors=False,
|
||||||
' skipping.'.format(dev))
|
' skipping.'.format(dev))
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if is_mapped_luks_device(dev):
|
||||||
|
log('{} is a mapped LUKS device,'
|
||||||
|
' skipping.'.format(dev))
|
||||||
|
return
|
||||||
|
|
||||||
if cmp_pkgrevno('ceph', '12.2.4') >= 0:
|
if cmp_pkgrevno('ceph', '12.2.4') >= 0:
|
||||||
cmd = _ceph_volume(dev,
|
cmd = _ceph_volume(dev,
|
||||||
osd_journal,
|
osd_journal,
|
||||||
|
@ -1664,6 +1683,29 @@ def is_active_bluestore_device(dev):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def is_luks_device(dev):
|
||||||
|
"""
|
||||||
|
Determine if dev is a LUKS-formatted block device.
|
||||||
|
|
||||||
|
:param: dev: A full path to a block device to check for LUKS header
|
||||||
|
presence
|
||||||
|
:returns: boolean: indicates whether a device is used based on LUKS header.
|
||||||
|
"""
|
||||||
|
return True if _luks_uuid(dev) else False
|
||||||
|
|
||||||
|
|
||||||
|
def is_mapped_luks_device(dev):
|
||||||
|
"""
|
||||||
|
Determine if dev is a mapped LUKS device
|
||||||
|
:param: dev: A full path to a block device to be checked
|
||||||
|
:returns: boolean: indicates whether a device is mapped
|
||||||
|
"""
|
||||||
|
_, dirs, _ = next(os.walk('/sys/class/block/{}/holders/'
|
||||||
|
.format(os.path.basename(dev))))
|
||||||
|
is_held = len(dirs) > 0
|
||||||
|
return is_held and is_luks_device(dev)
|
||||||
|
|
||||||
|
|
||||||
def get_conf(variable):
|
def get_conf(variable):
|
||||||
"""
|
"""
|
||||||
Get the value of the given configuration variable from the
|
Get the value of the given configuration variable from the
|
||||||
|
|
|
@ -26,10 +26,12 @@ class ZapDiskActionTests(CharmTestCase):
|
||||||
'is_block_device',
|
'is_block_device',
|
||||||
'is_device_mounted',
|
'is_device_mounted',
|
||||||
'is_active_bluestore_device',
|
'is_active_bluestore_device',
|
||||||
|
'is_mapped_luks_device',
|
||||||
'kv'])
|
'kv'])
|
||||||
self.is_device_mounted.return_value = False
|
self.is_device_mounted.return_value = False
|
||||||
self.is_block_device.return_value = True
|
self.is_block_device.return_value = True
|
||||||
self.is_active_bluestore_device.return_value = False
|
self.is_active_bluestore_device.return_value = False
|
||||||
|
self.is_mapped_luks_device.return_value = False
|
||||||
self.kv.return_value = self.kv
|
self.kv.return_value = self.kv
|
||||||
self.hookenv.local_unit.return_value = "ceph-osd-test/0"
|
self.hookenv.local_unit.return_value = "ceph-osd-test/0"
|
||||||
|
|
||||||
|
@ -127,3 +129,44 @@ class ZapDiskActionTests(CharmTestCase):
|
||||||
_zap_disk.assert_not_called()
|
_zap_disk.assert_not_called()
|
||||||
self.hookenv.action_fail.assert_called_with(
|
self.hookenv.action_fail.assert_called_with(
|
||||||
"1 devices are mounted: /dev/vdb")
|
"1 devices are mounted: /dev/vdb")
|
||||||
|
|
||||||
|
@mock.patch.object(zap_disk, 'zap_disk')
|
||||||
|
def test_wont_zap__mapped_luks_device(self, _zap_disk):
|
||||||
|
"""Will not zap a disk that has a LUKS header"""
|
||||||
|
def side_effect(arg):
|
||||||
|
return {
|
||||||
|
'devices': '/dev/vdb',
|
||||||
|
'i-really-mean-it': True,
|
||||||
|
}.get(arg)
|
||||||
|
self.hookenv.action_get.side_effect = side_effect
|
||||||
|
self.is_active_bluestore_device.return_value = False
|
||||||
|
self.is_mapped_luks_device.return_value = True
|
||||||
|
zap_disk.zap()
|
||||||
|
_zap_disk.assert_not_called()
|
||||||
|
self.hookenv.action_fail.assert_called_with(
|
||||||
|
"1 devices are mounted: /dev/vdb")
|
||||||
|
|
||||||
|
@mock.patch.object(zap_disk, 'zap_disk')
|
||||||
|
def test_zap_luks_not_mapped(self, _zap_disk):
|
||||||
|
"""Will zap disk with extra config set"""
|
||||||
|
def side_effect(arg):
|
||||||
|
return {
|
||||||
|
'devices': '/dev/vdb',
|
||||||
|
'i-really-mean-it': True,
|
||||||
|
}.get(arg)
|
||||||
|
|
||||||
|
self.is_active_bluestore_device.return_value = False
|
||||||
|
self.is_mapped_luks_device.return_value = False
|
||||||
|
|
||||||
|
self.hookenv.action_get.side_effect = side_effect
|
||||||
|
self.kv.get.return_value = ['/dev/vdb', '/dev/vdz']
|
||||||
|
zap_disk.zap()
|
||||||
|
_zap_disk.assert_called_with('/dev/vdb')
|
||||||
|
self.kv.get.assert_called_with('osd-devices', [])
|
||||||
|
self.kv.set.assert_called_with('osd-devices', ['/dev/vdz'])
|
||||||
|
self.hookenv.action_set.assert_called_with({
|
||||||
|
'message': "1 disk(s) have been zapped, to use "
|
||||||
|
"them as OSDs, run: \njuju "
|
||||||
|
"run-action ceph-osd-test/0 add-disk "
|
||||||
|
"osd-devices=\"/dev/vdb\""
|
||||||
|
})
|
||||||
|
|
Loading…
Reference in New Issue