Statistics
| Branch: | Tag: | Revision:

root / lib / storage / drbd_cmdgen.py @ 688b5752

History | View | Annotate | Download (14.5 kB)

1 09a78e1c Thomas Thrainer
#
2 09a78e1c Thomas Thrainer
#
3 09a78e1c Thomas Thrainer
4 09a78e1c Thomas Thrainer
# Copyright (C) 2006, 2007, 2010, 2011, 2012, 2013 Google Inc.
5 09a78e1c Thomas Thrainer
#
6 09a78e1c Thomas Thrainer
# This program is free software; you can redistribute it and/or modify
7 09a78e1c Thomas Thrainer
# it under the terms of the GNU General Public License as published by
8 09a78e1c Thomas Thrainer
# the Free Software Foundation; either version 2 of the License, or
9 09a78e1c Thomas Thrainer
# (at your option) any later version.
10 09a78e1c Thomas Thrainer
#
11 09a78e1c Thomas Thrainer
# This program is distributed in the hope that it will be useful, but
12 09a78e1c Thomas Thrainer
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 09a78e1c Thomas Thrainer
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 09a78e1c Thomas Thrainer
# General Public License for more details.
15 09a78e1c Thomas Thrainer
#
16 09a78e1c Thomas Thrainer
# You should have received a copy of the GNU General Public License
17 09a78e1c Thomas Thrainer
# along with this program; if not, write to the Free Software
18 09a78e1c Thomas Thrainer
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 09a78e1c Thomas Thrainer
# 02110-1301, USA.
20 09a78e1c Thomas Thrainer
21 09a78e1c Thomas Thrainer
22 09a78e1c Thomas Thrainer
"""DRBD command generating classes"""
23 09a78e1c Thomas Thrainer
24 09a78e1c Thomas Thrainer
import logging
25 09a78e1c Thomas Thrainer
import shlex
26 09a78e1c Thomas Thrainer
27 09a78e1c Thomas Thrainer
from ganeti import constants
28 09a78e1c Thomas Thrainer
from ganeti import errors
29 09a78e1c Thomas Thrainer
30 09a78e1c Thomas Thrainer
31 daec28a7 Thomas Thrainer
class BaseDRBDCmdGenerator(object):
32 daec28a7 Thomas Thrainer
  """Base class for DRBD command generators.
33 daec28a7 Thomas Thrainer

34 daec28a7 Thomas Thrainer
  This class defines the interface for the command generators and holds shared
35 daec28a7 Thomas Thrainer
  code.
36 daec28a7 Thomas Thrainer

37 daec28a7 Thomas Thrainer
  """
38 daec28a7 Thomas Thrainer
  def __init__(self, version):
39 daec28a7 Thomas Thrainer
    self._version = version
40 daec28a7 Thomas Thrainer
41 daec28a7 Thomas Thrainer
  def GenShowCmd(self, minor):
42 daec28a7 Thomas Thrainer
    raise NotImplementedError
43 daec28a7 Thomas Thrainer
44 daec28a7 Thomas Thrainer
  def GenInitMetaCmd(self, minor, meta_dev):
45 daec28a7 Thomas Thrainer
    raise NotImplementedError
46 daec28a7 Thomas Thrainer
47 daec28a7 Thomas Thrainer
  def GenLocalInitCmds(self, minor, data_dev, meta_dev, size_mb, params):
48 daec28a7 Thomas Thrainer
    raise NotImplementedError
49 daec28a7 Thomas Thrainer
50 daec28a7 Thomas Thrainer
  def GenNetInitCmd(self, minor, family, lhost, lport, rhost, rport, protocol,
51 daec28a7 Thomas Thrainer
                    dual_pri, hmac, secret, params):
52 daec28a7 Thomas Thrainer
    raise NotImplementedError
53 daec28a7 Thomas Thrainer
54 daec28a7 Thomas Thrainer
  def GenSyncParamsCmd(self, minor, params):
55 daec28a7 Thomas Thrainer
    raise NotImplementedError
56 daec28a7 Thomas Thrainer
57 daec28a7 Thomas Thrainer
  def GenPauseSyncCmd(self, minor):
58 daec28a7 Thomas Thrainer
    raise NotImplementedError
59 daec28a7 Thomas Thrainer
60 daec28a7 Thomas Thrainer
  def GenResumeSyncCmd(self, minor):
61 daec28a7 Thomas Thrainer
    raise NotImplementedError
62 daec28a7 Thomas Thrainer
63 daec28a7 Thomas Thrainer
  def GenPrimaryCmd(self, minor, force):
