Browse Source

Merge "ignore devices that have already been processed"

changes/95/583495/1
Zuul 1 year ago
parent
commit
fc4a4604ba
5 changed files with 111 additions and 6 deletions
  1. 4
    1
      actions/zap_disk.py
  2. 12
    0
      hooks/ceph_hooks.py
  3. 6
    1
      lib/ceph/broker.py
  4. 46
    4
      lib/ceph/utils.py
  5. 43
    0
      unit_tests/test_actions_zap_disk.py

+ 4
- 1
actions/zap_disk.py View File

@@ -28,6 +28,7 @@ from charmhelpers.contrib.storage.linux.utils import (
28 28
 )
29 29
 from charmhelpers.core.unitdata import kv
30 30
 from ceph.utils import is_active_bluestore_device
31
+from ceph.utils import is_mapped_luks_device
31 32
 
32 33
 
33 34
 def get_devices():
@@ -53,7 +54,9 @@ def zap():
53 54
     for device in devices:
54 55
         if not is_block_device(device):
55 56
             not_block_devices.append(device)
56
-        if is_device_mounted(device) or is_active_bluestore_device(device):
57
+        if (is_device_mounted(device) or
58
+                is_active_bluestore_device(device) or
59
+                is_mapped_luks_device(device)):
57 60
             failed_devices.append(device)
58 61
 
59 62
     if failed_devices or not_block_devices:

+ 12
- 0
hooks/ceph_hooks.py View File

