Revision 09a78e1c

b/Makefile.am
320 320
	lib/block/bdev.py \
321 321
	lib/block/base.py \
322 322
	lib/block/drbd.py \
323
	lib/block/drbd_info.py
323
	lib/block/drbd_info.py \
324
	lib/block/drbd_cmdgen.py
324 325

  
325 326
rapi_PYTHON = \
326 327
	lib/rapi/__init__.py \
b/lib/block/drbd.py
23 23

  
24 24
import errno
25 25
import logging
26
import shlex
27 26
import time
28 27

  
29 28
from ganeti import constants
......
35 34
from ganeti.block.drbd_info import DRBD8Info
36 35
from ganeti.block.drbd_info import DRBD83ShowInfo
37 36
from ganeti.block.drbd_info import DRBD84ShowInfo
37
from ganeti.block import drbd_cmdgen
38 38

  
39 39

  
40 40
# Size of reads in _CanReadDevice
......
64 64
  # timeout constants
65 65
  _NET_RECONFIG_TIMEOUT = 60
66 66

  
67
  # command line options for barriers
68
  _DISABLE_DISK_OPTION = "--no-disk-barrier"  # -a
69
  _DISABLE_DRAIN_OPTION = "--no-disk-drain"   # -D
70
  _DISABLE_FLUSH_OPTION = "--no-disk-flushes" # -i
71
  _DISABLE_META_FLUSH_OPTION = "--no-md-flushes"  # -m
72

  
73 67
  def __init__(self, unique_id, children, size, params):
74 68
    if children and children.count(None) > 0:
75 69
      children = []
......
96 90

  
97 91
    if version["k_minor"] <= 3:
98 92
      self._show_info_cls = DRBD83ShowInfo
93
      self._cmd_gen = drbd_cmdgen.DRBD83CmdGenerator(drbd_info)
99 94
    else:
100 95
      self._show_info_cls = DRBD84ShowInfo
96
      # FIXME: use proper command generator!
97
      self._cmd_gen = None
101 98

  
102 99
    if (self._lhost is not None and self._lhost == self._rhost and
103 100
            self._lport == self._rport):
......
230 227

  
231 228
    return highest + 1
232 229

  
233
  @classmethod
234
  def _GetShowData(cls, minor):
230
  def _GetShowData(self, minor):
235 231
    """Return the `drbdsetup show` data for a minor.
236 232

  
237 233
    """
238
    result = utils.RunCmd(["drbdsetup", cls._DevPath(minor), "show"])
234
    result = utils.RunCmd(self._cmd_gen.GenShowCmd(minor))
239 235
    if result.failed:
240 236
      logging.error("Can't display the drbd config: %s - %s",
241 237
                    result.fail_reason, result.output)
......
303 299
    """Configure the local part of a DRBD device.
304 300

  
305 301
    """
306
    args = ["drbdsetup", self._DevPath(minor), "disk",
307
            backend, meta, "0",
308
            "-e", "detach",
309
            "--create-device"]
310
    if size:
311
      args.extend(["-d", "%sm" % size])
312

  
313
    drbd_info = DRBD8Info.CreateFromFile()
314
    version = drbd_info.GetVersion()
315
    vmaj = version["k_major"]
316
    vmin = version["k_minor"]
317
    vrel = version["k_point"]
318

  
319
    barrier_args = \
320
      self._ComputeDiskBarrierArgs(vmaj, vmin, vrel,
321
                                   self.params[constants.LDP_BARRIERS],
322
                                   self.params[constants.LDP_NO_META_FLUSH])
323
    args.extend(barrier_args)
324

  
325
    if self.params[constants.LDP_DISK_CUSTOM]:
326
      args.extend(shlex.split(self.params[constants.LDP_DISK_CUSTOM]))
327

  
328
    result = utils.RunCmd(args)
329
    if result.failed:
330
      base.ThrowError("drbd%d: can't attach local disk: %s",
331
                      minor, result.output)
332

  
333
  @classmethod
334
  def _ComputeDiskBarrierArgs(cls, vmaj, vmin, vrel, disabled_barriers,
335
                              disable_meta_flush):