64 daec28a7 Thomas Thrainer
    raise NotImplementedError
65 daec28a7 Thomas Thrainer
66 daec28a7 Thomas Thrainer
  def GenSecondaryCmd(self, minor):
67 daec28a7 Thomas Thrainer
    raise NotImplementedError
68 daec28a7 Thomas Thrainer
69 daec28a7 Thomas Thrainer
  def GenDetachCmd(self, minor):
70 daec28a7 Thomas Thrainer
    raise NotImplementedError
71 daec28a7 Thomas Thrainer
72 daec28a7 Thomas Thrainer
  def GenDisconnectCmd(self, minor, family, lhost, lport, rhost, rport):
73 daec28a7 Thomas Thrainer
    raise NotImplementedError
74 daec28a7 Thomas Thrainer
75 daec28a7 Thomas Thrainer
  def GenDownCmd(self, minor):
76 daec28a7 Thomas Thrainer
    raise NotImplementedError
77 daec28a7 Thomas Thrainer
78 daec28a7 Thomas Thrainer
  def GenResizeCmd(self, minor, size_mb):
79 daec28a7 Thomas Thrainer
    raise NotImplementedError
80 daec28a7 Thomas Thrainer
81 daec28a7 Thomas Thrainer
  @staticmethod
82 daec28a7 Thomas Thrainer
  def _DevPath(minor):
83 daec28a7 Thomas Thrainer
    """Return the path to a drbd device for a given minor.
84 daec28a7 Thomas Thrainer

85 daec28a7 Thomas Thrainer
    """
86 daec28a7 Thomas Thrainer
    return "/dev/drbd%d" % minor
87 daec28a7 Thomas Thrainer
88 daec28a7 Thomas Thrainer
89 daec28a7 Thomas Thrainer
class DRBD83CmdGenerator(BaseDRBDCmdGenerator):
90 daec28a7 Thomas Thrainer
  """Generates drbdsetup commands suited for the DRBD <= 8.3 syntax.
91 09a78e1c Thomas Thrainer

92 09a78e1c Thomas Thrainer
  """
93 09a78e1c Thomas Thrainer
  # command line options for barriers
94 09a78e1c Thomas Thrainer
  _DISABLE_DISK_OPTION = "--no-disk-barrier"  # -a
95 09a78e1c Thomas Thrainer
  _DISABLE_DRAIN_OPTION = "--no-disk-drain"   # -D
96 09a78e1c Thomas Thrainer
  _DISABLE_FLUSH_OPTION = "--no-disk-flushes" # -i
97 09a78e1c Thomas Thrainer
  _DISABLE_META_FLUSH_OPTION = "--no-md-flushes"  # -m
98 09a78e1c Thomas Thrainer
99 daec28a7 Thomas Thrainer
  def __init__(self, version):
100 daec28a7 Thomas Thrainer
    super(DRBD83CmdGenerator, self).__init__(version)
101 09a78e1c Thomas Thrainer
102 09a78e1c Thomas Thrainer
  def GenShowCmd(self, minor):
103 09a78e1c Thomas Thrainer
    return ["drbdsetup", self._DevPath(minor), "show"]
104 09a78e1c Thomas Thrainer
105 daec28a7 Thomas Thrainer
  def GenInitMetaCmd(self, minor, meta_dev):
106 daec28a7 Thomas Thrainer
    return ["drbdmeta", "--force", self._DevPath(minor),
107 daec28a7 Thomas Thrainer
            "v08", meta_dev, "0", "create-md"]
108 daec28a7 Thomas Thrainer
109 09a78e1c Thomas Thrainer
  def GenLocalInitCmds(self, minor, data_dev, meta_dev, size_mb, params):
110 09a78e1c Thomas Thrainer
    args = ["drbdsetup", self._DevPath(minor), "disk",
111 09a78e1c Thomas Thrainer
            data_dev, meta_dev, "0",
112 09a78e1c Thomas Thrainer
            "-e", "detach",
113 09a78e1c Thomas Thrainer
            "--create-device"]
114 09a78e1c Thomas Thrainer
    if size_mb:
115 09a78e1c Thomas Thrainer
      args.extend(["-d", "%sm" % size_mb])
116 09a78e1c Thomas Thrainer
117 daec28a7 Thomas Thrainer
    vmaj = self._version["k_major"]
118 daec28a7 Thomas Thrainer
    vmin = self._version["k_minor"]
119 daec28a7 Thomas Thrainer
    vrel = self._version["k_point"]
120 09a78e1c Thomas Thrainer
121 09a78e1c Thomas Thrainer
    barrier_args = \