@@ -93,6 +93,8 @@ from charmhelpers.contrib.storage.linux.utils import (
93 93
 from charmhelpers.contrib.charmsupport import nrpe
94 94
 from charmhelpers.contrib.hardening.harden import harden
95 95
 
96
+from charmhelpers.core.unitdata import kv
97
+
96 98
 import charmhelpers.contrib.openstack.vaultlocker as vaultlocker
97 99
 
98 100
 hooks = Hooks()
@@ -426,6 +428,15 @@ def prepare_disks_and_activate():
426 428
 
427 429
     # pre-flight check of eligible device pristinity
428 430
     devices = get_devices()
431
+
432
+    # if a device has been previously touched we need to consider it as
433
+    # non-pristine. If it needs to be re-processed it has to be zapped
434
+    # via the respective action which also clears the unitdata entry.
435
+    db = kv()
436
+    touched_devices = db.get('osd-devices', [])
437
+    devices = [dev for dev in devices if dev not in touched_devices]
438
+    log('Skipping osd devices previously processed by this unit: {}'
439
+        .format(touched_devices))
429 440
     # filter osd-devices that are file system paths
430 441
     devices = [dev for dev in devices if dev.startswith('/dev')]
431 442
     # filter osd-devices that does not exist on this unit
@@ -435,6 +446,7 @@ def prepare_disks_and_activate():
435 446
     # filter osd-devices that are active bluestore devices
436 447
     devices = [dev for dev in devices
437 448
                if not ceph.is_active_bluestore_device(dev)]
449
+
438 450
     log('Checking for pristine devices: "{}"'.format(devices), level=DEBUG)
439 451
     if not all(ceph.is_pristine_disk(dev) for dev in devices):
440 452
         status_set('blocked',

+ 6
- 1
lib/ceph/broker.py View File

@@ -81,6 +81,10 @@ POOL_KEYS = {
81 81
     "cache_min_flush_age": [int],
82 82
     "cache_min_evict_age": [int],
83 83
     "fast_read": [bool],
84
+    "allow_ec_overwrites": [bool],
85
+    "compression_mode": [str, ["none", "passive", "aggressive", "force"]],
86
+    "compression_algorithm": [str, ["lz4", "snappy", "zlib", "zstd"]],
87
+    "compression_required_ratio": [float, [0.0, 1.0]],
84 88
 }
85 89
 
86 90
 CEPH_BUCKET_TYPES = [
@@ -251,7 +255,8 @@ def pool_permission_list_for_service(service):
251 255
         for prefix in prefixes:
252 256
             permissions.append("allow {} object_prefix {}".format(permission,
253 257
                                                                   prefix))
254
-    return ["mon", "allow r", "osd", ', '.join(permissions)]
258
+    return ['mon', 'allow r, allow command "osd blacklist"',
259
+            'osd', ', '.join(permissions)]
255 260
 
256 261
 
257 262
 def get_service_groups(service, namespace=None):

+ 46
- 4
lib/ceph/utils.py View File

@@ -1096,7 +1096,8 @@ def get_mds_bootstrap_key():
1096 1096
 
1097 1097
 
1098 1098
 _default_caps = collections.OrderedDict([
1099
-    ('mon', ['allow r']),
1099
+    ('mon', ['allow r',
1100
+             'allow command "osd blacklist"']),
1100 1101
     ('osd', ['allow rwx']),
1101 1102
 ])
1102 1103
 
@@ -1163,6 +1164,7 @@ def get_named_key(name, caps=None, pool_list=None):
1163 1164
     :param caps: dict of cephx capabilities
1164 1165
     :returns: Returns a cephx key
1165 1166
     """
1167
+    key_name = 'client.{}'.format(name)
1166 1168
     try:
1167 1169
         # Does the key already exist?
1168 1170
         output = str(subprocess.check_output(
@@ -1177,8 +1179,14 @@ def get_named_key(name, caps=None, pool_list=None):
1177 1179
                 ),
1178 1180
                 'auth',
1179 1181
                 'get',
1180
-                'client.{}'.format(name),
1182
+                key_name,
1181 1183
             ]).decode('UTF-8')).strip()
1184
+        # NOTE(jamespage);
1185
+        # Apply any changes to key capabilities, dealing with
1186
+        # upgrades which requires new caps for operation.
1187
+        upgrade_key_caps(key_name,
1188
+                         caps or _default_caps,
1189
+                         pool_list)
1182 1190
         return parse_key(output)
1183 1191
     except subprocess.CalledProcessError:
1184 1192
         # Couldn't get the key, time to create it!
@@ -1194,7 +1202,7 @@ def get_named_key(name, caps=None, pool_list=None):
1194 1202
         '/var/lib/ceph/mon/ceph-{}/keyring'.format(
1195 1203
             socket.gethostname()
1196 1204
         ),
1197
-        'auth', 'get-or-create', 'client.{}'.format(name),
1205
+        'auth', 'get-or-create', key_name,
1198 1206
     ]
1199 1207
     # Add capabilities
1200 1208
     for subsystem, subcaps in caps.items():
@@ -1213,7 +1221,7 @@ def get_named_key(name, caps=None, pool_list=None):
1213 1221
                      .strip())  # IGNORE:E1103
1214 1222
 
1215 1223
 
1216
-def upgrade_key_caps(key, caps):
1224
+def upgrade_key_caps(key, caps, pool_list=None):
1217 1225
     """ Upgrade key to have capabilities caps """
1218 1226
     if not is_leader():
1219 1227
         # Not the MON leader OR not clustered
@@ -1222,6 +1230,12 @@ def upgrade_key_caps(key, caps):
1222 1230
         "sudo", "-u", ceph_user(), 'ceph', 'auth', 'caps', key
1223 1231
     ]
1224 1232
     for subsystem, subcaps in caps.items():
1233
+        if subsystem == 'osd':
1234
+            if pool_list:
1235
+                # This will output a string similar to:
1236
+                # "pool=rgw pool=rbd pool=something"
1237
+                pools = " ".join(['pool={0}'.format(i) for i in pool_list])
1238
+                subcaps[0] = subcaps[0] + " " + pools
1225 1239
         cmd.extend([subsystem, '; '.join(subcaps)])
1226 1240
     subprocess.check_call(cmd)
1227 1241
 
@@ -1453,6 +1467,11 @@ def osdize_dev(dev, osd_format, osd_journal, ignore_errors=False,
1453 1467
             ' skipping.'.format(dev))
1454 1468
         return
1455 1469
 
1470
+    if is_mapped_luks_device(dev):
1471
+        log('{} is a mapped LUKS device,'
1472
+            ' skipping.'.format(dev))
1473
+        return
1474
+
1456 1475
     if cmp_pkgrevno('ceph', '12.2.4') >= 0:
1457 1476
         cmd = _ceph_volume(dev,
1458 1477
                            osd_journal,
@@ -1664,6 +1683,29 @@ def is_active_bluestore_device(dev):
1664 1683
     return False
1665 1684
 
1666 1685
 
1686
+def is_luks_device(dev):
1687
+    """
1688
+    Determine if dev is a LUKS-formatted block device.
1689
+
1690
+    :param: dev: A full path to a block device to check for LUKS header
1691
+    presence
1692
+    :returns: boolean: indicates whether a device is used based on LUKS header.
1693
+    """
1694
+    return True if _luks_uuid(dev) else False
1695
+
1696
+
1697
+def is_mapped_luks_device(dev):
1698
+    """
1699
+    Determine if dev is a mapped LUKS device
1700
+    :param: dev: A full path to a block device to be checked
1701
+    :returns: boolean: indicates whether a device is mapped
1702
+    """
1703
+    _, dirs, _ = next(os.walk('/sys/class/block/{}/holders/'
1704
+                              .format(os.path.basename(dev))))
1705
+    is_held = len(dirs) > 0
1706
+    return is_held and is_luks_device(dev)
1707
+
1708
+
1667 1709
 def get_conf(variable):
1668 1710
     """
1669 1711
     Get the value of the given configuration variable from the

+ 43
- 0
unit_tests/test_actions_zap_disk.py View File

@@ -26,10 +26,12 @@ class ZapDiskActionTests(CharmTestCase):
26 26
                        'is_block_device',
27 27
                        'is_device_mounted',
28 28
                        'is_active_bluestore_device',
29
+                       'is_mapped_luks_device',
29 30
                        'kv'])
30 31
         self.is_device_mounted.return_value = False
31 32
         self.is_block_device.return_value = True
32 33
         self.is_active_bluestore_device.return_value = False
34
+        self.is_mapped_luks_device.return_value = False
33 35
         self.kv.return_value = self.kv
34 36
         self.hookenv.local_unit.return_value = "ceph-osd-test/0"
35 37
 
@@ -127,3 +129,44 @@ class ZapDiskActionTests(CharmTestCase):
127 129
         _zap_disk.assert_not_called()
128 130
         self.hookenv.action_fail.assert_called_with(
129 131
             "1 devices are mounted: /dev/vdb")
132
+
133
+    @mock.patch.object(zap_disk, 'zap_disk')
134
+    def test_wont_zap__mapped_luks_device(self, _zap_disk):
135
+        """Will not zap a disk that has a LUKS header"""
136
+        def side_effect(arg):
137
+            return {
138
+                'devices': '/dev/vdb',
139
+                'i-really-mean-it': True,
140
+            }.get(arg)
141
+        self.hookenv.action_get.side_effect = side_effect
142
+        self.is_active_bluestore_device.return_value = False
143
+        self.is_mapped_luks_device.return_value = True
144
+        zap_disk.zap()
145
+        _zap_disk.assert_not_called()
146
+        self.hookenv.action_fail.assert_called_with(
147
+            "1 devices are mounted: /dev/vdb")
148
+
149
+    @mock.patch.object(zap_disk, 'zap_disk')
150
+    def test_zap_luks_not_mapped(self, _zap_disk):
151
+        """Will zap disk with extra config set"""
152
+        def side_effect(arg):
153
+            return {
154
+                'devices': '/dev/vdb',
155
+                'i-really-mean-it': True,
156
+            }.get(arg)
157
+
158
+        self.is_active_bluestore_device.return_value = False
159
+        self.is_mapped_luks_device.return_value = False
160
+
161
+        self.hookenv.action_get.side_effect = side_effect
162
+        self.kv.get.return_value = ['/dev/vdb', '/dev/vdz']
163
+        zap_disk.zap()
164
+        _zap_disk.assert_called_with('/dev/vdb')
165
+        self.kv.get.assert_called_with('osd-devices', [])
166
+        self.kv.set.assert_called_with('osd-devices', ['/dev/vdz'])
167
+        self.hookenv.action_set.assert_called_with({
168
+            'message': "1 disk(s) have been zapped, to use "
169
+                       "them as OSDs, run: \njuju "
170
+                       "run-action ceph-osd-test/0 add-disk "
171
+                       "osd-devices=\"/dev/vdb\""
172
+        })

Loading…
Cancel
Save