336
    """Compute the DRBD command line parameters for disk barriers
302
    cmds = self._cmd_gen.GenLocalInitCmds(minor, backend, meta,
303
                                          size, self.params)
337 304

  
338
    Returns a list of the disk barrier parameters as requested via the
339
    disabled_barriers and disable_meta_flush arguments, and according to the
340
    supported ones in the DRBD version vmaj.vmin.vrel
341

  
342
    If the desired option is unsupported, raises errors.BlockDeviceError.
343

  
344
    """
345
    disabled_barriers_set = frozenset(disabled_barriers)
346
    if not disabled_barriers_set in constants.DRBD_VALID_BARRIER_OPT:
347
      raise errors.BlockDeviceError("%s is not a valid option set for DRBD"
348
                                    " barriers" % disabled_barriers)
349

  
350
    args = []
351

  
352
    # The following code assumes DRBD 8.x, with x < 4 and x != 1 (DRBD 8.1.x
353
    # does not exist)
354
    if not vmaj == 8 and vmin in (0, 2, 3):
355
      raise errors.BlockDeviceError("Unsupported DRBD version: %d.%d.%d" %
356
                                    (vmaj, vmin, vrel))
357

  
358
    def _AppendOrRaise(option, min_version):
359
      """Helper for DRBD options"""
360
      if min_version is not None and vrel >= min_version:
361
        args.append(option)
362
      else:
363
        raise errors.BlockDeviceError("Could not use the option %s as the"
364
                                      " DRBD version %d.%d.%d does not support"
365
                                      " it." % (option, vmaj, vmin, vrel))
366

  
367
    # the minimum version for each feature is encoded via pairs of (minor
368
    # version -> x) where x is version in which support for the option was
369
    # introduced.
370
    meta_flush_supported = disk_flush_supported = {
371
      0: 12,
372
      2: 7,
373
      3: 0,
374
      }
375

  
376
    disk_drain_supported = {
377
      2: 7,
378
      3: 0,
379
      }
380

  
381
    disk_barriers_supported = {
382
      3: 0,
383
      }
384

  
385
    # meta flushes
386
    if disable_meta_flush:
387
      _AppendOrRaise(cls._DISABLE_META_FLUSH_OPTION,
388
                     meta_flush_supported.get(vmin, None))
389

  
390
    # disk flushes
391
    if constants.DRBD_B_DISK_FLUSH in disabled_barriers_set:
392
      _AppendOrRaise(cls._DISABLE_FLUSH_OPTION,
393
                     disk_flush_supported.get(vmin, None))
394

  
395
    # disk drain
396
    if constants.DRBD_B_DISK_DRAIN in disabled_barriers_set:
397
      _AppendOrRaise(cls._DISABLE_DRAIN_OPTION,
398
                     disk_drain_supported.get(vmin, None))
399

  
400
    # disk barriers
401
    if constants.DRBD_B_DISK_BARRIERS in disabled_barriers_set:
402
      _AppendOrRaise(cls._DISABLE_DISK_OPTION,
403
                     disk_barriers_supported.get(vmin, None))
404

  
405
    return args
305
    for cmd in cmds:
306
      result = utils.RunCmd(cmd)
307
      if result.failed:
308
        base.ThrowError("drbd%d: can't attach local disk: %s",
309
                        minor, result.output)
406 310

  
407 311
  def _AssembleNet(self, minor, net_info, protocol,
408 312
                   dual_pri=False, hmac=None, secret=None):
......
440 344
    else:
441 345
      base.ThrowError("drbd%d: Invalid ip %s" % (minor, lhost))
442 346

  
443
    args = ["drbdsetup", self._DevPath(minor), "net",
444
            "%s:%s:%s" % (family, lhost, lport),
445
            "%s:%s:%s" % (family, rhost, rport), protocol,
446
            "-A", "discard-zero-changes",
447
            "-B", "consensus",
448
            "--create-device",
449
            ]
450
    if dual_pri:
451
      args.append("-m")
452
    if hmac and secret:
453
      args.extend(["-a", hmac, "-x", secret])
454

  
455
    if self.params[constants.LDP_NET_CUSTOM]:
456
      args.extend(shlex.split(self.params[constants.LDP_NET_CUSTOM]))
457

  
458
    result = utils.RunCmd(args)
347
    cmd = self._cmd_gen.GenNetInitCmd(minor, family, lhost, lport,
348
                                      rhost, rport, protocol,
349
                                      dual_pri, hmac, secret, self.params)
350

  
351
    result = utils.RunCmd(cmd)
459 352
    if result.failed:
460 353
      base.ThrowError("drbd%d: can't setup network: %s - %s",
461 354
                      minor, result.fail_reason, result.output)
......
539 432
    @return: a list of error messages
540 433

  
541 434
    """
542

  
543
    args = ["drbdsetup", self._DevPath(minor), "syncer"]
544
    if params[constants.LDP_DYNAMIC_RESYNC]:
545
      drbd_info = DRBD8Info.CreateFromFile()
546
      version = drbd_info.GetVersion()
547
      vmin = version["k_minor"]
548
      vrel = version["k_point"]
549

  
550
      # By definition we are using 8.x, so just check the rest of the version
551
      # number
552
      if vmin != 3 or vrel < 9:
553
        msg = ("The current DRBD version (8.%d.%d) does not support the "
554
               "dynamic resync speed controller" % (vmin, vrel))
555
        logging.error(msg)
556
        return [msg]
557

  
558
      if params[constants.LDP_PLAN_AHEAD] == 0:
559
        msg = ("A value of 0 for c-plan-ahead disables the dynamic sync speed"
560
               " controller at DRBD level. If you want to disable it, please"
561
               " set the dynamic-resync disk parameter to False.")
562
        logging.error(msg)
563
        return [msg]
564

  
565
      # add the c-* parameters to args
566
      args.extend(["--c-plan-ahead", params[constants.LDP_PLAN_AHEAD],
567
                   "--c-fill-target", params[constants.LDP_FILL_TARGET],
568
                   "--c-delay-target", params[constants.LDP_DELAY_TARGET],
569
                   "--c-max-rate", params[constants.LDP_MAX_RATE],
570
                   "--c-min-rate", params[constants.LDP_MIN_RATE],
571
                   ])
572

  
573
    else:
574
      args.extend(["-r", "%d" % params[constants.LDP_RESYNC_RATE]])
575

  
576
    args.append("--create-device")
577
    result = utils.RunCmd(args)
435
    cmd = self._cmd_gen.GenSyncParamsCmd(minor, params)
436
    result = utils.RunCmd(cmd)
578 437
    if result.failed:
579 438
      msg = ("Can't change syncer rate: %s - %s" %
580 439
             (result.fail_reason, result.output))
......
616 475
    children_result = super(DRBD8, self).PauseResumeSync(pause)
617 476

  
618 477
    if pause:
619
      cmd = "pause-sync"
478
      cmd = self._cmd_gen.GenPauseSyncCmd(self.minor)
620 479
    else:
621
      cmd = "resume-sync"
480
      cmd = self._cmd_gen.GenResumeSyncCmd(self.minor)
622 481

  
623
    result = utils.RunCmd(["drbdsetup", self.dev_path, cmd])
482
    result = utils.RunCmd(cmd)
624 483
    if result.failed:
625 484
      logging.error("Can't %s: %s - %s", cmd,
626 485
                    result.fail_reason, result.output)
......
689 548
    if self.minor is None and not self.Attach():
690 549
      logging.error("DRBD cannot attach to a device during open")
691 550
      return False
692
    cmd = ["drbdsetup", self.dev_path, "primary"]
693
    if force:
694
      cmd.append("-o")
551

  
552
    cmd = self._cmd_gen.GenPrimaryCmd(self.minor, force)
553

  
695 554
    result = utils.RunCmd(cmd)
696 555
    if result.failed:
697 556
      base.ThrowError("drbd%d: can't make drbd device primary: %s", self.minor,
......
705 564
    """
706 565
    if self.minor is None and not self.Attach():
707 566
      base.ThrowError("drbd%d: can't Attach() in Close()", self._aminor)
708
    result = utils.RunCmd(["drbdsetup", self.dev_path, "secondary"])