122 09a78e1c Thomas Thrainer
      self._ComputeDiskBarrierArgs(vmaj, vmin, vrel,
123 09a78e1c Thomas Thrainer
                                   params[constants.LDP_BARRIERS],
124 09a78e1c Thomas Thrainer
                                   params[constants.LDP_NO_META_FLUSH])
125 09a78e1c Thomas Thrainer
    args.extend(barrier_args)
126 09a78e1c Thomas Thrainer
127 09a78e1c Thomas Thrainer
    if params[constants.LDP_DISK_CUSTOM]:
128 09a78e1c Thomas Thrainer
      args.extend(shlex.split(params[constants.LDP_DISK_CUSTOM]))
129 09a78e1c Thomas Thrainer
130 09a78e1c Thomas Thrainer
    return [args]
131 09a78e1c Thomas Thrainer
132 09a78e1c Thomas Thrainer
  def GenNetInitCmd(self, minor, family, lhost, lport, rhost, rport, protocol,
133 09a78e1c Thomas Thrainer
                    dual_pri, hmac, secret, params):
134 09a78e1c Thomas Thrainer
    args = ["drbdsetup", self._DevPath(minor), "net",
135 09a78e1c Thomas Thrainer
            "%s:%s:%s" % (family, lhost, lport),
136 09a78e1c Thomas Thrainer
            "%s:%s:%s" % (family, rhost, rport), protocol,
137 09a78e1c Thomas Thrainer
            "-A", "discard-zero-changes",
138 09a78e1c Thomas Thrainer
            "-B", "consensus",
139 09a78e1c Thomas Thrainer
            "--create-device",
140 09a78e1c Thomas Thrainer
            ]
141 09a78e1c Thomas Thrainer
    if dual_pri:
142 09a78e1c Thomas Thrainer
      args.append("-m")
143 09a78e1c Thomas Thrainer
    if hmac and secret:
144 09a78e1c Thomas Thrainer
      args.extend(["-a", hmac, "-x", secret])
145 09a78e1c Thomas Thrainer
146 09a78e1c Thomas Thrainer
    if params[constants.LDP_NET_CUSTOM]:
147 09a78e1c Thomas Thrainer
      args.extend(shlex.split(params[constants.LDP_NET_CUSTOM]))
148 09a78e1c Thomas Thrainer
149 09a78e1c Thomas Thrainer
    return args
150 09a78e1c Thomas Thrainer
151 09a78e1c Thomas Thrainer
  def GenSyncParamsCmd(self, minor, params):
152 09a78e1c Thomas Thrainer
    args = ["drbdsetup", self._DevPath(minor), "syncer"]
153 09a78e1c Thomas Thrainer
    if params[constants.LDP_DYNAMIC_RESYNC]:
154 daec28a7 Thomas Thrainer
      vmin = self._version["k_minor"]
155 daec28a7 Thomas Thrainer
      vrel = self._version["k_point"]
156 09a78e1c Thomas Thrainer
157 09a78e1c Thomas Thrainer
      # By definition we are using 8.x, so just check the rest of the version
158 09a78e1c Thomas Thrainer
      # number
159 09a78e1c Thomas Thrainer
      if vmin != 3 or vrel < 9:
160 09a78e1c Thomas Thrainer
        msg = ("The current DRBD version (8.%d.%d) does not support the "
161 09a78e1c Thomas Thrainer
               "dynamic resync speed controller" % (vmin, vrel))
162 09a78e1c Thomas Thrainer
        logging.error(msg)
163 09a78e1c Thomas Thrainer
        return [msg]
164 09a78e1c Thomas Thrainer
165 09a78e1c Thomas Thrainer
      if params[constants.LDP_PLAN_AHEAD] == 0:
166 09a78e1c Thomas Thrainer
        msg = ("A value of 0 for c-plan-ahead disables the dynamic sync speed"
167 09a78e1c Thomas Thrainer
               " controller at DRBD level. If you want to disable it, please"
168 09a78e1c Thomas Thrainer
               " set the dynamic-resync disk parameter to False.")
169 09a78e1c Thomas Thrainer
        logging.error(msg)
170 09a78e1c Thomas Thrainer
        return [msg]
171 09a78e1c Thomas Thrainer
172 09a78e1c Thomas Thrainer
      # add the c-* parameters to args
