Revision 8a69b3a8

b/Makefile.am
985 985
	  echo "TOOLSDIR = '$(toolsdir)'"; \
986 986
	  echo "GNT_SCRIPTS = [$(foreach i,$(notdir $(gnt_scripts)),'$(i)',)]"; \
987 987
	  echo "PKGLIBDIR = '$(pkglibdir)'"; \
988
	  echo "DRBD_BARRIERS = $(DRBD_BARRIERS)"; \
988
	  echo "DRBD_BARRIERS = '$(DRBD_BARRIERS)'"; \
989
	  echo "DRBD_NO_META_FLUSH = $(DRBD_NO_META_FLUSH)"; \
989 990
	  echo "SYSLOG_USAGE = '$(SYSLOG_USAGE)'"; \
990 991
	  echo "DAEMONS_GROUP = '$(DAEMONS_GROUP)'"; \
991 992
	  echo "ADMIN_GROUP = '$(ADMIN_GROUP)'"; \
b/configure.ac
208 208
# --enable-drbd-barriers
209 209
AC_ARG_ENABLE([drbd-barriers],
210 210
  [AS_HELP_STRING([--enable-drbd-barriers],
211
    [enable the DRBD barrier functionality (>= 8.0.12) (default: enabled)])],
211
    [enable by default the DRBD barriers functionality (>= 8.0.12) (default: enabled)])],
212 212
  [[if test "$enableval" != no; then
213
      DRBD_BARRIERS=True
213
      DRBD_BARRIERS=n
214
      DRBD_NO_META_FLUSH=False
214 215
    else
215
      DRBD_BARRIERS=False
216
      DRBD_BARRIERS=bfd
217
      DRBD_NO_META_FLUSH=True
216 218
    fi
217 219
  ]],
218
  [DRBD_BARRIERS=True])
220
  [DRBD_BARRIERS=n
221
   DRBD_NO_META_FLUSH=False
222
  ])
219 223
AC_SUBST(DRBD_BARRIERS, $DRBD_BARRIERS)
224
AC_SUBST(DRBD_NO_META_FLUSH, $DRBD_NO_META_FLUSH)
220 225

  
221 226
# --enable-syslog[=no/yes/only]
222 227
AC_ARG_ENABLE([syslog],
b/doc/design-resource-model.rst
724 724
|        |             |                         |as the meta LVs are  |      |
725 725
|        |             |                         |small                |      |
726 726
+--------+-------------+-------------------------+---------------------+------+
727
|drbd    |disk_barriers|What kind of barriers to |Either all enabled or|string|
727
|drbd    |disk-barriers|What kind of barriers to |Either all enabled or|string|
728 728
|        |             |*disable* for disks;     |all disabled, per    |      |
729 729
|        |             |either "n" or a string   |./configure time     |      |
730 730
|        |             |containing a subset of   |option               |      |
731 731
|        |             |"bfd"                    |                     |      |
732 732
+--------+-------------+-------------------------+---------------------+------+
733
|drbd    |meta_barriers|Whether barriers are     |Handled together with|bool  |
734
|        |             |enabled or not for the   |disk_barriers        |      |
735
|        |             |meta volume              |                     |      |
733
|drbd    |meta-barriers|Whether to disable or not|Handled together with|bool  |
734
|        |             |the barriers for the meta|disk-barriers        |      |
735
|        |             |volume                   |                     |      |
736 736
+--------+-------------+-------------------------+---------------------+------+
737
|drbd    |resync_rate  |The (static) resync rate |Hardcoded in         |int   |
737
|drbd    |resync-rate  |The (static) resync rate |Hardcoded in         |int   |
738 738
|        |             |for drbd, when using the |constants.py, not    |      |
739 739
|        |             |static syncer, in MiB/s  |changeable via Ganeti|      |
740 740
+--------+-------------+-------------------------+---------------------+------+
741
|drbd    |disk_custom  |Free-form string that    |Not supported        |string|
741
|drbd    |disk-custom  |Free-form string that    |Not supported        |string|
742 742
|        |             |will be appended to the  |                     |      |
743 743
|        |             |drbdsetup disk command   |                     |      |
744 744
|        |             |line, for custom options |                     |      |
745 745
|        |             |not supported by Ganeti  |                     |      |
746 746
|        |             |itself                   |                     |      |
747 747
+--------+-------------+-------------------------+---------------------+------+
748
|drbd    |net_custom   |Free-form string for     |Not supported        |string|
748
|drbd    |net-custom   |Free-form string for     |Not supported        |string|
749 749
|        |             |custom net setup options |                     |      |
750 750
+--------+-------------+-------------------------+---------------------+------+
751 751

  
b/lib/bdev.py
1103 1103
  # timeout constants
1104 1104
  _NET_RECONFIG_TIMEOUT = 60
1105 1105

  
1106
  # command line options for barriers
1107
  _DISABLE_DISK_OPTION = "--no-disk-barrier"  # -a
1108
  _DISABLE_DRAIN_OPTION = "--no-disk-drain"   # -D
1109
  _DISABLE_FLUSH_OPTION = "--no-disk-flushes" # -i
1110
  _DISABLE_META_FLUSH_OPTION = "--no-md-flushes"  # -m
1111

  
1106 1112
  def __init__(self, unique_id, children, size, params):
1107 1113
    if children and children.count(None) > 0:
1108 1114
      children = []
......
1344 1350
              info["remote_addr"] == (self._rhost, self._rport))