567
    cmd = self._cmd_gen.GenSecondaryCmd(self.minor)
568
    result = utils.RunCmd(cmd)
709 569
    if result.failed:
710 570
      base.ThrowError("drbd%d: can't switch drbd device to secondary: %s",
711 571
                      self.minor, result.output)
......
938 798
                        hmac=constants.DRBD_HMAC_ALG, secret=self._secret)
939 799
    self._SetFromMinor(minor)
940 800

  
941
  @classmethod
942
  def _ShutdownLocal(cls, minor):
801
  def _ShutdownLocal(self, minor):
943 802
    """Detach from the local device.
944 803

  
945 804
    I/Os will continue to be served from the remote device. If we
946 805
    don't have a remote device, this operation will fail.
947 806

  
948 807
    """
949
    result = utils.RunCmd(["drbdsetup", cls._DevPath(minor), "detach"])
808
    cmd = self._cmd_gen.GenDetachCmd(minor)
809
    result = utils.RunCmd(cmd)
950 810
    if result.failed:
951 811
      base.ThrowError("drbd%d: can't detach local disk: %s",
952 812
                      minor, result.output)
953 813

  
954
  @classmethod
955
  def _ShutdownNet(cls, minor):
814
  def _ShutdownNet(self, minor):
956 815
    """Disconnect from the remote peer.
957 816

  
958 817
    This fails if we don't have a local device.
959 818

  
960 819
    """
961
    result = utils.RunCmd(["drbdsetup", cls._DevPath(minor), "disconnect"])
820
    cmd = self._cmd_gen.GenDisconnectCmd(minor)
821
    result = utils.RunCmd(cmd)
962 822
    if result.failed:
963 823
      base.ThrowError("drbd%d: can't shutdown network: %s",
964 824
                      minor, result.output)
......
970 830
    This will, of course, fail if the device is in use.
971 831

  
972 832
    """
973
    result = utils.RunCmd(["drbdsetup", cls._DevPath(minor), "down"])
833
    # FIXME: _ShutdownAll, despite being private, is used in nodemaint.py.
834
    # That's why we can't make it an instance method, which in turn requires
835
    # us to duplicate code here (from __init__). This should be proberly fixed.
836
    drbd_info = DRBD8Info.CreateFromFile()
837
    if drbd_info.GetVersion()["k_minor"] <= 3:
838
      cmd_gen = drbd_cmdgen.DRBD83CmdGenerator(drbd_info)
839
    else:
840
      # FIXME: use proper command generator!
841
      cmd_gen = None
842

  
843
    cmd = cmd_gen.GenDownCmd(minor)
844
    result = utils.RunCmd(cmd)
974 845
    if result.failed:
975 846
      base.ThrowError("drbd%d: can't shutdown drbd device: %s",
976 847
                      minor, result.output)
......
1048 919
      # DRBD does not support dry-run mode and is not backing storage,
1049 920
      # so we'll return here
1050 921
      return
1051
    result = utils.RunCmd(["drbdsetup", self.dev_path, "resize", "-s",
1052
                           "%dm" % (self.size + amount)])
922
    cmd = self._cmd_gen.GenResizeCmd(self.minor, self.size + amount)
923
    result = utils.RunCmd(cmd)
1053 924
    if result.failed:
1054 925
      base.ThrowError("drbd%d: resize failed: %s", self.minor, result.output)
1055 926

  
b/lib/block/drbd_cmdgen.py
1
#
2
#
3

  
4
# Copyright (C) 2006, 2007, 2010, 2011, 2012, 2013 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

  
21

  
22
"""DRBD command generating classes"""
23

  
24
import logging
25
import shlex
26

  
27
from ganeti import constants
28
from ganeti import errors
29

  
30

  
31
class DRBD83CmdGenerator(object):
32
  """Generates drbdsetup commands suited for the DRBD <= 8.3 syntax