173 09a78e1c Thomas Thrainer
      args.extend(["--c-plan-ahead", params[constants.LDP_PLAN_AHEAD],
174 09a78e1c Thomas Thrainer
                   "--c-fill-target", params[constants.LDP_FILL_TARGET],
175 09a78e1c Thomas Thrainer
                   "--c-delay-target", params[constants.LDP_DELAY_TARGET],
176 09a78e1c Thomas Thrainer
                   "--c-max-rate", params[constants.LDP_MAX_RATE],
177 09a78e1c Thomas Thrainer
                   "--c-min-rate", params[constants.LDP_MIN_RATE],
178 09a78e1c Thomas Thrainer
                   ])
179 09a78e1c Thomas Thrainer
180 09a78e1c Thomas Thrainer
    else:
181 09a78e1c Thomas Thrainer
      args.extend(["-r", "%d" % params[constants.LDP_RESYNC_RATE]])
182 09a78e1c Thomas Thrainer
183 09a78e1c Thomas Thrainer
    args.append("--create-device")
184 09a78e1c Thomas Thrainer
185 09a78e1c Thomas Thrainer
    return args
186 09a78e1c Thomas Thrainer
187 09a78e1c Thomas Thrainer
  def GenPauseSyncCmd(self, minor):
188 09a78e1c Thomas Thrainer
    return ["drbdsetup", self._DevPath(minor), "pause-sync"]
189 09a78e1c Thomas Thrainer
190 09a78e1c Thomas Thrainer
  def GenResumeSyncCmd(self, minor):
191 09a78e1c Thomas Thrainer
    return ["drbdsetup", self._DevPath(minor), "resume-sync"]
192 09a78e1c Thomas Thrainer
193 09a78e1c Thomas Thrainer
  def GenPrimaryCmd(self, minor, force):
194 09a78e1c Thomas Thrainer
    cmd = ["drbdsetup", self._DevPath(minor), "primary"]
195 09a78e1c Thomas Thrainer
196 09a78e1c Thomas Thrainer
    if force:
197 09a78e1c Thomas Thrainer
      cmd.append("-o")
198 09a78e1c Thomas Thrainer
199 09a78e1c Thomas Thrainer
    return cmd
200 09a78e1c Thomas Thrainer
201 09a78e1c Thomas Thrainer
  def GenSecondaryCmd(self, minor):
202 09a78e1c Thomas Thrainer
    return ["drbdsetup", self._DevPath(minor), "secondary"]
203 09a78e1c Thomas Thrainer
204 09a78e1c Thomas Thrainer
  def GenDetachCmd(self, minor):
205 09a78e1c Thomas Thrainer
    return ["drbdsetup", self._DevPath(minor), "detach"]
206 09a78e1c Thomas Thrainer
207 daec28a7 Thomas Thrainer
  def GenDisconnectCmd(self, minor, family, lhost, lport, rhost, rport):
208 09a78e1c Thomas Thrainer
    return ["drbdsetup", self._DevPath(minor), "disconnect"]
209 09a78e1c Thomas Thrainer
210 09a78e1c Thomas Thrainer
  def GenDownCmd(self, minor):
211 09a78e1c Thomas Thrainer
    return ["drbdsetup", self._DevPath(minor), "down"]
212 09a78e1c Thomas Thrainer
213 09a78e1c Thomas Thrainer
  def GenResizeCmd(self, minor, size_mb):
214 09a78e1c Thomas Thrainer
    return ["drbdsetup", self._DevPath(minor), "resize", "-s", "%dm" % size_mb]
215 09a78e1c Thomas Thrainer
216 09a78e1c Thomas Thrainer
  @classmethod
217 09a78e1c Thomas Thrainer
  def _ComputeDiskBarrierArgs(cls, vmaj, vmin, vrel, disabled_barriers,
218 09a78e1c Thomas Thrainer
                              disable_meta_flush):
219 09a78e1c Thomas Thrainer
    """Compute the DRBD command line parameters for disk barriers
220 09a78e1c Thomas Thrainer

221 09a78e1c Thomas Thrainer
    Returns a list of the disk barrier parameters as requested via the
222 09a78e1c Thomas Thrainer
    disabled_barriers and disable_meta_flush arguments, and according to the
223 09a78e1c Thomas Thrainer
    supported ones in the DRBD version vmaj.vmin.vrel
224 09a78e1c Thomas Thrainer

225 09a78e1c Thomas Thrainer
    If the desired option is unsupported, raises errors.BlockDeviceError.
226 09a78e1c Thomas Thrainer

227 09a78e1c Thomas Thrainer
    """
228 09a78e1c Thomas Thrainer
    disabled_barriers_set = frozenset(disabled_barriers)
229 09a78e1c Thomas Thrainer
    if not disabled_barriers_set in constants.DRBD_VALID_BARRIER_OPT:
230 09a78e1c Thomas Thrainer
      raise errors.BlockDeviceError("%s is not a valid option set for DRBD"
231 09a78e1c Thomas Thrainer
                                    " barriers" % disabled_barriers)
232 09a78e1c Thomas Thrainer
233 09a78e1c Thomas Thrainer
    args = []
234 09a78e1c Thomas Thrainer
235 09a78e1c Thomas Thrainer
    # The following code assumes DRBD 8.x, with x < 4 and x != 1 (DRBD 8.1.x
236 09a78e1c Thomas Thrainer
    # does not exist)
237 09a78e1c Thomas Thrainer
    if not vmaj == 8 and vmin in (0, 2, 3):
238 09a78e1c Thomas Thrainer
      raise errors.BlockDeviceError("Unsupported DRBD version: %d.%d.%d" %
239 09a78e1c Thomas Thrainer
                                    (vmaj, vmin, vrel))
240 09a78e1c Thomas Thrainer
241 09a78e1c Thomas Thrainer
    def _AppendOrRaise(option, min_version):
242 09a78e1c Thomas Thrainer
      """Helper for DRBD options"""
243 09a78e1c Thomas Thrainer
      if min_version is not None and vrel >= min_version:
244 09a78e1c Thomas Thrainer
        args.append(option)
245 09a78e1c Thomas Thrainer
      else:
246 09a78e1c Thomas Thrainer
        raise errors.BlockDeviceError("Could not use the option %s as the"
247 09a78e1c Thomas Thrainer
                                      " DRBD version %d.%d.%d does not support"
248 09a78e1c Thomas Thrainer
                                      " it." % (option, vmaj, vmin, vrel))
249 09a78e1c Thomas Thrainer
250 09a78e1c Thomas Thrainer
    # the minimum version for each feature is encoded via pairs of (minor
251 09a78e1c Thomas Thrainer
    # version -> x) where x is version in which support for the option was
252 09a78e1c Thomas Thrainer
    # introduced.
253 09a78e1c Thomas Thrainer
    meta_flush_supported = disk_flush_supported = {
254 09a78e1c Thomas Thrainer
      0: 12,
255 09a78e1c Thomas Thrainer
      2: 7,
256 09a78e1c Thomas Thrainer
      3: 0,
257 09a78e1c Thomas Thrainer
      }
258 09a78e1c Thomas Thrainer
259 09a78e1c Thomas Thrainer
    disk_drain_supported = {
260 09a78e1c Thomas Thrainer
      2: 7,
261 09a78e1c Thomas Thrainer
      3: 0,
262 09a78e1c Thomas Thrainer
      }
263 09a78e1c Thomas Thrainer
264 09a78e1c Thomas Thrainer
    disk_barriers_supported = {
265 09a78e1c Thomas Thrainer
      3: 0,
266 09a78e1c Thomas Thrainer
      }
267 09a78e1c Thomas Thrainer
268 09a78e1c Thomas Thrainer
    # meta flushes
269 09a78e1c Thomas Thrainer
    if disable_meta_flush:
270 09a78e1c Thomas Thrainer
      _AppendOrRaise(cls._DISABLE_META_FLUSH_OPTION,
271 09a78e1c Thomas Thrainer
                     meta_flush_supported.get(vmin, None))
272 09a78e1c Thomas Thrainer
273 09a78e1c Thomas Thrainer
    # disk flushes
274 09a78e1c Thomas Thrainer
    if constants.DRBD_B_DISK_FLUSH in disabled_barriers_set:
275 09a78e1c Thomas Thrainer
      _AppendOrRaise(cls._DISABLE_FLUSH_OPTION,
276 09a78e1c Thomas Thrainer
                     disk_flush_supported.get(vmin, None))
277 09a78e1c Thomas Thrainer
278 09a78e1c Thomas Thrainer
    # disk drain
279 09a78e1c Thomas Thrainer
    if constants.DRBD_B_DISK_DRAIN in disabled_barriers_set:
280 09a78e1c Thomas Thrainer
      _AppendOrRaise(cls._DISABLE_DRAIN_OPTION,
281 09a78e1c Thomas Thrainer
                     disk_drain_supported.get(vmin, None))
282 09a78e1c Thomas Thrainer
283 09a78e1c Thomas Thrainer
    # disk barriers
284 09a78e1c Thomas Thrainer
    if constants.DRBD_B_DISK_BARRIERS in disabled_barriers_set:
285 09a78e1c Thomas Thrainer
      _AppendOrRaise(cls._DISABLE_DISK_OPTION,
286 09a78e1c Thomas Thrainer
                     disk_barriers_supported.get(vmin, None))