1345 1351
    return retval
1346 1352

  
1347
  @classmethod
1348
  def _AssembleLocal(cls, minor, backend, meta, size):
1353
  def _AssembleLocal(self, minor, backend, meta, size):
1349 1354
    """Configure the local part of a DRBD device.
1350 1355

  
1351 1356
    """
1352
    args = ["drbdsetup", cls._DevPath(minor), "disk",
1357
    args = ["drbdsetup", self._DevPath(minor), "disk",
1353 1358
            backend, meta, "0",
1354 1359
            "-e", "detach",
1355 1360
            "--create-device"]
1356 1361
    if size:
1357 1362
      args.extend(["-d", "%sm" % size])
1358
    if not constants.DRBD_BARRIERS: # disable barriers, if configured so
1359
      version = cls._GetVersion(cls._GetProcData())
1360
      # various DRBD versions support different disk barrier options;
1361
      # what we aim here is to revert back to the 'drain' method of
1362
      # disk flushes and to disable metadata barriers, in effect going
1363
      # back to pre-8.0.7 behaviour
1364
      vmaj = version["k_major"]
1365
      vmin = version["k_minor"]
1366
      vrel = version["k_point"]
1367
      assert vmaj == 8
1368
      if vmin == 0: # 8.0.x
1369
        if vrel >= 12:
1370
          args.extend(["-i", "-m"])
1371
      elif vmin == 2: # 8.2.x
1372
        if vrel >= 7:
1373
          args.extend(["-i", "-m"])
1374
      elif vmaj >= 3: # 8.3.x or newer
1375
        args.extend(["-i", "-a", "m"])
1363

  
1364
    version = self._GetVersion(self._GetProcData())
1365
    vmaj = version["k_major"]
1366
    vmin = version["k_minor"]
1367
    vrel = version["k_point"]
1368

  
1369
    barrier_args = \
1370
      self._ComputeDiskBarrierArgs(vmaj, vmin, vrel,
1371
                                   self.params[constants.BARRIERS],
1372
                                   self.params[constants.NO_META_FLUSH])
1373
    args.extend(barrier_args)
1374

  
1376 1375
    result = utils.RunCmd(args)
1377 1376
    if result.failed:
1378 1377
      _ThrowError("drbd%d: can't attach local disk: %s", minor, result.output)
1379 1378

  
1379
  @classmethod
1380
  def _ComputeDiskBarrierArgs(cls, vmaj, vmin, vrel, disabled_barriers,
1381
      disable_meta_flush):
1382
    """Compute the DRBD command line parameters for disk barriers
1383

  
1384
    Returns a list of the disk barrier parameters as requested via the
1385
    disabled_barriers and disable_meta_flush arguments, and according to the
1386
    supported ones in the DRBD version vmaj.vmin.vrel
1387

  
1388
    If the desired option is unsupported, raises errors.BlockDeviceError.
1389

  
1390
    """
1391
    disabled_barriers_set = frozenset(disabled_barriers)
1392
    if not disabled_barriers_set in constants.DRBD_VALID_BARRIER_OPT:
1393
      raise errors.BlockDeviceError("%s is not a valid option set for DRBD"
1394
                                    " barriers" % disabled_barriers)
1395

  
1396
    args = []
1397

  
1398
    # The following code assumes DRBD 8.x, with x < 4 and x != 1 (DRBD 8.1.x
1399
    # does not exist)
1400
    if not vmaj == 8 and vmin in (0, 2, 3):
1401
      raise errors.BlockDeviceError("Unsupported DRBD version: %d.%d.%d" %
1402
                                    (vmaj, vmin, vrel))
1403

  
1404
    def _AppendOrRaise(option, min_version):
1405
      """Helper for DRBD options"""
1406
      if min_version is not None and vrel >= min_version:
1407
        args.append(option)
1408
      else:
1409
        raise errors.BlockDeviceError("Could not use the option %s as the"
1410
                                      " DRBD version %d.%d.%d does not support"
1411
                                      " it." % (option, vmaj, vmin, vrel))
1412

  
1413
    # the minimum version for each feature is encoded via pairs of (minor
1414
    # version -> x) where x is version in which support for the option was
1415
    # introduced.
1416
    meta_flush_supported = disk_flush_supported = {
1417
      0: 12,
1418
      2: 7,
1419
      3: 0,
1420
      }
1421

  
1422
    disk_drain_supported = {
1423
      2: 7,
1424
      3: 0,
1425
      }
1426

  
1427
    disk_barriers_supported = {
1428
      3: 0,
1429
      }
1430

  
1431
    # meta flushes
1432
    if disable_meta_flush:
1433
      _AppendOrRaise(cls._DISABLE_META_FLUSH_OPTION,
1434
                     meta_flush_supported.get(vmin, None))
1435

  
1436
    # disk flushes
1437
    if constants.DRBD_B_DISK_FLUSH in disabled_barriers_set:
1438
      _AppendOrRaise(cls._DISABLE_FLUSH_OPTION,
1439
                     disk_flush_supported.get(vmin, None))
1440

  
1441
    # disk drain
1442
    if constants.DRBD_B_DISK_DRAIN in disabled_barriers_set:
1443
      _AppendOrRaise(cls._DISABLE_DRAIN_OPTION,
1444
                     disk_drain_supported.get(vmin, None))
1445

  
1446
    # disk barriers
1447
    if constants.DRBD_B_DISK_BARRIERS in disabled_barriers_set:
1448
      _AppendOrRaise(cls._DISABLE_DISK_OPTION,
1449
                     disk_barriers_supported.get(vmin, None))
1450

  
1451
    return args
1452

  
1380 1453
  def _AssembleNet(self, minor, net_info, protocol,
1381 1454
                   dual_pri=False, hmac=None, secret=None):
1382 1455
    """Configure the network part of the device.
b/lib/cmdlib.py
8058 8058
  dt_params = disk_params[disk_template]
8059 8059
  if disk_template == constants.DT_DRBD8:
8060 8060
    drbd_params = {
8061
      constants.RESYNC_RATE: dt_params[constants.DRBD_RESYNC_RATE]
8061
      constants.RESYNC_RATE: dt_params[constants.DRBD_RESYNC_RATE],
8062
      constants.BARRIERS: dt_params[constants.DRBD_DISK_BARRIERS],
8063
      constants.NO_META_FLUSH: dt_params[constants.DRBD_META_BARRIERS],
8062 8064
      }
8063 8065

  
8064 8066
    drbd_params = \
b/lib/constants.py
472 472
# drbd constants
473 473
DRBD_HMAC_ALG = "md5"
474 474
DRBD_NET_PROTOCOL = "C"
475
DRBD_BARRIERS = _autoconf.DRBD_BARRIERS
475

  
476
# drbd barrier types
477
DRBD_B_NONE = "n"
478
DRBD_B_DISK_BARRIERS = "b"
479
DRBD_B_DISK_DRAIN = "d"
480
DRBD_B_DISK_FLUSH = "f"
481

  
482
# Valid barrier combinations: "n" or any non-null subset of "bfd"
483
DRBD_VALID_BARRIER_OPT = frozenset([
484
  frozenset([DRBD_B_NONE]),
485
  frozenset([DRBD_B_DISK_BARRIERS]),
486
  frozenset([DRBD_B_DISK_DRAIN]),
487
  frozenset([DRBD_B_DISK_FLUSH]),
488
  frozenset([DRBD_B_DISK_DRAIN, DRBD_B_DISK_FLUSH]),
489
  frozenset([DRBD_B_DISK_DRAIN, DRBD_B_DISK_FLUSH]),
490
  frozenset([DRBD_B_DISK_BARRIERS, DRBD_B_DISK_DRAIN]),
491
  frozenset([DRBD_B_DISK_BARRIERS, DRBD_B_DISK_FLUSH]),
492
  frozenset([DRBD_B_DISK_BARRIERS, DRBD_B_DISK_FLUSH, DRBD_B_DISK_DRAIN]),
493
  ])
476 494

  
477 495
# file backend driver
478 496
FD_LOOP = "loop"
......
898 916
# Logical Disks parameters
899 917
RESYNC_RATE = "resync-rate"
900 918
STRIPES = "stripes"
919
BARRIERS = "disabled-barriers"
920
NO_META_FLUSH = "disable-meta-flush"
901 921
DISK_LD_TYPES = {
902 922
  RESYNC_RATE: VTYPE_INT,
903 923
  STRIPES: VTYPE_INT,
924
  BARRIERS: VTYPE_STRING,
925
  NO_META_FLUSH: VTYPE_BOOL,
904 926
  }
905 927
DISK_LD_PARAMETERS = frozenset(DISK_LD_TYPES.keys())
906 928

  
......
908 930
DRBD_RESYNC_RATE = "resync-rate"
909 931
DRBD_DATA_STRIPES = "data-stripes"
910 932
DRBD_META_STRIPES = "meta-stripes"
933
DRBD_DISK_BARRIERS = "disk-barriers"
934
DRBD_META_BARRIERS = "meta-barriers"
911 935
LV_STRIPES = "stripes"
912 936
DISK_DT_TYPES = {
913 937
  DRBD_RESYNC_RATE: VTYPE_INT,
914 938
  DRBD_DATA_STRIPES: VTYPE_INT,
915 939
  DRBD_META_STRIPES: VTYPE_INT,
940
  DRBD_DISK_BARRIERS: VTYPE_STRING,
941
  DRBD_META_BARRIERS: VTYPE_BOOL,
916 942
  LV_STRIPES: VTYPE_INT,
917 943
  }
918 944

  
......
1683 1709
DISK_LD_DEFAULTS = {
1684 1710
  LD_DRBD8: {
1685 1711
    RESYNC_RATE: CLASSIC_DRBD_SYNC_SPEED,
1712
    BARRIERS: _autoconf.DRBD_BARRIERS,
1713
    NO_META_FLUSH: _autoconf.DRBD_NO_META_FLUSH,
1686 1714
    },
1687 1715
  LD_LV: {
1688 1716
    STRIPES: _autoconf.LVM_STRIPECOUNT
......
1701 1729
    DRBD_RESYNC_RATE: DISK_LD_DEFAULTS[LD_DRBD8][RESYNC_RATE],
1702 1730
    DRBD_DATA_STRIPES: DISK_LD_DEFAULTS[LD_LV][STRIPES],
1703 1731
    DRBD_META_STRIPES: DISK_LD_DEFAULTS[LD_LV][STRIPES],
1732
    DRBD_DISK_BARRIERS: DISK_LD_DEFAULTS[LD_DRBD8][BARRIERS],
1733
    DRBD_META_BARRIERS: DISK_LD_DEFAULTS[LD_DRBD8][NO_META_FLUSH],
1704 1734
    },
1705 1735
  DT_DISKLESS: {
1706 1736
    },
b/test/ganeti.bdev_unittest.py
27 27

  
28 28
from ganeti import bdev
29 29
from ganeti import errors
30
from ganeti import constants
30 31

  
31 32
import testutils
32 33

  
......
156 157
                     "remote_addr" not in result),
157 158
                    "Should not find network info")
158 159

  
160
  def testBarriersOptions(self):
161
    """Test class method that generates drbdsetup options for disk barriers"""
162
    # Tests that should fail because of wrong version/options combinations
163
    should_fail = [
164
      (8, 0, 12, "bfd", True),
165
      (8, 0, 12, "fd", False),
166
      (8, 0, 12, "b", True),
167
      (8, 2, 7, "bfd", True),
168
      (8, 2, 7, "b", True)
169
    ]
170

  
171
    for vmaj, vmin, vrel, opts, meta in should_fail:
172
      self.assertRaises(errors.BlockDeviceError,
173
                        bdev.DRBD8._ComputeDiskBarrierArgs,
174
                        vmaj, vmin, vrel, opts, meta)
175

  
176
    # get the valid options from the frozenset(frozenset()) in constants.
177
    valid_options = [list(x)[0] for x in constants.DRBD_VALID_BARRIER_OPT]
178

  
179
    # Versions that do not support anything
180
    for vmaj, vmin, vrel in ((8, 0, 0), (8, 0, 11), (8, 2, 6)):
181
      for opts in valid_options:
182
        self.assertRaises(errors.BlockDeviceError,
183
                          bdev.DRBD8._ComputeDiskBarrierArgs,
184
                          vmaj, vmin, vrel, opts, True)
185

  
186
    # Versions with partial support (testing only options that are supported)
187
    tests = [
188
      (8, 0, 12, "n", False, []),
189
      (8, 0, 12, "n", True, ["--no-md-flushes"]),
190
      (8, 2, 7, "n", False, []),
191
      (8, 2, 7, "fd", False, ["--no-disk-flushes", "--no-disk-drain"]),
192
      (8, 0, 12, "n", True, ["--no-md-flushes"]),
193
      ]
194

  
195
    # Versions that support everything
196
    for vmaj, vmin, vrel in ((8, 3, 0), (8, 3, 12)):
197
      tests.append((vmaj, vmin, vrel, "bfd", True,
198
                    ["--no-disk-barrier", "--no-disk-drain",
199
                     "--no-disk-flushes", "--no-md-flushes"]))
200
      tests.append((vmaj, vmin, vrel, "n", False, []))
201
      tests.append((vmaj, vmin, vrel, "b", True,
202
                    ["--no-disk-barrier", "--no-md-flushes"]))
203
      tests.append((vmaj, vmin, vrel, "fd", False,
204
                    ["--no-disk-flushes", "--no-disk-drain"]))
205
      tests.append((vmaj, vmin, vrel, "n", True, ["--no-md-flushes"]))
206

  
207
    # Test execution
208
    for test in tests:
209
      vmaj, vmin, vrel, disabled_barriers, disable_meta_flush, expected = test
210
      args = \
211
        bdev.DRBD8._ComputeDiskBarrierArgs(vmaj, vmin, vrel,
212
                                           disabled_barriers,
213
                                           disable_meta_flush)
214
      self.failUnless(set(args) == set(expected),
215
                      "For test %s, got wrong results %s" % (test, args))
216

  
217
    # Unsupported or invalid versions
218
    for vmaj, vmin, vrel in ((0, 7, 25), (9, 0, 0), (7, 0, 0), (8, 4, 0)):
219
      self.assertRaises(errors.BlockDeviceError,
220
                        bdev.DRBD8._ComputeDiskBarrierArgs,
221
                        vmaj, vmin, vrel, "n", True)
222

  
223
    # Invalid options
224
    for option in ("", "c", "whatever", "nbdfc", "nf"):
225
      self.assertRaises(errors.BlockDeviceError,
226
                        bdev.DRBD8._ComputeDiskBarrierArgs,
227
                        8, 3, 11, option, True)
228

  
159 229

  
160 230
class TestDRBD8Status(testutils.GanetiTestCase):
161 231
  """Testing case for DRBD8 /proc status"""

Also available in: Unified diff