33

  
34
  """
35
  # command line options for barriers
36
  _DISABLE_DISK_OPTION = "--no-disk-barrier"  # -a
37
  _DISABLE_DRAIN_OPTION = "--no-disk-drain"   # -D
38
  _DISABLE_FLUSH_OPTION = "--no-disk-flushes" # -i
39
  _DISABLE_META_FLUSH_OPTION = "--no-md-flushes"  # -m
40

  
41
  def __init__(self, drbd_info):
42
    self._drbd_info = drbd_info
43

  
44
  def GenShowCmd(self, minor):
45
    return ["drbdsetup", self._DevPath(minor), "show"]
46

  
47
  def GenLocalInitCmds(self, minor, data_dev, meta_dev, size_mb, params):
48
    args = ["drbdsetup", self._DevPath(minor), "disk",
49
            data_dev, meta_dev, "0",
50
            "-e", "detach",
51
            "--create-device"]
52
    if size_mb:
53
      args.extend(["-d", "%sm" % size_mb])
54

  
55
    version = self._drbd_info.GetVersion()
56
    vmaj = version["k_major"]
57
    vmin = version["k_minor"]
58
    vrel = version["k_point"]
59

  
60
    barrier_args = \
61
      self._ComputeDiskBarrierArgs(vmaj, vmin, vrel,
62
                                   params[constants.LDP_BARRIERS],
63
                                   params[constants.LDP_NO_META_FLUSH])
64
    args.extend(barrier_args)
65

  
66
    if params[constants.LDP_DISK_CUSTOM]:
67
      args.extend(shlex.split(params[constants.LDP_DISK_CUSTOM]))
68

  
69
    return [args]
70

  
71
  def GenNetInitCmd(self, minor, family, lhost, lport, rhost, rport, protocol,
72
                    dual_pri, hmac, secret, params):
73
    args = ["drbdsetup", self._DevPath(minor), "net",
74
            "%s:%s:%s" % (family, lhost, lport),
75
            "%s:%s:%s" % (family, rhost, rport), protocol,
76
            "-A", "discard-zero-changes",
77
            "-B", "consensus",
78
            "--create-device",
79
            ]
80
    if dual_pri:
81
      args.append("-m")
82
    if hmac and secret:
83
      args.extend(["-a", hmac, "-x", secret])
84

  
85
    if params[constants.LDP_NET_CUSTOM]:
86
      args.extend(shlex.split(params[constants.LDP_NET_CUSTOM]))
87

  
88
    return args
89

  
90
  def GenSyncParamsCmd(self, minor, params):
91
    args = ["drbdsetup", self._DevPath(minor), "syncer"]
92
    if params[constants.LDP_DYNAMIC_RESYNC]:
93
      version = self._drbd_info.GetVersion()
94
      vmin = version["k_minor"]
95
      vrel = version["k_point"]
96

  
97
      # By definition we are using 8.x, so just check the rest of the version
98
      # number
99
      if vmin != 3 or vrel < 9:
100
        msg = ("The current DRBD version (8.%d.%d) does not support the "
101
               "dynamic resync speed controller" % (vmin, vrel))
102
        logging.error(msg)
103
        return [msg]
104

  
105
      if params[constants.LDP_PLAN_AHEAD] == 0:
106
        msg = ("A value of 0 for c-plan-ahead disables the dynamic sync speed"
107
               " controller at DRBD level. If you want to disable it, please"
108
               " set the dynamic-resync disk parameter to False.")
109
        logging.error(msg)
110
        return [msg]
111

  
112
      # add the c-* parameters to args
113
      args.extend(["--c-plan-ahead", params[constants.LDP_PLAN_AHEAD],
114
                   "--c-fill-target", params[constants.LDP_FILL_TARGET],
115
                   "--c-delay-target", params[constants.LDP_DELAY_TARGET],
116
                   "--c-max-rate", params[constants.LDP_MAX_RATE],
117
                   "--c-min-rate", params[constants.LDP_MIN_RATE],
118
                   ])
119

  
120
    else:
121
      args.extend(["-r", "%d" % params[constants.LDP_RESYNC_RATE]])
122

  
123
    args.append("--create-device")
124

  
125
    return args
126

  
127
  def GenPauseSyncCmd(self, minor):
128
    return ["drbdsetup", self._DevPath(minor), "pause-sync"]
129

  
130
  def GenResumeSyncCmd(self, minor):
131
    return ["drbdsetup", self._DevPath(minor), "resume-sync"]
132

  
133
  def GenPrimaryCmd(self, minor, force):
134
    cmd = ["drbdsetup", self._DevPath(minor), "primary"]
135

  
136
    if force:
137
      cmd.append("-o")
138

  
139
    return cmd
140

  
141
  def GenSecondaryCmd(self, minor):
142
    return ["drbdsetup", self._DevPath(minor), "secondary"]
143

  
144
  def GenDetachCmd(self, minor):
145
    return ["drbdsetup", self._DevPath(minor), "detach"]
146

  
147
  def GenDisconnectCmd(self, minor):
148
    return ["drbdsetup", self._DevPath(minor), "disconnect"]
149

  
150
  def GenDownCmd(self, minor):
151
    return ["drbdsetup", self._DevPath(minor), "down"]
152

  
153
  def GenResizeCmd(self, minor, size_mb):
154
    return ["drbdsetup", self._DevPath(minor), "resize", "-s", "%dm" % size_mb]
155

  
156
  @staticmethod
157
  def _DevPath(minor):
158
    """Return the path to a drbd device for a given minor.