287 09a78e1c Thomas Thrainer
288 09a78e1c Thomas Thrainer
    return args
289 daec28a7 Thomas Thrainer
290 daec28a7 Thomas Thrainer
291 daec28a7 Thomas Thrainer
class DRBD84CmdGenerator(BaseDRBDCmdGenerator):
292 daec28a7 Thomas Thrainer
  """Generates drbdsetup commands suited for the DRBD >= 8.4 syntax.
293 daec28a7 Thomas Thrainer

294 daec28a7 Thomas Thrainer
  """
295 daec28a7 Thomas Thrainer
  # command line options for barriers
296 daec28a7 Thomas Thrainer
  _DISABLE_DISK_OPTION = "--disk-barrier=no"
297 daec28a7 Thomas Thrainer
  _DISABLE_DRAIN_OPTION = "--disk-drain=no"
298 daec28a7 Thomas Thrainer
  _DISABLE_FLUSH_OPTION = "--disk-flushes=no"
299 daec28a7 Thomas Thrainer
  _DISABLE_META_FLUSH_OPTION = "--md-flushes=no"
300 daec28a7 Thomas Thrainer
301 daec28a7 Thomas Thrainer
  def __init__(self, version):
302 daec28a7 Thomas Thrainer
    super(DRBD84CmdGenerator, self).__init__(version)
303 daec28a7 Thomas Thrainer
304 daec28a7 Thomas Thrainer
  def GenShowCmd(self, minor):
305 daec28a7 Thomas Thrainer
    return ["drbdsetup", "show", minor]
306 daec28a7 Thomas Thrainer
307 daec28a7 Thomas Thrainer
  def GenInitMetaCmd(self, minor, meta_dev):
308 daec28a7 Thomas Thrainer
    return ["drbdmeta", "--force", self._DevPath(minor),
309 d30fa488 Thomas Thrainer
            "v08", meta_dev, "flex-external", "create-md"]
310 daec28a7 Thomas Thrainer
311 daec28a7 Thomas Thrainer
  def GenLocalInitCmds(self, minor, data_dev, meta_dev, size_mb, params):
312 daec28a7 Thomas Thrainer
    cmds = []
313 daec28a7 Thomas Thrainer
314 daec28a7 Thomas Thrainer
    cmds.append(["drbdsetup", "new-resource", self._GetResource(minor)])
315 daec28a7 Thomas Thrainer
    cmds.append(["drbdsetup", "new-minor", self._GetResource(minor),
316 daec28a7 Thomas Thrainer
                 str(minor), "0"])
317 daec28a7 Thomas Thrainer
    # We need to apply the activity log before attaching the disk else drbdsetup
318 daec28a7 Thomas Thrainer
    # will fail.
319 daec28a7 Thomas Thrainer
    cmds.append(["drbdmeta", self._DevPath(minor),
320 d30fa488 Thomas Thrainer
                 "v08", meta_dev, "flex-external", "apply-al"])
321 daec28a7 Thomas Thrainer
322 d30fa488 Thomas Thrainer
    attach_cmd = ["drbdsetup", "attach", minor, data_dev, meta_dev, "flexible",
323 daec28a7 Thomas Thrainer
                  "--on-io-error=detach"]
324 daec28a7 Thomas Thrainer
    if size_mb:
325 daec28a7 Thomas Thrainer
      attach_cmd.extend(["--size", "%sm" % size_mb])
326 daec28a7 Thomas Thrainer
327 daec28a7 Thomas Thrainer
    barrier_args = \
328 daec28a7 Thomas Thrainer
      self._ComputeDiskBarrierArgs(params[constants.LDP_BARRIERS],
329 daec28a7 Thomas Thrainer
                                   params[constants.LDP_NO_META_FLUSH])
330 daec28a7 Thomas Thrainer
    attach_cmd.extend(barrier_args)
331 daec28a7 Thomas Thrainer
332 daec28a7 Thomas Thrainer
    if params[constants.LDP_DISK_CUSTOM]:
333 daec28a7 Thomas Thrainer
      attach_cmd.extend(shlex.split(params[constants.LDP_DISK_CUSTOM]))
334 daec28a7 Thomas Thrainer
335 daec28a7 Thomas Thrainer
    cmds.append(attach_cmd)
336 daec28a7 Thomas Thrainer
337 daec28a7 Thomas Thrainer
    return cmds
338 daec28a7 Thomas Thrainer
339 daec28a7 Thomas Thrainer
  def GenNetInitCmd(self, minor, family, lhost, lport, rhost, rport, protocol,
340 daec28a7 Thomas Thrainer
                    dual_pri, hmac, secret, params):
