Statistics
| Branch: | Tag: | Revision:

root / lib / block / drbd_cmdgen.py @ 09a78e1c

History | View | Annotate | Download (7.7 kB)

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