159

  
160
    """
161
    return "/dev/drbd%d" % minor
162

  
163
  @classmethod
164
  def _ComputeDiskBarrierArgs(cls, vmaj, vmin, vrel, disabled_barriers,
165
                              disable_meta_flush):
166
    """Compute the DRBD command line parameters for disk barriers
167

  
168
    Returns a list of the disk barrier parameters as requested via the
169
    disabled_barriers and disable_meta_flush arguments, and according to the
170
    supported ones in the DRBD version vmaj.vmin.vrel
171

  
172
    If the desired option is unsupported, raises errors.BlockDeviceError.
173

  
174
    """
175
    disabled_barriers_set = frozenset(disabled_barriers)
176
    if not disabled_barriers_set in constants.DRBD_VALID_BARRIER_OPT:
177
      raise errors.BlockDeviceError("%s is not a valid option set for DRBD"
178
                                    " barriers" % disabled_barriers)
179

  
180
    args = []
181

  
182
    # The following code assumes DRBD 8.x, with x < 4 and x != 1 (DRBD 8.1.x
183
    # does not exist)
184
    if not vmaj == 8 and vmin in (0, 2, 3):
185
      raise errors.BlockDeviceError("Unsupported DRBD version: %d.%d.%d" %
186
                                    (vmaj, vmin, vrel))
187

  
188
    def _AppendOrRaise(option, min_version):
189
      """Helper for DRBD options"""
190
      if min_version is not None and vrel >= min_version:
191
        args.append(option)
192
      else:
193
        raise errors.BlockDeviceError("Could not use the option %s as the"
194
                                      " DRBD version %d.%d.%d does not support"
195
                                      " it." % (option, vmaj, vmin, vrel))
196

  
197
    # the minimum version for each feature is encoded via pairs of (minor
198
    # version -> x) where x is version in which support for the option was
199
    # introduced.
200
    meta_flush_supported = disk_flush_supported = {
201
      0: 12,
202
      2: 7,
203
      3: 0,
204
      }
205

  
206
    disk_drain_supported = {
207
      2: 7,
208
      3: 0,
209
      }
210

  
211
    disk_barriers_supported = {
212
      3: 0,
213
      }
214

  
215
    # meta flushes
216
    if disable_meta_flush:
217
      _AppendOrRaise(cls._DISABLE_META_FLUSH_OPTION,
218
                     meta_flush_supported.get(vmin, None))
219

  
220
    # disk flushes
221
    if constants.DRBD_B_DISK_FLUSH in disabled_barriers_set:
222
      _AppendOrRaise(cls._DISABLE_FLUSH_OPTION,
223
                     disk_flush_supported.get(vmin, None))
224

  
225
    # disk drain
226
    if constants.DRBD_B_DISK_DRAIN in disabled_barriers_set:
227
      _AppendOrRaise(cls._DISABLE_DRAIN_OPTION,
228
                     disk_drain_supported.get(vmin, None))
229

  
230
    # disk barriers
231
    if constants.DRBD_B_DISK_BARRIERS in disabled_barriers_set:
232
      _AppendOrRaise(cls._DISABLE_DISK_OPTION,
233
                     disk_barriers_supported.get(vmin, None))
234

  
235
    return args
b/test/data/bdev-drbd-8.4.txt
1
resource test0 {
1
resource resource0 {
2 2
    options {
3 3
    }
4 4
    net {
5
        cram-hmac-alg           "md5";
6
        shared-secret           "shared_secret_123";
7
        after-sb-0pri           discard-zero-changes;
8
        after-sb-1pri           consensus;
5 9
    }
6 10
    _remote_host {
7 11
        address                 ipv4 192.0.2.2:11000;
......
13 17
            disk                        "/dev/xenvg/test.data";
14 18
            meta-disk                   "/dev/xenvg/test.meta" [ 0 ];
15 19
            disk {
20
                size                    2097152s; # bytes
21
                resync-rate             61440k; # bytes/second
16 22
            }
17 23
        }
18 24
    }
b/test/py/ganeti.block.bdev_unittest.py
34 34
from ganeti.block import bdev
35 35
from ganeti.block import drbd
36 36
from ganeti.block import drbd_info
37
from ganeti.block import drbd_cmdgen
37 38

  
38 39
import testutils
39 40

  
......
192 193

  
193 194
    for vmaj, vmin, vrel, opts, meta in should_fail:
194 195
      self.assertRaises(errors.BlockDeviceError,
195
                        drbd.DRBD8._ComputeDiskBarrierArgs,
196
                        drbd_cmdgen.DRBD83CmdGenerator._ComputeDiskBarrierArgs,
196 197
                        vmaj, vmin, vrel, opts, meta)
197 198

  
198 199
    # get the valid options from the frozenset(frozenset()) in constants.
......
201 202
    # Versions that do not support anything
202 203
    for vmaj, vmin, vrel in ((8, 0, 0), (8, 0, 11), (8, 2, 6)):
203 204
      for opts in valid_options:
204
        self.assertRaises(errors.BlockDeviceError,
205
                          drbd.DRBD8._ComputeDiskBarrierArgs,
206
                          vmaj, vmin, vrel, opts, True)
205
        self.assertRaises(
206
          errors.BlockDeviceError,
207
          drbd_cmdgen.DRBD83CmdGenerator._ComputeDiskBarrierArgs,
208
          vmaj, vmin, vrel, opts, True)
207 209

  
208 210
    # Versions with partial support (testing only options that are supported)
209 211
    tests = [
......
230 232
    for test in tests:
231 233
      vmaj, vmin, vrel, disabled_barriers, disable_meta_flush, expected = test
232 234
      args = \
233
        drbd.DRBD8._ComputeDiskBarrierArgs(vmaj, vmin, vrel,
234
                                           disabled_barriers,
235
                                           disable_meta_flush)
235
        drbd_cmdgen.DRBD83CmdGenerator._ComputeDiskBarrierArgs(
236
          vmaj, vmin, vrel,
237
          disabled_barriers,
238
          disable_meta_flush)
236 239
      self.failUnless(set(args) == set(expected),
237 240
                      "For test %s, got wrong results %s" % (test, args))
238 241

  
239 242
    # Unsupported or invalid versions
240 243
    for vmaj, vmin, vrel in ((0, 7, 25), (9, 0, 0), (7, 0, 0), (8, 4, 0)):
241 244
      self.assertRaises(errors.BlockDeviceError,
242
                        drbd.DRBD8._ComputeDiskBarrierArgs,
245
                        drbd_cmdgen.DRBD83CmdGenerator._ComputeDiskBarrierArgs,
243 246
                        vmaj, vmin, vrel, "n", True)
244 247

  
245 248
    # Invalid options
246 249
    for option in ("", "c", "whatever", "nbdfc", "nf"):
247 250
      self.assertRaises(errors.BlockDeviceError,
248
                        drbd.DRBD8._ComputeDiskBarrierArgs,
251
                        drbd_cmdgen.DRBD83CmdGenerator._ComputeDiskBarrierArgs,
249 252
                        8, 3, 11, option, True)
250 253

  
251 254

  

Also available in: Unified diff