341 daec28a7 Thomas Thrainer
    args = ["drbdsetup", "connect", self._GetResource(minor),
342 daec28a7 Thomas Thrainer
            "%s:%s:%s" % (family, lhost, lport),
343 daec28a7 Thomas Thrainer
            "%s:%s:%s" % (family, rhost, rport),
344 daec28a7 Thomas Thrainer
            "--protocol", protocol,
345 daec28a7 Thomas Thrainer
            "--after-sb-0pri", "discard-zero-changes",
346 daec28a7 Thomas Thrainer
            "--after-sb-1pri", "consensus"
347 daec28a7 Thomas Thrainer
            ]
348 daec28a7 Thomas Thrainer
    if dual_pri:
349 daec28a7 Thomas Thrainer
      args.append("--allow-two-primaries")
350 daec28a7 Thomas Thrainer
    if hmac and secret:
351 daec28a7 Thomas Thrainer
      args.extend(["--cram-hmac-alg", hmac, "--shared-secret", secret])
352 daec28a7 Thomas Thrainer
353 daec28a7 Thomas Thrainer
    if params[constants.LDP_NET_CUSTOM]:
354 daec28a7 Thomas Thrainer
      args.extend(shlex.split(params[constants.LDP_NET_CUSTOM]))
355 daec28a7 Thomas Thrainer
356 daec28a7 Thomas Thrainer
    return args
357 daec28a7 Thomas Thrainer
358 daec28a7 Thomas Thrainer
  def GenSyncParamsCmd(self, minor, params):
359 daec28a7 Thomas Thrainer
    args = ["drbdsetup", "disk-options", minor]
360 daec28a7 Thomas Thrainer
    if params[constants.LDP_DYNAMIC_RESYNC]:
361 daec28a7 Thomas Thrainer
      if params[constants.LDP_PLAN_AHEAD] == 0:
362 daec28a7 Thomas Thrainer
        msg = ("A value of 0 for c-plan-ahead disables the dynamic sync speed"
363 daec28a7 Thomas Thrainer
               " controller at DRBD level. If you want to disable it, please"
364 daec28a7 Thomas Thrainer
               " set the dynamic-resync disk parameter to False.")
365 daec28a7 Thomas Thrainer
        logging.error(msg)
366 daec28a7 Thomas Thrainer
        return [msg]
367 daec28a7 Thomas Thrainer
368 daec28a7 Thomas Thrainer
      # add the c-* parameters to args
369 daec28a7 Thomas Thrainer
      args.extend(["--c-plan-ahead", params[constants.LDP_PLAN_AHEAD],
370 daec28a7 Thomas Thrainer
                   "--c-fill-target", params[constants.LDP_FILL_TARGET],
371 daec28a7 Thomas Thrainer
                   "--c-delay-target", params[constants.LDP_DELAY_TARGET],
372 daec28a7 Thomas Thrainer
                   "--c-max-rate", params[constants.LDP_MAX_RATE],
373 daec28a7 Thomas Thrainer
                   "--c-min-rate", params[constants.LDP_MIN_RATE],
374 daec28a7 Thomas Thrainer
                   ])
375 daec28a7 Thomas Thrainer
376 daec28a7 Thomas Thrainer
    else:
377 daec28a7 Thomas Thrainer
      args.extend(["--resync-rate", "%d" % params[constants.LDP_RESYNC_RATE]])
378 daec28a7 Thomas Thrainer
379 daec28a7 Thomas Thrainer
    return args
380 daec28a7 Thomas Thrainer
381 daec28a7 Thomas Thrainer
  def GenPauseSyncCmd(self, minor):
382 daec28a7 Thomas Thrainer
    return ["drbdsetup", "pause-sync", minor]
383 daec28a7 Thomas Thrainer
384 daec28a7 Thomas Thrainer
  def GenResumeSyncCmd(self, minor):
385 daec28a7 Thomas Thrainer
    return ["drbdsetup", "resume-sync", minor]
386 daec28a7 Thomas Thrainer
387 daec28a7 Thomas Thrainer
  def GenPrimaryCmd(self, minor, force):
388 daec28a7 Thomas Thrainer
    cmd = ["drbdsetup", "primary", minor]
389 daec28a7 Thomas Thrainer
390 daec28a7 Thomas Thrainer
    if force:
391 daec28a7 Thomas Thrainer
      cmd.append("--force")
392 daec28a7 Thomas Thrainer
393 daec28a7 Thomas Thrainer
    return cmd
394 daec28a7 Thomas Thrainer
395 daec28a7 Thomas Thrainer
  def GenSecondaryCmd(self, minor):
396 daec28a7 Thomas Thrainer
    return ["drbdsetup", "secondary", minor]
397 daec28a7 Thomas Thrainer
398 daec28a7 Thomas Thrainer
  def GenDetachCmd(self, minor):
399 daec28a7 Thomas Thrainer
    return ["drbdsetup", "detach", minor]
400 daec28a7 Thomas Thrainer
401 daec28a7 Thomas Thrainer
  def GenDisconnectCmd(self, minor, family, lhost, lport, rhost, rport):
402 daec28a7 Thomas Thrainer
    return ["drbdsetup", "disconnect",
403 daec28a7 Thomas Thrainer
            "%s:%s:%s" % (family, lhost, lport),
404 daec28a7 Thomas Thrainer
            "%s:%s:%s" % (family, rhost, rport)]
405 daec28a7 Thomas Thrainer
406 daec28a7 Thomas Thrainer
  def GenDownCmd(self, minor):
407 daec28a7 Thomas Thrainer
    return ["drbdsetup", "down", self._GetResource(minor)]
408 daec28a7 Thomas Thrainer
409 daec28a7 Thomas Thrainer
  def GenResizeCmd(self, minor, size_mb):
410 daec28a7 Thomas Thrainer
    return ["drbdsetup", "resize", minor, "--size", "%dm" % size_mb]
411 daec28a7 Thomas Thrainer
412 daec28a7 Thomas Thrainer
  @staticmethod
413 daec28a7 Thomas Thrainer
  def _GetResource(minor):
414 daec28a7 Thomas Thrainer
    """Return the resource name for a given minor.
415 daec28a7 Thomas Thrainer

416 daec28a7 Thomas Thrainer
    Currently we don't support DRBD volumes which share a resource, so we
417 daec28a7 Thomas Thrainer
    generate the resource name based on the minor the resulting volumes is
418 daec28a7 Thomas Thrainer
    assigned to.
419 daec28a7 Thomas Thrainer

420 daec28a7 Thomas Thrainer
    """
421 daec28a7 Thomas Thrainer
    return "resource%d" % minor
422 daec28a7 Thomas Thrainer
423 daec28a7 Thomas Thrainer
  @classmethod
424 daec28a7 Thomas Thrainer
  def _ComputeDiskBarrierArgs(cls, disabled_barriers, disable_meta_flush):
425 daec28a7 Thomas Thrainer
    """Compute the DRBD command line parameters for disk barriers
426 daec28a7 Thomas Thrainer

427 daec28a7 Thomas Thrainer
    """
428 daec28a7 Thomas Thrainer
    disabled_barriers_set = frozenset(disabled_barriers)
429 daec28a7 Thomas Thrainer
    if not disabled_barriers_set in constants.DRBD_VALID_BARRIER_OPT:
430 daec28a7 Thomas Thrainer
      raise errors.BlockDeviceError("%s is not a valid option set for DRBD"
431 daec28a7 Thomas Thrainer
                                    " barriers" % disabled_barriers)
432 daec28a7 Thomas Thrainer
433 daec28a7 Thomas Thrainer
    args = []
434 daec28a7 Thomas Thrainer
435 daec28a7 Thomas Thrainer
    # meta flushes
436 daec28a7 Thomas Thrainer
    if disable_meta_flush:
437 daec28a7 Thomas Thrainer
      args.append(cls._DISABLE_META_FLUSH_OPTION)
438 daec28a7 Thomas Thrainer
439 daec28a7 Thomas Thrainer
    # disk flushes
440 daec28a7 Thomas Thrainer
    if constants.DRBD_B_DISK_FLUSH in disabled_barriers_set:
441 daec28a7 Thomas Thrainer
      args.append(cls._DISABLE_FLUSH_OPTION)
442 daec28a7 Thomas Thrainer
443 daec28a7 Thomas Thrainer
    # disk drain
444 daec28a7 Thomas Thrainer
    if constants.DRBD_B_DISK_DRAIN in disabled_barriers_set:
445 daec28a7 Thomas Thrainer
      args.append(cls._DISABLE_DRAIN_OPTION)
446 daec28a7 Thomas Thrainer
447 daec28a7 Thomas Thrainer
    # disk barriers
448 daec28a7 Thomas Thrainer
    if constants.DRBD_B_DISK_BARRIERS in disabled_barriers_set:
449 daec28a7 Thomas Thrainer
      args.append(cls._DISABLE_DISK_OPTION)
450 daec28a7 Thomas Thrainer
451 daec28a7 Thomas Thrainer
    return args